create debug session and attempt to write

This commit is contained in:
Beau Kujath committed 2023-05-02 15:31:16 -06:00
1 parent f285b60d7c
commit b4151cf76d
513 files changed
+40503 -2188

No files matched your search

@@ -0,0 +1,256 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.util.Xml;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ListView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.io.OutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class ActivityDns extends AppCompatActivity {
private static final String TAG = "NetGuard.DNS";
private static final int REQUEST_EXPORT = 1;
private boolean running;
private AdapterDns adapter = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
Util.setTheme(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.resolving);
getSupportActionBar().setTitle(R.string.setting_show_resolved);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ListView lvDns = findViewById(R.id.lvDns);
adapter = new AdapterDns(this, DatabaseHelper.getInstance(this).getDns());
lvDns.setAdapter(adapter);
running = true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.dns, menu);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
PackageManager pm = getPackageManager();
menu.findItem(R.id.menu_export).setEnabled(getIntentExport().resolveActivity(pm) != null);
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_refresh:
refresh();
return true;
case R.id.menu_cleanup:
cleanup();
return true;
case R.id.menu_clear:
Util.areYouSure(this, R.string.menu_clear, new Util.DoubtListener() {
@Override
public void onSure() {
clear();
}
});
return true;
case R.id.menu_export:
export();
return true;
}
return false;
}
private void refresh() {
updateAdapter();
}
private void cleanup() {
new AsyncTask<Object, Object, Object>() {
@Override
protected Long doInBackground(Object... objects) {
Log.i(TAG, "Cleanup DNS");
DatabaseHelper.getInstance(ActivityDns.this).cleanupDns();
return null;
}
@Override
protected void onPostExecute(Object result) {
ServiceSinkhole.reload("DNS cleanup", ActivityDns.this, false);
updateAdapter();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private void clear() {
new AsyncTask<Object, Object, Object>() {
@Override
protected Long doInBackground(Object... objects) {
Log.i(TAG, "Clear DNS");
DatabaseHelper.getInstance(ActivityDns.this).clearDns();
return null;
}
@Override
protected void onPostExecute(Object result) {
ServiceSinkhole.reload("DNS clear", ActivityDns.this, false);
updateAdapter();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private void export() {
startActivityForResult(getIntentExport(), REQUEST_EXPORT);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.i(TAG, "onActivityResult request=" + requestCode + " result=" + requestCode + " ok=" + (resultCode == RESULT_OK));
if (requestCode == REQUEST_EXPORT) {
if (resultCode == RESULT_OK && data != null)
handleExport(data);
}
}
private Intent getIntentExport() {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*"); // text/xml
intent.putExtra(Intent.EXTRA_TITLE, "netguard_dns_" + new SimpleDateFormat("yyyyMMdd").format(new Date().getTime()) + ".xml");
return intent;
}
private void handleExport(final Intent data) {
new AsyncTask<Object, Object, Throwable>() {
@Override
protected Throwable doInBackground(Object... objects) {
OutputStream out = null;
try {
Uri target = data.getData();
Log.i(TAG, "Writing URI=" + target);
out = getContentResolver().openOutputStream(target);
xmlExport(out);
return null;
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
return ex;
} finally {
if (out != null)
try {
out.close();
} catch (IOException ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
}
}
@Override
protected void onPostExecute(Throwable ex) {
if (running) {
if (ex == null)
Toast.makeText(ActivityDns.this, R.string.msg_completed, Toast.LENGTH_LONG).show();
else
Toast.makeText(ActivityDns.this, ex.toString(), Toast.LENGTH_LONG).show();
}
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private void xmlExport(OutputStream out) throws IOException {
XmlSerializer serializer = Xml.newSerializer();
serializer.setOutput(out, "UTF-8");
serializer.startDocument(null, true);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startTag(null, "netguard");
DateFormat df = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss Z", Locale.US); // RFC 822
try (Cursor cursor = DatabaseHelper.getInstance(this).getDns()) {
int colTime = cursor.getColumnIndex("time");
int colQName = cursor.getColumnIndex("qname");
int colAName = cursor.getColumnIndex("aname");
int colResource = cursor.getColumnIndex("resource");
int colTTL = cursor.getColumnIndex("ttl");
while (cursor.moveToNext()) {
long time = cursor.getLong(colTime);
String qname = cursor.getString(colQName);
String aname = cursor.getString(colAName);
String resource = cursor.getString(colResource);
int ttl = cursor.getInt(colTTL);
serializer.startTag(null, "dns");
serializer.attribute(null, "time", df.format(time));
serializer.attribute(null, "qname", qname);
serializer.attribute(null, "aname", aname);
serializer.attribute(null, "resource", resource);
serializer.attribute(null, "ttl", Integer.toString(ttl));
serializer.endTag(null, "dns");
}
}
serializer.endTag(null, "netguard");
serializer.endDocument();
serializer.flush();
}
private void updateAdapter() {
if (adapter != null)
adapter.changeCursor(DatabaseHelper.getInstance(this).getDns());
}
@Override
protected void onDestroy() {
running = false;
adapter = null;
super.onDestroy();
}
}
@@ -0,0 +1,130 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.net.InetAddress;
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";
static {
try {
System.loadLibrary("netguard");
} catch (UnsatisfiedLinkError ignored) {
System.exit(1);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.forwardapproval);
final int protocol = getIntent().getIntExtra("protocol", 0);
final int dport = getIntent().getIntExtra("dport", 0);
String addr = getIntent().getStringExtra("raddr");
final int rport = getIntent().getIntExtra("rport", 0);
final int ruid = getIntent().getIntExtra("ruid", 0);
final String raddr = (addr == null ? "127.0.0.1" : addr);
try {
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");
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
finish();
}
String pname;
if (protocol == 6)
pname = getString(R.string.menu_protocol_tcp);
else if (protocol == 17)
pname = getString(R.string.menu_protocol_udp);
else
pname = Integer.toString(protocol);
TextView tvForward = findViewById(R.id.tvForward);
if (ACTION_START_PORT_FORWARD.equals(getIntent().getAction()))
tvForward.setText(getString(R.string.msg_start_forward,
pname, dport, raddr, rport,
TextUtils.join(", ", Util.getApplicationNames(ruid, this))));
else
tvForward.setText(getString(R.string.msg_stop_forward, pname, dport));
Button btnOk = findViewById(R.id.btnOk);
Button btnCancel = findViewById(R.id.btnCancel);
btnOk.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (ACTION_START_PORT_FORWARD.equals(getIntent().getAction())) {
/*
am start -a eu.faircode.netguard.START_PORT_FORWARD \
-n eu.faircode.netguard/eu.faircode.netguard.ActivityForwardApproval \
--ei protocol 17 \
--ei dport 53 \
--es raddr 8.8.4.4 \
--ei rport 53 \
--ei ruid 9999 \
--user 0
*/
Log.i(TAG, "Start forwarding protocol " + protocol + " port " + dport + " to " + raddr + "/" + rport + " uid " + ruid);
DatabaseHelper dh = DatabaseHelper.getInstance(ActivityForwardApproval.this);
dh.deleteForward(protocol, dport);
dh.addForward(protocol, dport, raddr, rport, ruid);
} 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.ActivityForwardApproval \
--ei protocol 17 \
--ei dport 53 \
--user 0
*/
Log.i(TAG, "Stop forwarding protocol " + protocol + " port " + dport);
DatabaseHelper.getInstance(ActivityForwardApproval.this).deleteForward(protocol, dport);
}
ServiceSinkhole.reload("forwarding", ActivityForwardApproval.this, false);
finish();
}
});
btnCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
}
}
@@ -0,0 +1,251 @@
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-2019 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 androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import java.net.InetAddress;
import java.util.List;
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);
}
}
}
@@ -0,0 +1,643 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.CompoundButton;
import android.widget.FilterQueryProvider;
import android.widget.ListView;
import android.widget.PopupMenu;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.SwitchCompat;
import androidx.core.app.NavUtils;
import androidx.preference.PreferenceManager;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ActivityLog extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "NetGuard.Log";
private boolean running = false;
private ListView lvLog;
private AdapterLog adapter;
private MenuItem menuSearch = null;
private boolean live;
private boolean resolve;
private boolean organization;
private InetAddress vpn4 = null;
private InetAddress vpn6 = null;
private static final int REQUEST_PCAP = 1;
private DatabaseHelper.LogChangedListener listener = new DatabaseHelper.LogChangedListener() {
@Override
public void onChanged() {
runOnUiThread(new Runnable() {
@Override
public void run() {
updateAdapter();
}
});
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
if (!IAB.isPurchased(ActivityPro.SKU_LOG, this)) {
startActivity(new Intent(this, ActivityPro.class));
finish();
}
Util.setTheme(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.logging);
running = true;
// Action bar
View actionView = getLayoutInflater().inflate(R.layout.actionlog, null, false);
SwitchCompat swEnabled = actionView.findViewById(R.id.swEnabled);
getSupportActionBar().setDisplayShowCustomEnabled(true);
getSupportActionBar().setCustomView(actionView);
getSupportActionBar().setTitle(R.string.menu_log);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Get settings
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
resolve = prefs.getBoolean("resolve", false);
organization = prefs.getBoolean("organization", false);
boolean log = prefs.getBoolean("log", false);
// Show disabled message
TextView tvDisabled = findViewById(R.id.tvDisabled);
tvDisabled.setVisibility(log ? View.GONE : View.VISIBLE);
// Set enabled switch
swEnabled.setChecked(log);
swEnabled.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
prefs.edit().putBoolean("log", isChecked).apply();
}
});
// Listen for preference changes
prefs.registerOnSharedPreferenceChangeListener(this);
lvLog = findViewById(R.id.lvLog);
boolean udp = prefs.getBoolean("proto_udp", true);
boolean tcp = prefs.getBoolean("proto_tcp", true);
boolean other = prefs.getBoolean("proto_other", true);
boolean allowed = prefs.getBoolean("traffic_allowed", true);
boolean blocked = prefs.getBoolean("traffic_blocked", true);
adapter = new AdapterLog(this, DatabaseHelper.getInstance(this).getLog(udp, tcp, other, allowed, blocked), resolve, organization);
adapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return DatabaseHelper.getInstance(ActivityLog.this).searchLog(constraint.toString());
}
});
lvLog.setAdapter(adapter);
try {
vpn4 = InetAddress.getByName(prefs.getString("vpn4", "10.1.10.1"));
vpn6 = InetAddress.getByName(prefs.getString("vpn6", "fd00:1:fd00:1:fd00:1:fd00:1"));
} catch (UnknownHostException ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
lvLog.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);
long time = cursor.getLong(cursor.getColumnIndex("time"));
int version = cursor.getInt(cursor.getColumnIndex("version"));
int protocol = cursor.getInt(cursor.getColumnIndex("protocol"));
final String saddr = cursor.getString(cursor.getColumnIndex("saddr"));
final int sport = (cursor.isNull(cursor.getColumnIndex("sport")) ? -1 : cursor.getInt(cursor.getColumnIndex("sport")));
final String daddr = cursor.getString(cursor.getColumnIndex("daddr"));
final int dport = (cursor.isNull(cursor.getColumnIndex("dport")) ? -1 : cursor.getInt(cursor.getColumnIndex("dport")));
final String dname = cursor.getString(cursor.getColumnIndex("dname"));
final int uid = (cursor.isNull(cursor.getColumnIndex("uid")) ? -1 : cursor.getInt(cursor.getColumnIndex("uid")));
int allowed = (cursor.isNull(cursor.getColumnIndex("allowed")) ? -1 : cursor.getInt(cursor.getColumnIndex("allowed")));
// Get external address
InetAddress addr = null;
try {
addr = InetAddress.getByName(daddr);
} catch (UnknownHostException ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
String ip;
int port;
if (addr.equals(vpn4) || addr.equals(vpn6)) {
ip = saddr;
port = sport;
} else {
ip = daddr;
port = dport;
}
// Build popup menu
PopupMenu popup = new PopupMenu(ActivityLog.this, findViewById(R.id.vwPopupAnchor));
popup.inflate(R.menu.log);
// Application name
if (uid >= 0)
popup.getMenu().findItem(R.id.menu_application).setTitle(TextUtils.join(", ", Util.getApplicationNames(uid, ActivityLog.this)));
else
popup.getMenu().removeItem(R.id.menu_application);
// Destination IP
popup.getMenu().findItem(R.id.menu_protocol).setTitle(Util.getProtocolName(protocol, version, false));
// Whois
final Intent lookupIP = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.dnslytics.com/whois-lookup/" + ip));
if (pm.resolveActivity(lookupIP, 0) == null)
popup.getMenu().removeItem(R.id.menu_whois);
else
popup.getMenu().findItem(R.id.menu_whois).setTitle(getString(R.string.title_log_whois, ip));
// Lookup port
final Intent lookupPort = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.speedguide.net/port.php?port=" + port));
if (port <= 0 || pm.resolveActivity(lookupPort, 0) == null)
popup.getMenu().removeItem(R.id.menu_port);
else
popup.getMenu().findItem(R.id.menu_port).setTitle(getString(R.string.title_log_port, port));
if (prefs.getBoolean("filter", false)) {
if (uid <= 0) {
popup.getMenu().removeItem(R.id.menu_allow);
popup.getMenu().removeItem(R.id.menu_block);
}
} else {
popup.getMenu().removeItem(R.id.menu_allow);
popup.getMenu().removeItem(R.id.menu_block);
}
final Packet packet = new Packet();
packet.version = version;
packet.protocol = protocol;
packet.daddr = daddr;
packet.dport = dport;
packet.time = time;
packet.uid = uid;
packet.allowed = (allowed > 0);
// Time
popup.getMenu().findItem(R.id.menu_time).setTitle(SimpleDateFormat.getDateTimeInstance().format(time));
// Handle click
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.menu_application: {
Intent main = new Intent(ActivityLog.this, ActivityMain.class);
main.putExtra(ActivityMain.EXTRA_SEARCH, Integer.toString(uid));
startActivity(main);
return true;
}
case R.id.menu_whois:
startActivity(lookupIP);
return true;
case R.id.menu_port:
startActivity(lookupPort);
return true;
case R.id.menu_allow:
if (IAB.isPurchased(ActivityPro.SKU_FILTER, ActivityLog.this)) {
DatabaseHelper.getInstance(ActivityLog.this).updateAccess(packet, dname, 0);
ServiceSinkhole.reload("allow host", ActivityLog.this, false);
Intent main = new Intent(ActivityLog.this, ActivityMain.class);
main.putExtra(ActivityMain.EXTRA_SEARCH, Integer.toString(uid));
startActivity(main);
} else
startActivity(new Intent(ActivityLog.this, ActivityPro.class));
return true;
case R.id.menu_block:
if (IAB.isPurchased(ActivityPro.SKU_FILTER, ActivityLog.this)) {
DatabaseHelper.getInstance(ActivityLog.this).updateAccess(packet, dname, 1);
ServiceSinkhole.reload("block host", ActivityLog.this, false);
Intent main = new Intent(ActivityLog.this, ActivityMain.class);
main.putExtra(ActivityMain.EXTRA_SEARCH, Integer.toString(uid));
startActivity(main);
} else
startActivity(new Intent(ActivityLog.this, ActivityPro.class));
return true;
case R.id.menu_copy:
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("netguard", dname == null ? daddr : dname);
clipboard.setPrimaryClip(clip);
return true;
default:
return false;
}
}
});
// Show
popup.show();
}
});
live = true;
}
@Override
protected void onResume() {
super.onResume();
if (live) {
DatabaseHelper.getInstance(this).addLogChangedListener(listener);
updateAdapter();
}
}
@Override
protected void onPause() {
super.onPause();
if (live)
DatabaseHelper.getInstance(this).removeLogChangedListener(listener);
}
@Override
protected void onDestroy() {
running = false;
adapter = null;
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String name) {
Log.i(TAG, "Preference " + name + "=" + prefs.getAll().get(name));
if ("log".equals(name)) {
// Get enabled
boolean log = prefs.getBoolean(name, false);
// Display disabled warning
TextView tvDisabled = findViewById(R.id.tvDisabled);
tvDisabled.setVisibility(log ? View.GONE : View.VISIBLE);
// Check switch state
SwitchCompat swEnabled = getSupportActionBar().getCustomView().findViewById(R.id.swEnabled);
if (swEnabled.isChecked() != log)
swEnabled.setChecked(log);
ServiceSinkhole.reload("changed " + name, ActivityLog.this, false);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.logging, menu);
menuSearch = menu.findItem(R.id.menu_search);
SearchView searchView = (SearchView) menuSearch.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
if (adapter != null)
adapter.getFilter().filter(getUidForName(query));
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
if (adapter != null)
adapter.getFilter().filter(getUidForName(newText));
return true;
}
});
searchView.setOnCloseListener(new SearchView.OnCloseListener() {
@Override
public boolean onClose() {
if (adapter != null)
adapter.getFilter().filter(null);
return true;
}
});
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
// https://gist.github.com/granoeste/5574148
File pcap_file = new File(getDir("data", MODE_PRIVATE), "netguard.pcap");
boolean export = (getPackageManager().resolveActivity(getIntentPCAPDocument(), 0) != null);
menu.findItem(R.id.menu_protocol_udp).setChecked(prefs.getBoolean("proto_udp", true));
menu.findItem(R.id.menu_protocol_tcp).setChecked(prefs.getBoolean("proto_tcp", true));
menu.findItem(R.id.menu_protocol_other).setChecked(prefs.getBoolean("proto_other", true));
menu.findItem(R.id.menu_traffic_allowed).setEnabled(prefs.getBoolean("filter", false));
menu.findItem(R.id.menu_traffic_allowed).setChecked(prefs.getBoolean("traffic_allowed", true));
menu.findItem(R.id.menu_traffic_blocked).setChecked(prefs.getBoolean("traffic_blocked", true));
menu.findItem(R.id.menu_refresh).setEnabled(!menu.findItem(R.id.menu_log_live).isChecked());
menu.findItem(R.id.menu_log_resolve).setChecked(prefs.getBoolean("resolve", false));
menu.findItem(R.id.menu_log_organization).setChecked(prefs.getBoolean("organization", false));
menu.findItem(R.id.menu_pcap_enabled).setChecked(prefs.getBoolean("pcap", false));
menu.findItem(R.id.menu_pcap_export).setEnabled(pcap_file.exists() && export);
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
final File pcap_file = new File(getDir("data", MODE_PRIVATE), "netguard.pcap");
switch (item.getItemId()) {
case android.R.id.home:
Log.i(TAG, "Up");
NavUtils.navigateUpFromSameTask(this);
return true;
case R.id.menu_protocol_udp:
item.setChecked(!item.isChecked());
prefs.edit().putBoolean("proto_udp", item.isChecked()).apply();
updateAdapter();
return true;
case R.id.menu_protocol_tcp:
item.setChecked(!item.isChecked());
prefs.edit().putBoolean("proto_tcp", item.isChecked()).apply();
updateAdapter();
return true;
case R.id.menu_protocol_other:
item.setChecked(!item.isChecked());
prefs.edit().putBoolean("proto_other", item.isChecked()).apply();
updateAdapter();
return true;
case R.id.menu_traffic_allowed:
item.setChecked(!item.isChecked());
prefs.edit().putBoolean("traffic_allowed", item.isChecked()).apply();
updateAdapter();
return true;
case R.id.menu_traffic_blocked:
item.setChecked(!item.isChecked());
prefs.edit().putBoolean("traffic_blocked", item.isChecked()).apply();
updateAdapter();
return true;
case R.id.menu_log_live:
item.setChecked(!item.isChecked());
live = item.isChecked();
if (live) {
DatabaseHelper.getInstance(this).addLogChangedListener(listener);
updateAdapter();
} else
DatabaseHelper.getInstance(this).removeLogChangedListener(listener);
return true;
case R.id.menu_refresh:
updateAdapter();
return true;
case R.id.menu_log_resolve:
item.setChecked(!item.isChecked());
prefs.edit().putBoolean("resolve", item.isChecked()).apply();
adapter.setResolve(item.isChecked());
adapter.notifyDataSetChanged();
return true;
case R.id.menu_log_organization:
item.setChecked(!item.isChecked());
prefs.edit().putBoolean("organization", item.isChecked()).apply();
adapter.setOrganization(item.isChecked());
adapter.notifyDataSetChanged();
return true;
case R.id.menu_pcap_enabled:
item.setChecked(!item.isChecked());
prefs.edit().putBoolean("pcap", item.isChecked()).apply();
ServiceSinkhole.setPcap(item.isChecked(), ActivityLog.this);
return true;
case R.id.menu_pcap_export:
startActivityForResult(getIntentPCAPDocument(), REQUEST_PCAP);
return true;
case R.id.menu_log_clear:
new AsyncTask<Object, Object, Object>() {
@Override
protected Object doInBackground(Object... objects) {
DatabaseHelper.getInstance(ActivityLog.this).clearLog(-1);
if (prefs.getBoolean("pcap", false)) {
ServiceSinkhole.setPcap(false, ActivityLog.this);
if (pcap_file.exists() && !pcap_file.delete())
Log.w(TAG, "Delete PCAP failed");
ServiceSinkhole.setPcap(true, ActivityLog.this);
} else {
if (pcap_file.exists() && !pcap_file.delete())
Log.w(TAG, "Delete PCAP failed");
}
return null;
}
@Override
protected void onPostExecute(Object result) {
if (running)
updateAdapter();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
return true;
case R.id.menu_log_support:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq27"));
if (getPackageManager().resolveActivity(intent, 0) != null)
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void updateAdapter() {
if (adapter != null) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean udp = prefs.getBoolean("proto_udp", true);
boolean tcp = prefs.getBoolean("proto_tcp", true);
boolean other = prefs.getBoolean("proto_other", true);
boolean allowed = prefs.getBoolean("traffic_allowed", true);
boolean blocked = prefs.getBoolean("traffic_blocked", true);
adapter.changeCursor(DatabaseHelper.getInstance(this).getLog(udp, tcp, other, allowed, blocked));
if (menuSearch != null && menuSearch.isActionViewExpanded()) {
SearchView searchView = (SearchView) menuSearch.getActionView();
adapter.getFilter().filter(getUidForName(searchView.getQuery().toString()));
}
}
}
private String getUidForName(String query) {
if (query != null && query.length() > 0) {
for (Rule rule : Rule.getRules(true, ActivityLog.this))
if (rule.name != null && rule.name.toLowerCase().contains(query.toLowerCase())) {
String newQuery = Integer.toString(rule.uid);
Log.i(TAG, "Search " + query + " found " + rule.name + " new " + newQuery);
return newQuery;
}
Log.i(TAG, "Search " + query + " not found");
}
return query;
}
private Intent getIntentPCAPDocument() {
Intent intent;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
if (Util.isPackageInstalled("org.openintents.filemanager", this)) {
intent = new Intent("org.openintents.action.PICK_DIRECTORY");
} else {
intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://play.google.com/store/apps/details?id=org.openintents.filemanager"));
}
} else {
intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("application/octet-stream");
intent.putExtra(Intent.EXTRA_TITLE, "netguard_" + new SimpleDateFormat("yyyyMMdd").format(new Date().getTime()) + ".pcap");
}
return intent;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
Log.i(TAG, "onActivityResult request=" + requestCode + " result=" + requestCode + " ok=" + (resultCode == RESULT_OK));
if (requestCode == REQUEST_PCAP) {
if (resultCode == RESULT_OK && data != null)
handleExportPCAP(data);
} else {
Log.w(TAG, "Unknown activity result request=" + requestCode);
super.onActivityResult(requestCode, resultCode, data);
}
}
private void handleExportPCAP(final Intent data) {
new AsyncTask<Object, Object, Throwable>() {
@Override
protected Throwable doInBackground(Object... objects) {
OutputStream out = null;
FileInputStream in = null;
try {
// Stop capture
ServiceSinkhole.setPcap(false, ActivityLog.this);
Uri target = data.getData();
if (data.hasExtra("org.openintents.extra.DIR_PATH"))
target = Uri.parse(target + "/netguard.pcap");
Log.i(TAG, "Export PCAP URI=" + target);
out = getContentResolver().openOutputStream(target);
File pcap = new File(getDir("data", MODE_PRIVATE), "netguard.pcap");
in = new FileInputStream(pcap);
int len;
long total = 0;
byte[] buf = new byte[4096];
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
total += len;
}
Log.i(TAG, "Copied bytes=" + total);
return null;
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
return ex;
} finally {
if (out != null)
try {
out.close();
} catch (IOException ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
if (in != null)
try {
in.close();
} catch (IOException ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
// Resume capture
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ActivityLog.this);
if (prefs.getBoolean("pcap", false))
ServiceSinkhole.setPcap(true, ActivityLog.this);
}
}
@Override
protected void onPostExecute(Throwable ex) {
if (ex == null)
Toast.makeText(ActivityLog.this, R.string.msg_completed, Toast.LENGTH_LONG).show();
else
Toast.makeText(ActivityLog.this, ex.toString(), Toast.LENGTH_LONG).show();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,447 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.app.PendingIntent;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Paint;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NavUtils;
import static android.content.ClipDescription.MIMETYPE_TEXT_PLAIN;
public class ActivityPro extends AppCompatActivity {
private static final String TAG = "NetGuard.Pro";
private IAB iab;
// adb shell pm clear com.android.vending
// android.test.purchased
private static final int SKU_LOG_ID = 1;
private static final int SKU_FILTER_ID = 2;
private static final int SKU_NOTIFY_ID = 3;
private static final int SKU_SPEED_ID = 4;
private static final int SKU_THEME_ID = 5;
private static final int SKU_PRO1_ID = 6;
private static final int SKU_SUPPORT1_ID = 7;
private static final int SKU_SUPPORT2_ID = 8;
public static final String SKU_LOG = "log";
public static final String SKU_FILTER = "filter";
public static final String SKU_NOTIFY = "notify";
public static final String SKU_SPEED = "speed";
public static final String SKU_THEME = "theme";
public static final String SKU_PRO1 = "pro1";
public static final String SKU_SUPPORT1 = "support1";
public static final String SKU_SUPPORT2 = "support2";
public static final String SKU_DONATION = "donation";
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "Create");
Util.setTheme(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.pro);
getSupportActionBar().setTitle(R.string.title_pro);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
// Initial state
updateState();
TextView tvLogTitle = findViewById(R.id.tvLogTitle);
TextView tvFilterTitle = findViewById(R.id.tvFilterTitle);
TextView tvNotifyTitle = findViewById(R.id.tvNotifyTitle);
TextView tvSpeedTitle = findViewById(R.id.tvSpeedTitle);
TextView tvThemeTitle = findViewById(R.id.tvThemeTitle);
TextView tvAllTitle = findViewById(R.id.tvAllTitle);
TextView tvDev1Title = findViewById(R.id.tvDev1Title);
TextView tvDev2Title = findViewById(R.id.tvDev2Title);
tvLogTitle.setPaintFlags(tvLogTitle.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
tvFilterTitle.setPaintFlags(tvLogTitle.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
tvNotifyTitle.setPaintFlags(tvLogTitle.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
tvSpeedTitle.setPaintFlags(tvLogTitle.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
tvThemeTitle.setPaintFlags(tvLogTitle.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
tvAllTitle.setPaintFlags(tvLogTitle.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
tvDev1Title.setPaintFlags(tvLogTitle.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
tvDev2Title.setPaintFlags(tvLogTitle.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View view) {
String sku;
switch (view.getId()) {
case R.id.tvLogTitle:
sku = SKU_LOG;
break;
case R.id.tvFilterTitle:
sku = SKU_FILTER;
break;
case R.id.tvNotifyTitle:
sku = SKU_NOTIFY;
break;
case R.id.tvSpeedTitle:
sku = SKU_SPEED;
break;
case R.id.tvThemeTitle:
sku = SKU_THEME;
break;
case R.id.tvAllTitle:
sku = SKU_PRO1;
break;
case R.id.tvDev1Title:
sku = SKU_SUPPORT1;
break;
case R.id.tvDev2Title:
sku = SKU_SUPPORT2;
break;
default:
sku = SKU_PRO1;
break;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.netguard.me/#" + sku));
if (intent.resolveActivity(getPackageManager()) != null)
startActivity(intent);
}
};
tvLogTitle.setOnClickListener(listener);
tvFilterTitle.setOnClickListener(listener);
tvNotifyTitle.setOnClickListener(listener);
tvSpeedTitle.setOnClickListener(listener);
tvThemeTitle.setOnClickListener(listener);
tvAllTitle.setOnClickListener(listener);
tvDev1Title.setOnClickListener(listener);
tvDev2Title.setOnClickListener(listener);
try {
iab = new IAB(new IAB.Delegate() {
@Override
public void onReady(final IAB iab) {
Log.i(TAG, "IAB ready");
try {
iab.updatePurchases();
updateState();
final Button btnLog = findViewById(R.id.btnLog);
final Button btnFilter = findViewById(R.id.btnFilter);
final Button btnNotify = findViewById(R.id.btnNotify);
final Button btnSpeed = findViewById(R.id.btnSpeed);
final Button btnTheme = findViewById(R.id.btnTheme);
final Button btnAll = findViewById(R.id.btnAll);
final Button btnDev1 = findViewById(R.id.btnDev1);
final Button btnDev2 = findViewById(R.id.btnDev2);
View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
int id = 0;
PendingIntent pi = null;
if (view == btnLog) {
id = SKU_LOG_ID;
pi = iab.getBuyIntent(SKU_LOG, false);
} else if (view == btnFilter) {
id = SKU_FILTER_ID;
pi = iab.getBuyIntent(SKU_FILTER, false);
} else if (view == btnNotify) {
id = SKU_NOTIFY_ID;
pi = iab.getBuyIntent(SKU_NOTIFY, false);
} else if (view == btnSpeed) {
id = SKU_SPEED_ID;
pi = iab.getBuyIntent(SKU_SPEED, false);
} else if (view == btnTheme) {
id = SKU_THEME_ID;
pi = iab.getBuyIntent(SKU_THEME, false);
} else if (view == btnAll) {
id = SKU_PRO1_ID;
pi = iab.getBuyIntent(SKU_PRO1, false);
} else if (view == btnDev1) {
id = SKU_SUPPORT1_ID;
pi = iab.getBuyIntent(SKU_SUPPORT1, true);
} else if (view == btnDev2) {
id = SKU_SUPPORT2_ID;
pi = iab.getBuyIntent(SKU_SUPPORT2, true);
}
if (id > 0 && pi != null)
startIntentSenderForResult(pi.getIntentSender(), id, new Intent(), 0, 0, 0);
} catch (Throwable ex) {
Log.i(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
}
};
btnLog.setOnClickListener(listener);
btnFilter.setOnClickListener(listener);
btnNotify.setOnClickListener(listener);
btnSpeed.setOnClickListener(listener);
btnTheme.setOnClickListener(listener);
btnAll.setOnClickListener(listener);
btnDev1.setOnClickListener(listener);
btnDev2.setOnClickListener(listener);
btnLog.setEnabled(true);
btnFilter.setEnabled(true);
btnNotify.setEnabled(true);
btnSpeed.setEnabled(true);
btnTheme.setEnabled(true);
btnAll.setEnabled(true);
btnDev1.setEnabled(true);
btnDev2.setEnabled(true);
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
}
}, this);
iab.bind();
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
}
@Override
protected void onDestroy() {
Log.i(TAG, "Destroy");
iab.unbind();
iab = null;
super.onDestroy();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.pro, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Log.i(TAG, "Up");
NavUtils.navigateUpFromSameTask(this);
return true;
case R.id.menu_challenge:
menu_challenge();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (IAB.isPurchased(SKU_DONATION, this) || Util.isPlayStoreInstall(this))
menu.removeItem(R.id.menu_challenge);
return super.onPrepareOptionsMenu(menu);
}
private void menu_challenge() {
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.challenge, null, false);
final AlertDialog dialog = new AlertDialog.Builder(this)
.setView(view)
.setCancelable(true)
.create();
String android_id = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
final String challenge = (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? Build.SERIAL : "O3" + android_id);
String seed = (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? "NetGuard2" : "NetGuard3");
// Challenge
TextView tvChallenge = view.findViewById(R.id.tvChallenge);
tvChallenge.setText(challenge);
ImageButton ibCopy = view.findViewById(R.id.ibCopy);
ibCopy.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText(getString(R.string.title_pro_challenge), challenge);
clipboard.setPrimaryClip(clip);
Toast.makeText(ActivityPro.this, android.R.string.copy, Toast.LENGTH_LONG).show();
}
});
// Response
final EditText etResponse = view.findViewById(R.id.etResponse);
try {
final String response = Util.md5(challenge, seed);
etResponse.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// Do nothing
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Do nothing
}
@Override
public void afterTextChanged(Editable editable) {
if (response.equals(editable.toString().toUpperCase())) {
IAB.setBought(SKU_DONATION, ActivityPro.this);
dialog.dismiss();
invalidateOptionsMenu();
updateState();
}
}
});
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
ImageButton ibPaste = view.findViewById(R.id.ibPaste);
ibPaste.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
if (clipboard != null &&
clipboard.hasPrimaryClip() &&
clipboard.getPrimaryClipDescription().hasMimeType(MIMETYPE_TEXT_PLAIN)) {
ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);
etResponse.setText(item.getText().toString());
}
}
});
dialog.show();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case SKU_LOG_ID:
IAB.setBought(SKU_LOG, this);
updateState();
break;
case SKU_FILTER_ID:
IAB.setBought(SKU_FILTER, this);
updateState();
break;
case SKU_NOTIFY_ID:
IAB.setBought(SKU_NOTIFY, this);
updateState();
break;
case SKU_SPEED_ID:
IAB.setBought(SKU_SPEED, this);
updateState();
break;
case SKU_THEME_ID:
IAB.setBought(SKU_THEME, this);
updateState();
break;
case SKU_PRO1_ID:
IAB.setBought(SKU_PRO1, this);
updateState();
break;
case SKU_SUPPORT1_ID:
IAB.setBought(SKU_SUPPORT1, this);
updateState();
break;
case SKU_SUPPORT2_ID:
IAB.setBought(SKU_SUPPORT2, this);
updateState();
break;
}
}
}
private void updateState() {
Button btnLog = findViewById(R.id.btnLog);
Button btnFilter = findViewById(R.id.btnFilter);
Button btnNotify = findViewById(R.id.btnNotify);
Button btnSpeed = findViewById(R.id.btnSpeed);
Button btnTheme = findViewById(R.id.btnTheme);
Button btnAll = findViewById(R.id.btnAll);
Button btnDev1 = findViewById(R.id.btnDev1);
Button btnDev2 = findViewById(R.id.btnDev2);
TextView tvLog = findViewById(R.id.tvLog);
TextView tvFilter = findViewById(R.id.tvFilter);
TextView tvNotify = findViewById(R.id.tvNotify);
TextView tvSpeed = findViewById(R.id.tvSpeed);
TextView tvTheme = findViewById(R.id.tvTheme);
TextView tvAll = findViewById(R.id.tvAll);
TextView tvDev1 = findViewById(R.id.tvDev1);
TextView tvDev2 = findViewById(R.id.tvDev2);
TextView tvLogUnavailable = findViewById(R.id.tvLogUnavailable);
TextView tvFilterUnavailable = findViewById(R.id.tvFilterUnavailable);
boolean can = Util.canFilter(this);
btnLog.setVisibility(IAB.isPurchased(SKU_LOG, this) || !can ? View.GONE : View.VISIBLE);
btnFilter.setVisibility(IAB.isPurchased(SKU_FILTER, this) || !can ? View.GONE : View.VISIBLE);
btnNotify.setVisibility(IAB.isPurchased(SKU_NOTIFY, this) ? View.GONE : View.VISIBLE);
btnSpeed.setVisibility(IAB.isPurchased(SKU_SPEED, this) ? View.GONE : View.VISIBLE);
btnTheme.setVisibility(IAB.isPurchased(SKU_THEME, this) ? View.GONE : View.VISIBLE);
btnAll.setVisibility(IAB.isPurchased(SKU_PRO1, this) ? View.GONE : View.VISIBLE);
btnDev1.setVisibility(IAB.isPurchased(SKU_SUPPORT1, this) ? View.GONE : View.VISIBLE);
btnDev2.setVisibility(IAB.isPurchased(SKU_SUPPORT2, this) ? View.GONE : View.VISIBLE);
tvLog.setVisibility(IAB.isPurchased(SKU_LOG, this) && can ? View.VISIBLE : View.GONE);
tvFilter.setVisibility(IAB.isPurchased(SKU_FILTER, this) && can ? View.VISIBLE : View.GONE);
tvNotify.setVisibility(IAB.isPurchased(SKU_NOTIFY, this) ? View.VISIBLE : View.GONE);
tvSpeed.setVisibility(IAB.isPurchased(SKU_SPEED, this) ? View.VISIBLE : View.GONE);
tvTheme.setVisibility(IAB.isPurchased(SKU_THEME, this) ? View.VISIBLE : View.GONE);
tvAll.setVisibility(IAB.isPurchased(SKU_PRO1, this) ? View.VISIBLE : View.GONE);
tvDev1.setVisibility(IAB.isPurchased(SKU_SUPPORT1, this) ? View.VISIBLE : View.GONE);
tvDev2.setVisibility(IAB.isPurchased(SKU_SUPPORT2, this) ? View.VISIBLE : View.GONE);
tvLogUnavailable.setVisibility(can ? View.GONE : View.VISIBLE);
tvFilterUnavailable.setVisibility(can ? View.GONE : View.VISIBLE);
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,186 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.content.Context;
import android.content.res.TypedArray;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.text.SpannableString;
import android.text.style.UnderlineSpan;
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.LinearLayout;
import android.widget.TextView;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.view.ViewCompat;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
public class AdapterAccess extends CursorAdapter {
private int colVersion;
private int colProtocol;
private int colDaddr;
private int colDPort;
private int colTime;
private int colAllowed;
private int colBlock;
private int colCount;
private int colSent;
private int colReceived;
private int colConnections;
private int colorText;
private int colorOn;
private int colorOff;
public AdapterAccess(Context context, Cursor cursor) {
super(context, cursor, 0);
colVersion = cursor.getColumnIndex("version");
colProtocol = cursor.getColumnIndex("protocol");
colDaddr = cursor.getColumnIndex("daddr");
colDPort = cursor.getColumnIndex("dport");
colTime = cursor.getColumnIndex("time");
colAllowed = cursor.getColumnIndex("allowed");
colBlock = cursor.getColumnIndex("block");
colCount = cursor.getColumnIndex("count");
colSent = cursor.getColumnIndex("sent");
colReceived = cursor.getColumnIndex("received");
colConnections = cursor.getColumnIndex("connections");
TypedArray ta = context.getTheme().obtainStyledAttributes(new int[]{android.R.attr.textColorSecondary});
try {
colorText = ta.getColor(0, 0);
} finally {
ta.recycle();
}
TypedValue tv = new TypedValue();
context.getTheme().resolveAttribute(R.attr.colorOn, tv, true);
colorOn = tv.data;
context.getTheme().resolveAttribute(R.attr.colorOff, tv, true);
colorOff = tv.data;
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.access, parent, false);
}
@Override
public void bindView(final View view, final Context context, final Cursor cursor) {
// Get values
final int version = cursor.getInt(colVersion);
final int protocol = cursor.getInt(colProtocol);
final String daddr = cursor.getString(colDaddr);
final int dport = cursor.getInt(colDPort);
long time = cursor.getLong(colTime);
int allowed = cursor.getInt(colAllowed);
int block = cursor.getInt(colBlock);
int count = cursor.getInt(colCount);
long sent = cursor.isNull(colSent) ? -1 : cursor.getLong(colSent);
long received = cursor.isNull(colReceived) ? -1 : cursor.getLong(colReceived);
int connections = cursor.isNull(colConnections) ? -1 : cursor.getInt(colConnections);
// Get views
TextView tvTime = view.findViewById(R.id.tvTime);
ImageView ivBlock = view.findViewById(R.id.ivBlock);
final TextView tvDest = view.findViewById(R.id.tvDest);
LinearLayout llTraffic = view.findViewById(R.id.llTraffic);
TextView tvConnections = view.findViewById(R.id.tvConnections);
TextView tvTraffic = view.findViewById(R.id.tvTraffic);
// Set values
tvTime.setText(new SimpleDateFormat("dd HH:mm").format(time));
if (block < 0)
ivBlock.setImageDrawable(null);
else {
ivBlock.setImageResource(block > 0 ? R.drawable.host_blocked : R.drawable.host_allowed);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
Drawable wrap = DrawableCompat.wrap(ivBlock.getDrawable());
DrawableCompat.setTint(wrap, block > 0 ? colorOff : colorOn);
}
}
String dest = Util.getProtocolName(protocol, version, true) +
" " + daddr + (dport > 0 ? "/" + dport : "") + (count > 1 ? " ?" + count : "");
SpannableString span = new SpannableString(dest);
span.setSpan(new UnderlineSpan(), 0, dest.length(), 0);
tvDest.setText(span);
if (Util.isNumericAddress(daddr))
new AsyncTask<String, Object, String>() {
@Override
protected void onPreExecute() {
ViewCompat.setHasTransientState(tvDest, true);
}
@Override
protected String doInBackground(String... args) {
try {
return InetAddress.getByName(args[0]).getHostName();
} catch (UnknownHostException ignored) {
return args[0];
}
}
@Override
protected void onPostExecute(String addr) {
tvDest.setText(
Util.getProtocolName(protocol, version, true) +
" >" + addr + (dport > 0 ? "/" + dport : ""));
ViewCompat.setHasTransientState(tvDest, false);
}
}.execute(daddr);
if (allowed < 0)
tvDest.setTextColor(colorText);
else if (allowed > 0)
tvDest.setTextColor(colorOn);
else
tvDest.setTextColor(colorOff);
llTraffic.setVisibility(connections > 0 || sent > 0 || received > 0 ? View.VISIBLE : View.GONE);
if (connections > 0)
tvConnections.setText(context.getString(R.string.msg_count, connections));
if (sent > 1024 * 1204 * 1024L || received > 1024 * 1024 * 1024L)
tvTraffic.setText(context.getString(R.string.msg_gb,
(sent > 0 ? sent / (1024 * 1024 * 1024f) : 0),
(received > 0 ? received / (1024 * 1024 * 1024f) : 0)));
else if (sent > 1204 * 1024L || received > 1024 * 1024L)
tvTraffic.setText(context.getString(R.string.msg_mb,
(sent > 0 ? sent / (1024 * 1024f) : 0),
(received > 0 ? received / (1024 * 1024f) : 0)));
else
tvTraffic.setText(context.getString(R.string.msg_kb,
(sent > 0 ? sent / 1024f : 0),
(received > 0 ? received / 1024f : 0)));
}
}
@@ -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-2019 by Marcel Bokhorst (M66B)
*/
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.TextView;
import androidx.preference.PreferenceManager;
import java.text.SimpleDateFormat;
import java.util.Date;
public class AdapterDns extends CursorAdapter {
private int colorExpired;
private int colTime;
private int colQName;
private int colAName;
private int colResource;
private int colTTL;
public AdapterDns(Context context, Cursor cursor) {
super(context, cursor, 0);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
if (prefs.getBoolean("dark_theme", false))
colorExpired = Color.argb(128, Color.red(Color.DKGRAY), Color.green(Color.DKGRAY), Color.blue(Color.DKGRAY));
else
colorExpired = Color.argb(128, Color.red(Color.LTGRAY), Color.green(Color.LTGRAY), Color.blue(Color.LTGRAY));
colTime = cursor.getColumnIndex("time");
colQName = cursor.getColumnIndex("qname");
colAName = cursor.getColumnIndex("aname");
colResource = cursor.getColumnIndex("resource");
colTTL = cursor.getColumnIndex("ttl");
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.dns, parent, false);
}
@Override
public void bindView(final View view, final Context context, final Cursor cursor) {
// Get values
long time = cursor.getLong(colTime);
String qname = cursor.getString(colQName);
String aname = cursor.getString(colAName);
String resource = cursor.getString(colResource);
int ttl = cursor.getInt(colTTL);
long now = new Date().getTime();
boolean expired = (time + ttl < now);
view.setBackgroundColor(expired ? colorExpired : Color.TRANSPARENT);
// Get views
TextView tvTime = view.findViewById(R.id.tvTime);
TextView tvQName = view.findViewById(R.id.tvQName);
TextView tvAName = view.findViewById(R.id.tvAName);
TextView tvResource = view.findViewById(R.id.tvResource);
TextView tvTTL = view.findViewById(R.id.tvTTL);
// Set values
tvTime.setText(new SimpleDateFormat("dd HH:mm").format(time));
tvQName.setText(qname);
tvAName.setText(aname);
tvResource.setText(resource);
tvTTL.setText("+" + Integer.toString(ttl / 1000));
}
}
@@ -0,0 +1,74 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.content.Context;
import android.database.Cursor;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.TextView;
public class AdapterForwarding extends CursorAdapter {
private int colProtocol;
private int colDPort;
private int colRAddr;
private int colRPort;
private int colRUid;
public AdapterForwarding(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 = view.findViewById(R.id.tvProtocol);
TextView tvDPort = view.findViewById(R.id.tvDPort);
TextView tvRAddr = view.findViewById(R.id.tvRAddr);
TextView tvRPort = view.findViewById(R.id.tvRPort);
TextView tvRUid = 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)));
}
}
@@ -0,0 +1,370 @@
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-2019 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.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 androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.view.ViewCompat;
import androidx.preference.PreferenceManager;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.List;
public class AdapterLog extends CursorAdapter {
private static String TAG = "NetGuard.Log";
private boolean resolve;
private boolean organization;
private int colTime;
private int colVersion;
private int colProtocol;
private int colFlags;
private int colSAddr;
private int colSPort;
private int colDAddr;
private int colDPort;
private int colDName;
private int colUid;
private int colData;
private int colAllowed;
private int colConnection;
private int colInteractive;
private int colorOn;
private int colorOff;
private int iconSize;
private InetAddress dns1 = null;
private InetAddress dns2 = null;
private InetAddress vpn4 = null;
private InetAddress vpn6 = null;
public AdapterLog(Context context, Cursor cursor, boolean resolve, boolean organization) {
super(context, cursor, 0);
this.resolve = resolve;
this.organization = organization;
colTime = cursor.getColumnIndex("time");
colVersion = cursor.getColumnIndex("version");
colProtocol = cursor.getColumnIndex("protocol");
colFlags = cursor.getColumnIndex("flags");
colSAddr = cursor.getColumnIndex("saddr");
colSPort = cursor.getColumnIndex("sport");
colDAddr = cursor.getColumnIndex("daddr");
colDPort = cursor.getColumnIndex("dport");
colDName = cursor.getColumnIndex("dname");
colUid = cursor.getColumnIndex("uid");
colData = cursor.getColumnIndex("data");
colAllowed = cursor.getColumnIndex("allowed");
colConnection = cursor.getColumnIndex("connection");
colInteractive = cursor.getColumnIndex("interactive");
TypedValue tv = new TypedValue();
context.getTheme().resolveAttribute(R.attr.colorOn, tv, true);
colorOn = tv.data;
context.getTheme().resolveAttribute(R.attr.colorOff, tv, true);
colorOff = tv.data;
iconSize = Util.dips2pixels(24, context);
try {
List<InetAddress> lstDns = ServiceSinkhole.getDns(context);
dns1 = (lstDns.size() > 0 ? lstDns.get(0) : null);
dns2 = (lstDns.size() > 1 ? lstDns.get(1) : null);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
vpn4 = InetAddress.getByName(prefs.getString("vpn4", "10.1.10.1"));
vpn6 = InetAddress.getByName(prefs.getString("vpn6", "fd00:1:fd00:1:fd00:1:fd00:1"));
} catch (UnknownHostException ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
}
public void setResolve(boolean resolve) {
this.resolve = resolve;
}
public void setOrganization(boolean organization) {
this.organization = organization;
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.log, parent, false);
}
@Override
public void bindView(final View view, final Context context, final Cursor cursor) {
// Get values
long time = cursor.getLong(colTime);
int version = (cursor.isNull(colVersion) ? -1 : cursor.getInt(colVersion));
int protocol = (cursor.isNull(colProtocol) ? -1 : cursor.getInt(colProtocol));
String flags = cursor.getString(colFlags);
String saddr = cursor.getString(colSAddr);
int sport = (cursor.isNull(colSPort) ? -1 : cursor.getInt(colSPort));
String daddr = cursor.getString(colDAddr);
int dport = (cursor.isNull(colDPort) ? -1 : cursor.getInt(colDPort));
String dname = (cursor.isNull(colDName) ? null : cursor.getString(colDName));
int uid = (cursor.isNull(colUid) ? -1 : cursor.getInt(colUid));
String data = cursor.getString(colData);
int allowed = (cursor.isNull(colAllowed) ? -1 : cursor.getInt(colAllowed));
int connection = (cursor.isNull(colConnection) ? -1 : cursor.getInt(colConnection));
int interactive = (cursor.isNull(colInteractive) ? -1 : cursor.getInt(colInteractive));
// Get views
TextView tvTime = view.findViewById(R.id.tvTime);
TextView tvProtocol = view.findViewById(R.id.tvProtocol);
TextView tvFlags = view.findViewById(R.id.tvFlags);
TextView tvSAddr = view.findViewById(R.id.tvSAddr);
TextView tvSPort = view.findViewById(R.id.tvSPort);
final TextView tvDaddr = view.findViewById(R.id.tvDAddr);
TextView tvDPort = view.findViewById(R.id.tvDPort);
final TextView tvOrganization = view.findViewById(R.id.tvOrganization);
final ImageView ivIcon = view.findViewById(R.id.ivIcon);
TextView tvUid = view.findViewById(R.id.tvUid);
TextView tvData = view.findViewById(R.id.tvData);
ImageView ivConnection = view.findViewById(R.id.ivConnection);
ImageView ivInteractive = view.findViewById(R.id.ivInteractive);
// Show time
tvTime.setText(new SimpleDateFormat("HH:mm:ss").format(time));
// Show connection type
if (connection <= 0)
ivConnection.setImageResource(allowed > 0 ? R.drawable.host_allowed : R.drawable.host_blocked);
else {
if (allowed > 0)
ivConnection.setImageResource(connection == 1 ? R.drawable.wifi_on : R.drawable.other_on);
else
ivConnection.setImageResource(connection == 1 ? R.drawable.wifi_off : R.drawable.other_off);
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
Drawable wrap = DrawableCompat.wrap(ivConnection.getDrawable());
DrawableCompat.setTint(wrap, allowed > 0 ? colorOn : colorOff);
}
// Show if screen on
if (interactive <= 0)
ivInteractive.setImageDrawable(null);
else {
ivInteractive.setImageResource(R.drawable.screen_on);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
Drawable wrap = DrawableCompat.wrap(ivInteractive.getDrawable());
DrawableCompat.setTint(wrap, colorOn);
}
}
// Show protocol name
tvProtocol.setText(Util.getProtocolName(protocol, version, false));
// SHow TCP flags
tvFlags.setText(flags);
tvFlags.setVisibility(TextUtils.isEmpty(flags) ? View.GONE : View.VISIBLE);
// Show source and destination port
if (protocol == 6 || protocol == 17) {
tvSPort.setText(sport < 0 ? "" : getKnownPort(sport));
tvDPort.setText(dport < 0 ? "" : getKnownPort(dport));
} else {
tvSPort.setText(sport < 0 ? "" : Integer.toString(sport));
tvDPort.setText(dport < 0 ? "" : Integer.toString(dport));
}
// Application icon
ApplicationInfo info = null;
PackageManager pm = context.getPackageManager();
String[] pkg = pm.getPackagesForUid(uid);
if (pkg != null && pkg.length > 0)
try {
info = pm.getApplicationInfo(pkg[0], 0);
} catch (PackageManager.NameNotFoundException ignored) {
}
if (info == null)
ivIcon.setImageDrawable(null);
else {
if (info.icon <= 0)
ivIcon.setImageResource(android.R.drawable.sym_def_app_icon);
else {
Uri uri = Uri.parse("android.resource://" + info.packageName + "/" + info.icon);
GlideApp.with(context)
.load(uri)
//.diskCacheStrategy(DiskCacheStrategy.NONE)
//.skipMemoryCache(true)
.override(iconSize, iconSize)
.into(ivIcon);
}
}
boolean we = (android.os.Process.myUid() == uid);
// https://android.googlesource.com/platform/system/core/+/master/include/private/android_filesystem_config.h
uid = uid % 100000; // strip off user ID
if (uid == -1)
tvUid.setText("");
else if (uid == 0)
tvUid.setText(context.getString(R.string.title_root));
else if (uid == 9999)
tvUid.setText("-"); // nobody
else
tvUid.setText(Integer.toString(uid));
// Show source address
tvSAddr.setText(getKnownAddress(saddr));
// Show destination address
if (!we && resolve && !isKnownAddress(daddr))
if (dname == null) {
tvDaddr.setText(daddr);
new AsyncTask<String, Object, String>() {
@Override
protected void onPreExecute() {
ViewCompat.setHasTransientState(tvDaddr, true);
}
@Override
protected String doInBackground(String... args) {
try {
return InetAddress.getByName(args[0]).getHostName();
} catch (UnknownHostException ignored) {
return args[0];
}
}
@Override
protected void onPostExecute(String name) {
tvDaddr.setText(">" + name);
ViewCompat.setHasTransientState(tvDaddr, false);
}
}.execute(daddr);
} else
tvDaddr.setText(dname);
else
tvDaddr.setText(getKnownAddress(daddr));
// Show organization
tvOrganization.setVisibility(View.GONE);
if (!we && organization) {
if (!isKnownAddress(daddr))
new AsyncTask<String, Object, String>() {
@Override
protected void onPreExecute() {
ViewCompat.setHasTransientState(tvOrganization, true);
}
@Override
protected String doInBackground(String... args) {
try {
return Util.getOrganization(args[0]);
} catch (Throwable ex) {
Log.w(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
return null;
}
}
@Override
protected void onPostExecute(String organization) {
if (organization != null) {
tvOrganization.setText(organization);
tvOrganization.setVisibility(View.VISIBLE);
}
ViewCompat.setHasTransientState(tvOrganization, false);
}
}.execute(daddr);
}
// Show extra data
if (TextUtils.isEmpty(data)) {
tvData.setText("");
tvData.setVisibility(View.GONE);
} else {
tvData.setText(data);
tvData.setVisibility(View.VISIBLE);
}
}
public boolean isKnownAddress(String addr) {
try {
InetAddress a = InetAddress.getByName(addr);
if (a.equals(dns1) || a.equals(dns2) || a.equals(vpn4) || a.equals(vpn6))
return true;
} catch (UnknownHostException ignored) {
}
return false;
}
private String getKnownAddress(String addr) {
try {
InetAddress a = InetAddress.getByName(addr);
if (a.equals(dns1))
return "dns1";
if (a.equals(dns2))
return "dns2";
if (a.equals(vpn4) || a.equals(vpn6))
return "vpn";
} catch (UnknownHostException ignored) {
}
return addr;
}
private String getKnownPort(int port) {
// https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports
switch (port) {
case 7:
return "echo";
case 25:
return "smtp";
case 53:
return "dns";
case 80:
return "http";
case 110:
return "pop3";
case 143:
return "imap";
case 443:
return "https";
case 465:
return "smtps";
case 993:
return "imaps";
case 995:
return "pop3s";
default:
return Integer.toString(port);
}
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,35 @@
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-2019 by Marcel Bokhorst (M66B)
*/
public class Allowed {
public String raddr;
public int rport;
public Allowed() {
this.raddr = null;
this.rport = 0;
}
public Allowed(String raddr, int rport) {
this.raddr = raddr;
this.rport = rport;
}
}
@@ -0,0 +1,78 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.annotation.TargetApi;
import android.app.Application;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
import android.util.Log;
public class ApplicationEx extends Application {
private static final String TAG = "NetGuard.App";
private Thread.UncaughtExceptionHandler mPrevHandler;
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "Create version=" + Util.getSelfVersionName(this) + "/" + Util.getSelfVersionCode(this));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
createNotificationChannels();
mPrevHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if (Util.ownFault(ApplicationEx.this, ex)
&& Util.isPlayStoreInstall(ApplicationEx.this)) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
mPrevHandler.uncaughtException(thread, ex);
} else {
Log.w(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
System.exit(1);
}
}
});
}
@TargetApi(Build.VERSION_CODES.O)
private void createNotificationChannels() {
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel foreground = new NotificationChannel("foreground", getString(R.string.channel_foreground), NotificationManager.IMPORTANCE_MIN);
foreground.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
nm.createNotificationChannel(foreground);
NotificationChannel notify = new NotificationChannel("notify", getString(R.string.channel_notify), NotificationManager.IMPORTANCE_DEFAULT);
notify.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
notify.setBypassDnd(true);
nm.createNotificationChannel(notify);
NotificationChannel access = new NotificationChannel("access", getString(R.string.channel_access), NotificationManager.IMPORTANCE_DEFAULT);
access.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
access.setBypassDnd(true);
nm.createNotificationChannel(access);
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,181 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.PowerManager;
import android.util.Log;
import android.util.TypedValue;
import android.widget.Toast;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
public class DownloadTask extends AsyncTask<Object, Integer, Object> {
private static final String TAG = "NetGuard.Download";
private Context context;
private URL url;
private File file;
private Listener listener;
private PowerManager.WakeLock wakeLock;
public interface Listener {
void onCompleted();
void onCancelled();
void onException(Throwable ex);
}
public DownloadTask(Activity context, URL url, File file, Listener listener) {
this.context = context;
this.url = url;
this.file = file;
this.listener = listener;
}
@Override
protected void onPreExecute() {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
wakeLock.acquire();
showNotification(0);
Toast.makeText(context, context.getString(R.string.msg_downloading, url.toString()), Toast.LENGTH_SHORT).show();
}
@Override
protected Object doInBackground(Object... args) {
Log.i(TAG, "Downloading " + url + " into " + file);
InputStream in = null;
OutputStream out = null;
URLConnection connection = null;
try {
connection = url.openConnection();
connection.connect();
if (connection instanceof HttpURLConnection) {
HttpURLConnection httpConnection = (HttpURLConnection) connection;
if (httpConnection.getResponseCode() != HttpURLConnection.HTTP_OK)
throw new IOException(httpConnection.getResponseCode() + " " + httpConnection.getResponseMessage());
}
int contentLength = connection.getContentLength();
Log.i(TAG, "Content length=" + contentLength);
in = connection.getInputStream();
out = new FileOutputStream(file);
long size = 0;
byte buffer[] = new byte[4096];
int bytes;
while (!isCancelled() && (bytes = in.read(buffer)) != -1) {
out.write(buffer, 0, bytes);
size += bytes;
if (contentLength > 0)
publishProgress((int) (size * 100 / contentLength));
}
Log.i(TAG, "Downloaded size=" + size);
return null;
} catch (Throwable ex) {
return ex;
} finally {
try {
if (out != null)
out.close();
} catch (IOException ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
try {
if (in != null)
in.close();
} catch (IOException ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
if (connection instanceof HttpURLConnection)
((HttpURLConnection) connection).disconnect();
}
}
@Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
showNotification(progress[0]);
}
@Override
protected void onCancelled() {
super.onCancelled();
Log.i(TAG, "Cancelled");
listener.onCancelled();
}
@Override
protected void onPostExecute(Object result) {
wakeLock.release();
NotificationManagerCompat.from(context).cancel(ServiceSinkhole.NOTIFY_DOWNLOAD);
if (result instanceof Throwable) {
Log.e(TAG, result.toString() + "\n" + Log.getStackTraceString((Throwable) result));
listener.onException((Throwable) result);
} else
listener.onCompleted();
}
private void showNotification(int progress) {
Intent main = new Intent(context, ActivitySettings.class);
PendingIntent pi = PendingIntent.getActivity(context, ServiceSinkhole.NOTIFY_DOWNLOAD, main, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
TypedValue tv = new TypedValue();
context.getTheme().resolveAttribute(R.attr.colorOff, tv, true);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "notify");
builder.setSmallIcon(R.drawable.ic_file_download_white_24dp)
.setContentTitle(context.getString(R.string.app_name))
.setContentText(context.getString(R.string.msg_downloading, url.toString()))
.setContentIntent(pi)
.setProgress(100, progress, false)
.setColor(tv.data)
.setOngoing(true)
.setAutoCancel(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
builder.setCategory(NotificationCompat.CATEGORY_STATUS)
.setVisibility(NotificationCompat.VISIBILITY_SECRET);
NotificationManagerCompat.from(context).notify(ServiceSinkhole.NOTIFY_DOWNLOAD, builder.build());
}
}
@@ -0,0 +1,45 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;
// This requires list view items with equal heights
public class ExpandedListView extends ListView {
public ExpandedListView(Context context) {
super(context);
}
public ExpandedListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ExpandedListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 4, MeasureSpec.AT_MOST));
}
}
@@ -0,0 +1,33 @@
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-2019 by Marcel Bokhorst (M66B)
*/
public class Forward {
public int protocol;
public int dport;
public String raddr;
public int rport;
public int ruid;
@Override
public String toString() {
return "protocol=" + protocol + " port " + dport + " to " + raddr + "/" + rport + " uid " + ruid;
}
}
@@ -0,0 +1,32 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.os.Bundle;
import android.preference.PreferenceFragment;
public class FragmentSettings extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
@@ -0,0 +1,8 @@
package eu.faircode.netguard;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.AppGlideModule;
@GlideModule
public final class GlideHelper extends AppGlideModule {
}
@@ -0,0 +1,240 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import androidx.preference.PreferenceManager;
import com.android.vending.billing.IInAppBillingService;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class IAB implements ServiceConnection {
private static final String TAG = "NetGuard.IAB";
private Context context;
private Delegate delegate;
private IInAppBillingService service = null;
private static final int IAB_VERSION = 3;
public interface Delegate {
void onReady(IAB iab);
}
public IAB(Delegate delegate, Context context) {
this.context = context.getApplicationContext();
this.delegate = delegate;
}
public void bind() {
Log.i(TAG, "Bind");
Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
context.bindService(serviceIntent, this, Context.BIND_AUTO_CREATE);
}
public void unbind() {
if (service != null) {
Log.i(TAG, "Unbind");
context.unbindService(this);
service = null;
}
}
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
Log.i(TAG, "Connected");
service = IInAppBillingService.Stub.asInterface(binder);
delegate.onReady(this);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "Disconnected");
service = null;
}
public boolean isAvailable(String sku) throws RemoteException, JSONException {
// Get available SKUs
ArrayList<String> skuList = new ArrayList<>();
skuList.add(sku);
Bundle query = new Bundle();
query.putStringArrayList("ITEM_ID_LIST", skuList);
Bundle bundle = service.getSkuDetails(IAB_VERSION, context.getPackageName(), "inapp", query);
Log.i(TAG, "getSkuDetails");
Util.logBundle(bundle);
int response = (bundle == null ? -1 : bundle.getInt("RESPONSE_CODE", -1));
Log.i(TAG, "Response=" + getResult(response));
if (response != 0)
throw new IllegalArgumentException(getResult(response));
// Check available SKUs
boolean found = false;
ArrayList<String> details = bundle.getStringArrayList("DETAILS_LIST");
if (details != null)
for (String item : details) {
JSONObject object = new JSONObject(item);
if (sku.equals(object.getString("productId"))) {
found = true;
break;
}
}
Log.i(TAG, sku + "=" + found);
return found;
}
public void updatePurchases() throws RemoteException {
// Get purchases
List<String> skus = new ArrayList<>();
skus.addAll(getPurchases("inapp"));
skus.addAll(getPurchases("subs"));
SharedPreferences prefs = context.getSharedPreferences("IAB", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
for (String product : prefs.getAll().keySet())
if (!ActivityPro.SKU_DONATION.equals(product)) {
Log.i(TAG, "removing SKU=" + product);
editor.remove(product);
}
for (String sku : skus) {
Log.i(TAG, "adding SKU=" + sku);
editor.putBoolean(sku, true);
}
editor.apply();
}
public boolean isPurchased(String sku, String type) throws RemoteException {
return getPurchases(type).contains(sku);
}
public List<String> getPurchases(String type) throws RemoteException {
// Get purchases
Bundle bundle = service.getPurchases(IAB_VERSION, context.getPackageName(), type, null);
Log.i(TAG, "getPurchases");
Util.logBundle(bundle);
int response = (bundle == null ? -1 : bundle.getInt("RESPONSE_CODE", -1));
Log.i(TAG, "Response=" + getResult(response));
if (response != 0)
throw new IllegalArgumentException(getResult(response));
ArrayList<String> details = bundle.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
return (details == null ? new ArrayList<String>() : details);
}
public PendingIntent getBuyIntent(String sku, boolean subscription) throws RemoteException {
if (service == null)
return null;
Bundle bundle = service.getBuyIntent(IAB_VERSION, context.getPackageName(), sku, subscription ? "subs" : "inapp", "netguard");
Log.i(TAG, "getBuyIntent sku=" + sku + " subscription=" + subscription);
Util.logBundle(bundle);
int response = (bundle == null ? -1 : bundle.getInt("RESPONSE_CODE", -1));
Log.i(TAG, "Response=" + getResult(response));
if (response != 0)
throw new IllegalArgumentException(getResult(response));
if (!bundle.containsKey("BUY_INTENT"))
throw new IllegalArgumentException("BUY_INTENT missing");
return bundle.getParcelable("BUY_INTENT");
}
public static void setBought(String sku, Context context) {
Log.i(TAG, "Bought " + sku);
SharedPreferences prefs = context.getSharedPreferences("IAB", Context.MODE_PRIVATE);
prefs.edit().putBoolean(sku, true).apply();
}
public static boolean isPurchased(String sku, Context context) {
try {
if (Util.isDebuggable(context)) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return !prefs.getBoolean("debug_iab", false);
}
SharedPreferences prefs = context.getSharedPreferences("IAB", Context.MODE_PRIVATE);
if (ActivityPro.SKU_SUPPORT1.equals(sku) || ActivityPro.SKU_SUPPORT2.equals(sku))
return prefs.getBoolean(sku, false);
return (prefs.getBoolean(sku, false) ||
prefs.getBoolean(ActivityPro.SKU_PRO1, false) ||
prefs.getBoolean(ActivityPro.SKU_SUPPORT1, false) ||
prefs.getBoolean(ActivityPro.SKU_SUPPORT2, false) ||
prefs.getBoolean(ActivityPro.SKU_DONATION, false));
} catch (SecurityException ignored) {
return false;
}
}
public static boolean isPurchasedAny(Context context) {
try {
if (Util.isDebuggable(context)) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return !(prefs.getBoolean("debug_iab", false));
}
SharedPreferences prefs = context.getSharedPreferences("IAB", Context.MODE_PRIVATE);
for (String key : prefs.getAll().keySet())
if (prefs.getBoolean(key, false))
return true;
return false;
} catch (SecurityException ignored) {
return false;
}
}
public static String getResult(int responseCode) {
switch (responseCode) {
case 0:
return "OK";
case 1:
return "USER_CANCELED";
case 2:
return "SERVICE_UNAVAILABLE";
case 3:
return "BILLING_UNAVAILABLE";
case 4:
return "ITEM_UNAVAILABLE";
case 5:
return "DEVELOPER_ERROR";
case 6:
return "ERROR";
case 7:
return "ITEM_ALREADY_OWNED";
case 8:
return "ITEM_NOT_OWNED";
default:
return Integer.toString(responseCode);
}
}
}
@@ -0,0 +1,140 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.util.Log;
import androidx.annotation.NonNull;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
public class IPUtil {
private static final String TAG = "NetGuard.IPUtil";
public static List<CIDR> toCIDR(String start, String end) throws UnknownHostException {
return toCIDR(InetAddress.getByName(start), InetAddress.getByName(end));
}
public static List<CIDR> toCIDR(InetAddress start, InetAddress end) throws UnknownHostException {
List<CIDR> listResult = new ArrayList<>();
Log.i(TAG, "toCIDR(" + start.getHostAddress() + "," + end.getHostAddress() + ")");
long from = inet2long(start);
long to = inet2long(end);
while (to >= from) {
byte prefix = 32;
while (prefix > 0) {
long mask = prefix2mask(prefix - 1);
if ((from & mask) != from)
break;
prefix--;
}
byte max = (byte) (32 - Math.floor(Math.log(to - from + 1) / Math.log(2)));
if (prefix < max)
prefix = max;
listResult.add(new CIDR(long2inet(from), prefix));
from += Math.pow(2, (32 - prefix));
}
for (CIDR cidr : listResult)
Log.i(TAG, cidr.toString());
return listResult;
}
private static long prefix2mask(int bits) {
return (0xFFFFFFFF00000000L >> bits) & 0xFFFFFFFFL;
}
private static long inet2long(InetAddress addr) {
long result = 0;
if (addr != null)
for (byte b : addr.getAddress())
result = result << 8 | (b & 0xFF);
return result;
}
private static InetAddress long2inet(long addr) {
try {
byte[] b = new byte[4];
for (int i = b.length - 1; i >= 0; i--) {
b[i] = (byte) (addr & 0xFF);
addr = addr >> 8;
}
return InetAddress.getByAddress(b);
} catch (UnknownHostException ignore) {
return null;
}
}
public static InetAddress minus1(InetAddress addr) {
return long2inet(inet2long(addr) - 1);
}
public static InetAddress plus1(InetAddress addr) {
return long2inet(inet2long(addr) + 1);
}
public static class CIDR implements Comparable<CIDR> {
public InetAddress address;
public int prefix;
public CIDR(InetAddress address, int prefix) {
this.address = address;
this.prefix = prefix;
}
public CIDR(String ip, int prefix) {
try {
this.address = InetAddress.getByName(ip);
this.prefix = prefix;
} catch (UnknownHostException ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
}
public InetAddress getStart() {
return long2inet(inet2long(this.address) & prefix2mask(this.prefix));
}
public InetAddress getEnd() {
return long2inet((inet2long(this.address) & prefix2mask(this.prefix)) + (1L << (32 - this.prefix)) - 1);
}
@Override
public String toString() {
return address.getHostAddress() + "/" + prefix + "=" + getStart().getHostAddress() + "..." + getEnd().getHostAddress();
}
@Override
public int compareTo(@NonNull CIDR other) {
Long lcidr = IPUtil.inet2long(this.address);
Long lother = IPUtil.inet2long(other.address);
return lcidr.compareTo(lother);
}
}
}
@@ -0,0 +1,42 @@
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-2019 by Marcel Bokhorst (M66B)
*/
public class Packet {
public long time;
public int version;
public int protocol;
public String flags;
public String saddr;
public int sport;
public String daddr;
public int dport;
public String data;
public int uid;
public boolean allowed;
public Packet() {
}
@Override
public String toString() {
return "uid=" + uid + " v" + version + " p" + protocol + " " + daddr + "/" + dport;
}
}
@@ -0,0 +1,132 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.util.Log;
import androidx.preference.PreferenceManager;
import java.util.Map;
public class ReceiverAutostart extends BroadcastReceiver {
private static final String TAG = "NetGuard.Receiver";
@Override
public void onReceive(final Context context, Intent intent) {
Log.i(TAG, "Received " + intent);
Util.logExtras(intent);
String action = (intent == null ? null : intent.getAction());
if (Intent.ACTION_BOOT_COMPLETED.equals(action) || Intent.ACTION_MY_PACKAGE_REPLACED.equals(action))
try {
// Upgrade settings
upgrade(true, context);
// Start service
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
if (prefs.getBoolean("enabled", false))
ServiceSinkhole.start("receiver", context);
else if (prefs.getBoolean("show_stats", false))
ServiceSinkhole.run("receiver", context);
if (Util.isInteractive(context))
ServiceSinkhole.reloadStats("receiver", context);
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
}
public static void upgrade(boolean initialized, Context context) {
synchronized (context.getApplicationContext()) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
int oldVersion = prefs.getInt("version", -1);
int newVersion = Util.getSelfVersionCode(context);
if (oldVersion == newVersion)
return;
Log.i(TAG, "Upgrading from version " + oldVersion + " to " + newVersion);
SharedPreferences.Editor editor = prefs.edit();
if (initialized) {
if (oldVersion < 38) {
Log.i(TAG, "Converting screen wifi/mobile");
editor.putBoolean("screen_wifi", prefs.getBoolean("unused", false));
editor.putBoolean("screen_other", prefs.getBoolean("unused", false));
editor.remove("unused");
SharedPreferences unused = context.getSharedPreferences("unused", Context.MODE_PRIVATE);
SharedPreferences screen_wifi = context.getSharedPreferences("screen_wifi", Context.MODE_PRIVATE);
SharedPreferences screen_other = context.getSharedPreferences("screen_other", Context.MODE_PRIVATE);
Map<String, ?> punused = unused.getAll();
SharedPreferences.Editor edit_screen_wifi = screen_wifi.edit();
SharedPreferences.Editor edit_screen_other = screen_other.edit();
for (String key : punused.keySet()) {
edit_screen_wifi.putBoolean(key, (Boolean) punused.get(key));
edit_screen_other.putBoolean(key, (Boolean) punused.get(key));
}
edit_screen_wifi.apply();
edit_screen_other.apply();
} else if (oldVersion <= 2017032112)
editor.remove("ip6");
} else {
Log.i(TAG, "Initializing sdk=" + Build.VERSION.SDK_INT);
editor.putBoolean("filter_udp", true);
editor.putBoolean("whitelist_wifi", false);
editor.putBoolean("whitelist_other", false);
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP)
editor.putBoolean("filter", true); // Optional
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
editor.putBoolean("filter", true); // Mandatory
if (!Util.canFilter(context)) {
editor.putBoolean("log_app", false);
editor.putBoolean("filter", false);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
editor.remove("show_top");
if ("data".equals(prefs.getString("sort", "name")))
editor.remove("sort");
}
if (Util.isPlayStoreInstall(context)) {
editor.remove("update_check");
editor.remove("use_hosts");
editor.remove("hosts_url");
}
if (!Util.isDebuggable(context))
editor.remove("loglevel");
editor.putInt("version", newVersion);
editor.apply();
}
}
}
@@ -0,0 +1,50 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import androidx.core.app.NotificationManagerCompat;
public class ReceiverPackageRemoved extends BroadcastReceiver {
private static final String TAG = "NetGuard.Receiver";
@Override
public void onReceive(final Context context, Intent intent) {
Log.i(TAG, "Received " + intent);
Util.logExtras(intent);
String action = (intent == null ? null : intent.getAction());
if (Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) {
int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
if (uid > 0) {
DatabaseHelper dh = DatabaseHelper.getInstance(context);
dh.clearLog(uid);
dh.clearAccess(uid, false);
NotificationManagerCompat.from(context).cancel(uid); // installed notification
NotificationManagerCompat.from(context).cancel(uid + 10000); // access notification
}
}
}
}
@@ -0,0 +1,47 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ResourceRecord {
public long Time;
public String QName;
public String AName;
public String Resource;
public int TTL;
private static DateFormat formatter = SimpleDateFormat.getDateTimeInstance();
public ResourceRecord() {
}
@Override
public String toString() {
return formatter.format(new Date(Time).getTime()) +
" Q " + QName +
" A " + AName +
" R " + Resource +
" TTL " + TTL +
" " + formatter.format(new Date(Time + TTL * 1000L).getTime());
}
}
@@ -0,0 +1,453 @@
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-2019 by Marcel Bokhorst (M66B)
*/
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.content.res.XmlResourceParser;
import android.database.Cursor;
import android.os.Build;
import android.os.Process;
import android.util.Log;
import androidx.preference.PreferenceManager;
import org.xmlpull.v1.XmlPullParser;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class Rule {
private static final String TAG = "NetGuard.Rule";
public int uid;
public String packageName;
public int icon;
public String name;
public String version;
public boolean system;
public boolean internet;
public boolean enabled;
public boolean pkg = true;
public boolean wifi_default = false;
public boolean other_default = false;
public boolean screen_wifi_default = false;
public boolean screen_other_default = false;
public boolean roaming_default = false;
public boolean wifi_blocked = false;
public boolean other_blocked = false;
public boolean screen_wifi = false;
public boolean screen_other = false;
public boolean roaming = false;
public boolean lockdown = false;
public boolean apply = true;
public boolean notify = true;
public boolean relateduids = false;
public String[] related = null;
public long hosts;
public boolean changed;
public boolean expanded = false;
private static List<PackageInfo> cachePackageInfo = null;
private static Map<PackageInfo, String> cacheLabel = new HashMap<>();
private static Map<String, Boolean> cacheSystem = new HashMap<>();
private static Map<String, Boolean> cacheInternet = new HashMap<>();
private static Map<PackageInfo, Boolean> cacheEnabled = new HashMap<>();
private static List<PackageInfo> getPackages(Context context) {
if (cachePackageInfo == null) {
PackageManager pm = context.getPackageManager();
cachePackageInfo = pm.getInstalledPackages(0);
}
return new ArrayList<>(cachePackageInfo);
}
private static String getLabel(PackageInfo info, Context context) {
if (!cacheLabel.containsKey(info)) {
PackageManager pm = context.getPackageManager();
cacheLabel.put(info, info.applicationInfo.loadLabel(pm).toString());
}
return cacheLabel.get(info);
}
private static boolean isSystem(String packageName, Context context) {
if (!cacheSystem.containsKey(packageName))
cacheSystem.put(packageName, Util.isSystem(packageName, context));
return cacheSystem.get(packageName);
}
private static boolean hasInternet(String packageName, Context context) {
if (!cacheInternet.containsKey(packageName))
cacheInternet.put(packageName, Util.hasInternet(packageName, context));
return cacheInternet.get(packageName);
}
private static boolean isEnabled(PackageInfo info, Context context) {
if (!cacheEnabled.containsKey(info))
cacheEnabled.put(info, Util.isEnabled(info, context));
return cacheEnabled.get(info);
}
public static void clearCache(Context context) {
Log.i(TAG, "Clearing cache");
synchronized (context.getApplicationContext()) {
cachePackageInfo = null;
cacheLabel.clear();
cacheSystem.clear();
cacheInternet.clear();
cacheEnabled.clear();
}
DatabaseHelper dh = DatabaseHelper.getInstance(context);
dh.clearApps();
}
private Rule(DatabaseHelper dh, PackageInfo info, Context context) {
this.uid = info.applicationInfo.uid;
this.packageName = info.packageName;
this.icon = info.applicationInfo.icon;
this.version = info.versionName;
if (info.applicationInfo.uid == 0) {
this.name = context.getString(R.string.title_root);
this.system = true;
this.internet = true;
this.enabled = true;
this.pkg = false;
} else if (info.applicationInfo.uid == 1013) {
this.name = context.getString(R.string.title_mediaserver);
this.system = true;
this.internet = true;
this.enabled = true;
this.pkg = false;
} else if (info.applicationInfo.uid == 1020) {
this.name = "MulticastDNSResponder";
this.system = true;
this.internet = true;
this.enabled = true;
this.pkg = false;
} else if (info.applicationInfo.uid == 1021) {
this.name = context.getString(R.string.title_gpsdaemon);
this.system = true;
this.internet = true;
this.enabled = true;
this.pkg = false;
} else if (info.applicationInfo.uid == 1051) {
this.name = context.getString(R.string.title_dnsdaemon);
this.system = true;
this.internet = true;
this.enabled = true;
this.pkg = false;
} else if (info.applicationInfo.uid == 9999) {
this.name = context.getString(R.string.title_nobody);
this.system = true;
this.internet = true;
this.enabled = true;
this.pkg = false;
} else {
Cursor cursor = null;
try {
cursor = dh.getApp(this.packageName);
if (cursor.moveToNext()) {
this.name = cursor.getString(cursor.getColumnIndex("label"));
this.system = cursor.getInt(cursor.getColumnIndex("system")) > 0;
this.internet = cursor.getInt(cursor.getColumnIndex("internet")) > 0;
this.enabled = cursor.getInt(cursor.getColumnIndex("enabled")) > 0;
} else {
this.name = getLabel(info, context);
this.system = isSystem(info.packageName, context);
this.internet = hasInternet(info.packageName, context);
this.enabled = isEnabled(info, context);
dh.addApp(this.packageName, this.name, this.system, this.internet, this.enabled);
}
} finally {
if (cursor != null)
cursor.close();
}
}
}
public static List<Rule> getRules(final boolean all, Context context) {
synchronized (context.getApplicationContext()) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences wifi = context.getSharedPreferences("wifi", Context.MODE_PRIVATE);
SharedPreferences other = context.getSharedPreferences("other", Context.MODE_PRIVATE);
SharedPreferences screen_wifi = context.getSharedPreferences("screen_wifi", Context.MODE_PRIVATE);
SharedPreferences screen_other = context.getSharedPreferences("screen_other", Context.MODE_PRIVATE);
SharedPreferences roaming = context.getSharedPreferences("roaming", Context.MODE_PRIVATE);
SharedPreferences lockdown = context.getSharedPreferences("lockdown", Context.MODE_PRIVATE);
SharedPreferences apply = context.getSharedPreferences("apply", Context.MODE_PRIVATE);
SharedPreferences notify = context.getSharedPreferences("notify", Context.MODE_PRIVATE);
// Get settings
boolean default_wifi = prefs.getBoolean("whitelist_wifi", true);
boolean default_other = prefs.getBoolean("whitelist_other", true);
boolean default_screen_wifi = prefs.getBoolean("screen_wifi", false);
boolean default_screen_other = prefs.getBoolean("screen_other", false);
boolean default_roaming = prefs.getBoolean("whitelist_roaming", true);
boolean manage_system = prefs.getBoolean("manage_system", false);
boolean screen_on = prefs.getBoolean("screen_on", true);
boolean show_user = prefs.getBoolean("show_user", true);
boolean show_system = prefs.getBoolean("show_system", false);
boolean show_nointernet = prefs.getBoolean("show_nointernet", true);
boolean show_disabled = prefs.getBoolean("show_disabled", true);
default_screen_wifi = default_screen_wifi && screen_on;
default_screen_other = default_screen_other && screen_on;
// Get predefined rules
Map<String, Boolean> pre_wifi_blocked = new HashMap<>();
Map<String, Boolean> pre_other_blocked = new HashMap<>();
Map<String, Boolean> pre_roaming = new HashMap<>();
Map<String, String[]> pre_related = new HashMap<>();
Map<String, Boolean> pre_system = new HashMap<>();
try {
XmlResourceParser xml = context.getResources().getXml(R.xml.predefined);
int eventType = xml.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG)
if ("wifi".equals(xml.getName())) {
String pkg = xml.getAttributeValue(null, "package");
boolean pblocked = xml.getAttributeBooleanValue(null, "blocked", false);
pre_wifi_blocked.put(pkg, pblocked);
} else if ("other".equals(xml.getName())) {
String pkg = xml.getAttributeValue(null, "package");
boolean pblocked = xml.getAttributeBooleanValue(null, "blocked", false);
boolean proaming = xml.getAttributeBooleanValue(null, "roaming", default_roaming);
pre_other_blocked.put(pkg, pblocked);
pre_roaming.put(pkg, proaming);
} else if ("relation".equals(xml.getName())) {
String pkg = xml.getAttributeValue(null, "package");
String[] rel = xml.getAttributeValue(null, "related").split(",");
pre_related.put(pkg, rel);
} else if ("type".equals(xml.getName())) {
String pkg = xml.getAttributeValue(null, "package");
boolean system = xml.getAttributeBooleanValue(null, "system", true);
pre_system.put(pkg, system);
}
eventType = xml.next();
}
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
// Build rule list
List<Rule> listRules = new ArrayList<>();
List<PackageInfo> listPI = getPackages(context);
int userId = Process.myUid() / 100000;
// Add root
PackageInfo root = new PackageInfo();
root.packageName = "root";
root.versionCode = Build.VERSION.SDK_INT;
root.versionName = Build.VERSION.RELEASE;
root.applicationInfo = new ApplicationInfo();
root.applicationInfo.uid = 0;
root.applicationInfo.icon = 0;
listPI.add(root);
// Add mediaserver
PackageInfo media = new PackageInfo();
media.packageName = "android.media";
media.versionCode = Build.VERSION.SDK_INT;
media.versionName = Build.VERSION.RELEASE;
media.applicationInfo = new ApplicationInfo();
media.applicationInfo.uid = 1013 + userId * 100000;
media.applicationInfo.icon = 0;
listPI.add(media);
// MulticastDNSResponder
PackageInfo mdr = new PackageInfo();
mdr.packageName = "android.multicast";
mdr.versionCode = Build.VERSION.SDK_INT;
mdr.versionName = Build.VERSION.RELEASE;
mdr.applicationInfo = new ApplicationInfo();
mdr.applicationInfo.uid = 1020 + userId * 100000;
mdr.applicationInfo.icon = 0;
listPI.add(mdr);
// Add GPS daemon
PackageInfo gps = new PackageInfo();
gps.packageName = "android.gps";
gps.versionCode = Build.VERSION.SDK_INT;
gps.versionName = Build.VERSION.RELEASE;
gps.applicationInfo = new ApplicationInfo();
gps.applicationInfo.uid = 1021 + userId * 100000;
gps.applicationInfo.icon = 0;
listPI.add(gps);
// Add DNS daemon
PackageInfo dns = new PackageInfo();
dns.packageName = "android.dns";
dns.versionCode = Build.VERSION.SDK_INT;
dns.versionName = Build.VERSION.RELEASE;
dns.applicationInfo = new ApplicationInfo();
dns.applicationInfo.uid = 1051 + userId * 100000;
dns.applicationInfo.icon = 0;
listPI.add(dns);
// Add nobody
PackageInfo nobody = new PackageInfo();
nobody.packageName = "nobody";
nobody.versionCode = Build.VERSION.SDK_INT;
nobody.versionName = Build.VERSION.RELEASE;
nobody.applicationInfo = new ApplicationInfo();
nobody.applicationInfo.uid = 9999;
nobody.applicationInfo.icon = 0;
listPI.add(nobody);
DatabaseHelper dh = DatabaseHelper.getInstance(context);
for (PackageInfo info : listPI)
try {
// Skip self
if (info.applicationInfo.uid == Process.myUid())
continue;
Rule rule = new Rule(dh, info, context);
if (pre_system.containsKey(info.packageName))
rule.system = pre_system.get(info.packageName);
if (info.applicationInfo.uid == Process.myUid())
rule.system = true;
if (all ||
((rule.system ? show_system : show_user) &&
(show_nointernet || rule.internet) &&
(show_disabled || rule.enabled))) {
rule.wifi_default = (pre_wifi_blocked.containsKey(info.packageName) ? pre_wifi_blocked.get(info.packageName) : default_wifi);
rule.other_default = (pre_other_blocked.containsKey(info.packageName) ? pre_other_blocked.get(info.packageName) : default_other);
rule.screen_wifi_default = default_screen_wifi;
rule.screen_other_default = default_screen_other;
rule.roaming_default = (pre_roaming.containsKey(info.packageName) ? pre_roaming.get(info.packageName) : default_roaming);
rule.wifi_blocked = (!(rule.system && !manage_system) && wifi.getBoolean(info.packageName, rule.wifi_default));
rule.other_blocked = (!(rule.system && !manage_system) && other.getBoolean(info.packageName, rule.other_default));
rule.screen_wifi = screen_wifi.getBoolean(info.packageName, rule.screen_wifi_default) && screen_on;
rule.screen_other = screen_other.getBoolean(info.packageName, rule.screen_other_default) && screen_on;
rule.roaming = roaming.getBoolean(info.packageName, rule.roaming_default);
rule.lockdown = lockdown.getBoolean(info.packageName, false);
rule.apply = apply.getBoolean(info.packageName, true);
rule.notify = notify.getBoolean(info.packageName, true);
// Related packages
List<String> listPkg = new ArrayList<>();
if (pre_related.containsKey(info.packageName))
listPkg.addAll(Arrays.asList(pre_related.get(info.packageName)));
for (PackageInfo pi : listPI)
if (pi.applicationInfo.uid == rule.uid && !pi.packageName.equals(rule.packageName)) {
rule.relateduids = true;
listPkg.add(pi.packageName);
}
rule.related = listPkg.toArray(new String[0]);
rule.hosts = dh.getHostCount(rule.uid, true);
rule.updateChanged(default_wifi, default_other, default_roaming);
listRules.add(rule);
}
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
// Sort rule list
final Collator collator = Collator.getInstance(Locale.getDefault());
collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc
String sort = prefs.getString("sort", "name");
if ("uid".equals(sort))
Collections.sort(listRules, new Comparator<Rule>() {
@Override
public int compare(Rule rule, Rule other) {
if (rule.uid < other.uid)
return -1;
else if (rule.uid > other.uid)
return 1;
else {
int i = collator.compare(rule.name, other.name);
return (i == 0 ? rule.packageName.compareTo(other.packageName) : i);
}
}
});
else
Collections.sort(listRules, new Comparator<Rule>() {
@Override
public int compare(Rule rule, Rule other) {
if (all || rule.changed == other.changed) {
int i = collator.compare(rule.name, other.name);
return (i == 0 ? rule.packageName.compareTo(other.packageName) : i);
}
return (rule.changed ? -1 : 1);
}
});
return listRules;
}
}
private void updateChanged(boolean default_wifi, boolean default_other, boolean default_roaming) {
changed = (wifi_blocked != default_wifi ||
(other_blocked != default_other) ||
(wifi_blocked && screen_wifi != screen_wifi_default) ||
(other_blocked && screen_other != screen_other_default) ||
((!other_blocked || screen_other) && roaming != default_roaming) ||
hosts > 0 || lockdown || !apply);
}
public void updateChanged(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean screen_on = prefs.getBoolean("screen_on", false);
boolean default_wifi = prefs.getBoolean("whitelist_wifi", true) && screen_on;
boolean default_other = prefs.getBoolean("whitelist_other", true) && screen_on;
boolean default_roaming = prefs.getBoolean("whitelist_roaming", true);
updateChanged(default_wifi, default_other, default_roaming);
}
@Override
public String toString() {
// This is used in the port forwarding dialog application selector
return this.name;
}
}
@@ -0,0 +1,146 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.app.IntentService;
import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
import androidx.core.app.NotificationCompat;
import androidx.preference.PreferenceManager;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ServiceExternal extends IntentService {
private static final String TAG = "NetGuard.External";
private static final String ACTION_DOWNLOAD_HOSTS_FILE = "eu.faircode.netguard.DOWNLOAD_HOSTS_FILE";
// am startservice -a eu.faircode.netguard.DOWNLOAD_HOSTS_FILE
public ServiceExternal() {
super(TAG);
}
@Override
protected void onHandleIntent(Intent intent) {
try {
startForeground(ServiceSinkhole.NOTIFY_EXTERNAL, getForegroundNotification(this));
Log.i(TAG, "Received " + intent);
Util.logExtras(intent);
if (ACTION_DOWNLOAD_HOSTS_FILE.equals(intent.getAction())) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String hosts_url = prefs.getString("hosts_url", null);
if ("https://www.netguard.me/hosts".equals(hosts_url))
hosts_url = BuildConfig.HOSTS_FILE_URI;
File tmp = new File(getFilesDir(), "hosts.tmp");
File hosts = new File(getFilesDir(), "hosts.txt");
InputStream in = null;
OutputStream out = null;
URLConnection connection = null;
try {
URL url = new URL(hosts_url);
connection = url.openConnection();
connection.connect();
if (connection instanceof HttpURLConnection) {
HttpURLConnection httpConnection = (HttpURLConnection) connection;
if (httpConnection.getResponseCode() != HttpURLConnection.HTTP_OK)
throw new IOException(httpConnection.getResponseCode() + " " + httpConnection.getResponseMessage());
}
int contentLength = connection.getContentLength();
Log.i(TAG, "Content length=" + contentLength);
in = connection.getInputStream();
out = new FileOutputStream(tmp);
long size = 0;
byte buffer[] = new byte[4096];
int bytes;
while ((bytes = in.read(buffer)) != -1) {
out.write(buffer, 0, bytes);
size += bytes;
}
Log.i(TAG, "Downloaded size=" + size);
if (hosts.exists())
hosts.delete();
tmp.renameTo(hosts);
String last = SimpleDateFormat.getDateTimeInstance().format(new Date().getTime());
prefs.edit().putString("hosts_last_download", last).apply();
ServiceSinkhole.reload("hosts file download", this, false);
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
if (tmp.exists())
tmp.delete();
} finally {
try {
if (out != null)
out.close();
} catch (IOException ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
try {
if (in != null)
in.close();
} catch (IOException ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
if (connection instanceof HttpURLConnection)
((HttpURLConnection) connection).disconnect();
}
}
} finally {
stopForeground(true);
}
}
private static Notification getForegroundNotification(Context context) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "foreground");
builder.setSmallIcon(R.drawable.ic_hourglass_empty_white_24dp);
builder.setPriority(NotificationCompat.PRIORITY_MIN);
builder.setCategory(NotificationCompat.CATEGORY_STATUS);
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
builder.setContentTitle(context.getString(R.string.app_name));
return builder.build();
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,81 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.annotation.TargetApi;
import android.content.SharedPreferences;
import android.graphics.drawable.Icon;
import android.os.Build;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import android.util.Log;
import android.widget.Toast;
import androidx.preference.PreferenceManager;
@TargetApi(Build.VERSION_CODES.N)
public class ServiceTileFilter extends TileService implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "NetGuard.TileFilter";
public void onStartListening() {
Log.i(TAG, "Start listening");
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.registerOnSharedPreferenceChangeListener(this);
update();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if ("filter".equals(key))
update();
}
private void update() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean filter = prefs.getBoolean("filter", false);
Tile tile = getQsTile();
if (tile != null) {
tile.setState(filter ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
tile.setIcon(Icon.createWithResource(this, filter ? R.drawable.ic_filter_list_white_24dp : R.drawable.ic_filter_list_white_24dp_60));
tile.updateTile();
}
}
public void onStopListening() {
Log.i(TAG, "Stop listening");
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.unregisterOnSharedPreferenceChangeListener(this);
}
public void onClick() {
Log.i(TAG, "Click");
if (Util.canFilter(this)) {
if (IAB.isPurchased(ActivityPro.SKU_FILTER, this)) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.edit().putBoolean("filter", !prefs.getBoolean("filter", false)).apply();
ServiceSinkhole.reload("tile", this, false);
} else
Toast.makeText(this, R.string.title_pro_feature, Toast.LENGTH_SHORT).show();
} else
Toast.makeText(this, R.string.msg_unavailable, Toast.LENGTH_SHORT).show();
}
}
@@ -0,0 +1,80 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.annotation.TargetApi;
import android.content.SharedPreferences;
import android.graphics.drawable.Icon;
import android.os.Build;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import android.util.Log;
import android.widget.Toast;
import androidx.preference.PreferenceManager;
@TargetApi(Build.VERSION_CODES.N)
public class ServiceTileGraph extends TileService implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "NetGuard.TileGraph";
public void onStartListening() {
Log.i(TAG, "Start listening");
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.registerOnSharedPreferenceChangeListener(this);
update();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if ("show_stats".equals(key))
update();
}
private void update() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean stats = prefs.getBoolean("show_stats", false);
Tile tile = getQsTile();
if (tile != null) {
tile.setState(stats ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
tile.setIcon(Icon.createWithResource(this, stats ? R.drawable.ic_equalizer_white_24dp : R.drawable.ic_equalizer_white_24dp_60));
tile.updateTile();
}
}
public void onStopListening() {
Log.i(TAG, "Stop listening");
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.unregisterOnSharedPreferenceChangeListener(this);
}
public void onClick() {
Log.i(TAG, "Click");
// Check state
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean stats = !prefs.getBoolean("show_stats", false);
if (stats && !IAB.isPurchased(ActivityPro.SKU_SPEED, this))
Toast.makeText(this, R.string.title_pro_feature, Toast.LENGTH_SHORT).show();
else
prefs.edit().putBoolean("show_stats", stats).apply();
ServiceSinkhole.reloadStats("tile", this);
}
}
@@ -0,0 +1,75 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.annotation.TargetApi;
import android.content.SharedPreferences;
import android.graphics.drawable.Icon;
import android.os.Build;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import android.util.Log;
import androidx.preference.PreferenceManager;
@TargetApi(Build.VERSION_CODES.N)
public class ServiceTileLockdown extends TileService implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "NetGuard.TileLockdown";
public void onStartListening() {
Log.i(TAG, "Start listening");
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.registerOnSharedPreferenceChangeListener(this);
update();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if ("lockdown".equals(key))
update();
}
private void update() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean lockdown = prefs.getBoolean("lockdown", false);
Tile tile = getQsTile();
if (tile != null) {
tile.setState(lockdown ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
tile.setIcon(Icon.createWithResource(this, lockdown ? R.drawable.ic_lock_outline_white_24dp : R.drawable.ic_lock_outline_white_24dp_60));
tile.updateTile();
}
}
public void onStopListening() {
Log.i(TAG, "Stop listening");
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.unregisterOnSharedPreferenceChangeListener(this);
}
public void onClick() {
Log.i(TAG, "Click");
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.edit().putBoolean("lockdown", !prefs.getBoolean("lockdown", false)).apply();
ServiceSinkhole.reload("tile", this, false);
WidgetLockdown.updateWidgets(this);
}
}
@@ -0,0 +1,103 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.annotation.TargetApi;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.drawable.Icon;
import android.os.Build;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import android.util.Log;
import androidx.preference.PreferenceManager;
import java.util.Date;
@TargetApi(Build.VERSION_CODES.N)
public class ServiceTileMain extends TileService implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "NetGuard.TileMain";
public void onStartListening() {
Log.i(TAG, "Start listening");
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.registerOnSharedPreferenceChangeListener(this);
update();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if ("enabled".equals(key))
update();
}
private void update() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean enabled = prefs.getBoolean("enabled", false);
Tile tile = getQsTile();
if (tile != null) {
tile.setState(enabled ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
tile.setIcon(Icon.createWithResource(this, enabled ? R.drawable.ic_security_white_24dp : R.drawable.ic_security_white_24dp_60));
tile.updateTile();
}
}
public void onStopListening() {
Log.i(TAG, "Stop listening");
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.unregisterOnSharedPreferenceChangeListener(this);
}
public void onClick() {
Log.i(TAG, "Click");
// Cancel set alarm
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(WidgetAdmin.INTENT_ON);
intent.setPackage(getPackageName());
PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
am.cancel(pi);
// Check state
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean enabled = !prefs.getBoolean("enabled", false);
prefs.edit().putBoolean("enabled", enabled).apply();
if (enabled)
ServiceSinkhole.start("tile", this);
else {
ServiceSinkhole.stop("tile", this, false);
// Auto enable
int auto = Integer.parseInt(prefs.getString("auto_enable", "0"));
if (auto > 0) {
Log.i(TAG, "Scheduling enabled after minutes=" + auto);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
am.set(AlarmManager.RTC_WAKEUP, new Date().getTime() + auto * 60 * 1000L, pi);
else
am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, new Date().getTime() + auto * 60 * 1000L, pi);
}
}
}
}
@@ -0,0 +1,39 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.content.Context;
import android.util.AttributeSet;
// https://code.google.com/p/android/issues/detail?id=26194
public class SwitchPreference extends android.preference.SwitchPreference {
public SwitchPreference(Context context) {
this(context, null);
}
public SwitchPreference(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.switchPreferenceStyle);
}
public SwitchPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
}
@@ -0,0 +1,46 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Usage {
public long Time;
public int Version;
public int Protocol;
public String DAddr;
public int DPort;
public int Uid;
public long Sent;
public long Received;
private static DateFormat formatter = SimpleDateFormat.getDateTimeInstance();
@Override
public String toString() {
return formatter.format(new Date(Time).getTime()) +
" v" + Version + " p" + Protocol +
" " + DAddr + "/" + DPort +
" uid " + Uid +
" out " + Sent + " in " + Received;
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,50 @@
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-2019 by Marcel Bokhorst (M66B)
*/
public class Version implements Comparable<Version> {
private String version;
public Version(String version) {
this.version = version.replace("-beta", "");
}
@Override
public int compareTo(Version other) {
String[] lhs = this.version.split("\\.");
String[] rhs = other.version.split("\\.");
int length = Math.max(lhs.length, rhs.length);
for (int i = 0; i < length; i++) {
int vLhs = (i < lhs.length ? Integer.parseInt(lhs[i]) : 0);
int vRhs = (i < rhs.length ? Integer.parseInt(rhs[i]) : 0);
if (vLhs < vRhs)
return -1;
if (vLhs > vRhs)
return 1;
}
return 0;
}
@Override
public String toString() {
return version;
}
}
@@ -0,0 +1,99 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.util.Log;
import androidx.preference.PreferenceManager;
import java.util.Date;
public class WidgetAdmin extends ReceiverAutostart {
private static final String TAG = "NetGuard.Widget";
public static final String INTENT_ON = "eu.faircode.netguard.ON";
public static final String INTENT_OFF = "eu.faircode.netguard.OFF";
public static final String INTENT_LOCKDOWN_ON = "eu.faircode.netguard.LOCKDOWN_ON";
public static final String INTENT_LOCKDOWN_OFF = "eu.faircode.netguard.LOCKDOWN_OFF";
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
Log.i(TAG, "Received " + intent);
Util.logExtras(intent);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
// Cancel set alarm
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(INTENT_ON);
i.setPackage(context.getPackageName());
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
if (INTENT_ON.equals(intent.getAction()) || INTENT_OFF.equals(intent.getAction()))
am.cancel(pi);
// Vibrate
Vibrator vs = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
if (vs.hasVibrator())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
vs.vibrate(VibrationEffect.createOneShot(50, VibrationEffect.DEFAULT_AMPLITUDE));
else
vs.vibrate(50);
try {
if (INTENT_ON.equals(intent.getAction()) || INTENT_OFF.equals(intent.getAction())) {
boolean enabled = INTENT_ON.equals(intent.getAction());
prefs.edit().putBoolean("enabled", enabled).apply();
if (enabled)
ServiceSinkhole.start("widget", context);
else
ServiceSinkhole.stop("widget", context, false);
// Auto enable
int auto = Integer.parseInt(prefs.getString("auto_enable", "0"));
if (!enabled && auto > 0) {
Log.i(TAG, "Scheduling enabled after minutes=" + auto);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
am.set(AlarmManager.RTC_WAKEUP, new Date().getTime() + auto * 60 * 1000L, pi);
else
am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, new Date().getTime() + auto * 60 * 1000L, pi);
}
} else if (INTENT_LOCKDOWN_ON.equals(intent.getAction()) || INTENT_LOCKDOWN_OFF.equals(intent.getAction())) {
boolean lockdown = INTENT_LOCKDOWN_ON.equals(intent.getAction());
prefs.edit().putBoolean("lockdown", lockdown).apply();
ServiceSinkhole.reload("widget", context, false);
WidgetLockdown.updateWidgets(context);
}
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
}
}
@@ -0,0 +1,70 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
import android.widget.RemoteViews;
import androidx.preference.PreferenceManager;
public class WidgetLockdown extends AppWidgetProvider {
private static final String TAG = "NetGuard.WidgetLock";
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
update(appWidgetIds, appWidgetManager, context);
}
private static void update(int[] appWidgetIds, AppWidgetManager appWidgetManager, Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean lockdown = prefs.getBoolean("lockdown", false);
try {
try {
Intent intent = new Intent(lockdown ? WidgetAdmin.INTENT_LOCKDOWN_OFF : WidgetAdmin.INTENT_LOCKDOWN_ON);
intent.setPackage(context.getPackageName());
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
for (int id : appWidgetIds) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widgetlockdown);
views.setOnClickPendingIntent(R.id.ivEnabled, pi);
views.setImageViewResource(R.id.ivEnabled, lockdown ? R.drawable.ic_lock_outline_white_24dp : R.drawable.ic_lock_open_white_24dp);
appWidgetManager.updateAppWidget(id, views);
}
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
}
public static void updateWidgets(Context context) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int appWidgetIds[] = AppWidgetManager.getInstance(context).getAppWidgetIds(new ComponentName(context, WidgetLockdown.class));
update(appWidgetIds, appWidgetManager, context);
}
}
@@ -0,0 +1,70 @@
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-2019 by Marcel Bokhorst (M66B)
*/
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
import android.widget.RemoteViews;
import androidx.preference.PreferenceManager;
public class WidgetMain extends AppWidgetProvider {
private static final String TAG = "NetGuard.Widget";
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
update(appWidgetIds, appWidgetManager, context);
}
private static void update(int[] appWidgetIds, AppWidgetManager appWidgetManager, Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean enabled = prefs.getBoolean("enabled", false);
try {
try {
Intent intent = new Intent(enabled ? WidgetAdmin.INTENT_OFF : WidgetAdmin.INTENT_ON);
intent.setPackage(context.getPackageName());
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
for (int id : appWidgetIds) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widgetmain);
views.setOnClickPendingIntent(R.id.ivEnabled, pi);
views.setImageViewResource(R.id.ivEnabled, enabled ? R.drawable.ic_security_color_24dp : R.drawable.ic_security_white_24dp_60);
appWidgetManager.updateAppWidget(id, views);
}
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
}
public static void updateWidgets(Context context) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int appWidgetIds[] = AppWidgetManager.getInstance(context).getAppWidgetIds(new ComponentName(context, WidgetMain.class));
update(appWidgetIds, appWidgetManager, context);
}
}