Initial support for DNSMasq
This commit is contained in:
parent
7dcb8b2643
commit
311eb48c27
@ -22,8 +22,8 @@ import org.itxtech.daedalus.activity.MainActivity;
|
|||||||
import org.itxtech.daedalus.service.DaedalusVpnService;
|
import org.itxtech.daedalus.service.DaedalusVpnService;
|
||||||
import org.itxtech.daedalus.util.Configurations;
|
import org.itxtech.daedalus.util.Configurations;
|
||||||
import org.itxtech.daedalus.util.DnsServer;
|
import org.itxtech.daedalus.util.DnsServer;
|
||||||
import org.itxtech.daedalus.util.HostsProvider;
|
import org.itxtech.daedalus.util.RulesProvider;
|
||||||
import org.itxtech.daedalus.util.HostsResolver;
|
import org.itxtech.daedalus.util.RulesResolver;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -56,10 +56,14 @@ public class Daedalus extends Application {
|
|||||||
add(new DnsServer("123.206.21.48", R.string.server_aixyz_south_china));
|
add(new DnsServer("123.206.21.48", R.string.server_aixyz_south_china));
|
||||||
}};
|
}};
|
||||||
|
|
||||||
public static final List<HostsProvider> HOSTS_PROVIDERS = new ArrayList<HostsProvider>() {{
|
public static final List<RulesProvider> HOSTS_PROVIDERS = new ArrayList<RulesProvider>() {{
|
||||||
add(new HostsProvider("racaljk/hosts", "https://coding.net/u/scaffrey/p/hosts/git/raw/master/hosts"));
|
add(new RulesProvider("racaljk/hosts", "https://coding.net/u/scaffrey/p/hosts/git/raw/master/hosts"));
|
||||||
add(new HostsProvider("fengixng/google-hosts", "https://raw.githubusercontent.com/fengixng/google-hosts/master/hosts"));
|
add(new RulesProvider("fengixng/google-hosts", "https://raw.githubusercontent.com/fengixng/google-hosts/master/hosts"));
|
||||||
add(new HostsProvider("sy618/hosts", "https://raw.githubusercontent.com/sy618/hosts/master/ADFQ"));
|
add(new RulesProvider("sy618/hosts", "https://raw.githubusercontent.com/sy618/hosts/master/ADFQ"));
|
||||||
|
}};
|
||||||
|
|
||||||
|
public static final List<RulesProvider> DNSMASQ_PROVIDERS = new ArrayList<RulesProvider>() {{
|
||||||
|
|
||||||
}};
|
}};
|
||||||
|
|
||||||
public static final String[] DEFAULT_TEST_DOMAINS = new String[]{
|
public static final String[] DEFAULT_TEST_DOMAINS = new String[]{
|
||||||
@ -73,6 +77,7 @@ public class Daedalus extends Application {
|
|||||||
public static Configurations configurations;
|
public static Configurations configurations;
|
||||||
|
|
||||||
public static String hostsPath;
|
public static String hostsPath;
|
||||||
|
public static String dnsmasqPath;
|
||||||
public static String configPath;
|
public static String configPath;
|
||||||
|
|
||||||
private static Daedalus instance = null;
|
private static Daedalus instance = null;
|
||||||
@ -83,10 +88,11 @@ public class Daedalus extends Application {
|
|||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
mHostsResolver = new Thread(new HostsResolver());
|
mHostsResolver = new Thread(new RulesResolver());
|
||||||
mHostsResolver.start();
|
mHostsResolver.start();
|
||||||
|
|
||||||
hostsPath = getExternalFilesDir(null).getPath() + "/hosts";
|
hostsPath = getExternalFilesDir(null).getPath() + "/hosts";
|
||||||
|
dnsmasqPath = getExternalFilesDir(null).getPath() + "/dnsmasq";
|
||||||
configPath = getExternalFilesDir(null).getPath() + "/config.json";
|
configPath = getExternalFilesDir(null).getPath() + "/config.json";
|
||||||
|
|
||||||
initData();
|
initData();
|
||||||
@ -114,7 +120,7 @@ public class Daedalus extends Application {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public static void initHostsResolver() {
|
public static void initHostsResolver() {
|
||||||
if (Daedalus.getPrefs().getBoolean("settings_local_host_resolution", false)) {
|
if (Daedalus.getPrefs().getBoolean("settings_local_rules_resolution", false)) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
int permission = ActivityCompat.checkSelfPermission(Daedalus.getInstance(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
int permission = ActivityCompat.checkSelfPermission(Daedalus.getInstance(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||||
if (MainActivity.getInstance() != null) {
|
if (MainActivity.getInstance() != null) {
|
||||||
@ -125,8 +131,11 @@ public class Daedalus extends Application {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HostsResolver.startLoad(hostsPath);
|
if (Daedalus.getPrefs().getBoolean("settings_use_dnsmasq", false)) {
|
||||||
HostsResolver.setPanResolution(Daedalus.getPrefs().getBoolean("settings_pan_resolution", false));
|
RulesResolver.startLoadDnsmasq(dnsmasqPath);
|
||||||
|
} else {
|
||||||
|
RulesResolver.startLoadHosts(hostsPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static SharedPreferences getPrefs() {
|
public static SharedPreferences getPrefs() {
|
||||||
@ -140,9 +149,9 @@ public class Daedalus extends Application {
|
|||||||
|
|
||||||
instance = null;
|
instance = null;
|
||||||
prefs = null;
|
prefs = null;
|
||||||
HostsResolver.shutdown();
|
RulesResolver.shutdown();
|
||||||
mHostsResolver.interrupt();
|
mHostsResolver.interrupt();
|
||||||
HostsResolver.clean();
|
RulesResolver.clean();
|
||||||
mHostsResolver = null;
|
mHostsResolver = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||||||
public static final int FRAGMENT_DNS_TEST = 1;
|
public static final int FRAGMENT_DNS_TEST = 1;
|
||||||
public static final int FRAGMENT_SETTINGS = 2;
|
public static final int FRAGMENT_SETTINGS = 2;
|
||||||
public static final int FRAGMENT_ABOUT = 3;
|
public static final int FRAGMENT_ABOUT = 3;
|
||||||
public static final int FRAGMENT_HOSTS = 4;
|
public static final int FRAGMENT_RULES = 4;
|
||||||
public static final int FRAGMENT_DNS_SERVERS = 5;
|
public static final int FRAGMENT_DNS_SERVERS = 5;
|
||||||
|
|
||||||
private static MainActivity instance = null;
|
private static MainActivity instance = null;
|
||||||
@ -61,7 +61,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||||||
private DnsTestFragment mDnsTest;
|
private DnsTestFragment mDnsTest;
|
||||||
private SettingsFragment mSettings;
|
private SettingsFragment mSettings;
|
||||||
private AboutFragment mAbout;
|
private AboutFragment mAbout;
|
||||||
private HostsFragment mHosts;
|
private RulesFragment mHosts;
|
||||||
private DnsServersFragment mDnsServers;
|
private DnsServersFragment mDnsServers;
|
||||||
private int currentFragment = FRAGMENT_NONE;
|
private int currentFragment = FRAGMENT_NONE;
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||||||
case FRAGMENT_ABOUT:
|
case FRAGMENT_ABOUT:
|
||||||
menu.findItem(R.id.nav_about).setChecked(true);
|
menu.findItem(R.id.nav_about).setChecked(true);
|
||||||
break;
|
break;
|
||||||
case FRAGMENT_HOSTS:
|
case FRAGMENT_RULES:
|
||||||
menu.findItem(R.id.nav_hosts).setChecked(true);
|
menu.findItem(R.id.nav_hosts).setChecked(true);
|
||||||
break;
|
break;
|
||||||
case FRAGMENT_DNS_SERVERS:
|
case FRAGMENT_DNS_SERVERS:
|
||||||
@ -183,8 +183,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||||||
case FRAGMENT_ABOUT:
|
case FRAGMENT_ABOUT:
|
||||||
toolbar.setTitle(R.string.action_about);
|
toolbar.setTitle(R.string.action_about);
|
||||||
break;
|
break;
|
||||||
case FRAGMENT_HOSTS:
|
case FRAGMENT_RULES:
|
||||||
toolbar.setTitle(R.string.action_hosts);
|
toolbar.setTitle(R.string.action_rules);
|
||||||
break;
|
break;
|
||||||
case FRAGMENT_DNS_SERVERS:
|
case FRAGMENT_DNS_SERVERS:
|
||||||
toolbar.setTitle(R.string.action_dns_servers);
|
toolbar.setTitle(R.string.action_dns_servers);
|
||||||
@ -229,13 +229,13 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||||||
toolbar.setTitle(R.string.action_about);
|
toolbar.setTitle(R.string.action_about);
|
||||||
currentFragment = FRAGMENT_ABOUT;
|
currentFragment = FRAGMENT_ABOUT;
|
||||||
break;
|
break;
|
||||||
case FRAGMENT_HOSTS:
|
case FRAGMENT_RULES:
|
||||||
if (mHosts == null) {
|
if (mHosts == null) {
|
||||||
mHosts = new HostsFragment();
|
mHosts = new RulesFragment();
|
||||||
}
|
}
|
||||||
transaction.replace(R.id.id_content, mHosts);
|
transaction.replace(R.id.id_content, mHosts);
|
||||||
toolbar.setTitle(R.string.action_hosts);
|
toolbar.setTitle(R.string.action_rules);
|
||||||
currentFragment = FRAGMENT_HOSTS;
|
currentFragment = FRAGMENT_RULES;
|
||||||
break;
|
break;
|
||||||
case FRAGMENT_DNS_SERVERS:
|
case FRAGMENT_DNS_SERVERS:
|
||||||
if (mDnsServers == null) {
|
if (mDnsServers == null) {
|
||||||
@ -327,7 +327,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (id == R.id.nav_hosts) {
|
if (id == R.id.nav_hosts) {
|
||||||
switchFragment(FRAGMENT_HOSTS);
|
switchFragment(FRAGMENT_RULES);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id == R.id.nav_dns_server) {
|
if (id == R.id.nav_dns_server) {
|
||||||
|
@ -14,7 +14,7 @@ import android.widget.Spinner;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import org.itxtech.daedalus.Daedalus;
|
import org.itxtech.daedalus.Daedalus;
|
||||||
import org.itxtech.daedalus.R;
|
import org.itxtech.daedalus.R;
|
||||||
import org.itxtech.daedalus.util.HostsProvider;
|
import org.itxtech.daedalus.util.RulesProvider;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@ -33,7 +33,7 @@ import java.util.Date;
|
|||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*/
|
*/
|
||||||
public class HostsFragment extends Fragment {
|
public class RulesFragment extends Fragment {
|
||||||
|
|
||||||
private Thread mThread = null;
|
private Thread mThread = null;
|
||||||
private View view = null;
|
private View view = null;
|
||||||
@ -46,7 +46,7 @@ public class HostsFragment extends Fragment {
|
|||||||
mHandler = new HostsHandler().setView(view).setHostsFragment(this);
|
mHandler = new HostsHandler().setView(view).setHostsFragment(this);
|
||||||
|
|
||||||
final Spinner spinnerHosts = (Spinner) view.findViewById(R.id.spinner_hosts);
|
final Spinner spinnerHosts = (Spinner) view.findViewById(R.id.spinner_hosts);
|
||||||
ArrayAdapter spinnerArrayAdapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, HostsProvider.getHostsProviderNames());
|
ArrayAdapter spinnerArrayAdapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, RulesProvider.getHostsProviderNames());
|
||||||
spinnerHosts.setAdapter(spinnerArrayAdapter);
|
spinnerHosts.setAdapter(spinnerArrayAdapter);
|
||||||
spinnerHosts.setSelection(0);
|
spinnerHosts.setSelection(0);
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ public class HostsFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
URLConnection connection = new URL(HostsProvider.getDownloadUrlByName(spinnerHosts.getSelectedItem().toString())).openConnection();
|
URLConnection connection = new URL(RulesProvider.getDownloadUrlByName(spinnerHosts.getSelectedItem().toString())).openConnection();
|
||||||
InputStream inputStream = connection.getInputStream();
|
InputStream inputStream = connection.getInputStream();
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
@ -130,14 +130,14 @@ public class HostsFragment extends Fragment {
|
|||||||
static final int MSG_DOWNLOADED = 0;
|
static final int MSG_DOWNLOADED = 0;
|
||||||
|
|
||||||
private View view = null;
|
private View view = null;
|
||||||
private HostsFragment mFragment = null;
|
private RulesFragment mFragment = null;
|
||||||
|
|
||||||
HostsHandler setView(View view) {
|
HostsHandler setView(View view) {
|
||||||
this.view = view;
|
this.view = view;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
HostsHandler setHostsFragment(HostsFragment fragment) {
|
HostsHandler setHostsFragment(RulesFragment fragment) {
|
||||||
mFragment = fragment;
|
mFragment = fragment;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
@ -129,7 +129,7 @@ public class SettingsFragment extends PreferenceFragment {
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
view = super.onCreateView(inflater, container, savedInstanceState);
|
view = super.onCreateView(inflater, container, savedInstanceState);
|
||||||
SwitchPreference localHostResolution = (SwitchPreference) findPreference("settings_local_host_resolution");
|
SwitchPreference localHostResolution = (SwitchPreference) findPreference("settings_local_rules_resolution");
|
||||||
localHostResolution.setSummary(Daedalus.hostsPath);
|
localHostResolution.setSummary(Daedalus.hostsPath);
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import de.measite.minidns.Record;
|
|||||||
import de.measite.minidns.record.A;
|
import de.measite.minidns.record.A;
|
||||||
import org.itxtech.daedalus.service.DaedalusVpnService;
|
import org.itxtech.daedalus.service.DaedalusVpnService;
|
||||||
import org.itxtech.daedalus.util.DnsServerHelper;
|
import org.itxtech.daedalus.util.DnsServerHelper;
|
||||||
import org.itxtech.daedalus.util.HostsResolver;
|
import org.itxtech.daedalus.util.RulesResolver;
|
||||||
import org.pcap4j.packet.*;
|
import org.pcap4j.packet.*;
|
||||||
import org.pcap4j.packet.factory.PacketFactoryPropertiesLoader;
|
import org.pcap4j.packet.factory.PacketFactoryPropertiesLoader;
|
||||||
import org.pcap4j.util.PropertiesLoader;
|
import org.pcap4j.util.PropertiesLoader;
|
||||||
@ -74,7 +74,7 @@ public class UdpDnsProvider extends DnsProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void queueDeviceWrite(IpPacket ipOutPacket) {
|
private void queueDeviceWrite(IpPacket ipOutPacket) {
|
||||||
dnsQueryTimes++;
|
dnsQueryTimes++;
|
||||||
Log.i(TAG, "QT " + dnsQueryTimes);
|
Log.i(TAG, "QT " + dnsQueryTimes);
|
||||||
deviceWrites.add(ipOutPacket.getRawData());
|
deviceWrites.add(ipOutPacket.getRawData());
|
||||||
@ -340,8 +340,8 @@ public class UdpDnsProvider extends DnsProvider {
|
|||||||
String dnsQueryName = dnsMsg.getQuestion().name.toString();
|
String dnsQueryName = dnsMsg.getQuestion().name.toString();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (HostsResolver.canResolve(dnsQueryName)) {
|
if (RulesResolver.canResolve(dnsQueryName)) {
|
||||||
String response = HostsResolver.resolve(dnsQueryName);
|
String response = RulesResolver.resolve(dnsQueryName);
|
||||||
Log.i(TAG, "handleDnsRequest: DNS Name " + dnsQueryName + " address " + response + ", using local hosts to resolve.");
|
Log.i(TAG, "handleDnsRequest: DNS Name " + dnsQueryName + " address " + response + ", using local hosts to resolve.");
|
||||||
DNSMessage.Builder builder = dnsMsg.asBuilder();
|
DNSMessage.Builder builder = dnsMsg.asBuilder();
|
||||||
int[] ip = new int[4];
|
int[] ip = new int[4];
|
||||||
|
@ -20,7 +20,7 @@ import org.itxtech.daedalus.provider.TcpDnsProvider;
|
|||||||
import org.itxtech.daedalus.provider.UdpDnsProvider;
|
import org.itxtech.daedalus.provider.UdpDnsProvider;
|
||||||
import org.itxtech.daedalus.receiver.StatusBarBroadcastReceiver;
|
import org.itxtech.daedalus.receiver.StatusBarBroadcastReceiver;
|
||||||
import org.itxtech.daedalus.util.DnsServerHelper;
|
import org.itxtech.daedalus.util.DnsServerHelper;
|
||||||
import org.itxtech.daedalus.util.HostsResolver;
|
import org.itxtech.daedalus.util.RulesResolver;
|
||||||
|
|
||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
|
|
||||||
@ -146,7 +146,7 @@ public class DaedalusVpnService extends VpnService implements Runnable {
|
|||||||
Daedalus.updateShortcut(getApplicationContext());
|
Daedalus.updateShortcut(getApplicationContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
HostsResolver.clean();
|
RulesResolver.clean();
|
||||||
DnsServerHelper.cleanPortCache();
|
DnsServerHelper.cleanPortCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,151 +0,0 @@
|
|||||||
package org.itxtech.daedalus.util;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Daedalus Project
|
|
||||||
*
|
|
||||||
* @author iTX Technologies
|
|
||||||
* @link https://itxtech.org
|
|
||||||
* <p>
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*/
|
|
||||||
public class HostsResolver implements Runnable {
|
|
||||||
private static final String TAG = "DHostsResolver";
|
|
||||||
|
|
||||||
public static final int STATUS_LOADED = 0;
|
|
||||||
public static final int STATUS_LOADING = 1;
|
|
||||||
public static final int STATUS_NOT_LOADED = 2;
|
|
||||||
public static final int STATUS_PENDING_LOAD = 3;
|
|
||||||
|
|
||||||
private static int status = STATUS_NOT_LOADED;
|
|
||||||
private static String fileName;
|
|
||||||
private static HashMap<String, String> hosts;
|
|
||||||
private static boolean shutdown = false;
|
|
||||||
private static boolean panResolution = false;
|
|
||||||
|
|
||||||
public HostsResolver() {
|
|
||||||
status = STATUS_NOT_LOADED;
|
|
||||||
fileName = "";
|
|
||||||
shutdown = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void shutdown() {
|
|
||||||
shutdown = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isLoaded() {
|
|
||||||
return status == STATUS_LOADED;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void startLoad(String loadFile) {
|
|
||||||
Log.d(TAG, "Loading file " + loadFile);
|
|
||||||
fileName = loadFile;
|
|
||||||
status = STATUS_PENDING_LOAD;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setPanResolution(boolean resolution) {
|
|
||||||
panResolution = resolution;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void clean() {
|
|
||||||
hosts = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean canResolve(String hostname) {
|
|
||||||
if (hosts == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (hosts.containsKey(hostname)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (panResolution) {
|
|
||||||
String[] pieces = hostname.split("\\.");
|
|
||||||
StringBuilder builder;
|
|
||||||
builder = new StringBuilder();
|
|
||||||
builder.append("*");
|
|
||||||
for (int i = 1; i < pieces.length; i++) {
|
|
||||||
builder.append(".").append(pieces[i]);
|
|
||||||
}
|
|
||||||
if (hosts.containsKey(builder.toString())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String resolve(String hostname) {
|
|
||||||
if (hosts == null) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
if (hosts.containsKey(hostname)) {
|
|
||||||
return hosts.get(hostname);
|
|
||||||
}
|
|
||||||
if (panResolution) {
|
|
||||||
String[] pieces = hostname.split("\\.");
|
|
||||||
StringBuilder builder;
|
|
||||||
builder = new StringBuilder();
|
|
||||||
builder.append("*");
|
|
||||||
for (int i = 1; i < pieces.length; i++) {
|
|
||||||
builder.append(".").append(pieces[i]);
|
|
||||||
}
|
|
||||||
if (hosts.containsKey(builder.toString())) {
|
|
||||||
return hosts.get(builder.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
private void load() {
|
|
||||||
try {
|
|
||||||
status = STATUS_LOADING;
|
|
||||||
File file = new File(fileName);
|
|
||||||
if (file.exists() && file.canRead()) {
|
|
||||||
FileInputStream stream = new FileInputStream(file);
|
|
||||||
BufferedReader dataIO = new BufferedReader(new InputStreamReader(stream));
|
|
||||||
hosts = new HashMap<>();
|
|
||||||
String strLine;
|
|
||||||
String[] data;
|
|
||||||
while ((strLine = dataIO.readLine()) != null) {
|
|
||||||
//Log.d(TAG, strLine);
|
|
||||||
if (!strLine.equals("") && !strLine.startsWith("#")) {
|
|
||||||
data = strLine.split("\\s+");
|
|
||||||
hosts.put(data[1], data[0]);
|
|
||||||
Log.d(TAG, "Putting " + data[0] + " " + data[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dataIO.close();
|
|
||||||
stream.close();
|
|
||||||
status = STATUS_LOADED;
|
|
||||||
} else {
|
|
||||||
status = STATUS_NOT_LOADED;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
while (!shutdown) {
|
|
||||||
if (status == STATUS_PENDING_LOAD) {
|
|
||||||
load();
|
|
||||||
}
|
|
||||||
Thread.sleep(100);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,11 +15,11 @@ import java.util.ArrayList;
|
|||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*/
|
*/
|
||||||
public class HostsProvider {
|
public class RulesProvider {
|
||||||
private String name;
|
private String name;
|
||||||
private String downloadURL;
|
private String downloadURL;
|
||||||
|
|
||||||
public HostsProvider(String name, String downloadURL) {
|
public RulesProvider(String name, String downloadURL) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.downloadURL = downloadURL;
|
this.downloadURL = downloadURL;
|
||||||
}
|
}
|
||||||
@ -34,7 +34,7 @@ public class HostsProvider {
|
|||||||
|
|
||||||
public static String[] getHostsProviderNames() {
|
public static String[] getHostsProviderNames() {
|
||||||
ArrayList<String> servers = new ArrayList<>(Daedalus.HOSTS_PROVIDERS.size());
|
ArrayList<String> servers = new ArrayList<>(Daedalus.HOSTS_PROVIDERS.size());
|
||||||
for (HostsProvider hostsProvider : Daedalus.HOSTS_PROVIDERS) {
|
for (RulesProvider hostsProvider : Daedalus.HOSTS_PROVIDERS) {
|
||||||
servers.add(hostsProvider.getName());
|
servers.add(hostsProvider.getName());
|
||||||
}
|
}
|
||||||
String[] stringServers = new String[Daedalus.HOSTS_PROVIDERS.size()];
|
String[] stringServers = new String[Daedalus.HOSTS_PROVIDERS.size()];
|
||||||
@ -42,7 +42,7 @@ public class HostsProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getDownloadUrlByName(String name) {
|
public static String getDownloadUrlByName(String name) {
|
||||||
for (HostsProvider hostsProvider : Daedalus.HOSTS_PROVIDERS) {
|
for (RulesProvider hostsProvider : Daedalus.HOSTS_PROVIDERS) {
|
||||||
if (hostsProvider.getName().equals(name)) {
|
if (hostsProvider.getName().equals(name)) {
|
||||||
return hostsProvider.getDownloadURL();
|
return hostsProvider.getDownloadURL();
|
||||||
}
|
}
|
181
app/src/main/java/org/itxtech/daedalus/util/RulesResolver.java
Normal file
181
app/src/main/java/org/itxtech/daedalus/util/RulesResolver.java
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
package org.itxtech.daedalus.util;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Daedalus Project
|
||||||
|
*
|
||||||
|
* @author iTX Technologies
|
||||||
|
* @link https://itxtech.org
|
||||||
|
* <p>
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*/
|
||||||
|
public class RulesResolver implements Runnable {
|
||||||
|
private static final String TAG = "DRulesResolver";
|
||||||
|
|
||||||
|
public static final int STATUS_LOADED = 0;
|
||||||
|
public static final int STATUS_LOADING = 1;
|
||||||
|
public static final int STATUS_NOT_LOADED = 2;
|
||||||
|
public static final int STATUS_PENDING_LOAD = 3;
|
||||||
|
|
||||||
|
public static final int MODE_HOSTS = 0;
|
||||||
|
public static final int MODE_DNSMASQ = 1;
|
||||||
|
|
||||||
|
private static int status = STATUS_NOT_LOADED;
|
||||||
|
private static int mode = MODE_HOSTS;
|
||||||
|
private static String hostsFile;
|
||||||
|
private static String dnsmasqFile;
|
||||||
|
private static HashMap<String, String> rules;
|
||||||
|
private static boolean shutdown = false;
|
||||||
|
|
||||||
|
public RulesResolver() {
|
||||||
|
status = STATUS_NOT_LOADED;
|
||||||
|
hostsFile = "";
|
||||||
|
dnsmasqFile = "";
|
||||||
|
shutdown = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void shutdown() {
|
||||||
|
shutdown = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isLoaded() {
|
||||||
|
return status == STATUS_LOADED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startLoadHosts(String loadFile) {
|
||||||
|
Log.d(TAG, "Loading hosts file " + loadFile);
|
||||||
|
hostsFile = loadFile;
|
||||||
|
mode = MODE_HOSTS;
|
||||||
|
status = STATUS_PENDING_LOAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startLoadDnsmasq(String loadFile) {
|
||||||
|
Log.d(TAG, "Loading DNSMasq file " + loadFile);
|
||||||
|
dnsmasqFile = loadFile;
|
||||||
|
mode = MODE_DNSMASQ;
|
||||||
|
status = STATUS_PENDING_LOAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clean() {
|
||||||
|
rules = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canResolve(String hostname) {
|
||||||
|
if (rules == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rules.containsKey(hostname)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (mode == MODE_DNSMASQ) {
|
||||||
|
String[] pieces = hostname.split("\\.");
|
||||||
|
StringBuilder builder;
|
||||||
|
builder = new StringBuilder();
|
||||||
|
for (int i = 1; i < pieces.length; i++) {
|
||||||
|
builder.append(".").append(pieces[i]);
|
||||||
|
}
|
||||||
|
if (rules.containsKey(builder.toString())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String resolve(String hostname) {
|
||||||
|
if (rules == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (rules.containsKey(hostname)) {
|
||||||
|
return rules.get(hostname);
|
||||||
|
}
|
||||||
|
if (mode == MODE_DNSMASQ) {
|
||||||
|
String[] pieces = hostname.split("\\.");
|
||||||
|
StringBuilder builder;
|
||||||
|
builder = new StringBuilder();
|
||||||
|
for (int i = 1; i < pieces.length; i++) {
|
||||||
|
builder.append(".").append(pieces[i]);
|
||||||
|
}
|
||||||
|
if (rules.containsKey(builder.toString())) {
|
||||||
|
return rules.get(builder.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void load() {
|
||||||
|
try {
|
||||||
|
status = STATUS_LOADING;
|
||||||
|
rules = new HashMap<>();
|
||||||
|
if (mode == MODE_HOSTS) {
|
||||||
|
File file = new File(hostsFile);
|
||||||
|
if (file.exists() && file.canRead()) {
|
||||||
|
FileInputStream stream = new FileInputStream(file);
|
||||||
|
BufferedReader dataIO = new BufferedReader(new InputStreamReader(stream));
|
||||||
|
String strLine;
|
||||||
|
String[] data;
|
||||||
|
while ((strLine = dataIO.readLine()) != null) {
|
||||||
|
//Log.d(TAG, strLine);
|
||||||
|
if (!strLine.equals("") && !strLine.startsWith("#")) {
|
||||||
|
data = strLine.split("\\s+");
|
||||||
|
rules.put(data[1], data[0]);
|
||||||
|
Log.d(TAG, "Putting " + data[0] + " " + data[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dataIO.close();
|
||||||
|
stream.close();
|
||||||
|
}
|
||||||
|
} else if (mode == MODE_DNSMASQ) {
|
||||||
|
File file = new File(dnsmasqFile);
|
||||||
|
if (file.exists() && file.canRead()) {
|
||||||
|
FileInputStream stream = new FileInputStream(file);
|
||||||
|
BufferedReader dataIO = new BufferedReader(new InputStreamReader(stream));
|
||||||
|
String strLine;
|
||||||
|
String[] data;
|
||||||
|
while ((strLine = dataIO.readLine()) != null) {
|
||||||
|
//Log.d(TAG, strLine);
|
||||||
|
if (!strLine.equals("") && !strLine.startsWith("#")) {
|
||||||
|
data = strLine.split("/");
|
||||||
|
if (data.length == 3 && data[0].equals("address=")) {
|
||||||
|
rules.put(data[1], data[2]);
|
||||||
|
Log.d(TAG, "Putting " + data[0] + " " + data[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dataIO.close();
|
||||||
|
stream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
status = STATUS_LOADED;
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
|
||||||
|
status = STATUS_NOT_LOADED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
while (!shutdown) {
|
||||||
|
if (status == STATUS_PENDING_LOAD) {
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -21,7 +21,7 @@
|
|||||||
android:title="@string/action_dns_servers"
|
android:title="@string/action_dns_servers"
|
||||||
android:icon="@drawable/ic_device_hub"/>
|
android:icon="@drawable/ic_device_hub"/>
|
||||||
<item android:id="@+id/nav_hosts"
|
<item android:id="@+id/nav_hosts"
|
||||||
android:title="@string/action_hosts"
|
android:title="@string/action_rules"
|
||||||
android:checked="false"
|
android:checked="false"
|
||||||
android:icon="@drawable/ic_description"/>
|
android:icon="@drawable/ic_description"/>
|
||||||
</group>
|
</group>
|
||||||
|
@ -43,19 +43,18 @@
|
|||||||
<string name="nav_github">GitHub</string>
|
<string name="nav_github">GitHub</string>
|
||||||
<string name="settings_advanced">高级系统设置</string>
|
<string name="settings_advanced">高级系统设置</string>
|
||||||
<string name="settings_advanced_on">开启</string>
|
<string name="settings_advanced_on">开启</string>
|
||||||
<string name="settings_local_hosts_resolution">本地 hosts 解析</string>
|
<string name="settings_local_rules_resolution">本地规则解析</string>
|
||||||
<string name="notice_need_restart">重新启用 Daedalus 以应用设置。</string>
|
<string name="notice_need_restart">重新启用 Daedalus 以应用设置。</string>
|
||||||
<string name="notice_need_storage_perm">Daedalus 需要访问外部储存以实现本地 hosts 解析。</string>
|
<string name="notice_need_storage_perm">Daedalus 需要访问外部储存以实现本地规则解析。</string>
|
||||||
<string name="action_hosts">Hosts</string>
|
<string name="action_rules">规则</string>
|
||||||
<string name="button_text_download_hosts">下载 hosts</string>
|
<string name="button_text_download_hosts">下载 hosts</string>
|
||||||
<string name="notice_start_download">正在下载 hosts,请稍等 ……</string>
|
<string name="notice_start_download">正在下载 rules,请稍等 ……</string>
|
||||||
<string name="notice_downloaded">已下载 hosts 。</string>
|
<string name="notice_downloaded">已下载 hosts 。</string>
|
||||||
<string name="notice_now_downloading">Daedalus 当前正在下载hosts,请稍等。</string>
|
<string name="notice_now_downloading">Daedalus 当前正在下载规则,请稍等。</string>
|
||||||
<string name="hosts_not_found">找不到本地 hosts 文件。</string>
|
<string name="hosts_not_found">找不到本地 hosts 文件。</string>
|
||||||
<string name="hosts_path">本地 hosts 路径:</string>
|
<string name="hosts_path">本地 hosts 路径:</string>
|
||||||
<string name="hosts_last_modified">最后修改:</string>
|
<string name="hosts_last_modified">最后修改:</string>
|
||||||
<string name="hosts_size">大小:</string>
|
<string name="hosts_size">大小:</string>
|
||||||
<string name="settings_hosts_pan_domain_resolution">Hosts 域名泛解析</string>
|
|
||||||
<string name="action_dns_servers">服务器</string>
|
<string name="action_dns_servers">服务器</string>
|
||||||
<string name="settings_server_name">服务器名称</string>
|
<string name="settings_server_name">服务器名称</string>
|
||||||
<string name="settings_server_address">服务器地址</string>
|
<string name="settings_server_address">服务器地址</string>
|
||||||
@ -66,4 +65,5 @@
|
|||||||
<string name="settings_dns_over_tcp">DNS over TCP</string>
|
<string name="settings_dns_over_tcp">DNS over TCP</string>
|
||||||
<string name="action_removed">已移除。</string>
|
<string name="action_removed">已移除。</string>
|
||||||
<string name="action_undo">撤销</string>
|
<string name="action_undo">撤销</string>
|
||||||
|
<string name="settings_use_dnsmasq">使用 DNSMasq 替代 Hosts</string>
|
||||||
</resources>
|
</resources>
|
@ -42,20 +42,19 @@
|
|||||||
<string name="nav_github">GitHub</string>
|
<string name="nav_github">GitHub</string>
|
||||||
<string name="settings_advanced">Advanced System Settings</string>
|
<string name="settings_advanced">Advanced System Settings</string>
|
||||||
<string name="settings_advanced_on">On</string>
|
<string name="settings_advanced_on">On</string>
|
||||||
<string name="settings_local_hosts_resolution">Local hosts resolution</string>
|
<string name="settings_local_rules_resolution">Local hosts resolution</string>
|
||||||
<string name="notice_need_restart">Re-activate Daedalus to make the settings take effect.</string>
|
<string name="notice_need_restart">Re-activate Daedalus to make the settings take effect.</string>
|
||||||
<string name="notice_need_storage_perm">Daedalus requires access to external storage for local host resolution.
|
<string name="notice_need_storage_perm">Daedalus requires access to external storage for local rules resolution.
|
||||||
</string>
|
</string>
|
||||||
<string name="action_hosts">Hosts</string>
|
<string name="action_rules">Rules</string>
|
||||||
<string name="button_text_download_hosts">Download hosts</string>
|
<string name="button_text_download_hosts">Download hosts</string>
|
||||||
<string name="notice_start_download">Downloading hosts, please wait …</string>
|
<string name="notice_start_download">Downloading rules, please wait …</string>
|
||||||
<string name="notice_downloaded">Hosts has been downloaded.</string>
|
<string name="notice_downloaded">Hosts has been downloaded.</string>
|
||||||
<string name="notice_now_downloading">Daedalus is currently downloading hosts, please wait.</string>
|
<string name="notice_now_downloading">Daedalus is currently downloading rules, please wait.</string>
|
||||||
<string name="hosts_not_found">Local hosts not found.</string>
|
<string name="hosts_not_found">Local hosts not found.</string>
|
||||||
<string name="hosts_path">Local hosts path:</string>
|
<string name="hosts_path">Local hosts path:</string>
|
||||||
<string name="hosts_last_modified">Last modified:</string>
|
<string name="hosts_last_modified">Last modified:</string>
|
||||||
<string name="hosts_size">Size:</string>
|
<string name="hosts_size">Size:</string>
|
||||||
<string name="settings_hosts_pan_domain_resolution">Hosts pan domain name resolution</string>
|
|
||||||
<string name="action_dns_servers">Servers</string>
|
<string name="action_dns_servers">Servers</string>
|
||||||
<string name="settings_server_name">Server Name</string>
|
<string name="settings_server_name">Server Name</string>
|
||||||
<string name="settings_server_address">Server Address</string>
|
<string name="settings_server_address">Server Address</string>
|
||||||
@ -66,4 +65,5 @@
|
|||||||
<string name="settings_dns_over_tcp">DNS over TCP</string>
|
<string name="settings_dns_over_tcp">DNS over TCP</string>
|
||||||
<string name="action_removed">Removed.</string>
|
<string name="action_removed">Removed.</string>
|
||||||
<string name="action_undo">Undo</string>
|
<string name="action_undo">Undo</string>
|
||||||
|
<string name="settings_use_dnsmasq">Use DNSMasq instead of Hosts</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -50,13 +50,13 @@
|
|||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:enabled="false"/>
|
android:enabled="false"/>
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:key="settings_local_host_resolution"
|
android:key="settings_local_rules_resolution"
|
||||||
android:title="@string/settings_local_hosts_resolution"
|
android:title="@string/settings_local_rules_resolution"
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:enabled="false"/>
|
android:enabled="false"/>
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:key="settings_pan_resolution"
|
android:key="settings_use_dnsmasq"
|
||||||
android:title="@string/settings_hosts_pan_domain_resolution"
|
android:title="@string/settings_use_dnsmasq"
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:enabled="false"/>
|
android:enabled="false"/>
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
|
Loading…
x
Reference in New Issue
Block a user