Skip to content
This repository
Browse code

initial version

  • Loading branch information...
commit 47a9b692a06ffbb21ffd1fc2696b11c936081f7f 1 parent c5a6af3
Umakanthan Chandran authored

Showing 63 changed files with 4,047 additions and 0 deletions. Show diff stats Hide diff stats

  1. +8 0 .classpath
  2. +33 0 .project
  3. +11 0 Android.mk
  4. +83 0 AndroidManifest.xml
  5. +14 0 project.properties
  6. BIN  res/drawable-hdpi/icon.png
  7. BIN  res/drawable-hdpi/widget_off.png
  8. BIN  res/drawable-hdpi/widget_on.png
  9. BIN  res/drawable-ldpi/icon.png
  10. BIN  res/drawable-ldpi/widget_off.png
  11. BIN  res/drawable-ldpi/widget_on.png
  12. BIN  res/drawable/apply.png
  13. BIN  res/drawable/clear.png
  14. BIN  res/drawable/clearlog.png
  15. BIN  res/drawable/eth_3g.png
  16. BIN  res/drawable/eth_wifi.png
  17. BIN  res/drawable/exit.png
  18. BIN  res/drawable/help.png
  19. BIN  res/drawable/icon.png
  20. BIN  res/drawable/lock.png
  21. BIN  res/drawable/off.png
  22. BIN  res/drawable/on.png
  23. BIN  res/drawable/preferences.png
  24. BIN  res/drawable/reload.png
  25. BIN  res/drawable/roam.png
  26. BIN  res/drawable/script.png
  27. BIN  res/drawable/show.png
  28. BIN  res/drawable/spinner.png
  29. +6 0 res/drawable/widget_bg.xml
  30. BIN  res/drawable/widget_bg_focus.png
  31. BIN  res/drawable/widget_bg_pressed.png
  32. BIN  res/drawable/widget_off.png
  33. BIN  res/drawable/widget_on.png
  34. +22 0 res/layout/customscript.xml
  35. +78 0 res/layout/dialog_color_picker.xml
  36. +17 0 res/layout/help_dialog.xml
  37. +45 0 res/layout/listitem.xml
  38. +29 0 res/layout/main.xml
  39. +15 0 res/layout/onoff_widget.xml
  40. +11 0 res/layout/pass_dialog.xml
  41. +8 0 res/layout/preferences.xml
  42. BIN  res/raw/busybox_g1
  43. BIN  res/raw/iptables_armv5
  44. +7 0 res/values/arrays.xml
  45. +94 0 res/values/strings.xml
  46. +8 0 res/xml/onoff_widget.xml
  47. +24 0 res/xml/pref.xml
  48. +1,207 0 src/dev/ukanth/ufirewall/Api.java
  49. +12 0 src/dev/ukanth/ufirewall/Application.java
  50. +65 0 src/dev/ukanth/ufirewall/BootBroadcast.java
  51. +26 0 src/dev/ukanth/ufirewall/ConnectivityChangeReceiver.java
  52. +117 0 src/dev/ukanth/ufirewall/CustomScriptActivity.java
  53. +41 0 src/dev/ukanth/ufirewall/HelpDialog.java
  54. +970 0 src/dev/ukanth/ufirewall/MainActivity.java
  55. +102 0 src/dev/ukanth/ufirewall/PackageBroadcast.java
  56. +86 0 src/dev/ukanth/ufirewall/PassDialog.java
  57. +16 0 src/dev/ukanth/ufirewall/PrefsActivity.java
  58. +13 0 src/dev/ukanth/ufirewall/ShutdownReceiver.java
  59. +117 0 src/dev/ukanth/ufirewall/StatusWidget.java
  60. +128 0 src/net/margaritov/preference/colorpicker/AlphaPatternDrawable.java
  61. +143 0 src/net/margaritov/preference/colorpicker/ColorPickerDialog.java
  62. +171 0 src/net/margaritov/preference/colorpicker/ColorPickerPanelView.java
  63. +320 0 src/net/margaritov/preference/colorpicker/ColorPickerPreference.java
8 .classpath
... ... @@ -0,0 +1,8 @@
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<classpath>
  3 + <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
  4 + <classpathentry kind="src" path="src"/>
  5 + <classpathentry kind="src" path="gen"/>
  6 + <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
  7 + <classpathentry kind="output" path="bin/classes"/>
  8 +</classpath>
33 .project
... ... @@ -0,0 +1,33 @@
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<projectDescription>
  3 + <name>AFWall</name>
  4 + <comment></comment>
  5 + <projects>
  6 + </projects>
  7 + <buildSpec>
  8 + <buildCommand>
  9 + <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
  10 + <arguments>
  11 + </arguments>
  12 + </buildCommand>
  13 + <buildCommand>
  14 + <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
  15 + <arguments>
  16 + </arguments>
  17 + </buildCommand>
  18 + <buildCommand>
  19 + <name>org.eclipse.jdt.core.javabuilder</name>
  20 + <arguments>
  21 + </arguments>
  22 + </buildCommand>
  23 + <buildCommand>
  24 + <name>com.android.ide.eclipse.adt.ApkBuilder</name>
  25 + <arguments>
  26 + </arguments>
  27 + </buildCommand>
  28 + </buildSpec>
  29 + <natures>
  30 + <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
  31 + <nature>org.eclipse.jdt.core.javanature</nature>
  32 + </natures>
  33 +</projectDescription>
11 Android.mk
... ... @@ -0,0 +1,11 @@
  1 +LOCAL_PATH:= $(call my-dir)
  2 +include $(CLEAR_VARS)
  3 +
  4 +LOCAL_MODULE_TAGS := optional
  5 +
  6 +LOCAL_SRC_FILES := $(call all-java-files-under, src)
  7 +
  8 +LOCAL_PACKAGE_NAME := Droidwall
  9 +LOCAL_CERTIFICATE := platform
  10 +
  11 +include $(BUILD_PACKAGE)
83 AndroidManifest.xml
... ... @@ -0,0 +1,83 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3 + package="dev.ukanth.ufirewall"
  4 + android:versionCode="100"
  5 + android:versionName="1.0.0" >
  6 +
  7 + <uses-sdk
  8 + android:minSdkVersion="7"
  9 + android:targetSdkVersion="16" />
  10 +
  11 + <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
  12 + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  13 + <uses-permission android:name="android.permission.DEVICE_POWER" />
  14 +
  15 +
  16 + <application
  17 + android:icon="@drawable/icon"
  18 + android:label="@string/app_name"
  19 + android:theme="@style/Theme.Sherlock" >
  20 + <activity
  21 + android:name=".MainActivity"
  22 + android:label="@string/app_name" >
  23 + <intent-filter>
  24 + <action android:name="android.intent.action.MAIN" />
  25 + <category android:name="android.intent.category.DEFAULT" />
  26 + <category android:name="android.intent.category.LAUNCHER" />
  27 + </intent-filter>
  28 + </activity>
  29 + <activity
  30 + android:name="dev.ukanth.ufirewall.PrefsActivity"
  31 + android:theme="@android:style/Theme.Black.NoTitleBar" >
  32 + </activity>
  33 + <activity android:name=".CustomScriptActivity" />
  34 +
  35 + <receiver
  36 + android:name="BootBroadcast"
  37 + android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
  38 + <intent-filter>
  39 + <action android:name="android.intent.action.BOOT_COMPLETED" >
  40 + </action>
  41 + </intent-filter>
  42 + </receiver>
  43 +
  44 + <receiver android:name=".ShutdownReceiver">
  45 + <intent-filter>
  46 + <action android:name="android.intent.action.ACTION_SHUTDOWN" />
  47 + <action android:name="android.intent.action.QUICKBOOT_POWEROFF" />
  48 + </intent-filter>
  49 + </receiver>
  50 + <receiver android:name="PackageBroadcast" >
  51 + <intent-filter>
  52 + <action android:name="android.intent.action.PACKAGE_ADDED" />
  53 + <action android:name="android.intent.action.PACKAGE_REMOVED" />
  54 +
  55 + <data android:scheme="package" />
  56 + </intent-filter>
  57 + </receiver>
  58 +
  59 + <receiver android:name="ConnectivityChangeReceiver" >
  60 + <intent-filter>
  61 + <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
  62 + </intent-filter>
  63 + </receiver>
  64 + <receiver android:name="StatusWidget" >
  65 + <meta-data
  66 + android:name="android.appwidget.provider"
  67 + android:resource="@xml/onoff_widget" />
  68 +
  69 + <intent-filter>
  70 + <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
  71 + <action android:name="com.googlecode.droidwall.intent.action.STATUS_CHANGED" />
  72 + <action android:name="com.googlecode.droidwall.intent.action.TOGGLE_REQUEST" />
  73 + </intent-filter>
  74 + </receiver>
  75 + </application>
  76 +
  77 + <supports-screens
  78 + android:anyDensity="true"
  79 + android:largeScreens="true"
  80 + android:normalScreens="true"
  81 + android:smallScreens="true" />
  82 +
  83 +</manifest>
14 project.properties
... ... @@ -0,0 +1,14 @@
  1 +# This file is automatically generated by Android Tools.
  2 +# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
  3 +#
  4 +# This file must be checked in Version Control Systems.
  5 +#
  6 +# To customize properties used by the Ant build system use,
  7 +# "ant.properties", and override values to adapt the script to your
  8 +# project structure.
  9 +
  10 +# Project target.
  11 +target=android-16
  12 +android.library.reference.1=../ActionBarSherlock
  13 +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
  14 +
BIN  res/drawable-hdpi/icon.png
BIN  res/drawable-hdpi/widget_off.png
BIN  res/drawable-hdpi/widget_on.png
BIN  res/drawable-ldpi/icon.png
BIN  res/drawable-ldpi/widget_off.png
BIN  res/drawable-ldpi/widget_on.png
BIN  res/drawable/apply.png
BIN  res/drawable/clear.png
BIN  res/drawable/clearlog.png
BIN  res/drawable/eth_3g.png
BIN  res/drawable/eth_wifi.png
BIN  res/drawable/exit.png
BIN  res/drawable/help.png
BIN  res/drawable/icon.png
BIN  res/drawable/lock.png
BIN  res/drawable/off.png
BIN  res/drawable/on.png
BIN  res/drawable/preferences.png
BIN  res/drawable/reload.png
BIN  res/drawable/roam.png
BIN  res/drawable/script.png
BIN  res/drawable/show.png
BIN  res/drawable/spinner.png
6 res/drawable/widget_bg.xml
... ... @@ -0,0 +1,6 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +
  3 +<selector xmlns:android="http://schemas.android.com/apk/res/android">
  4 + <item android:state_pressed="true" android:drawable="@drawable/widget_bg_pressed" />
  5 + <item android:state_focused="true" android:state_enabled="true" android:drawable="@drawable/widget_bg_focus" />
  6 +</selector>
BIN  res/drawable/widget_bg_focus.png
BIN  res/drawable/widget_bg_pressed.png
BIN  res/drawable/widget_off.png
BIN  res/drawable/widget_on.png
22 res/layout/customscript.xml
... ... @@ -0,0 +1,22 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<ScrollView
  3 + xmlns:android="http://schemas.android.com/apk/res/android"
  4 + android:layout_width="fill_parent"
  5 + android:layout_height="fill_parent">
  6 + <LinearLayout
  7 + android:orientation="vertical"
  8 + android:layout_width="fill_parent"
  9 + android:layout_height="wrap_content">
  10 + <TextView android:id="@+id/customscript_link" android:text="@string/custom_script_info" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:textSize="22px"/>
  11 + <EditText android:id="@+id/customscript" android:layout_width="fill_parent" android:inputType="textMultiLine" android:layout_height="wrap_content" android:minLines="4" android:maxLines="4" android:gravity="top" android:scrollbars="horizontal|vertical">
  12 + <requestFocus></requestFocus>
  13 + </EditText>
  14 + <TextView android:text="@string/custom_script2_info" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:textSize="22px"/>
  15 + <EditText android:id="@+id/customscript2" android:layout_width="fill_parent" android:inputType="textMultiLine" android:layout_height="wrap_content" android:minLines="4" android:maxLines="4" android:gravity="top" android:scrollbars="horizontal|vertical">
  16 + </EditText>
  17 + <LinearLayout android:layout_height="wrap_content" android:layout_width="fill_parent" android:gravity="center_horizontal">
  18 + <Button android:layout_height="wrap_content" android:layout_width="wrap_content" android:id="@+id/customscript_ok" android:text="@android:string/ok" android:minWidth="100px"></Button>
  19 + <Button android:layout_height="wrap_content" android:layout_width="wrap_content" android:id="@+id/customscript_cancel" android:text="@android:string/cancel" android:minWidth="100px"></Button>
  20 + </LinearLayout>
  21 + </LinearLayout>
  22 +</ScrollView>
78 res/layout/dialog_color_picker.xml
... ... @@ -0,0 +1,78 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<!-- Copyright (C) 2010 Daniel Nilsson
  3 +
  4 + Licensed under the Apache License, Version 2.0 (the "License");
  5 + you may not use this file except in compliance with the License.
  6 + You may obtain a copy of the License at
  7 +
  8 + http://www.apache.org/licenses/LICENSE-2.0
  9 +
  10 + Unless required by applicable law or agreed to in writing, software
  11 + distributed under the License is distributed on an "AS IS" BASIS,
  12 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + See the License for the specific language governing permissions and
  14 + limitations under the License.
  15 +-->
  16 +
  17 +<LinearLayout
  18 + xmlns:android="http://schemas.android.com/apk/res/android"
  19 + android:layout_width="wrap_content"
  20 + android:layout_height="wrap_content"
  21 + android:paddingLeft="5dp"
  22 + android:paddingRight="5dp"
  23 + android:orientation="vertical">
  24 +
  25 + <net.margaritov.preference.colorpicker.ColorPickerView
  26 + android:id="@+id/color_picker_view"
  27 + android:layout_width="wrap_content"
  28 + android:layout_height="wrap_content"
  29 + android:layout_centerHorizontal="true"
  30 + android:tag="portrait"
  31 + android:layerType="software"
  32 + />
  33 +
  34 + <TextView
  35 + android:layout_width="wrap_content"
  36 + android:layout_height="wrap_content"
  37 + android:text="Press on Color to apply"
  38 + android:gravity="left"
  39 + android:layout_marginLeft="6dp"
  40 + android:layout_marginRight="6dp"
  41 + android:layout_marginBottom="5dp"
  42 + android:textAppearance="?android:attr/textAppearanceSmall"
  43 + />
  44 +
  45 + <LinearLayout
  46 + android:layout_width="wrap_content"
  47 + android:layout_height="40dp"
  48 + android:orientation="horizontal"
  49 + android:layout_below="@id/color_picker_view"
  50 + android:layout_marginBottom="10dp">
  51 +
  52 + <net.margaritov.preference.colorpicker.ColorPickerPanelView
  53 + android:id="@+id/old_color_panel"
  54 + android:layout_width="0px"
  55 + android:layout_height="fill_parent"
  56 + android:layout_weight="0.5"
  57 + />
  58 +
  59 + <TextView
  60 + android:layout_width="wrap_content"
  61 + android:layout_height="fill_parent"
  62 + android:text="→"
  63 + android:textSize="20sp"
  64 + android:gravity="center"
  65 + android:layout_marginLeft="10dp"
  66 + android:layout_marginRight="10dp"
  67 + />
  68 +
  69 + <net.margaritov.preference.colorpicker.ColorPickerPanelView
  70 + android:id="@+id/new_color_panel"
  71 + android:layout_width="0px"
  72 + android:layout_height="wrap_content"
  73 + android:layout_weight="0.5"
  74 + />
  75 +
  76 + </LinearLayout>
  77 +
  78 +</LinearLayout>
17 res/layout/help_dialog.xml
... ... @@ -0,0 +1,17 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="fill_parent" android:layout_height="wrap_content">
  4 + <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
  5 + android:layout_width="fill_parent" android:layout_height="fill_parent">
  6 + <!--
  7 + <LinearLayout android:layout_width="fill_parent"
  8 + android:layout_height="fill_parent" android:orientation="vertical">
  9 + <TextView android:id="@+id/help_dialog_disclaimer"
  10 + android:layout_height="fill_parent" android:layout_width="fill_parent"
  11 + android:padding="6dip" /> -->
  12 + <TextView android:layout_height="fill_parent"
  13 + android:layout_width="fill_parent" android:text="@string/help_dialog_text"
  14 + android:padding="6dip" />
  15 + <!-- </LinearLayout> -->
  16 + </ScrollView>
  17 +</FrameLayout>
45 res/layout/listitem.xml
... ... @@ -0,0 +1,45 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 + <LinearLayout
  3 + xmlns:android="http://schemas.android.com/apk/res/android"
  4 + android:layout_width="fill_parent"
  5 + android:layout_height="fill_parent"
  6 + android:baselineAligned="true"
  7 + android:orientation="horizontal"
  8 + android:paddingBottom="2dip"
  9 + android:paddingTop="2dip" >
  10 +
  11 + <ImageView
  12 + android:id="@+id/itemicon"
  13 + android:layout_width="34dip"
  14 + android:layout_height="34dip">
  15 + </ImageView>
  16 +
  17 + <CheckBox
  18 + android:id="@+id/itemcheck_wifi"
  19 + android:layout_width="34dip"
  20 + android:layout_height="34dip"
  21 + android:padding="0px" >
  22 + </CheckBox>
  23 +
  24 + <CheckBox
  25 + android:id="@+id/itemcheck_3g"
  26 + android:layout_width="34dip"
  27 + android:layout_height="34dip"
  28 + android:padding="0px" >
  29 + </CheckBox>
  30 +
  31 + <CheckBox
  32 + android:id="@+id/itemcheck_roam"
  33 + android:layout_width="34dip"
  34 + android:layout_height="34dip"
  35 + android:padding="0px" >
  36 + </CheckBox>
  37 +
  38 + <TextView
  39 + android:id="@+id/itemtext"
  40 + android:layout_width="fill_parent"
  41 + android:layout_height="wrap_content"
  42 + android:paddingLeft="5dip"
  43 + android:text="@string/empty" >
  44 + </TextView>
  45 + </LinearLayout>
29 res/layout/main.xml
... ... @@ -0,0 +1,29 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:duplicateParentState="false">
  3 + <View android:layout_width="fill_parent" android:layout_height="1px" android:background="#FFFFFFFF" />
  4 + <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/list"
  5 + android:layout_width="wrap_content"
  6 + android:layout_height="wrap_content"
  7 + android:drawSelectorOnTop="false"
  8 + android:scrollbarAlwaysDrawVerticalTrack="true"
  9 + />
  10 + <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="6px">
  11 + <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/label_mode" android:text="@string/mode" android:textSize="22px" android:clickable="true"></TextView>
  12 + <ImageView
  13 + android:src="@drawable/spinner"
  14 + android:layout_width="12dip"
  15 + android:layout_height="18dip">
  16 + </ImageView>
  17 + </LinearLayout>
  18 + <View android:layout_width="fill_parent" android:layout_height="1px" android:background="#FFFFFFFF" />
  19 + <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="0px">
  20 + <View android:layout_width="34dip" android:layout_height="fill_parent"/>
  21 + <ImageView android:layout_width="34dip" android:layout_height="wrap_content" android:id="@+id/img_wifi" android:src="@drawable/eth_wifi" android:clickable="true"></ImageView>
  22 + <ImageView android:layout_width="34dip" android:layout_height="wrap_content" android:id="@+id/img_3g" android:src="@drawable/eth_3g" android:clickable="true"></ImageView>
  23 + <ImageView android:layout_width="34dip" android:layout_height="wrap_content" android:id="@+id/img_roam" android:src="@drawable/roam" android:clickable="true"></ImageView>
  24 + <ImageView android:layout_width="34dip" android:layout_height="wrap_content" android:id="@+id/img_reset" android:src="@drawable/clear" android:clickable="true"></ImageView>
  25 + </LinearLayout>
  26 +
  27 + <ListView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/listview"></ListView>
  28 +
  29 +</LinearLayout>
15 res/layout/onoff_widget.xml
... ... @@ -0,0 +1,15 @@
  1 +<?xml version="1.0" encoding="UTF-8" ?>
  2 + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:id="@+id/main"
  4 + android:layout_width="40dip"
  5 + android:layout_height="40dip"
  6 + android:gravity="center">
  7 +
  8 + <ImageButton
  9 + android:id="@+id/widgetCanvas"
  10 + android:layout_width="40dip"
  11 + android:layout_height="40dip"
  12 + android:background="@drawable/widget_bg"
  13 + android:layout_gravity="center_horizontal"
  14 + />
  15 +</LinearLayout>
11 res/layout/pass_dialog.xml
... ... @@ -0,0 +1,11 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:duplicateParentState="false">
  3 +<TextView android:layout_height="wrap_content" android:id="@+id/pass_message" android:layout_width="fill_parent" android:gravity="center_horizontal|center" android:textSize="25px" android:text="@string/enternewpass" android:paddingLeft="5px" android:paddingRight="5px"></TextView>
  4 +<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="15px">
  5 +<EditText android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/pass_input" android:inputType="textPassword"></EditText>
  6 +</LinearLayout>
  7 +<LinearLayout android:layout_height="wrap_content" android:layout_width="fill_parent" android:gravity="center_horizontal">
  8 +<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/pass_ok" android:text="@android:string/ok" android:minWidth="70px"></Button>
  9 +<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@android:string/cancel" android:minWidth="70px" android:id="@+id/pass_cancel"></Button>
  10 +</LinearLayout>
  11 +</LinearLayout>
8 res/layout/preferences.xml
... ... @@ -0,0 +1,8 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +
  3 +<ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/list"
  4 + android:layout_width="fill_parent"
  5 + android:layout_height="fill_parent"
  6 + android:drawSelectorOnTop="false"
  7 + android:scrollbarAlwaysDrawVerticalTrack="true"
  8 + />
BIN  res/raw/busybox_g1
Binary file not shown
BIN  res/raw/iptables_armv5
Binary file not shown
7 res/values/arrays.xml
... ... @@ -0,0 +1,7 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 + <string-array name="modes">
  4 + <item>White list (allow selected)</item>
  5 + <item>Black list (block selected)</item>
  6 + </string-array>
  7 +</resources>
94 res/values/strings.xml
... ... @@ -0,0 +1,94 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 + <string name="app_name">AFWall+</string>
  4 + <string name="title_enabled">AFWall+ </string>
  5 + <string name="title_disabled">AFWall+ (Disabled)</string>
  6 + <string name="showrules">Show rules</string>
  7 + <string name="applyrules">Apply rules</string>
  8 + <string name="saverules">Save rules</string>
  9 + <string name="purgerules">Purge rules</string>
  10 + <string name="setpwd">Set password</string>
  11 + <string name="help">Help</string>
  12 + <string name="close">Close</string>
  13 + <string name="exit">Exit</string>
  14 + <string name="fw_enabled">Enabled</string>
  15 + <string name="fw_disabled">Disabled</string>
  16 + <string name="log_enabled">Log enabled</string>
  17 + <string name="log_disabled">Log disabled</string>
  18 + <string name="log_was_enabled">Log has been enabled</string>
  19 + <string name="log_was_disabled">Log has been disabled</string>
  20 + <string name="log_cleared">Log cleared</string>
  21 + <string name="flushed">Rules flushed</string>
  22 + <string name="show_log">Show log</string>
  23 + <string name="clear_log">Clear log</string>
  24 + <string name="applying_rules">Applying iptables rules.</string>
  25 + <string name="saving_rules">Saving iptables rules.</string>
  26 + <string name="deleting_rules">Deleting iptables rules.</string>
  27 + <string name="rules_applied">Rules applied with success</string>
  28 + <string name="rules_saved">Rules saved with success</string>
  29 + <string name="rules_deleted">Rules deleted with success</string>
  30 + <string name="pass_titleset">Set password lock</string>
  31 + <string name="pass_titleget">Password required</string>
  32 + <string name="enterpass">Enter the password:</string>
  33 + <string name="enternewpass">Enter the new password (leave blank to remove):</string>
  34 + <string name="passdefined">Password lock defined</string>
  35 + <string name="passremoved">Password lock removed</string>
  36 + <string name="passerror">Error changing password lock</string>
  37 + <string name="working">Working...</string>
  38 + <string name="reading_apps">Reading installed applications</string>
  39 + <string name="please_wait">Please wait</string>
  40 + <string name="mode_header">Mode: %s</string>
  41 + <string name="mode_whitelist">White list (allow selected)</string>
  42 + <string name="mode_blacklist">Black list (block selected)</string>
  43 + <string name="toast_bin_installed">AFWall+: Binary files installed!</string>
  44 + <string name="toast_enabled">AFWall+: Firewall enabled!</string>
  45 + <string name="toast_error_enabling">AFWall+: Error enabling firewall!</string>
  46 + <string name="toast_disabled">AFWall+: Firewall disabled!</string>
  47 + <string name="toast_error_disabling">AFWall+: Error disabling firewall!</string>
  48 + <string name="set_custom_script">Set custom script</string>
  49 + <string name="preferences">Preferences</string>
  50 + <string name="reload">Reload Applications</string>
  51 + <string name="flush">Flush Rules</string>
  52 + <string name="custom_script_defined">Custom script defined</string>
  53 + <string name="custom_script_removed">Custom script removed</string>
  54 + <string name="custom_script_error">Error saving custom script</string>
  55 + <string name="custom_script_info"><b>Enter your custom script bellow.</b>
  56 + \n<i>(Leave it blank to remove)</i>
  57 + \nFor information about custom scripts, click <a href="http://code.google.com/p/droidwall/wiki/CustomScripts">here</a>.
  58 + </string>
  59 + <string name="custom_script2_info">
  60 + \n<b>Custom shutdown script</b>
  61 + \nYou can also define a custom script to be executed when the firewall is <b>disabled</b>:</string>
  62 + <string name="unsaved_changes">Unsaved changes</string>
  63 + <string name="unsaved_changes_message">You have unsaved changes.\nDo you want to apply or discard them?</string>
  64 + <string name="apply">Apply</string>
  65 + <string name="discard">Discard</string>
  66 + <string name="help_dialog_text"><i>Developer: Umakanthan Chandran (Original Author: Rodrigo Zechin Rosauro(DroidWall))</i>
  67 + \n<i>Contact me - cumakt@gmail.com (@ukanth- Twitter)</i>
  68 + \n<i><a href="https://github.com/ukanth/afwall/">https://github.com/ukanth/afwall/</a></i>
  69 + \n
  70 + \n<i>AFWall+ - Android Firewall</i> is a front-end application for the powerful <b>iptables</b> Linux firewall.
  71 + It allows you to restrict which applications are permitted to access your data networks.
  72 + \nThis is the perfect solution if you don\'t have an unlimited data plan, or just wants to see your battery lasting longer.
  73 + \n
  74 + \n<b>Using AFWall+:</b>
  75 + \n<b>1.</b> Click on <b>Mode</b> to switch between <i>White List</i> and <i>Black List</i> modes.
  76 + \n<b>2.</b> Mark the applications that you want to block or allow (depending on the selected mode), for each interface.
  77 + \n<b>3.</b> Open the menu and enable the firewall. If the firewall is already enabled, just select <b>Apply rules</b>.
  78 + \nThe rules will be saved and automatically restored when you restart your phone.
  79 + \nIf you want to check all current iptables rules, select <b>Show rules</b> in the menu.
  80 + \n
  81 + \n<b>Widget:</b>
  82 + \nTo quickly enable or disable the firewall, add the AFWall+ widget to your home screen.
  83 + \n
  84 + \n<b>Firewall logs:</b>
  85 + \nIf you want to see which applications have been blocked by AFWall+, open the menu and enable the Log.
  86 + \nAFWall+ will then log each application blocked. You can check the log by opening the menu and selecting <b>More -> Show log</b>.
  87 + \n
  88 + \n<b>Password lock:</b>
  89 + \nYou can set a password lock for AFWall+ by using the <b>Set password</b> menu option.
  90 + \nTo remove the password protection, just reset it to blank.
  91 + </string>
  92 + <string name="empty"></string>
  93 + <string name="mode">Mode: </string>
  94 +</resources>
8 res/xml/onoff_widget.xml
... ... @@ -0,0 +1,8 @@
  1 +<?xml version="1.0" encoding="UTF-8" ?>
  2 +
  3 +<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
  4 + android:minWidth="72dip"
  5 + android:minHeight="72dip"
  6 + android:updatePeriodMillis="0"
  7 + android:initialLayout="@layout/onoff_widget">
  8 +</appwidget-provider>
24 res/xml/pref.xml
... ... @@ -0,0 +1,24 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
  3 +
  4 + <PreferenceCategory
  5 + android:summary="AFWall+ Options"
  6 + android:title="AFWall+ Preferences" >
  7 + <CheckBoxPreference
  8 + android:key="notifyAppInstall"
  9 + android:summary="Enable will notify to open AFWall+ on new installtions"
  10 + android:title="Notify on new installs" />
  11 + <CheckBoxPreference
  12 + android:key="showToast"
  13 + android:title="Disable Toast Messages" />
  14 +
  15 + <net.margaritov.preference.colorpicker.ColorPickerPreference
  16 + android:key="sysColor"
  17 + android:title="System Apps Highlight"
  18 + android:summary="Highlight system applications"
  19 + android:defaultValue="0xff000000"
  20 + />
  21 +
  22 + </PreferenceCategory>
  23 +
  24 +</PreferenceScreen>
1,207 src/dev/ukanth/ufirewall/Api.java
... ... @@ -0,0 +1,1207 @@
  1 +/**
  2 + * Contains shared programming interfaces.
  3 + * All iptables "communication" is handled by this class.
  4 + *
  5 + * Copyright (C) 2009-2011 Rodrigo Zechin Rosauro
  6 + *
  7 + * This program is free software: you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation, either version 3 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19 + *
  20 + * @author Rodrigo Zechin Rosauro
  21 + * @version 1.0
  22 + */
  23 +
  24 +package dev.ukanth.ufirewall;
  25 +
  26 +import java.io.BufferedReader;
  27 +import java.io.File;
  28 +import java.io.FileOutputStream;
  29 +import java.io.IOException;
  30 +import java.io.InputStream;
  31 +import java.io.OutputStreamWriter;
  32 +import java.io.StringReader;
  33 +import java.util.Arrays;
  34 +import java.util.HashMap;
  35 +import java.util.LinkedList;
  36 +import java.util.List;
  37 +import java.util.StringTokenizer;
  38 +
  39 +import android.Manifest;
  40 +import android.app.AlertDialog;
  41 +import android.content.Context;
  42 +import android.content.Intent;
  43 +import android.content.SharedPreferences;
  44 +import android.content.SharedPreferences.Editor;
  45 +import android.content.pm.ApplicationInfo;
  46 +import android.content.pm.PackageManager;
  47 +import android.graphics.drawable.Drawable;
  48 +import android.preference.PreferenceManager;
  49 +import android.telephony.TelephonyManager;
  50 +import android.util.Log;
  51 +import android.widget.Toast;
  52 +
  53 +/**
  54 + * Contains shared programming interfaces.
  55 + * All iptables "communication" is handled by this class.
  56 + */
  57 +public final class Api {
  58 + /** application version string */
  59 + public static final String VERSION = "1.0.1a";
  60 + /** special application UID used to indicate "any application" */
  61 + public static final int SPECIAL_UID_ANY = -10;
  62 + /** special application UID used to indicate the Linux Kernel */
  63 + public static final int SPECIAL_UID_KERNEL = -11;
  64 + /** root script filename */
  65 + private static final String SCRIPT_FILE = "droidwall.sh";
  66 +
  67 + // Preferences
  68 + public static final String PREFS_NAME = "DroidWallPrefs";
  69 + public static final String PREF_3G_UIDS = "AllowedUids3G";
  70 + public static final String PREF_WIFI_UIDS = "AllowedUidsWifi";
  71 + public static final String PREF_ROAMING_UIDS = "AllowedUidsRoaming";
  72 + public static final String PREF_PASSWORD = "Password";
  73 + public static final String PREF_CUSTOMSCRIPT = "CustomScript";
  74 + public static final String PREF_CUSTOMSCRIPT2 = "CustomScript2"; // Executed on shutdown
  75 + public static final String PREF_MODE = "BlockMode";
  76 + public static final String PREF_ENABLED = "Enabled";
  77 + public static final String PREF_LOGENABLED = "LogEnabled";
  78 + // Modes
  79 + public static final String MODE_WHITELIST = "whitelist";
  80 + public static final String MODE_BLACKLIST = "blacklist";
  81 + // Messages
  82 + public static final String STATUS_CHANGED_MSG = "dev.ukanth.ufirewall.intent.action.STATUS_CHANGED";
  83 + public static final String TOGGLE_REQUEST_MSG = "dev.ukanth.ufirewall.intent.action.TOGGLE_REQUEST";
  84 + public static final String CUSTOM_SCRIPT_MSG = "dev.ukanth.ufirewall.intent.action.CUSTOM_SCRIPT";
  85 + // Message extras (parameters)
  86 + public static final String STATUS_EXTRA = "dev.ukanth.ufirewall.intent.extra.STATUS";
  87 + public static final String SCRIPT_EXTRA = "dev.ukanth.ufirewall.intent.extra.SCRIPT";
  88 + public static final String SCRIPT2_EXTRA = "dev.ukanth.ufirewall.intent.extra.SCRIPT2";
  89 +
  90 + // Cached applications
  91 + public static DroidApp applications[] = null;
  92 + // Do we have root access?
  93 + private static boolean hasroot = false;
  94 +
  95 + /**
  96 + * Display a simple alert box
  97 + * @param ctx context
  98 + * @param msg message
  99 + */
  100 + public static void alert(Context ctx, CharSequence msg) {
  101 + if (ctx != null) {
  102 + new AlertDialog.Builder(ctx)
  103 + .setNeutralButton(android.R.string.ok, null)
  104 + .setMessage(msg)
  105 + .show();
  106 + }
  107 + }
  108 +
  109 + public static boolean isRoaming(Context context) {
  110 + TelephonyManager localTelephonyManager = (TelephonyManager) context
  111 + .getSystemService("phone");
  112 + try {
  113 + return localTelephonyManager.isNetworkRoaming();
  114 + } catch (Exception i) {
  115 + while (true) {
  116 + }
  117 + }
  118 + }
  119 + /**
  120 + * Create the generic shell script header used to determine which iptables binary to use.
  121 + * @param ctx context
  122 + * @return script header
  123 + */
  124 + private static String scriptHeader(Context ctx) {
  125 + final String dir = ctx.getDir("bin",0).getAbsolutePath();
  126 + final String myiptables = dir + "/iptables_armv5";
  127 + return "" +
  128 + "IPTABLES=iptables\n" +
  129 + "BUSYBOX=busybox\n" +
  130 + "GREP=grep\n" +
  131 + "ECHO=echo\n" +
  132 + "# Try to find busybox\n" +
  133 + "if " + dir + "/busybox_g1 --help >/dev/null 2>/dev/null ; then\n" +
  134 + " BUSYBOX="+dir+"/busybox_g1\n" +
  135 + " GREP=\"$BUSYBOX grep\"\n" +
  136 + " ECHO=\"$BUSYBOX echo\"\n" +
  137 + "elif busybox --help >/dev/null 2>/dev/null ; then\n" +
  138 + " BUSYBOX=busybox\n" +
  139 + "elif /system/xbin/busybox --help >/dev/null 2>/dev/null ; then\n" +
  140 + " BUSYBOX=/system/xbin/busybox\n" +
  141 + "elif /system/bin/busybox --help >/dev/null 2>/dev/null ; then\n" +
  142 + " BUSYBOX=/system/bin/busybox\n" +
  143 + "fi\n" +
  144 + "# Try to find grep\n" +
  145 + "if ! $ECHO 1 | $GREP -q 1 >/dev/null 2>/dev/null ; then\n" +
  146 + " if $ECHO 1 | $BUSYBOX grep -q 1 >/dev/null 2>/dev/null ; then\n" +
  147 + " GREP=\"$BUSYBOX grep\"\n" +
  148 + " fi\n" +
  149 + " # Grep is absolutely required\n" +
  150 + " if ! $ECHO 1 | $GREP -q 1 >/dev/null 2>/dev/null ; then\n" +
  151 + " $ECHO The grep command is required. AFWall+ will not work.\n" +
  152 + " exit 1\n" +
  153 + " fi\n" +
  154 + "fi\n" +
  155 + "# Try to find iptables\n" +
  156 + "# Added if iptables binary already in system then use it, if not use implemented one\n" +
  157 + "if ! command -v iptables &> /dev/null; then\n" +
  158 + "if " + myiptables + " --version >/dev/null 2>/dev/null ; then\n" +
  159 + " IPTABLES="+myiptables+"\n" +
  160 + "fi\nfi\n" +
  161 + "";
  162 + }
  163 + /**
  164 + * Copies a raw resource file, given its ID to the given location
  165 + * @param ctx context
  166 + * @param resid resource id
  167 + * @param file destination file
  168 + * @param mode file permissions (E.g.: "755")
  169 + * @throws IOException on error
  170 + * @throws InterruptedException when interrupted
  171 + */
  172 + private static void copyRawFile(Context ctx, int resid, File file, String mode) throws IOException, InterruptedException
  173 + {
  174 + final String abspath = file.getAbsolutePath();
  175 + // Write the iptables binary
  176 + final FileOutputStream out = new FileOutputStream(file);
  177 + final InputStream is = ctx.getResources().openRawResource(resid);
  178 + byte buf[] = new byte[1024];
  179 + int len;
  180 + while ((len = is.read(buf)) > 0) {
  181 + out.write(buf, 0, len);
  182 + }
  183 + out.close();
  184 + is.close();
  185 + // Change the permissions
  186 + Runtime.getRuntime().exec("chmod "+mode+" "+abspath).waitFor();
  187 + }
  188 + /**
  189 + * Purge and re-add all rules (internal implementation).
  190 + * @param ctx application context (mandatory)
  191 + * @param uidsWifi list of selected UIDs for WIFI to allow or disallow (depending on the working mode)
  192 + * @param uids3g list of selected UIDs for 2G/3G to allow or disallow (depending on the working mode)
  193 + * @param showErrors indicates if errors should be alerted
  194 + */
  195 + private static boolean applyIptablesRulesImpl(Context ctx, List<Integer> uidsWifi, List<Integer> uids3g, List<Integer> uidsRoam, boolean showErrors) {
  196 + if (ctx == null) {
  197 + return false;
  198 + }
  199 + assertBinaries(ctx, showErrors);
  200 + final String ITFS_WIFI[] = {"eth+", "wlan+", "tiwlan+", "athwlan+", "ra+"};
  201 + final String ITFS_3G[] = {"rmnet+", "ppp+", "pdp+", "pnp+", "rmnet_sdio+", "uwbr+", "wimax+", "vsnet+", "usb+", "ccmni+"};
  202 + final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0);
  203 + final boolean whitelist = prefs.getString(PREF_MODE, MODE_WHITELIST).equals(MODE_WHITELIST);
  204 + final boolean blacklist = !whitelist;
  205 + final boolean logenabled = ctx.getSharedPreferences(PREFS_NAME, 0).getBoolean(PREF_LOGENABLED, false);
  206 + final String customScript = ctx.getSharedPreferences(Api.PREFS_NAME, 0).getString(Api.PREF_CUSTOMSCRIPT, "");
  207 +
  208 + final StringBuilder script = new StringBuilder();
  209 + try {
  210 + int code;
  211 + script.append(scriptHeader(ctx));
  212 + script.append("" +
  213 + "$IPTABLES --version || exit 1\n" +
  214 + "# Create the droidwall chains if necessary\n" +
  215 + "$IPTABLES -L droidwall >/dev/null 2>/dev/null || $IPTABLES --new droidwall || exit 2\n" +
  216 + "$IPTABLES -L droidwall-3g >/dev/null 2>/dev/null || $IPTABLES --new droidwall-3g || exit 3\n" +
  217 + "$IPTABLES -L droidwall-wifi >/dev/null 2>/dev/null || $IPTABLES --new droidwall-wifi || exit 4\n" +
  218 + "$IPTABLES -L droidwall-reject >/dev/null 2>/dev/null || $IPTABLES --new droidwall-reject || exit 5\n" +
  219 + "# Add droidwall chain to OUTPUT chain if necessary\n" +
  220 + "$IPTABLES -L OUTPUT | $GREP -q droidwall || $IPTABLES -A OUTPUT -j droidwall || exit 6\n" +
  221 + "# Flush existing rules\n" +
  222 + "$IPTABLES -F droidwall || exit 7\n" +
  223 + "$IPTABLES -F droidwall-3g || exit 8\n" +
  224 + "$IPTABLES -F droidwall-wifi || exit 9\n" +
  225 + "$IPTABLES -F droidwall-reject || exit 10\n" +
  226 + "");
  227 + // Check if logging is enabled
  228 + if (logenabled) {
  229 + script.append("" +
  230 + "# Create the log and reject rules (ignore errors on the LOG target just in case it is not available)\n" +
  231 + "$IPTABLES -A droidwall-reject -j LOG --log-prefix \"[DROIDWALL] \" --log-uid\n" +
  232 + "$IPTABLES -A droidwall-reject -j REJECT || exit 11\n" +
  233 + "");
  234 + } else {
  235 + script.append("" +
  236 + "# Create the reject rule (log disabled)\n" +
  237 + "$IPTABLES -A droidwall-reject -j REJECT || exit 11\n" +
  238 + "");
  239 + }
  240 + if (customScript.length() > 0) {
  241 + script.append("\n# BEGIN OF CUSTOM SCRIPT (user-defined)\n");
  242 + script.append(customScript);
  243 + script.append("\n# END OF CUSTOM SCRIPT (user-defined)\n\n");
  244 + }
  245 + if (whitelist && logenabled) {
  246 + script.append("# Allow DNS lookups on white-list for a better logging (ignore errors)\n");
  247 + script.append("$IPTABLES -A droidwall -p udp --dport 53 -j RETURN\n");
  248 + }
  249 + script.append("# Main rules (per interface)\n");
  250 + for (final String itf : ITFS_3G) {
  251 + script.append("$IPTABLES -A droidwall -o ").append(itf).append(" -j droidwall-3g || exit\n");
  252 + }
  253 + for (final String itf : ITFS_WIFI) {
  254 + script.append("$IPTABLES -A droidwall -o ").append(itf).append(" -j droidwall-wifi || exit\n");
  255 + }
  256 +
  257 + script.append("# Filtering rules\n");
  258 + final String targetRule = (whitelist ? "RETURN" : "droidwall-reject");
  259 + final boolean any_3g = uids3g.indexOf(SPECIAL_UID_ANY) >= 0;
  260 + final boolean any_wifi = uidsWifi.indexOf(SPECIAL_UID_ANY) >= 0;
  261 + if (whitelist && !any_wifi) {
  262 + // When "white listing" wifi, we need to ensure that the dhcp and wifi users are allowed
  263 + int uid = android.os.Process.getUidForName("dhcp");
  264 + if (uid != -1) {
  265 + script.append("# dhcp user\n");
  266 + script.append("$IPTABLES -A droidwall-wifi -m owner --uid-owner ").append(uid).append(" -j RETURN || exit\n");
  267 + }
  268 + uid = android.os.Process.getUidForName("wifi");
  269 + if (uid != -1) {
  270 + script.append("# wifi user\n");
  271 + script.append("$IPTABLES -A droidwall-wifi -m owner --uid-owner ").append(uid).append(" -j RETURN || exit\n");
  272 + }
  273 + }
  274 + if (any_3g) {
  275 + if (blacklist) {
  276 + /* block any application on this interface */
  277 + script.append("$IPTABLES -A droidwall-3g -j ").append(targetRule).append(" || exit\n");
  278 + }
  279 + } else {
  280 + /* release/block individual applications on this interface */
  281 + if(isRoaming(ctx)) {
  282 + for (final Integer uid : uidsRoam) {
  283 + if (uid >= 0) script.append("$IPTABLES -A droidwall-3g -m owner --uid-owner ").append(uid).append(" -j ").append(targetRule).append(" || exit\n");
  284 + }
  285 +
  286 + } else {
  287 + for (final Integer uid : uids3g) {
  288 + if (uid >= 0) script.append("$IPTABLES -A droidwall-3g -m owner --uid-owner ").append(uid).append(" -j ").append(targetRule).append(" || exit\n");
  289 + //Roaming
  290 + if(isRoaming(ctx)){
  291 + //iptables -A OUTPUT -o pdp0 -j REJECT
  292 + }
  293 + }
  294 + }
  295 + }
  296 + if (any_wifi) {
  297 + if (blacklist) {
  298 + /* block any application on this interface */
  299 + script.append("$IPTABLES -A droidwall-wifi -j ").append(targetRule).append(" || exit\n");
  300 + }
  301 + } else {
  302 + /* release/block individual applications on this interface */
  303 + for (final Integer uid : uidsWifi) {
  304 + if (uid >= 0) script.append("$IPTABLES -A droidwall-wifi -m owner --uid-owner ").append(uid).append(" -j ").append(targetRule).append(" || exit\n");
  305 + }
  306 + }
  307 + if (whitelist) {
  308 + if (!any_3g) {
  309 + if (uids3g.indexOf(SPECIAL_UID_KERNEL) >= 0) {
  310 + script.append("# hack to allow kernel packets on white-list\n");
  311 + script.append("$IPTABLES -A droidwall-3g -m owner --uid-owner 0:999999999 -j droidwall-reject || exit\n");
  312 + } else {
  313 + script.append("$IPTABLES -A droidwall-3g -j droidwall-reject || exit\n");
  314 + }
  315 + }
  316 + if (!any_wifi) {
  317 + if (uidsWifi.indexOf(SPECIAL_UID_KERNEL) >= 0) {
  318 + script.append("# hack to allow kernel packets on white-list\n");
  319 + script.append("$IPTABLES -A droidwall-wifi -m owner --uid-owner 0:999999999 -j droidwall-reject || exit\n");
  320 + } else {
  321 + script.append("$IPTABLES -A droidwall-wifi -j droidwall-reject || exit\n");
  322 + }
  323 + }
  324 + } else {
  325 + if (uids3g.indexOf(SPECIAL_UID_KERNEL) >= 0) {
  326 + script.append("# hack to BLOCK kernel packets on black-list\n");
  327 + script.append("$IPTABLES -A droidwall-3g -m owner --uid-owner 0:999999999 -j RETURN || exit\n");
  328 + script.append("$IPTABLES -A droidwall-3g -j droidwall-reject || exit\n");
  329 + }
  330 + if (uidsWifi.indexOf(SPECIAL_UID_KERNEL) >= 0) {
  331 + script.append("# hack to BLOCK kernel packets on black-list\n");
  332 + script.append("$IPTABLES -A droidwall-wifi -m owner --uid-owner 0:999999999 -j RETURN || exit\n");
  333 + script.append("$IPTABLES -A droidwall-wifi -j droidwall-reject || exit\n");
  334 + }
  335 + }
  336 + final StringBuilder res = new StringBuilder();
  337 + code = runScriptAsRoot(ctx, script.toString(), res);
  338 + if (showErrors && code != 0) {
  339 + String msg = res.toString();
  340 + Log.e("AFWall+", msg);
  341 + // Remove unnecessary help message from output
  342 + if (msg.indexOf("\nTry `iptables -h' or 'iptables --help' for more information.") != -1) {
  343 + msg = msg.replace("\nTry `iptables -h' or 'iptables --help' for more information.", "");
  344 + }
  345 + alert(ctx, "Error applying iptables rules. Exit code: " + code + "\n\n" + msg.trim());
  346 + } else {
  347 + return true;
  348 + }
  349 + } catch (Exception e) {
  350 + if (showErrors) alert(ctx, "error refreshing iptables: " + e);
  351 + }
  352 + return false;
  353 + }
  354 + /**
  355 + * Purge and re-add all saved rules (not in-memory ones).
  356 + * This is much faster than just calling "applyIptablesRules", since it don't need to read installed applications.
  357 + * @param ctx application context (mandatory)
  358 + * @param showErrors indicates if errors should be alerted
  359 + */
  360 + public static boolean applySavedIptablesRules(Context ctx, boolean showErrors) {
  361 + if (ctx == null) {
  362 + return false;
  363 + }
  364 + final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0);
  365 + final String savedUids_wifi = prefs.getString(PREF_WIFI_UIDS, "");
  366 + final String savedUids_3g = prefs.getString(PREF_3G_UIDS, "");
  367 + final String savedUids_roam = prefs.getString(PREF_ROAMING_UIDS, "");
  368 + final List<Integer> uids_wifi = new LinkedList<Integer>();
  369 + if (savedUids_wifi.length() > 0) {
  370 + // Check which applications are allowed on wifi
  371 + final StringTokenizer tok = new StringTokenizer(savedUids_wifi, "|");
  372 + while (tok.hasMoreTokens()) {
  373 + final String uid = tok.nextToken();
  374 + if (!uid.equals("")) {
  375 + try {
  376 + uids_wifi.add(Integer.parseInt(uid));
  377 + } catch (Exception ex) {
  378 + }
  379 + }
  380 + }
  381 + }
  382 + final List<Integer> uids_3g = new LinkedList<Integer>();
  383 + if (savedUids_3g.length() > 0) {
  384 + // Check which applications are allowed on 2G/3G
  385 + final StringTokenizer tok = new StringTokenizer(savedUids_3g, "|");
  386 + while (tok.hasMoreTokens()) {
  387 + final String uid = tok.nextToken();
  388 + if (!uid.equals("")) {
  389 + try {
  390 + uids_3g.add(Integer.parseInt(uid));
  391 + } catch (Exception ex) {
  392 + }
  393 + }
  394 + }
  395 + }
  396 + final List<Integer> uids_roam = new LinkedList<Integer>();
  397 + if (savedUids_roam.length() > 0) {
  398 + // Check which applications are allowed on 2G/3G
  399 + final StringTokenizer tok = new StringTokenizer(savedUids_roam, "|");
  400 + while (tok.hasMoreTokens()) {
  401 + final String uid = tok.nextToken();
  402 + if (!uid.equals("")) {
  403 + try {
  404 + uids_3g.add(Integer.parseInt(uid));
  405 + } catch (Exception ex) {
  406 + }
  407 + }
  408 + }
  409 + }
  410 + return applyIptablesRulesImpl(ctx, uids_wifi, uids_3g, uids_roam, showErrors);
  411 + }
  412 +
  413 + /**
  414 + * Purge and re-add all rules.
  415 + * @param ctx application context (mandatory)
  416 + * @param showErrors indicates if errors should be alerted
  417 + */
  418 + public static boolean applyIptablesRules(Context ctx, boolean showErrors) {
  419 + if (ctx == null) {
  420 + return false;
  421 + }
  422 + saveRules(ctx);
  423 + return applySavedIptablesRules(ctx, showErrors);
  424 + }
  425 +
  426 + /**
  427 + * Save current rules using the preferences storage.
  428 + * @param ctx application context (mandatory)
  429 + */
  430 + public static void saveRules(Context ctx) {
  431 + final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_NAME, 0);
  432 + final DroidApp[] apps = getApps(ctx);
  433 + // Builds a pipe-separated list of names
  434 + final StringBuilder newuids_wifi = new StringBuilder();
  435 + final StringBuilder newuids_3g = new StringBuilder();
  436 + final StringBuilder newuids_roam = new StringBuilder();
  437 + for (int i=0; i<apps.length; i++) {
  438 + if (apps[i].selected_wifi) {
  439 + if (newuids_wifi.length() != 0) newuids_wifi.append('|');
  440 + newuids_wifi.append(apps[i].uid);
  441 + }
  442 + if (apps[i].selected_3g) {
  443 + if (newuids_3g.length() != 0) newuids_3g.append('|');
  444 + newuids_3g.append(apps[i].uid);
  445 + }
  446 + if (apps[i].selected_roam) {
  447 + if (newuids_roam.length() != 0) newuids_roam.append('|');
  448 + newuids_roam.append(apps[i].uid);
  449 + }
  450 +
  451 + }
  452 + // save the new list of UIDs
  453 + final Editor edit = prefs.edit();
  454 + edit.putString(PREF_WIFI_UIDS, newuids_wifi.toString());
  455 + edit.putString(PREF_3G_UIDS, newuids_3g.toString());
  456 + edit.putString(PREF_ROAMING_UIDS, newuids_roam.toString());
  457 + edit.commit();
  458 + }
  459 +
  460 + /**
  461 + * Purge all iptables rules.
  462 + * @param ctx mandatory context
  463 + * @param showErrors indicates if errors should be alerted
  464 + * @return true if the rules were purged
  465 + */
  466 + public static boolean purgeIptables(Context ctx, boolean showErrors) {
  467 + final StringBuilder res = new StringBuilder();
  468 + try {
  469 + assertBinaries(ctx, showErrors);
  470 + // Custom "shutdown" script
  471 + final String customScript = ctx.getSharedPreferences(Api.PREFS_NAME, 0).getString(Api.PREF_CUSTOMSCRIPT2, "");
  472 + final StringBuilder script = new StringBuilder();
  473 + script.append(scriptHeader(ctx));
  474 + script.append("" +
  475 + "$IPTABLES -F droidwall\n" +
  476 + "$IPTABLES -F droidwall-reject\n" +
  477 + "$IPTABLES -F droidwall-3g\n" +
  478 + "$IPTABLES -F droidwall-wifi\n" +
  479 + "");
  480 + if (customScript.length() > 0) {
  481 + script.append("\n# BEGIN OF CUSTOM SCRIPT (user-defined)\n");
  482 + script.append(customScript);
  483 + script.append("\n# END OF CUSTOM SCRIPT (user-defined)\n\n");
  484 + }
  485 + int code = runScriptAsRoot(ctx, script.toString(), res);
  486 + if (code == -1) {
  487 + if (showErrors) alert(ctx, "Error purging iptables. exit code: " + code + "\n" + res);
  488 + return false;
  489 + }
  490 + return true;
  491 + } catch (Exception e) {
  492 + if (showErrors) alert(ctx, "Error purging iptables: " + e);
  493 + return false;
  494 + }
  495 + }
  496 +
  497 + /**
  498 + * Display iptables rules output
  499 + * @param ctx application context
  500 + */
  501 + public static void showIptablesRules(Context ctx) {
  502 + try {
  503 + final StringBuilder res = new StringBuilder();
  504 + runScriptAsRoot(ctx, scriptHeader(ctx) +
  505 + "$ECHO $IPTABLES\n" +
  506 + "$IPTABLES -L -v -n\n", res);
  507 + alert(ctx, res);
  508 + } catch (Exception e) {
  509 + alert(ctx, "error: " + e);
  510 + }
  511 + }
  512 +
  513 + /**
  514 + * Display logs
  515 + * @param ctx application context
  516 + * @return true if the clogs were cleared
  517 + */
  518 + public static boolean clearLog(Context ctx) {
  519 + try {
  520 + final StringBuilder res = new StringBuilder();
  521 + int code = runScriptAsRoot(ctx, "dmesg -c >/dev/null || exit\n", res);
  522 + if (code != 0) {
  523 + alert(ctx, res);
  524 + return false;
  525 + }
  526 + return true;
  527 + } catch (Exception e) {
  528 + alert(ctx, "error: " + e);
  529 + }
  530 + return false;
  531 + }
  532 + /**
  533 + * Display logs
  534 + * @param ctx application context