- 浏览: 284991 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
wakikyou320:
楼主能否共享jar包呢?都木找到额
Android应用开发中如何使用隐藏API -
ihopethatwell:
注释/etc/apt/sources.list中 #deb h ...
ubuntu安装android 2.3 -
qq123zhz:
有wma和mp3的吗?
JAVA 读取 ASF(WMA 和 WMV)文件信息 -
zhmeup:
doveqian 写道
朋友:将android 2.3的set ...
debug调试setting源码 -
doveqian:
帮忙下:doveqian@163.com
debug调试setting源码
/** * Broadcast receiver that set iptable rules on system startup. * This is necessary because the iptables rules are not persistent. * * Copyright (C) 2009-2010 Rodrigo Zechin Rosauro * * 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. * * @author Rodrigo Zechin Rosauro * @version 1.0 */ package com.googlecode.droidwall; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Handler; import android.os.Message; import android.widget.Toast; /** * Broadcast receiver that set iptables rules on system startup. This is * necessary because the rules are not persistent. */ public class BootAndShutdownBroadcast extends BroadcastReceiver { @Override public void onReceive(final Context context, final Intent intent) { if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { if (Api.isEnabled(context)) { final Handler toaster = new Handler() { public void handleMessage(Message msg) { if (msg.arg1 != 0) Toast.makeText(context, msg.arg1, Toast.LENGTH_SHORT).show(); } }; // Start a new thread to enable the firewall - this prevents ANR new Thread() { @Override public void run() { if (!Api.applySavedIptablesRules(context, false)) { // Error enabling firewall on boot final Message msg = new Message(); msg.arg1 = R.string.toast_error_enabling; toaster.sendMessage(msg); Api.setEnabled(context, false); } } }.start(); } } else if (Intent.ACTION_SHUTDOWN.equals(intent.getAction())) { new Thread() { @Override public void run() { Api.storageTraffic(context); } }.start(); } } }
api.java
/** * Contains shared programming interfaces. * All iptables "communication" is handled by this class. * * Copyright (C) 2009-2010 Rodrigo Zechin Rosauro * * 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. * * @author Rodrigo Zechin Rosauro * @version 1.0 */ package com.googlecode.droidwall; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.StringReader; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.StringTokenizer; import android.Manifest; import android.app.AlertDialog; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.net.TrafficStats; import android.text.format.Time; import android.util.Log; import android.widget.Toast; /** * Contains shared programming interfaces. All iptables "communication" is * handled by this class. */ public final class Api { /** application version string */ public static final String VERSION = "1.5.1c"; /** special application UID used to indicate "any application" */ public static final int SPECIAL_UID_ANY = -10; /** special application UID used to indicate the Linux Kernel */ public static final int SPECIAL_UID_KERNEL = -11; /** root script filename */ private static final String SCRIPT_FILE = "droidwall.sh"; // Preferences public static final String PREFS_NAME = "DroidWallPrefs"; public static final String PREF_3G_UIDS = "AllowedUids3G"; public static final String PREF_WIFI_UIDS = "AllowedUidsWifi"; public static final String PREF_PASSWORD = "Password"; public static final String PREF_MODE = "BlockMode"; public static final String PREF_ENABLED = "Enabled"; public static final String PREF_LOGENABLED = "LogEnabled"; // Modes public static final String MODE_WHITELIST = "whitelist"; public static final String MODE_BLACKLIST = "blacklist"; // Messages public static final String STATUS_CHANGED_MSG = "com.googlecode.droidwall.intent.action.STATUS_CHANGED"; public static final String TOGGLE_REQUEST_MSG = "com.googlecode.droidwall.intent.action.TOGGLE_REQUEST"; public static final String STATUS_EXTRA = "com.googlecode.droidwall.intent.extra.STATUS"; // Cached applications public static DroidApp applications[] = null; // Do we have root access? private static boolean hasroot = false; /** * Display a simple alert box * * @param ctx * context * @param msg * message */ public static void alert(Context ctx, CharSequence msg) { if (ctx != null) { new AlertDialog.Builder(ctx) .setNeutralButton(android.R.string.ok, null) .setMessage(msg).show(); } } /** * Create the generic shell script header used to determine which iptables * binary to use. * * @param ctx * context * @return script header */ private static String scriptHeader(Context ctx) { final String dir = ctx.getDir("bin", 0).getAbsolutePath(); final String myiptables = dir + "/iptables_armv5"; return "" + "IPTABLES=iptables\n" + "BUSYBOX=busybox\n" + "GREP=grep\n" + "ECHO=echo\n" + "# Try to find busybox\n" + "if " + dir + "/busybox_g1 --help >/dev/null 2>/dev/null ; then\n" + " BUSYBOX=" + dir + "/busybox_g1\n" + " GREP=\"$BUSYBOX grep\"\n" + " ECHO=\"$BUSYBOX echo\"\n" + "elif busybox --help >/dev/null 2>/dev/null ; then\n" + " BUSYBOX=busybox\n" + "elif /system/xbin/busybox --help >/dev/null 2>/dev/null ; then\n" + " BUSYBOX=/system/xbin/busybox\n" + "elif /system/bin/busybox --help >/dev/null 2>/dev/null ; then\n" + " BUSYBOX=/system/bin/busybox\n" + "fi\n" + "# Try to find grep\n" + "if ! $ECHO 1 | $GREP -q 1 >/dev/null 2>/dev/null ; then\n" + " if $ECHO 1 | $BUSYBOX grep -q 1 >/dev/null 2>/dev/null ; then\n" + " GREP=\"$BUSYBOX grep\"\n" + " fi\n" + " # Grep is absolutely required\n" + " if ! $ECHO 1 | $GREP -q 1 >/dev/null 2>/dev/null ; then\n" + " $ECHO The grep command is required. DroidWall will not work.\n" + " exit 1\n" + " fi\n" + "fi\n" + "# Try to find iptables\n" + "if " + myiptables + " --version >/dev/null 2>/dev/null ; then\n" + " IPTABLES=" + myiptables + "\n" + "fi\n" + ""; } /** * Copies a raw resource file, given its ID to the given location * * @param ctx * context * @param resid * resource id * @param file * destination file * @param mode * file permissions (E.g.: "755") * @throws IOException * on error * @throws InterruptedException * when interrupted */ private static void copyRawFile(Context ctx, int resid, File file, String mode) throws IOException, InterruptedException { final String abspath = file.getAbsolutePath(); // Write the iptables binary final FileOutputStream out = new FileOutputStream(file); final InputStream is = ctx.getResources().openRawResource(resid); byte buf[] = new byte[1024]; int len; while ((len = is.read(buf)) > 0) { out.write(buf, 0, len); } out.close(); is.close(); // Change the permissions Runtime.getRuntime().exec("chmod " + mode + " " + abspath).waitFor(); } /** * Purge and re-add all rules (internal implementation). * * @param ctx * application context (mandatory) * @param uidsWifi * list of selected UIDs for WIFI to allow or disallow (depending * on the working mode) * @param uids3g * list of selected UIDs for 2G/3G to allow or disallow * (depending on the working mode) * @param showErrors * indicates if errors should be alerted */ private static boolean applyIptablesRulesImpl(Context ctx, List<Integer> uidsWifi, List<Integer> uids3g, boolean showErrors) { if (ctx == null) { return false; } assertBinaries(ctx, showErrors); final String ITFS_WIFI[] = { "tiwlan+", "wlan+", "eth+" }; final String ITFS_3G[] = { "rmnet+", "pdp+", "ppp+", "uwbr+", "wimax+", "vsnet+" }; final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0); final boolean whitelist = prefs.getString(PREF_MODE, MODE_WHITELIST) .equals(MODE_WHITELIST); final boolean blacklist = !whitelist; final boolean logenabled = ctx.getSharedPreferences(PREFS_NAME, 0) .getBoolean(PREF_LOGENABLED, false); final StringBuilder script = new StringBuilder(); try { int code; script.append(scriptHeader(ctx)); script.append("" + "$IPTABLES --version || exit 1\n" + "# Create the droidwall chains if necessary\n" + "$IPTABLES -L droidwall >/dev/null 2>/dev/null || $IPTABLES --new droidwall || exit 2\n" + "$IPTABLES -L droidwall-3g >/dev/null 2>/dev/null || $IPTABLES --new droidwall-3g || exit 3\n" + "$IPTABLES -L droidwall-wifi >/dev/null 2>/dev/null || $IPTABLES --new droidwall-wifi || exit 4\n" + "$IPTABLES -L droidwall-reject >/dev/null 2>/dev/null || $IPTABLES --new droidwall-reject || exit 5\n" + "# Add droidwall chain to OUTPUT chain if necessary\n" + "$IPTABLES -L OUTPUT | $GREP -q droidwall || $IPTABLES -A OUTPUT -j droidwall || exit 6\n" + "# Flush existing rules\n" + "$IPTABLES -F droidwall || exit 7\n" + "$IPTABLES -F droidwall-3g || exit 8\n" + "$IPTABLES -F droidwall-wifi || exit 9\n" + "$IPTABLES -F droidwall-reject || exit 10\n" + ""); // Check if logging is enabled if (logenabled) { script.append("" + "# Create the log and reject rules (ignore errors on the LOG target just in case it is not available)\n" + "$IPTABLES -A droidwall-reject -j LOG --log-prefix \"[DROIDWALL] \" --log-uid\n" + "$IPTABLES -A droidwall-reject -j REJECT || exit 11\n" + ""); } else { script.append("" + "# Create the reject rule (log disabled)\n" + "$IPTABLES -A droidwall-reject -j REJECT || exit 11\n" + ""); } if (whitelist && logenabled) { script.append("# Allow DNS lookups on white-list for a better logging (ignore errors)\n"); script.append("$IPTABLES -A droidwall -p udp --dport 53 -j RETURN\n"); } script.append("# Main rules (per interface)\n"); for (final String itf : ITFS_3G) { script.append("$IPTABLES -A droidwall -o ").append(itf) .append(" -j droidwall-3g || exit\n"); } for (final String itf : ITFS_WIFI) { script.append("$IPTABLES -A droidwall -o ").append(itf) .append(" -j droidwall-wifi || exit\n"); } script.append("# Filtering rules\n"); final String targetRule = (whitelist ? "RETURN" : "droidwall-reject"); final boolean any_3g = uids3g.indexOf(SPECIAL_UID_ANY) >= 0; final boolean any_wifi = uidsWifi.indexOf(SPECIAL_UID_ANY) >= 0; if (whitelist && !any_wifi) { // When "white listing" wifi, we need to ensure that the dhcp // and wifi users are allowed int uid = android.os.Process.getUidForName("dhcp"); if (uid != -1) { script.append("# dhcp user\n"); script.append( "$IPTABLES -A droidwall-wifi -m owner --uid-owner ") .append(uid).append(" -j RETURN || exit\n"); } uid = android.os.Process.getUidForName("wifi"); if (uid != -1) { script.append("# wifi user\n"); script.append( "$IPTABLES -A droidwall-wifi -m owner --uid-owner ") .append(uid).append(" -j RETURN || exit\n"); } } if (any_3g) { if (blacklist) { /* block any application on this interface */ script.append("$IPTABLES -A droidwall-3g -j ") .append(targetRule).append(" || exit\n"); } } else { /* release/block individual applications on this interface */ for (final Integer uid : uids3g) { if (uid >= 0) script.append( "$IPTABLES -A droidwall-3g -m owner --uid-owner ") .append(uid).append(" -j ").append(targetRule) .append(" || exit\n"); } } if (any_wifi) { if (blacklist) { /* block any application on this interface */ script.append("$IPTABLES -A droidwall-wifi -j ") .append(targetRule).append(" || exit\n"); } } else { /* release/block individual applications on this interface */ for (final Integer uid : uidsWifi) { if (uid >= 0) script.append( "$IPTABLES -A droidwall-wifi -m owner --uid-owner ") .append(uid).append(" -j ").append(targetRule) .append(" || exit\n"); } } if (whitelist) { if (!any_3g) { if (uids3g.indexOf(SPECIAL_UID_KERNEL) >= 0) { script.append("# hack to allow kernel packets on white-list\n"); script.append("$IPTABLES -A droidwall-3g -m owner --uid-owner 0:999999999 -j droidwall-reject || exit\n"); } else { script.append("$IPTABLES -A droidwall-3g -j droidwall-reject || exit\n"); } } if (!any_wifi) { if (uidsWifi.indexOf(SPECIAL_UID_KERNEL) >= 0) { script.append("# hack to allow kernel packets on white-list\n"); script.append("$IPTABLES -A droidwall-wifi -m owner --uid-owner 0:999999999 -j droidwall-reject || exit\n"); } else { script.append("$IPTABLES -A droidwall-wifi -j droidwall-reject || exit\n"); } } } else { if (uids3g.indexOf(SPECIAL_UID_KERNEL) >= 0) { script.append("# hack to BLOCK kernel packets on black-list\n"); script.append("$IPTABLES -A droidwall-3g -m owner --uid-owner 0:999999999 -j RETURN || exit\n"); script.append("$IPTABLES -A droidwall-3g -j droidwall-reject || exit\n"); } if (uidsWifi.indexOf(SPECIAL_UID_KERNEL) >= 0) { script.append("# hack to BLOCK kernel packets on black-list\n"); script.append("$IPTABLES -A droidwall-wifi -m owner --uid-owner 0:999999999 -j RETURN || exit\n"); script.append("$IPTABLES -A droidwall-wifi -j droidwall-reject || exit\n"); } } final StringBuilder res = new StringBuilder(); code = runScriptAsRoot(ctx, script.toString(), res); if (showErrors && code != 0) { String msg = res.toString(); Log.e("DroidWall", msg); // Remove unnecessary help message from output if (msg.indexOf("\nTry `iptables -h' or 'iptables --help' for more information.") != -1) { msg = msg .replace( "\nTry `iptables -h' or 'iptables --help' for more information.", ""); } alert(ctx, "Error applying iptables rules. Exit code: " + code + "\n\n" + msg.trim()); } else { return true; } } catch (Exception e) { if (showErrors) alert(ctx, "error refreshing iptables: " + e); } return false; } /** * Purge and re-add all saved rules (not in-memory ones). This is much * faster than just calling "applyIptablesRules", since it don't need to * read installed applications. * * @param ctx * application context (mandatory) * @param showErrors * indicates if errors should be alerted */ public static boolean applySavedIptablesRules(Context ctx, boolean showErrors) { if (ctx == null) { return false; } final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0); final String savedUids_wifi = prefs.getString(PREF_WIFI_UIDS, ""); final String savedUids_3g = prefs.getString(PREF_3G_UIDS, ""); final List<Integer> uids_wifi = new LinkedList<Integer>(); if (savedUids_wifi.length() > 0) { // Check which applications are allowed on wifi final StringTokenizer tok = new StringTokenizer(savedUids_wifi, "|"); while (tok.hasMoreTokens()) { final String uid = tok.nextToken(); if (!uid.equals("")) { try { uids_wifi.add(Integer.parseInt(uid)); } catch (Exception ex) { } } } } final List<Integer> uids_3g = new LinkedList<Integer>(); if (savedUids_3g.length() > 0) { // Check which applications are allowed on 2G/3G final StringTokenizer tok = new StringTokenizer(savedUids_3g, "|"); while (tok.hasMoreTokens()) { final String uid = tok.nextToken(); if (!uid.equals("")) { try { uids_3g.add(Integer.parseInt(uid)); } catch (Exception ex) { } } } } return applyIptablesRulesImpl(ctx, uids_wifi, uids_3g, showErrors); } /** * Purge and re-add all rules. * * @param ctx * application context (mandatory) * @param showErrors * indicates if errors should be alerted */ public static boolean applyIptablesRules(Context ctx, boolean showErrors) { if (ctx == null) { return false; } saveRules(ctx); return applySavedIptablesRules(ctx, showErrors); } /** * Save current rules using the preferences storage. * * @param ctx * application context (mandatory) */ public static void saveRules(Context ctx) { final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0); final DroidApp[] apps = getApps(ctx); // Builds a pipe-separated list of names final StringBuilder newuids_wifi = new StringBuilder(); final StringBuilder newuids_3g = new StringBuilder(); for (int i = 0; i < apps.length; i++) { if (apps[i].selected_wifi) { if (newuids_wifi.length() != 0) newuids_wifi.append('|'); newuids_wifi.append(apps[i].uid); } if (apps[i].selected_3g) { if (newuids_3g.length() != 0) newuids_3g.append('|'); newuids_3g.append(apps[i].uid); } } // save the new list of UIDs final Editor edit = prefs.edit(); edit.putString(PREF_WIFI_UIDS, newuids_wifi.toString()); edit.putString(PREF_3G_UIDS, newuids_3g.toString()); edit.commit(); } /** * Purge all iptables rules. * * @param ctx * mandatory context * @param showErrors * indicates if errors should be alerted * @return true if the rules were purged */ public static boolean purgeIptables(Context ctx, boolean showErrors) { StringBuilder res = new StringBuilder(); try { assertBinaries(ctx, showErrors); int code = runScriptAsRoot(ctx, scriptHeader(ctx) + "$IPTABLES -F droidwall\n" + "$IPTABLES -F droidwall-reject\n" + "$IPTABLES -F droidwall-3g\n" + "$IPTABLES -F droidwall-wifi\n", res); if (code == -1) { if (showErrors) alert(ctx, "error purging iptables. exit code: " + code + "\n" + res); return false; } return true; } catch (Exception e) { if (showErrors) alert(ctx, "error purging iptables: " + e); return false; } } /** * Display iptables rules output * * @param ctx * application context */ public static void showIptablesRules(Context ctx) { try { final StringBuilder res = new StringBuilder(); runScriptAsRoot(ctx, scriptHeader(ctx) + "$ECHO $IPTABLES\n" + "$IPTABLES -L -v\n", res); alert(ctx, res); } catch (Exception e) { alert(ctx, "error: " + e); } } /** * Display logs * * @param ctx * application context * @return true if the clogs were cleared */ public static boolean clearLog(Context ctx) { try { final StringBuilder res = new StringBuilder(); int code = runScriptAsRoot(ctx, "dmesg -c >/dev/null || exit\n", res); if (code != 0) { alert(ctx, res); return false; } return true; } catch (Exception e) { alert(ctx, "error: " + e); } return false; } /** * Display logs * * @param ctx * application context */ public static void showLog(Context ctx) { try { StringBuilder res = new StringBuilder(); int code = runScriptAsRoot(ctx, scriptHeader(ctx) + "dmesg | $GREP DROIDWALL\n", res); if (code != 0) { if (res.length() == 0) { res.append("Log is empty"); } alert(ctx, res); return; } final BufferedReader r = new BufferedReader(new StringReader( res.toString())); final Integer unknownUID = -99; res = new StringBuilder(); String line; int start, end; Integer appid; final HashMap<Integer, LogInfo> map = new HashMap<Integer, LogInfo>(); LogInfo loginfo = null; while ((line = r.readLine()) != null) { if (line.indexOf("[DROIDWALL]") == -1) continue; appid = unknownUID; if (((start = line.indexOf("UID=")) != -1) && ((end = line.indexOf(" ", start)) != -1)) { appid = Integer.parseInt(line.substring(start + 4, end)); } loginfo = map.get(appid); if (loginfo == null) { loginfo = new LogInfo(); map.put(appid, loginfo); } loginfo.totalBlocked += 1; if (((start = line.indexOf("DST=")) != -1) && ((end = line.indexOf(" ", start)) != -1)) { String dst = line.substring(start + 4, end); if (loginfo.dstBlocked.containsKey(dst)) { loginfo.dstBlocked.put(dst, loginfo.dstBlocked.get(dst) + 1); } else { loginfo.dstBlocked.put(dst, 1); } } } final DroidApp[] apps = getApps(ctx); for (Integer id : map.keySet()) { res.append("App ID "); if (id != unknownUID) { res.append(id); for (DroidApp app : apps) { if (app.uid == id) { res.append(" (").append(app.names[0]); if (app.names.length > 1) { res.append(", ...)"); } else { res.append(")"); } break; } } } else { res.append("(kernel)"); } loginfo = map.get(id); res.append(" - Blocked ").append(loginfo.totalBlocked) .append(" packets"); if (loginfo.dstBlocked.size() > 0) { res.append(" ("); boolean first = true; for (String dst : loginfo.dstBlocked.keySet()) { if (!first) { res.append(", "); } res.append(loginfo.dstBlocked.get(dst)) .append(" packets for ").append(dst); first = false; } res.append(")"); } res.append("\n\n"); } if (res.length() == 0) { res.append("Log is empty"); } alert(ctx, res); } catch (Exception e) { alert(ctx, "error: " + e); } } /** * @param ctx * application context (mandatory) * @return a list of applications */ public static DroidApp[] getApps(Context ctx) { if (applications != null) { // return cached instance return applications; } final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0); // allowed application names separated by pipe '|' (persisted) final String savedUids_wifi = prefs.getString(PREF_WIFI_UIDS, ""); final String savedUids_3g = prefs.getString(PREF_3G_UIDS, ""); int selected_wifi[] = new int[0]; int selected_3g[] = new int[0]; if (savedUids_wifi.length() > 0) { // Check which applications are allowed final StringTokenizer tok = new StringTokenizer(savedUids_wifi, "|"); selected_wifi = new int[tok.countTokens()]; for (int i = 0; i < selected_wifi.length; i++) { final String uid = tok.nextToken(); if (!uid.equals("")) { try { selected_wifi[i] = Integer.parseInt(uid); } catch (Exception ex) { selected_wifi[i] = -1; } } } // Sort the array to allow using "Arrays.binarySearch" later Arrays.sort(selected_wifi); } if (savedUids_3g.length() > 0) { // Check which applications are allowed final StringTokenizer tok = new StringTokenizer(savedUids_3g, "|"); selected_3g = new int[tok.countTokens()]; for (int i = 0; i < selected_3g.length; i++) { final String uid = tok.nextToken(); if (!uid.equals("")) { try { selected_3g[i] = Integer.parseInt(uid); } catch (Exception ex) { selected_3g[i] = -1; } } } // Sort the array to allow using "Arrays.binarySearch" later Arrays.sort(selected_3g); } try { final PackageManager pkgmanager = ctx.getPackageManager(); final List<ApplicationInfo> installed = pkgmanager .getInstalledApplications(0); final HashMap<Integer, DroidApp> map = new HashMap<Integer, DroidApp>(); final Editor edit = prefs.edit(); boolean changed = false; String name = null; String cachekey = null; DroidApp app = null; for (final ApplicationInfo apinfo : installed) { app = map.get(apinfo.uid); // filter applications which are not allowed to access the // Internet if (app == null && PackageManager.PERMISSION_GRANTED != pkgmanager .checkPermission(Manifest.permission.INTERNET, apinfo.packageName)) { continue; } // try to get the application label from our cache - // getApplicationLabel() is horribly slow!!!! cachekey = "cache.label." + apinfo.packageName; name = prefs.getString(cachekey, ""); if (name.length() == 0) { // get label and put on cache name = pkgmanager.getApplicationLabel(apinfo).toString(); edit.putString(cachekey, name); changed = true; } if (app == null) { app = new DroidApp(); app.uid = apinfo.uid; app.names = new String[] { name }; map.put(apinfo.uid, app); } else { final String newnames[] = new String[app.names.length + 1]; System.arraycopy(app.names, 0, newnames, 0, app.names.length); newnames[app.names.length] = name; app.names = newnames; } // check if this application is selected if (!app.selected_wifi && Arrays.binarySearch(selected_wifi, app.uid) >= 0) { app.selected_wifi = true; } if (!app.selected_3g && Arrays.binarySearch(selected_3g, app.uid) >= 0) { app.selected_3g = true; } } if (changed) { edit.commit(); } /* add special applications to the list */ final DroidApp special[] = { new DroidApp( SPECIAL_UID_ANY, "(Any application) - Same as selecting all applications", false, false), new DroidApp(SPECIAL_UID_KERNEL, "(Kernel) - Linux kernel", false, false), new DroidApp(android.os.Process.getUidForName("root"), "(root) - Applications running as root", false, false), new DroidApp(android.os.Process.getUidForName("media"), "Media server", false, false), new DroidApp(android.os.Process.getUidForName("vpn"), "VPN networking", false, false), new DroidApp(android.os.Process.getUidForName("shell"), "Linux shell", false, false), new DroidApp(android.os.Process.getUidForName("gps"), "GPS", false, false), }; for (int i = 0; i < special.length; i++) { app = special[i]; if (app.uid != -1 && !map.containsKey(app.uid)) { // check if this application is allowed if (Arrays.binarySearch(selected_wifi, app.uid) >= 0) { app.selected_wifi = true; } if (Arrays.binarySearch(selected_3g, app.uid) >= 0) { app.selected_3g = true; } map.put(app.uid, app); } } applications = new DroidApp[map.size()]; int index = 0; for (DroidApp application : map.values()) applications[index++] = application; return applications; } catch (Exception e) { alert(ctx, "error: " + e); } return null; } /** * Check if we have root access * * @param ctx * mandatory context * @param showErrors * indicates if errors should be alerted * @return boolean true if we have root */ public static boolean hasRootAccess(Context ctx, boolean showErrors) { if (hasroot) return true; final StringBuilder res = new StringBuilder(); try { // Run an empty script just to check root access if (runScriptAsRoot(ctx, "exit 0", res) == 0) { hasroot = true; return true; } } catch (Exception e) { } if (showErrors) { alert(ctx, "Could not acquire root access.\n" + "You need a rooted phone to run DroidWall.\n\n" + "If this phone is already rooted, please make sure DroidWall has enough permissions to execute the \"su\" command.\n" + "Error message: " + res.toString()); } return false; } /** * Runs a script, wither as root or as a regular user (multiple commands * separated by "\n"). * * @param ctx * mandatory context * @param script * the script to be executed * @param res * the script output response (stdout + stderr) * @param timeout * timeout in milliseconds (-1 for none) * @return the script exit code */ public static int runScript(Context ctx, String script, StringBuilder res, long timeout, boolean asroot) { final File file = new File(ctx.getDir("bin", 0), SCRIPT_FILE); final ScriptRunner runner = new ScriptRunner(file, script, res, asroot); runner.start(); try { if (timeout > 0) { runner.join(timeout); } else { runner.join(); } if (runner.isAlive()) { // Timed-out runner.interrupt(); runner.join(150); runner.destroy(); runner.join(50); } } catch (InterruptedException ex) { } return runner.exitcode; } /** * Runs a script as root (multiple commands separated by "\n"). * * @param ctx * mandatory context * @param script * the script to be executed * @param res * the script output response (stdout + stderr) * @param timeout * timeout in milliseconds (-1 for none) * @return the script exit code */ public static int runScriptAsRoot(Context ctx, String script, StringBuilder res, long timeout) { return runScript(ctx, script, res, timeout, true); } /** * Runs a script as root (multiple commands separated by "\n") with a * default timeout of 20 seconds. * * @param ctx * mandatory context * @param script * the script to be executed * @param res * the script output response (stdout + stderr) * @param timeout * timeout in milliseconds (-1 for none) * @return the script exit code * @throws IOException * on any error executing the script, or writing it to disk */ public static int runScriptAsRoot(Context ctx, String script, StringBuilder res) throws IOException { return runScriptAsRoot(ctx, script, res, 40000); } /** * Runs a script as a regular user (multiple commands separated by "\n") * with a default timeout of 20 seconds. * * @param ctx * mandatory context * @param script * the script to be executed * @param res * the script output response (stdout + stderr) * @param timeout * timeout in milliseconds (-1 for none) * @return the script exit code * @throws IOException * on any error executing the script, or writing it to disk */ public static int runScript(Context ctx, String script, StringBuilder res) throws IOException { return runScript(ctx, script, res, 40000, false); } /** * Asserts that the binary files are installed in the cache directory. * * @param ctx * context * @param showErrors * indicates if errors should be alerted * @return false if the binary files could not be installed */ public static boolean assertBinaries(Context ctx, boolean showErrors) { boolean changed = false; try { // Check iptables_armv5 File file = new File(ctx.getDir("bin", 0), "iptables_armv5"); if (!file.exists()) { copyRawFile(ctx, R.raw.iptables_armv5, file, "755"); changed = true; } // Check busybox file = new File(ctx.getDir("bin", 0), "busybox_g1"); if (!file.exists()) { copyRawFile(ctx, R.raw.busybox_g1, file, "755"); changed = true; } if (changed) { Toast.makeText(ctx, R.string.toast_bin_installed, Toast.LENGTH_LONG).show(); } } catch (Exception e) { if (showErrors) alert(ctx, "Error installing binary files: " + e); return false; } return true; } /** * Check if the firewall is enabled * * @param ctx * mandatory context * @return boolean */ public static boolean isEnabled(Context ctx) { if (ctx == null) return false; return ctx.getSharedPreferences(PREFS_NAME, 0).getBoolean(PREF_ENABLED, false); } /** * Defines if the firewall is enabled and broadcasts the new status * * @param ctx * mandatory context * @param enabled * enabled flag */ public static void setEnabled(Context ctx, boolean enabled) { if (ctx == null) return; final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0); if (prefs.getBoolean(PREF_ENABLED, false) == enabled) { return; } final Editor edit = prefs.edit(); edit.putBoolean(PREF_ENABLED, enabled); if (!edit.commit()) { alert(ctx, "Error writing to preferences"); return; } /* notify */ final Intent message = new Intent(Api.STATUS_CHANGED_MSG); message.putExtra(Api.STATUS_EXTRA, enabled); ctx.sendBroadcast(message); } /** * Called when an application in removed (un-installed) from the system. * This will look for that application in the selected list and update the * persisted values if necessary * * @param ctx * mandatory app context * @param uid * UID of the application that has been removed */ public static void applicationRemoved(Context ctx, int uid) { final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0); final Editor editor = prefs.edit(); // allowed application names separated by pipe '|' (persisted) final String savedUids_wifi = prefs.getString(PREF_WIFI_UIDS, ""); final String savedUids_3g = prefs.getString(PREF_3G_UIDS, ""); final String uid_str = uid + ""; boolean changed = false; // look for the removed application in the "wi-fi" list if (savedUids_wifi.length() > 0) { final StringBuilder newuids = new StringBuilder(); final StringTokenizer tok = new StringTokenizer(savedUids_wifi, "|"); while (tok.hasMoreTokens()) { final String token = tok.nextToken(); if (uid_str.equals(token)) { Log.d("DroidWall", "Removing UID " + token + " from the wi-fi list (package removed)!"); changed = true; } else { if (newuids.length() > 0) newuids.append('|'); newuids.append(token); } } if (changed) { editor.putString(PREF_WIFI_UIDS, newuids.toString()); } } // look for the removed application in the "3g" list if (savedUids_3g.length() > 0) { final StringBuilder newuids = new StringBuilder(); final StringTokenizer tok = new StringTokenizer(savedUids_3g, "|"); while (tok.hasMoreTokens()) { final String token = tok.nextToken(); if (uid_str.equals(token)) { Log.d("DroidWall", "Removing UID " + token + " from the 3G list (package removed)!"); changed = true; } else { if (newuids.length() > 0) newuids.append('|'); newuids.append(token); } } if (changed) { editor.putString(PREF_3G_UIDS, newuids.toString()); } } // if anything has changed, save the new prefs... if (changed) { editor.commit(); if (isEnabled(ctx)) { // .. and also re-apply the rules if the firewall is enabled applySavedIptablesRules(ctx, false); } } } /** * Small structure to hold an application info */ public static final class DroidApp { /** linux user id */ int uid; /** application names belonging to this user id */ String names[]; /** indicates if this application is selected for wifi */ boolean selected_wifi; /** indicates if this application is selected for 3g */ boolean selected_3g; /** toString cache */ String tostr; public DroidApp() { } public DroidApp(int uid, String name, boolean selected_wifi, boolean selected_3g) { this.uid = uid; this.names = new String[] { name }; this.selected_wifi = selected_wifi; this.selected_3g = selected_3g; } /** * Screen representation of this application */ @Override public String toString() { if (tostr == null) { final StringBuilder s = new StringBuilder(); if (uid > 0) s.append(uid + ": "); for (int i = 0; i < names.length; i++) { if (i != 0) s.append(", "); s.append(names[i]); } s.append("\n"); tostr = s.toString(); } return tostr; } } /** * Small internal structure used to hold log information */ private static final class LogInfo { private int totalBlocked; // Total number of packets blocked private HashMap<String, Integer> dstBlocked; // Number of packets // blocked per // destination IP // address private LogInfo() { this.dstBlocked = new HashMap<String, Integer>(); } } /** * Internal thread used to execute scripts (as root or not). */ private static final class ScriptRunner extends Thread { private final File file; private final String script; private final StringBuilder res; private final boolean asroot; public int exitcode = -1; private Process exec; /** * Creates a new script runner. * * @param file * temporary script file * @param script * script to run * @param res * response output * @param asroot * if true, executes the script as root */ public ScriptRunner(File file, String script, StringBuilder res, boolean asroot) { this.file = file; this.script = script; this.res = res; this.asroot = asroot; } @Override public void run() { try { file.createNewFile(); final String abspath = file.getAbsolutePath(); // make sure we have execution permission on the script file Runtime.getRuntime().exec("chmod 777 " + abspath).waitFor(); // Write the script to be executed final OutputStreamWriter out = new OutputStreamWriter( new FileOutputStream(file)); if (new File("/system/bin/sh").exists()) { out.write("#!/system/bin/sh\n"); } out.write(script); if (!script.endsWith("\n")) out.write("\n"); out.write("exit\n"); out.flush(); out.close(); if (this.asroot) { // Create the "su" request to run the script exec = Runtime.getRuntime().exec("su -c " + abspath); } else { // Create the "sh" request to run the script exec = Runtime.getRuntime().exec("sh " + abspath); } InputStreamReader r = new InputStreamReader( exec.getInputStream()); final char buf[] = new char[1024]; int read = 0; // Consume the "stdout" while ((read = r.read(buf)) != -1) { if (res != null) res.append(buf, 0, read); } // Consume the "stderr" r = new InputStreamReader(exec.getErrorStream()); read = 0; while ((read = r.read(buf)) != -1) { if (res != null) res.append(buf, 0, read); } // get the process exit code if (exec != null) this.exitcode = exec.waitFor(); } catch (InterruptedException ex) { if (res != null) res.append("\nOperation timed-out"); } catch (Exception ex) { if (res != null) res.append("\n" + ex); } finally { destroy(); } } /** * Destroy this script runner */ public synchronized void destroy() { if (exec != null) exec.destroy(); exec = null; } } /** * 鏇存柊鏈堟祦閲忎娇鐢ㄦ暟鎹埌閰嶇疆鏂囦欢 * @param ctx */ public static void storageTraffic(Context ctx) { long rx = TrafficStats.getMobileRxBytes(); long tx = TrafficStats.getMobileTxBytes(); if (rx != -1 && tx != -1) { Editor editor = null; try { Time time = new Time(); time.setToNow(); String trafficKey = time.month + "TrafficBytes"; SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0); editor = prefs.edit(); if (prefs.contains(trafficKey)) { String trafficStr = prefs.getString(trafficKey, "0,0,0"); long[] longArray = StringSplit(trafficStr); longArray[0] += rx + tx; longArray[1] += tx; longArray[2] += rx; trafficStr = longArray[0] + "," + longArray[1] + "," + longArray[2]; longArray = null; editor.putString(trafficKey, trafficStr); } else { long total = rx + tx; editor.putString(trafficKey, total + "," + tx + "," + rx); if (time.month == 0) { editor.remove(11 + "TrafficBytes"); } else { int previousMonth = time.month - 1; editor.remove(previousMonth + "TrafficBytes"); } } } finally { if (editor != null) { editor.commit(); } } } } /** * 杩斿洖Dialog闇�鐨勬暟鎹� * * @param ctx * @return 濡傛灉鎵嬫満涓嶆敮鎸佽鍔熻兘锛屽垯杩斿洖null锛屽惁鍒欒繑鍥瀕ong[]鏁扮粍 * */ public static long[] showTraffic(Context ctx) { long rx = TrafficStats.getMobileRxBytes(); long tx = TrafficStats.getMobileTxBytes(); long[] longArray = null; if (rx != -1 && tx != -1) { longArray = new long[3]; Time time = new Time(); time.setToNow(); String trafficKey = time.month + "TrafficBytes"; SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0); if (prefs.contains(trafficKey)) { String trafficStr = prefs.getString(trafficKey, "0,0,0"); longArray = StringSplit(trafficStr); longArray[0] += rx + tx; longArray[1] += tx; longArray[2] += rx; } else { longArray[0] = rx + tx; longArray[1] = tx; longArray[2] = rx; } } return longArray; } private static long[] StringSplit(String str) { long[] longArray = new long[3]; int index = 0, offset = 0; int i = 0; while ((index = str.indexOf(",", index + 1)) != -1) { longArray[i] = Long.parseLong(str.substring(offset, index)); offset = index + 1; i++; } longArray[i] = Long.parseLong(str.substring(offset)); return longArray; } }
MainActivity.java
/** * Main application activity. * This is the screen displayed when you open the application * * Copyright (C) 2009-2010 Rodrigo Zechin Rosauro * * 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. * * @author Rodrigo Zechin Rosauro * @version 1.0 */ package com.googlecode.droidwall; import java.text.DecimalFormat; import java.util.Arrays; import java.util.Comparator; import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.res.Resources; import android.net.TrafficStats; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.View.OnClickListener; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import android.widget.CompoundButton.OnCheckedChangeListener; import com.googlecode.droidwall.Api.DroidApp; /** * Main application activity. This is the screen displayed when you open the * application */ public class MainActivity extends Activity implements OnCheckedChangeListener, OnClickListener { // Menu options private static final int MENU_DISABLE = 0; private static final int MENU_TOGGLELOG = 1; private static final int MENU_APPLY = 2; private static final int MENU_EXIT = 3; private static final int MENU_TRAFFIC = 4; private static final int MENU_HELP = 5; private static final int MENU_SHOWLOG = 6; private static final int MENU_SHOWRULES = 7; private static final int MENU_CLEARLOG = 8; private static final int MENU_SETPWD = 9; /** progress dialog instance */ private ListView listview; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); checkPreferences(); setContentView(R.layout.main); this.findViewById(R.id.label_mode).setOnClickListener(this); Api.assertBinaries(this, true); } @Override protected void onStart() { super.onStart(); // Force re-loading the application list Log.d("DroidWall", "onStart() - Forcing APP list reload!"); Api.applications = null; } @Override protected void onResume() { super.onResume(); if (this.listview == null) { this.listview = (ListView) this.findViewById(R.id.listview); } refreshHeader(); final String pwd = getSharedPreferences(Api.PREFS_NAME, 0).getString( Api.PREF_PASSWORD, ""); if (pwd.length() == 0) { // No password lock showOrLoadApplications(); } else { // Check the password requestPassword(pwd); } } @Override protected void onPause() { super.onPause(); this.listview.setAdapter(null); } /** * Check if the stored preferences are OK */ private void checkPreferences() { final SharedPreferences prefs = getSharedPreferences(Api.PREFS_NAME, 0); final Editor editor = prefs.edit(); boolean changed = false; if (prefs.getString(Api.PREF_MODE, "").length() == 0) { editor.putString(Api.PREF_MODE, Api.MODE_WHITELIST); changed = true; } /* delete the old preference names */ if (prefs.contains("AllowedUids")) { editor.remove("AllowedUids"); changed = true; } if (prefs.contains("Interfaces")) { editor.remove("Interfaces"); changed = true; } if (changed) editor.commit(); } /** * Refresh informative header */ private void refreshHeader() { final SharedPreferences prefs = getSharedPreferences(Api.PREFS_NAME, 0); final String mode = prefs.getString(Api.PREF_MODE, Api.MODE_WHITELIST); final TextView labelmode = (TextView) this .findViewById(R.id.label_mode); final Resources res = getResources(); int resid = (mode.equals(Api.MODE_WHITELIST) ? R.string.mode_whitelist : R.string.mode_blacklist); labelmode.setText(res.getString(R.string.mode_header, res.getString(resid))); resid = (Api.isEnabled(this) ? R.string.title_enabled : R.string.title_disabled); setTitle(res.getString(resid, Api.VERSION)); } /** * Displays a dialog box to select the operation mode (black or white list) */ private void selectMode() { final Resources res = getResources(); new AlertDialog.Builder(this) .setItems( new String[] { res.getString(R.string.mode_whitelist), res.getString(R.string.mode_blacklist) }, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { final String mode = (which == 0 ? Api.MODE_WHITELIST : Api.MODE_BLACKLIST); final Editor editor = getSharedPreferences( Api.PREFS_NAME, 0).edit(); editor.putString(Api.PREF_MODE, mode); editor.commit(); refreshHeader(); } }).setTitle("Select mode:").show(); } /** * Set a new password lock * * @param pwd * new password (empty to remove the lock) */ private void setPassword(String pwd) { final Resources res = getResources(); final Editor editor = getSharedPreferences(Api.PREFS_NAME, 0).edit(); editor.putString(Api.PREF_PASSWORD, pwd); String msg; if (editor.commit()) { if (pwd.length() > 0) { msg = res.getString(R.string.passdefined); } else { msg = res.getString(R.string.passremoved); } } else { msg = res.getString(R.string.passerror); } Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show(); } /** * Request the password lock before displayed the main screen. */ private void requestPassword(final String pwd) { new PassDialog(this, false, new android.os.Handler.Callback() { public boolean handleMessage(Message msg) { if (msg.obj == null) { MainActivity.this.finish(); android.os.Process.killProcess(android.os.Process.myPid()); return false; } if (!pwd.equals(msg.obj)) { requestPassword(pwd); return false; } // Password correct showOrLoadApplications(); return false; } }).show(); } /** * Toggle iptables log enabled/disabled */ private void toggleLogEnabled() { final SharedPreferences prefs = getSharedPreferences(Api.PREFS_NAME, 0); final boolean enabled = !prefs.getBoolean(Api.PREF_LOGENABLED, false); final Editor editor = prefs.edit(); editor.putBoolean(Api.PREF_LOGENABLED, enabled); editor.commit(); if (Api.isEnabled(this)) { Api.applySavedIptablesRules(this, true); } Toast.makeText( MainActivity.this, (enabled ? R.string.log_was_enabled : R.string.log_was_disabled), Toast.LENGTH_SHORT).show(); } /** * If the applications are cached, just show them, otherwise load and show */ private void showOrLoadApplications() { final Resources res = getResources(); if (Api.applications == null) { // The applications are not cached.. so lets display the progress // dialog final ProgressDialog progress = ProgressDialog.show(this, res.getString(R.string.working), res.getString(R.string.reading_apps), true); final Handler handler = new Handler() { public void handleMessage(Message msg) { try { progress.dismiss(); } catch (Exception ex) { } showApplications(); } }; new Thread() { public void run() { Api.getApps(MainActivity.this); handler.sendEmptyMessage(0); } }.start(); } else { // the applications are cached, just show the list showApplications(); } } /** * Show the list of applications */ private void showApplications() { final DroidApp[] apps = Api.getApps(this); // Sort applications - selected first, then alphabetically Arrays.sort(apps, new Comparator<DroidApp>() { @Override public int compare(DroidApp o1, DroidApp o2) { if ((o1.selected_wifi | o1.selected_3g) == (o2.selected_wifi | o2.selected_3g)) { return String.CASE_INSENSITIVE_ORDER.compare(o1.names[0], o2.names[0]); } if (o1.selected_wifi || o1.selected_3g) return -1; return 1; } }); final LayoutInflater inflater = getLayoutInflater(); final ListAdapter adapter = new ArrayAdapter<DroidApp>(this, R.layout.listitem, R.id.app_text, apps) { @Override public View getView(int position, View convertView, ViewGroup parent) { ListEntry entry; if (convertView == null) { // Inflate a new view convertView = inflater.inflate(R.layout.listitem, parent, false); entry = new ListEntry(); entry.box_wifi = (CheckBox) convertView .findViewById(R.id.itemcheck_wifi); entry.box_3g = (CheckBox) convertView .findViewById(R.id.itemcheck_3g); entry.app_text = (TextView) convertView .findViewById(R.id.app_text); entry.upload = (TextView) convertView .findViewById(R.id.upload); entry.download = (TextView) convertView .findViewById(R.id.download); convertView.setTag(entry); entry.box_wifi .setOnCheckedChangeListener(MainActivity.this); entry.box_3g.setOnCheckedChangeListener(MainActivity.this); } else { // Convert an existing view entry = (ListEntry) convertView.getTag(); } final DroidApp app = apps[position]; entry.app_text.setText(app.toString()); convertAndSetColor(TrafficStats.getUidTxBytes(app.uid), entry.upload); convertAndSetColor(TrafficStats.getUidRxBytes(app.uid), entry.download); final CheckBox box_wifi = entry.box_wifi; box_wifi.setTag(app); box_wifi.setChecked(app.selected_wifi); final CheckBox box_3g = entry.box_3g; box_3g.setTag(app); box_3g.setChecked(app.selected_3g); return convertView; } /* * 杞崲鎴愭槗鐪嬬殑鍗曚綅骞朵笂鑹� */ private void convertAndSetColor(long count, TextView text) { String value = null; if (count == -1) { value = "N/A "; text.setText(value); text.setTextColor(0xff919191); return; } else { value = unitHandler(count); } text.setText(value); text.setTextColor(0xffff0300); } }; this.listview.setAdapter(adapter); } @Override public boolean onCreateOptionsMenu(Menu menu) { menu.add(0, MENU_DISABLE, 0, R.string.fw_enabled).setIcon( android.R.drawable.button_onoff_indicator_on); menu.add(0, MENU_TOGGLELOG, 0, R.string.log_enabled).setIcon( android.R.drawable.button_onoff_indicator_on); menu.add(0, MENU_APPLY, 0, R.string.applyrules).setIcon( R.drawable.apply); menu.add(0, MENU_EXIT, 0, R.string.exit).setIcon( android.R.drawable.ic_menu_close_clear_cancel); menu.add(0, MENU_TRAFFIC, 0, R.string.traffic).setIcon( android.R.drawable.ic_menu_info_details); menu.add(0, MENU_HELP, 0, R.string.help).setIcon( android.R.drawable.ic_menu_help); menu.add(0, MENU_SHOWLOG, 0, R.string.show_log) .setIcon(R.drawable.show); menu.add(0, MENU_SHOWRULES, 0, R.string.showrules).setIcon( R.drawable.show); menu.add(0, MENU_CLEARLOG, 0, R.string.clear_log).setIcon( android.R.drawable.ic_menu_close_clear_cancel); menu.add(0, MENU_SETPWD, 0, R.string.setpwd).setIcon( android.R.drawable.ic_lock_lock); return true; } @Override public boolean onPrepareOptionsMenu(Menu menu) { final MenuItem item_onoff = menu.getItem(MENU_DISABLE); final MenuItem item_apply = menu.getItem(MENU_APPLY); final boolean enabled = Api.isEnabled(this); if (enabled) { item_onoff.setIcon(android.R.drawable.button_onoff_indicator_on); item_onoff.setTitle(R.string.fw_enabled); item_apply.setTitle(R.string.applyrules); } else { item_onoff.setIcon(android.R.drawable.button_onoff_indicator_off); item_onoff.setTitle(R.string.fw_disabled); item_apply.setTitle(R.string.saverules); } final MenuItem item_log = menu.getItem(MENU_TOGGLELOG); final boolean logenabled = getSharedPreferences(Api.PREFS_NAME, 0) .getBoolean(Api.PREF_LOGENABLED, false); if (logenabled) { item_log.setIcon(android.R.drawable.button_onoff_indicator_on); item_log.setTitle(R.string.log_enabled); } else { item_log.setIcon(android.R.drawable.button_onoff_indicator_off); item_log.setTitle(R.string.log_disabled); } return super.onPrepareOptionsMenu(menu); } @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { switch (item.getItemId()) { case MENU_DISABLE: disableOrEnable(); return true; case MENU_TOGGLELOG: toggleLogEnabled(); return true; case MENU_APPLY: applyOrSaveRules(); return true; case MENU_EXIT: finish(); System.exit(0); return true; case MENU_TRAFFIC: showTrafficDialog(); return true; case MENU_HELP: new HelpDialog(this).show(); return true; case MENU_SETPWD: setPassword(); return true; case MENU_SHOWLOG: showLog(); return true; case MENU_SHOWRULES: showRules(); return true; case MENU_CLEARLOG: clearLog(); return true; } return false; } private void showTrafficDialog() { String message = null; long[] trafficArray = Api.showTraffic(this); if (trafficArray != null) { message = "褰撴湀宸蹭娇鐢細" + unitHandler(trafficArray[0]) + "\n宸叉帴鏀讹細" + unitHandler(trafficArray[1]) + "\n宸插彂閫侊細" + unitHandler(trafficArray[2]); } else { message = "瀵逛笉璧凤紝鎮ㄥ彲鑳借繕娌′骇鐢熸祦閲忥紝鎴栬�鎮ㄧ殑璁惧涓嶆敮鎸佽鍔熻兘銆�; } Api.alert(this, message); } private String unitHandler(long count) { String value = null; long temp = count; float floatnum = count; if ((temp = temp / 1000) < 1) { value = count + "B"; } else if ((floatnum = (float)temp / 1000) < 1) { value = temp + "KB"; } else { DecimalFormat format = new DecimalFormat("0.#"); value = format.format(floatnum) + "MB"; } return value; } /** * Enables or disables the firewall */ private void disableOrEnable() { final boolean enabled = !Api.isEnabled(this); Log.d("DroidWall", "Changing enabled status to: " + enabled); Api.setEnabled(this, enabled); if (enabled) { applyOrSaveRules(); } else { purgeRules(); } refreshHeader(); } /** * Set a new lock password */ private void setPassword() { new PassDialog(this, true, new android.os.Handler.Callback() { public boolean handleMessage(Message msg) { if (msg.obj != null) { setPassword((String) msg.obj); } return false; } }).show(); } /** * Show iptable rules on a dialog */ private void showRules() { final Resources res = getResources(); final ProgressDialog progress = ProgressDialog.show(this, res.getString(R.string.working), res.getString(R.string.please_wait), true); final Handler handler = new Handler() { public void handleMessage(Message msg) { try { progress.dismiss(); } catch (Exception ex) { } if (!Api.hasRootAccess(MainActivity.this, true)) return; Api.showIptablesRules(MainActivity.this); } }; handler.sendEmptyMessageDelayed(0, 100); } /** * Show logs on a dialog */ private void showLog() { final Resources res = getResources(); final ProgressDialog progress = ProgressDialog.show(this, res.getString(R.string.working), res.getString(R.string.please_wait), true); final Handler handler = new Handler() { public void handleMessage(Message msg) { try { progress.dismiss(); } catch (Exception ex) { } Api.showLog(MainActivity.this); } }; handler.sendEmptyMessageDelayed(0, 100); } /** * Clear logs */ private void clearLog() { final Resources res = getResources(); final ProgressDialog progress = ProgressDialog.show(this, res.getString(R.string.working), res.getString(R.string.please_wait), true); final Handler handler = new Handler() { public void handleMessage(Message msg) { try { progress.dismiss(); } catch (Exception ex) { } if (!Api.hasRootAccess(MainActivity.this, true)) return; if (Api.clearLog(MainActivity.this)) { Toast.makeText(MainActivity.this, R.string.log_cleared, Toast.LENGTH_SHORT).show(); } } }; handler.sendEmptyMessageDelayed(0, 100); } /** * Apply or save iptable rules, showing a visual indication */ private void applyOrSaveRules() { final Resources res = getResources(); final boolean enabled = Api.isEnabled(this); final ProgressDialog progress = ProgressDialog.show(this, res .getString(R.string.working), res .getString(enabled ? R.string.applying_rules : R.string.saving_rules), true); final Handler handler = new Handler() { public void handleMessage(Message msg) { try { progress.dismiss(); } catch (Exception ex) { } if (enabled) { Log.d("DroidWall", "Applying rules."); if (Api.hasRootAccess(MainActivity.this, true) && Api.applyIptablesRules(MainActivity.this, true)) { Toast.makeText(MainActivity.this, R.string.rules_applied, Toast.LENGTH_SHORT) .show(); } else { Log.d("DroidWall", "Failed - Disabling firewall."); Api.setEnabled(MainActivity.this, false); } } else { Log.d("DroidWall", "Saving rules."); Api.saveRules(MainActivity.this); Toast.makeText(MainActivity.this, R.string.rules_saved, Toast.LENGTH_SHORT).show(); } } }; handler.sendEmptyMessageDelayed(0, 100); } /** * Purge iptable rules, showing a visual indication */ private void purgeRules() { final Resources res = getResources(); final ProgressDialog progress = ProgressDialog.show(this, res.getString(R.string.working), res.getString(R.string.deleting_rules), true); final Handler handler = new Handler() { public void handleMessage(Message msg) { try { progress.dismiss(); } catch (Exception ex) { } if (!Api.hasRootAccess(MainActivity.this, true)) return; if (Api.purgeIptables(MainActivity.this, true)) { Toast.makeText(MainActivity.this, R.string.rules_deleted, Toast.LENGTH_SHORT).show(); } } }; handler.sendEmptyMessageDelayed(0, 100); } /** * Called an application is check/unchecked */ @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { final DroidApp app = (DroidApp) buttonView.getTag(); if (app != null) { switch (buttonView.getId()) { case R.id.itemcheck_wifi: app.selected_wifi = isChecked; break; case R.id.itemcheck_3g: app.selected_3g = isChecked; break; } } } private static class ListEntry { private CheckBox box_wifi; private CheckBox box_3g; private TextView app_text; private TextView upload; private TextView download; } @Override public void onClick(View v) { switch (v.getId()) { case R.id.label_mode: selectMode(); break; } } }
PackageBroadcast.java
/** * Broadcast receiver responsible for removing rules that affect uninstalled apps. * * Copyright (C) 2009-2011 Rodrigo Zechin Rosauro * * 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. * * @author Rodrigo Zechin Rosauro * @version 1.0 */ package com.googlecode.droidwall; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; /** * Broadcast receiver responsible for removing rules that affect uninstalled apps. */ public class PackageBroadcast extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) { // Ignore application updates final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); if (!replacing) { final int uid = intent.getIntExtra(Intent.EXTRA_UID, -123); Api.applicationRemoved(context, uid); } } } }
BootAndShutdownBroadcast.java
发表评论
-
RTP/RTCP/RTSP/SIP/SDP
2012-11-07 16:20 1237RTP sdfs Real-time Transpor ... -
SIP SDP RTP HTTP相关标准列表
2012-11-07 16:19 1107SIP Standards Core SIP Docume ... -
RTPSession翻译(转)
2012-09-12 15:49 1374RTPSession 对于 ... -
获得网络状态
2012-04-20 17:08 980public static boolean hasConne ... -
CMDExecute
2011-09-21 21:14 1428package com.TaskManager; imp ...
相关推荐
IPTable/Netfilter是Linux系统的包过滤体系架构。据此,可以构造防火墙,NAT等系统。本资源是一个客户端(Iptable)的使用手册。
linux iptable 防火墙(Firewall)、网址转换(NAT)、数据包(package)记录、流量统计,这些功能全是Linux核心里的Netfilter子系统所提供的,而iptables是控管Netfilter的唯一工具程序
iptable+完整版,江iptable相关的东西
多个实用的linux iptable实例应用。让你快速掌握好linux iptable的部署使用。
用iptable做端口映射 用iptable做端口映射
防火牆工具 — iptable ,ppt版本,希望对大家有用!
iptable 中文指南 iptable 中文指南
redhat iptable AS 详解 配置 安装,超级详细,可以解决所有LINUX配置问题
LINUX iptable应用手册
iptable能够为Unix、Linux和BSD个人工作站创建一个防火墙,也可以为一个子网创建防火墙以保护其它的系统平台。iptable只读取数据包头,不会给信息流增加负担,也无需进行验证。要想获得更加好的的安全性,可以将其和...
linux防火墙iptable命令.pdf
模拟超时、低带宽测试神器之Iptable Iptable 是一种强大的网络工具,可以模拟超时、低带宽测试,帮助开发者和测试者更好地模拟真实的业务场景,提高测试效率和质量。本文将详细介绍 Iptable 的使用方法和原理,并...
2小时玩转iptable
非常好的iptable学习资料,iptable就应该从这里学起,跟随大师的脚步了解防火墙的配置
IP tables防火墙的详细见解,描述了IPtables防火墙的使用和作用
iptable防火墙课程设计 本课程设计主要讨论了iptables防火墙的原理、配置、语法和测试方案。iptables是 LINUX操作系统中的一款防火墙软件,通过安装特定的防火墙内核,LINUX操作系统会对接收到的数据包按一定的策略...
iptable的配置,有详细的示例,希望对大家有所帮助
Linux 2.6 的 iptables 是一个强大的包过滤和防火墙工具,它基于 netfilter 框架。本文将深入探讨 iptables 在 Linux 2.6.28.10 内核中的实现细节,包括用户空间的处理流程以及内核中的数据结构。...
iptable 的安装程序,,请大家研究一下
Linux Iptables命令列表: 用iptables -ADC 来指定链的规则,-A添加 -D删除 -C 修改 iptables - [RI] chain rule num rule-specification[option] 用iptables - RI 通过规则的顺序指定 iptables -D chain rule ...