mirror of https://github.com/M66B/NetGuard.git
parent
831786b542
commit
fff2ba4082
|
@ -22,7 +22,6 @@ package eu.faircode.netguard;
|
|||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.database.Cursor;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
|
|
@ -33,7 +33,6 @@ import android.support.v7.widget.SearchView;
|
|||
import android.support.v7.widget.SwitchCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
|
@ -301,7 +300,6 @@ public class ActivityLog extends AppCompatActivity implements SharedPreferences.
|
|||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
File pcap_file = new File(getCacheDir(), "netguard.pcap");
|
||||
|
||||
boolean log = prefs.getBoolean("log", false);
|
||||
boolean resolve = prefs.getBoolean("resolve", false);
|
||||
boolean filter = prefs.getBoolean("filter", false);
|
||||
boolean pcap_enabled = prefs.getBoolean("pcap", false);
|
||||
|
|
|
@ -19,7 +19,6 @@ package eu.faircode.netguard;
|
|||
Copyright 2015-2016 by Marcel Bokhorst (M66B)
|
||||
*/
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
|
@ -37,6 +36,7 @@ import android.support.v4.content.LocalBroadcastManager;
|
|||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
@ -573,7 +573,6 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
|
|||
return true;
|
||||
|
||||
case R.id.menu_app_system:
|
||||
boolean manage = prefs.getBoolean("manage_system", false);
|
||||
item.setChecked(!item.isChecked());
|
||||
prefs.edit().putBoolean("show_system", item.isChecked()).apply();
|
||||
return true;
|
||||
|
@ -662,7 +661,7 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences
|
|||
|
||||
Intent intent = getIntentLogcat();
|
||||
if (intent.resolveActivity(getPackageManager()) != null)
|
||||
startActivityForResult(intent, REQUEST_LOGCAT, null);
|
||||
startActivityForResult(intent, REQUEST_LOGCAT);
|
||||
|
||||
} else if (tap > 3) {
|
||||
toast.setText(Integer.toString(7 - tap));
|
||||
|
|
|
@ -147,6 +147,10 @@ public class ActivitySettings extends AppCompatActivity implements SharedPrefere
|
|||
pref_wifi_homes.setEntries(listSSID.toArray(new CharSequence[0]));
|
||||
pref_wifi_homes.setEntryValues(listSSID.toArray(new CharSequence[0]));
|
||||
|
||||
// Filtering always enabled
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
|
||||
screen.findPreference("filter").setEnabled(false);
|
||||
|
||||
// VPN parameters
|
||||
screen.findPreference("vpn4").setTitle(getString(R.string.setting_vpn4, prefs.getString("vpn4", "10.1.10.1")));
|
||||
screen.findPreference("vpn6").setTitle(getString(R.string.setting_vpn6, prefs.getString("vpn6", "fd00:1:fd00:1:fd00:1:fd00:1")));
|
||||
|
@ -427,7 +431,6 @@ public class ActivitySettings extends AppCompatActivity implements SharedPrefere
|
|||
prefs.edit().putBoolean(name, false).apply();
|
||||
((SwitchPreference) getPreferenceScreen().findPreference(name)).setChecked(false);
|
||||
startActivity(new Intent(this, ActivityPro.class));
|
||||
return;
|
||||
} else
|
||||
SinkholeService.reload(null, "changed " + name, this);
|
||||
|
||||
|
|
|
@ -25,10 +25,8 @@ import android.content.BroadcastReceiver;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.os.PowerManager;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.NotificationManagerCompat;
|
||||
|
@ -95,8 +93,7 @@ public class Receiver extends BroadcastReceiver {
|
|||
Util.sendCrashReport(ex, context);
|
||||
}
|
||||
|
||||
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
if (pm.isInteractive())
|
||||
if (Util.isInteractive(context))
|
||||
SinkholeService.reloadStats("receiver", context);
|
||||
}
|
||||
}
|
||||
|
@ -195,6 +192,7 @@ public class Receiver extends BroadcastReceiver {
|
|||
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");
|
||||
|
@ -221,9 +219,13 @@ public class Receiver extends BroadcastReceiver {
|
|||
} else {
|
||||
editor.putBoolean("whitelist_wifi", false);
|
||||
editor.putBoolean("whitelist_other", false);
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1)
|
||||
editor.putBoolean("filter", true);
|
||||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1)
|
||||
editor.putBoolean("filter", true); // Optional
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
|
||||
editor.putBoolean("filter", true); // Mandatory
|
||||
|
||||
editor.putInt("version", newVersion);
|
||||
editor.apply();
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ package eu.faircode.netguard;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.XmlResourceParser;
|
||||
|
@ -107,8 +106,6 @@ public class Rule {
|
|||
SharedPreferences roaming = context.getSharedPreferences("roaming", Context.MODE_PRIVATE);
|
||||
|
||||
// Get settings
|
||||
boolean haswifi = Util.hasWifi(context);
|
||||
boolean hastelephony = Util.hasTelephony(context);
|
||||
boolean default_wifi = prefs.getBoolean("whitelist_wifi", true);
|
||||
boolean default_other = prefs.getBoolean("whitelist_other", true);
|
||||
boolean default_screen_wifi = prefs.getBoolean("screen_wifi", true);
|
||||
|
@ -173,9 +170,6 @@ public class Rule {
|
|||
|
||||
|
||||
for (PackageInfo info : context.getPackageManager().getInstalledPackages(0)) {
|
||||
if (info.applicationInfo.uid == Process.myUid())
|
||||
continue;
|
||||
|
||||
Rule rule = new Rule(info, context);
|
||||
|
||||
if (pre_system.containsKey(info.packageName))
|
||||
|
@ -183,29 +177,35 @@ public class Rule {
|
|||
|
||||
if (all ||
|
||||
((rule.system ? show_system : show_user) &&
|
||||
(show_nointernet ? true : rule.internet) &&
|
||||
(show_disabled ? true : rule.enabled))) {
|
||||
(show_nointernet || rule.internet) &&
|
||||
(show_disabled || rule.enabled) &&
|
||||
info.applicationInfo.uid != Process.myUid())) {
|
||||
|
||||
if (info.applicationInfo.uid == Process.myUid()) {
|
||||
// Internet access is needed to resolve host names
|
||||
rule.wifi_default = false;
|
||||
rule.other_default = false;
|
||||
rule.screen_wifi_default = false;
|
||||
rule.screen_other_default = false;
|
||||
rule.roaming_default = false;
|
||||
|
||||
rule.wifi_blocked = false;
|
||||
rule.other_blocked = false;
|
||||
rule.screen_wifi = false;
|
||||
rule.screen_other = false;
|
||||
rule.roaming = false;
|
||||
} else {
|
||||
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 ? false : wifi.getBoolean(info.packageName, rule.wifi_default));
|
||||
rule.other_blocked = (rule.system && !manage_system ? false : other.getBoolean(info.packageName, rule.other_default));
|
||||
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);
|
||||
rule.screen_other = screen_other.getBoolean(info.packageName, rule.screen_other_default);
|
||||
rule.roaming = roaming.getBoolean(info.packageName, rule.roaming_default);
|
||||
|
||||
if (!haswifi) {
|
||||
rule.wifi_blocked = true;
|
||||
rule.screen_wifi = false;
|
||||
}
|
||||
|
||||
if (!hastelephony) {
|
||||
rule.other_blocked = true;
|
||||
rule.screen_other = false;
|
||||
}
|
||||
|
||||
if (pre_related.containsKey(info.packageName))
|
||||
|
@ -217,7 +217,7 @@ public class Rule {
|
|||
rule.upspeed = (float) up * 24 * 3600 * 1000 / 1024f / 1024f / now;
|
||||
rule.downspeed = (float) down * 24 * 3600 * 1000 / 1024f / 1024f / now;
|
||||
|
||||
rule.updateChanged(default_wifi, default_other, default_roaming, haswifi, hastelephony);
|
||||
rule.updateChanged(default_wifi, default_other, default_roaming);
|
||||
|
||||
listRules.add(rule);
|
||||
}
|
||||
|
@ -252,12 +252,12 @@ public class Rule {
|
|||
return listRules;
|
||||
}
|
||||
|
||||
private void updateChanged(boolean default_wifi, boolean default_other, boolean default_roaming, boolean wifi, boolean telephony) {
|
||||
changed = (wifi && wifi_blocked != default_wifi ||
|
||||
(telephony && other_blocked != default_other) ||
|
||||
(wifi && wifi_blocked && screen_wifi != screen_wifi_default) ||
|
||||
(telephony && other_blocked && screen_other != screen_other_default) ||
|
||||
(telephony && (!other_blocked || screen_other) && roaming != default_roaming));
|
||||
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));
|
||||
}
|
||||
|
||||
public void updateChanged(Context context) {
|
||||
|
@ -265,8 +265,6 @@ public class Rule {
|
|||
boolean default_wifi = prefs.getBoolean("whitelist_wifi", true);
|
||||
boolean default_other = prefs.getBoolean("whitelist_other", true);
|
||||
boolean default_roaming = prefs.getBoolean("whitelist_roaming", true);
|
||||
boolean wifi = Util.hasWifi(context);
|
||||
boolean telephony = Util.hasTelephony(context);
|
||||
updateChanged(default_wifi, default_other, default_roaming, wifi, telephony);
|
||||
updateChanged(default_wifi, default_other, default_roaming);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ import android.support.v4.app.NotificationManagerCompat;
|
|||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.TouchDelegate;
|
||||
|
|
|
@ -103,6 +103,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
private Object subscriptionsChangedListener = null;
|
||||
private ParcelFileDescriptor vpn = null;
|
||||
|
||||
private static final Map<String, ResourceRecord> mapRR = new HashMap<>();
|
||||
private Map<String, Boolean> mapHostsBlocked = new HashMap<>();
|
||||
private Map<Integer, Boolean> mapUidAllowed = new HashMap<>();
|
||||
private Map<Integer, Map<Integer, Map<InetAddress, Boolean>>> mapUidIPFilters = new HashMap<>();
|
||||
|
@ -748,6 +749,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private ParcelFileDescriptor startVPN(List<Rule> listAllowed) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
boolean tethering = prefs.getBoolean("tethering", false);
|
||||
|
@ -800,13 +802,6 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
||||
}
|
||||
|
||||
// Allow internet to resolve host names
|
||||
try {
|
||||
builder.addDisallowedApplication(getPackageName());
|
||||
} catch (PackageManager.NameNotFoundException ex) {
|
||||
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
||||
}
|
||||
|
||||
// Build configure intent
|
||||
Intent configure = new Intent(this, ActivityMain.class);
|
||||
PendingIntent pi = PendingIntent.getActivity(this, 0, configure, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
@ -966,7 +961,8 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
if (roaming && national)
|
||||
roaming = Util.isInternational(this);
|
||||
|
||||
Log.i(TAG, "Starting connected=" + last_connected +
|
||||
Log.i(TAG, "Get allowed" +
|
||||
" connected=" + last_connected +
|
||||
" wifi=" + wifi +
|
||||
" home=" + TextUtils.join(",", ssidHomes) +
|
||||
" network=" + ssidNetwork +
|
||||
|
@ -978,6 +974,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
" tethering=" + tethering +
|
||||
" filter=" + filter);
|
||||
|
||||
if (last_connected)
|
||||
for (Rule rule : listRule) {
|
||||
boolean blocked = (metered ? rule.other_blocked : rule.wifi_blocked);
|
||||
boolean screen = (metered ? rule.screen_other : rule.screen_wifi);
|
||||
|
@ -1010,15 +1007,12 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
|
||||
// Called from native code
|
||||
private void logPacket(Packet packet) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
Message msg = mServiceHandler.obtainMessage();
|
||||
msg.obj = packet;
|
||||
msg.what = MSG_PACKET;
|
||||
mServiceHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private static HashMap<String, ResourceRecord> mapRR = new HashMap<>();
|
||||
|
||||
// Called from native code
|
||||
private void dnsResolved(ResourceRecord rr) {
|
||||
synchronized (mapRR) {
|
||||
|
@ -1052,8 +1046,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
|
||||
// Called from native code
|
||||
private boolean isDomainBlocked(String name) {
|
||||
boolean blocked = (mapHostsBlocked.containsKey(name) && mapHostsBlocked.get(name));
|
||||
return blocked;
|
||||
return (mapHostsBlocked.containsKey(name) && mapHostsBlocked.get(name));
|
||||
}
|
||||
|
||||
// Called from native code
|
||||
|
@ -1122,8 +1115,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
}
|
||||
|
||||
// Start/stop stats
|
||||
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||
mServiceHandler.sendEmptyMessage(pm.isInteractive() ? MSG_STATS_START : MSG_STATS_STOP);
|
||||
mServiceHandler.sendEmptyMessage(Util.isInteractive(SinkholeService.this) ? MSG_STATS_START : MSG_STATS_STOP);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -40,12 +40,12 @@ import android.os.Bundle;
|
|||
import android.os.PowerManager;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.provider.Settings;
|
||||
import android.support.v4.net.ConnectivityManagerCompat;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
|
@ -56,13 +56,11 @@ import java.io.StringWriter;
|
|||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -124,7 +122,7 @@ public class Util {
|
|||
|
||||
public static boolean isMeteredNetwork(Context context) {
|
||||
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
return (cm != null && cm.isActiveNetworkMetered());
|
||||
return (cm != null && ConnectivityManagerCompat.isActiveNetworkMetered(cm));
|
||||
}
|
||||
|
||||
public static String getWifiSSID(Context context) {
|
||||
|
@ -179,7 +177,7 @@ public class Util {
|
|||
}
|
||||
}
|
||||
|
||||
return (tm == null || tm.getSimCountryIso() == null ? true : !tm.getSimCountryIso().equals(tm.getNetworkCountryIso()));
|
||||
return (tm == null || tm.getSimCountryIso() == null || !tm.getSimCountryIso().equals(tm.getNetworkCountryIso()));
|
||||
}
|
||||
|
||||
public static String getNetworkGeneration(int networkType) {
|
||||
|
@ -287,6 +285,9 @@ public class Util {
|
|||
|
||||
public static boolean isInteractive(Context context) {
|
||||
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT_WATCH)
|
||||
return (pm != null && pm.isScreenOn());
|
||||
else
|
||||
return (pm != null && pm.isInteractive());
|
||||
}
|
||||
|
||||
|
@ -376,8 +377,8 @@ public class Util {
|
|||
MessageDigest digest = MessageDigest.getInstance("SHA1");
|
||||
byte[] bytes = digest.digest(cert);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < bytes.length; ++i)
|
||||
sb.append(Integer.toString(bytes[i] & 0xff, 16).toLowerCase());
|
||||
for (byte b : bytes)
|
||||
sb.append(Integer.toString(b & 0xff, 16).toLowerCase());
|
||||
String calculated = sb.toString();
|
||||
String expected = context.getString(R.string.fingerprint);
|
||||
return calculated.equals(expected);
|
||||
|
@ -387,8 +388,6 @@ public class Util {
|
|||
}
|
||||
}
|
||||
|
||||
private static Map<String, String> mapIPHost = new HashMap<String, String>();
|
||||
|
||||
public static void setTheme(Context context) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean dark = prefs.getBoolean("dark_theme", false);
|
||||
|
@ -512,9 +511,18 @@ public class Util {
|
|||
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
|
||||
NetworkInfo ani = cm.getActiveNetworkInfo();
|
||||
List<NetworkInfo> listNI = new ArrayList<>();
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
|
||||
listNI.addAll(Arrays.asList(cm.getAllNetworkInfo()));
|
||||
else
|
||||
for (Network network : cm.getAllNetworks()) {
|
||||
NetworkInfo ni = cm.getNetworkInfo(network);
|
||||
if (ni != null)
|
||||
listNI.add(cm.getNetworkInfo(network));
|
||||
}
|
||||
|
||||
for (NetworkInfo ni : listNI) {
|
||||
sb.append(ni.getTypeName())
|
||||
.append('/')
|
||||
.append(ni.getSubtypeName())
|
||||
|
@ -609,9 +617,7 @@ public class Util {
|
|||
.append(' ')
|
||||
.append(String.format("%B", getDataEnabled.invoke(tm, si.getSubscriptionId())))
|
||||
.append("\r\n");
|
||||
} catch (IllegalAccessException ex) {
|
||||
Log.w(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
||||
} catch (InvocationTargetException ex) {
|
||||
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
Log.w(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
||||
}
|
||||
}
|
||||
|
@ -720,7 +726,6 @@ public class Util {
|
|||
}
|
||||
|
||||
private static StringBuilder getLogcat() {
|
||||
String pid = Integer.toString(android.os.Process.myPid());
|
||||
StringBuilder builder = new StringBuilder();
|
||||
Process process = null;
|
||||
BufferedReader br = null;
|
||||
|
|
Loading…
Reference in New Issue