aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFil <fil.bergamo@riseup.net>2017-12-17 12:59:08 +0100
committerFil <fil.bergamo@riseup.net>2017-12-17 13:32:16 +0100
commitbf2cc09307e404a8d6de0bfd77e1e8366e1a0497 (patch)
treea402e530fbba54a1a50c3fae5ef63a8c33204a5c
parent4a005f9be829b18438f5343d5104c840efd36ea5 (diff)
downloadRepWifiApp-bf2cc09307e404a8d6de0bfd77e1e8366e1a0497.tar.gz
RepWifiApp-bf2cc09307e404a8d6de0bfd77e1e8366e1a0497.tar.bz2
RepWifiApp-bf2cc09307e404a8d6de0bfd77e1e8366e1a0497.zip
new version v0.6 - new features plus code cleanupv0.6
* NEW: introduced static IP/gateway settings per network. * NEW: added OpenVPN support via interaction with de.blinkt.openvpn * completed french translation by Nicola Spanti. * improved stability by changing dhcpcd options. * better shell command handling, with direct output reading. * better network storage, based on JSON instead of TSV. * cleaned up engine's code. * clean up xml styling files * replaced all string litterals with @string resoruces
-rw-r--r--CHANGELOG11
-rw-r--r--TODO6
-rw-r--r--app/AndroidManifest.xml15
-rw-r--r--app/gen/de/blinkt/openvpn/api/IOpenVPNAPIService.java545
-rw-r--r--app/gen/de/blinkt/openvpn/api/IOpenVPNStatusCallback.java107
-rw-r--r--app/gen/fil/libre/repwifiapp/R.java335
-rw-r--r--app/res/drawable/fil_logo.pngbin0 -> 21529 bytes
-rw-r--r--app/res/layout/activity_credits.xml36
-rw-r--r--app/res/layout/activity_ipv4_settings.xml126
-rw-r--r--app/res/layout/activity_long_task.xml1
-rw-r--r--app/res/layout/activity_network_details.xml27
-rw-r--r--app/res/layout/activity_vpn_settings.xml55
-rw-r--r--app/res/menu/activity_ipv4_settings.xml9
-rw-r--r--app/res/menu/activity_main.xml10
-rw-r--r--app/res/menu/activity_vpn_settings.xml9
-rw-r--r--app/res/values-fr/strings.xml106
-rw-r--r--app/res/values-fr/strings_activity_input_password.xml29
-rw-r--r--app/res/values-fr/strings_activity_settings.xml56
-rw-r--r--app/res/values/strings.xml81
-rw-r--r--app/res/values/strings_activity_input_password.xml11
-rw-r--r--app/res/values/strings_activity_settings.xml43
-rw-r--r--app/res/values/styles.xml2
-rw-r--r--app/res/xml/debug_settings.xml9
-rw-r--r--app/res/xml/general_settings.xml26
-rw-r--r--app/res/xml/settings_headers.xml8
-rw-r--r--app/src/de/blinkt/openvpn/api/APIVpnProfile.aidl3
-rw-r--r--app/src/de/blinkt/openvpn/api/APIVpnProfile.java61
-rw-r--r--app/src/de/blinkt/openvpn/api/DO_NOT_RENAME1
-rw-r--r--app/src/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl66
-rw-r--r--app/src/de/blinkt/openvpn/api/IOpenVPNStatusCallback.aidl13
-rw-r--r--app/src/fil/libre/repwifiapp/ActivityLauncher.java46
-rw-r--r--app/src/fil/libre/repwifiapp/Commons.java134
-rw-r--r--app/src/fil/libre/repwifiapp/RepWifiIntentReceiver.java3
-rw-r--r--app/src/fil/libre/repwifiapp/activities/InputPasswordActivity.java4
-rw-r--r--app/src/fil/libre/repwifiapp/activities/InputSsidActivity.java4
-rw-r--r--app/src/fil/libre/repwifiapp/activities/Ipv4SettingsActivity.java181
-rw-r--r--app/src/fil/libre/repwifiapp/activities/LongTaskActivity.java37
-rw-r--r--app/src/fil/libre/repwifiapp/activities/MainActivity.java67
-rw-r--r--app/src/fil/libre/repwifiapp/activities/MenuEnabledActivity.java88
-rw-r--r--app/src/fil/libre/repwifiapp/activities/NetworkDetailsActivity.java20
-rw-r--r--app/src/fil/libre/repwifiapp/activities/SelectNetworkActivity.java10
-rw-r--r--app/src/fil/libre/repwifiapp/activities/SettingsActivity.java43
-rw-r--r--app/src/fil/libre/repwifiapp/activities/ShowStatusActivity.java183
-rw-r--r--app/src/fil/libre/repwifiapp/activities/VpnSettingsActivity.java201
-rw-r--r--app/src/fil/libre/repwifiapp/helpers/AccessPointInfo.java173
-rw-r--r--app/src/fil/libre/repwifiapp/helpers/ConnectionStatus.java8
-rw-r--r--app/src/fil/libre/repwifiapp/helpers/DhcpSettings.java205
-rw-r--r--app/src/fil/libre/repwifiapp/helpers/Engine.java415
-rw-r--r--app/src/fil/libre/repwifiapp/helpers/Engine6p0.java249
-rw-r--r--app/src/fil/libre/repwifiapp/helpers/IEngine.java8
-rw-r--r--app/src/fil/libre/repwifiapp/helpers/NetworkManager.java170
-rw-r--r--app/src/fil/libre/repwifiapp/helpers/OpenVpnManager.java237
-rw-r--r--app/src/fil/libre/repwifiapp/helpers/RootCommand.java68
-rw-r--r--app/src/fil/libre/repwifiapp/helpers/ShellCommand.java23
-rw-r--r--app/src/fil/libre/repwifiapp/helpers/Utils.java231
-rw-r--r--app/src/fil/libre/repwifiapp/helpers/WpaCli.java263
-rw-r--r--app/src/fil/libre/repwifiapp/helpers/WpaSupplicant.java65
57 files changed, 3819 insertions, 1124 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 8d1eaf6..a1b22b7 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,14 @@
+## [v0.6] - 2017-12-17
+* NEW: introduced static IP/gateway settings per network.
+* NEW: added OpenVPN support via interaction with de.blinkt.openvpn
+* NEW: french translation by Nicola Spanti.
+* improved stability by changing dhcpcd options.
+* better shell command handling, with direct output reading.
+* better network storage, based on JSON instead of TSV.
+* cleaned up engine's code.
+* clean up xml styling files
+* replaced all string litterals with @string resoruces
+
## [v0.5] - 2017-08-25
* removed dependency on prebuilt android-support-v4.jar.
* introduced support for hidden networks.
diff --git a/TODO b/TODO
index be6a7c9..9d2e86f 100644
--- a/TODO
+++ b/TODO
@@ -1,9 +1,5 @@
TODO
-as of 2017-08-25
+as of 2017-12-17
-*) clean up engine's code
*) turn backend engine into a service
*) introduce support for EAP authentication (if possible at all)
-*) publish on fdroid
-*) clean up xml styling files
-*) replace all string litterals with @string resoruces
diff --git a/app/AndroidManifest.xml b/app/AndroidManifest.xml
index 891cca9..c20db8a 100644
--- a/app/AndroidManifest.xml
+++ b/app/AndroidManifest.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="fil.libre.repwifiapp"
- android:versionCode="3"
- android:versionName="0.5" >
+ android:versionCode="4"
+ android:versionName="0.6" >
<uses-sdk
android:minSdkVersion="17"
@@ -48,7 +48,7 @@
<activity
android:name="fil.libre.repwifiapp.activities.MainActivity"
android:label="@string/app_name"
- android:launchMode="singleTop"
+ android:launchMode="singleTop"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -87,6 +87,15 @@
android:name="fil.libre.repwifiapp.activities.InputSsidActivity"
android:label="@string/title_activity_input_ssid" >
</activity>
+ <activity
+ android:name="fil.libre.repwifiapp.activities.Ipv4SettingsActivity"
+ android:label="@string/title_activity_ipv4_settings" >
+ </activity>
+ <activity
+ android:name="fil.libre.repwifiapp.activities.VpnSettingsActivity"
+ android:label="@string/title_activity_vpn_settings" >
+ </activity>
+ <service android:name="de.blinkt.openvpn.api.IOpenVPNAPIService"></service>
</application>
</manifest> \ No newline at end of file
diff --git a/app/gen/de/blinkt/openvpn/api/IOpenVPNAPIService.java b/app/gen/de/blinkt/openvpn/api/IOpenVPNAPIService.java
new file mode 100644
index 0000000..7f11034
--- /dev/null
+++ b/app/gen/de/blinkt/openvpn/api/IOpenVPNAPIService.java
@@ -0,0 +1,545 @@
+/*
+ * This file is auto-generated. DO NOT MODIFY.
+ * Original file: /home/fil/workspace/RepWifiApp/src/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl
+ */
+package de.blinkt.openvpn.api;
+public interface IOpenVPNAPIService extends android.os.IInterface
+{
+/** Local-side IPC implementation stub class. */
+public static abstract class Stub extends android.os.Binder implements de.blinkt.openvpn.api.IOpenVPNAPIService
+{
+private static final java.lang.String DESCRIPTOR = "de.blinkt.openvpn.api.IOpenVPNAPIService";
+/** Construct the stub at attach it to the interface. */
+public Stub()
+{
+this.attachInterface(this, DESCRIPTOR);
+}
+/**
+ * Cast an IBinder object into an de.blinkt.openvpn.api.IOpenVPNAPIService interface,
+ * generating a proxy if needed.
+ */
+public static de.blinkt.openvpn.api.IOpenVPNAPIService asInterface(android.os.IBinder obj)
+{
+if ((obj==null)) {
+return null;
+}
+android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
+if (((iin!=null)&&(iin instanceof de.blinkt.openvpn.api.IOpenVPNAPIService))) {
+return ((de.blinkt.openvpn.api.IOpenVPNAPIService)iin);
+}
+return new de.blinkt.openvpn.api.IOpenVPNAPIService.Stub.Proxy(obj);
+}
+@Override public android.os.IBinder asBinder()
+{
+return this;
+}
+@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
+{
+switch (code)
+{
+case INTERFACE_TRANSACTION:
+{
+reply.writeString(DESCRIPTOR);
+return true;
+}
+case TRANSACTION_getProfiles:
+{
+data.enforceInterface(DESCRIPTOR);
+java.util.List<de.blinkt.openvpn.api.APIVpnProfile> _result = this.getProfiles();
+reply.writeNoException();
+reply.writeTypedList(_result);
+return true;
+}
+case TRANSACTION_startProfile:
+{
+data.enforceInterface(DESCRIPTOR);
+java.lang.String _arg0;
+_arg0 = data.readString();
+this.startProfile(_arg0);
+reply.writeNoException();
+return true;
+}
+case TRANSACTION_addVPNProfile:
+{
+data.enforceInterface(DESCRIPTOR);
+java.lang.String _arg0;
+_arg0 = data.readString();
+java.lang.String _arg1;
+_arg1 = data.readString();
+boolean _result = this.addVPNProfile(_arg0, _arg1);
+reply.writeNoException();
+reply.writeInt(((_result)?(1):(0)));
+return true;
+}
+case TRANSACTION_startVPN:
+{
+data.enforceInterface(DESCRIPTOR);
+java.lang.String _arg0;
+_arg0 = data.readString();
+this.startVPN(_arg0);
+reply.writeNoException();
+return true;
+}
+case TRANSACTION_prepare:
+{
+data.enforceInterface(DESCRIPTOR);
+java.lang.String _arg0;
+_arg0 = data.readString();
+android.content.Intent _result = this.prepare(_arg0);
+reply.writeNoException();
+if ((_result!=null)) {
+reply.writeInt(1);
+_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+}
+else {
+reply.writeInt(0);
+}
+return true;
+}
+case TRANSACTION_prepareVPNService:
+{
+data.enforceInterface(DESCRIPTOR);
+android.content.Intent _result = this.prepareVPNService();
+reply.writeNoException();
+if ((_result!=null)) {
+reply.writeInt(1);
+_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+}
+else {
+reply.writeInt(0);
+}
+return true;
+}
+case TRANSACTION_disconnect:
+{
+data.enforceInterface(DESCRIPTOR);
+this.disconnect();
+reply.writeNoException();
+return true;
+}
+case TRANSACTION_pause:
+{
+data.enforceInterface(DESCRIPTOR);
+this.pause();
+reply.writeNoException();
+return true;
+}
+case TRANSACTION_resume:
+{
+data.enforceInterface(DESCRIPTOR);
+this.resume();
+reply.writeNoException();
+return true;
+}
+case TRANSACTION_registerStatusCallback:
+{
+data.enforceInterface(DESCRIPTOR);
+de.blinkt.openvpn.api.IOpenVPNStatusCallback _arg0;
+_arg0 = de.blinkt.openvpn.api.IOpenVPNStatusCallback.Stub.asInterface(data.readStrongBinder());
+this.registerStatusCallback(_arg0);
+reply.writeNoException();
+return true;
+}
+case TRANSACTION_unregisterStatusCallback:
+{
+data.enforceInterface(DESCRIPTOR);
+de.blinkt.openvpn.api.IOpenVPNStatusCallback _arg0;
+_arg0 = de.blinkt.openvpn.api.IOpenVPNStatusCallback.Stub.asInterface(data.readStrongBinder());
+this.unregisterStatusCallback(_arg0);
+reply.writeNoException();
+return true;
+}
+case TRANSACTION_removeProfile:
+{
+data.enforceInterface(DESCRIPTOR);
+java.lang.String _arg0;
+_arg0 = data.readString();
+this.removeProfile(_arg0);
+reply.writeNoException();
+return true;
+}
+case TRANSACTION_protectSocket:
+{
+data.enforceInterface(DESCRIPTOR);
+android.os.ParcelFileDescriptor _arg0;
+if ((0!=data.readInt())) {
+_arg0 = android.os.ParcelFileDescriptor.CREATOR.createFromParcel(data);
+}
+else {
+_arg0 = null;
+}
+boolean _result = this.protectSocket(_arg0);
+reply.writeNoException();
+reply.writeInt(((_result)?(1):(0)));
+return true;
+}
+case TRANSACTION_addNewVPNProfile:
+{
+data.enforceInterface(DESCRIPTOR);
+java.lang.String _arg0;
+_arg0 = data.readString();
+boolean _arg1;
+_arg1 = (0!=data.readInt());
+java.lang.String _arg2;
+_arg2 = data.readString();
+de.blinkt.openvpn.api.APIVpnProfile _result = this.addNewVPNProfile(_arg0, _arg1, _arg2);
+reply.writeNoException();
+if ((_result!=null)) {
+reply.writeInt(1);
+_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+}
+else {
+reply.writeInt(0);
+}
+return true;
+}
+}
+return super.onTransact(code, data, reply, flags);
+}
+private static class Proxy implements de.blinkt.openvpn.api.IOpenVPNAPIService
+{
+private android.os.IBinder mRemote;
+Proxy(android.os.IBinder remote)
+{
+mRemote = remote;
+}
+@Override public android.os.IBinder asBinder()
+{
+return mRemote;
+}
+public java.lang.String getInterfaceDescriptor()
+{
+return DESCRIPTOR;
+}
+@Override public java.util.List<de.blinkt.openvpn.api.APIVpnProfile> getProfiles() throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+java.util.List<de.blinkt.openvpn.api.APIVpnProfile> _result;
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_getProfiles, _data, _reply, 0);
+_reply.readException();
+_result = _reply.createTypedArrayList(de.blinkt.openvpn.api.APIVpnProfile.CREATOR);
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+return _result;
+}
+@Override public void startProfile(java.lang.String profileUUID) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+_data.writeString(profileUUID);
+mRemote.transact(Stub.TRANSACTION_startProfile, _data, _reply, 0);
+_reply.readException();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+}
+/** Use a profile with all certificates etc. embedded,
+ * old version which does not return the UUID of the addded profile, see
+ * below for a version that return the UUID on add */
+@Override public boolean addVPNProfile(java.lang.String name, java.lang.String config) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+boolean _result;
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+_data.writeString(name);
+_data.writeString(config);
+mRemote.transact(Stub.TRANSACTION_addVPNProfile, _data, _reply, 0);
+_reply.readException();
+_result = (0!=_reply.readInt());
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+return _result;
+}
+/** start a profile using a config as inline string. Make sure that all needed data is inlined,
+ * e.g., using <ca>...</ca> or <auth-user-data>...</auth-user-data>
+ * See the OpenVPN manual page for more on inlining files */
+@Override public void startVPN(java.lang.String inlineconfig) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+_data.writeString(inlineconfig);
+mRemote.transact(Stub.TRANSACTION_startVPN, _data, _reply, 0);
+_reply.readException();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+}
+/** This permission framework is used to avoid confused deputy style attack to the VPN
+ * calling this will give null if the app is allowed to use the external API and an Intent
+ * that can be launched to request permissions otherwise */
+@Override public android.content.Intent prepare(java.lang.String packagename) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+android.content.Intent _result;
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+_data.writeString(packagename);
+mRemote.transact(Stub.TRANSACTION_prepare, _data, _reply, 0);
+_reply.readException();
+if ((0!=_reply.readInt())) {
+_result = android.content.Intent.CREATOR.createFromParcel(_reply);
+}
+else {
+_result = null;
+}
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+return _result;
+}
+/** Used to trigger to the Android VPN permission dialog (VPNService.prepare()) in advance,
+ * if this return null OpenVPN for ANdroid already has the permissions otherwise you can start the returned Intent
+ * to let OpenVPN for Android request the permission */
+@Override public android.content.Intent prepareVPNService() throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+android.content.Intent _result;
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_prepareVPNService, _data, _reply, 0);
+_reply.readException();
+if ((0!=_reply.readInt())) {
+_result = android.content.Intent.CREATOR.createFromParcel(_reply);
+}
+else {
+_result = null;
+}
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+return _result;
+}
+/* Disconnect the VPN */
+@Override public void disconnect() throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_disconnect, _data, _reply, 0);
+_reply.readException();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+}
+/* Pause the VPN (same as using the pause feature in the notifcation bar) */
+@Override public void pause() throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_pause, _data, _reply, 0);
+_reply.readException();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+}
+/* Resume the VPN (same as using the pause feature in the notifcation bar) */
+@Override public void resume() throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+mRemote.transact(Stub.TRANSACTION_resume, _data, _reply, 0);
+_reply.readException();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+}
+/**
+ * Registers to receive OpenVPN Status Updates
+ */
+@Override public void registerStatusCallback(de.blinkt.openvpn.api.IOpenVPNStatusCallback cb) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+_data.writeStrongBinder((((cb!=null))?(cb.asBinder()):(null)));
+mRemote.transact(Stub.TRANSACTION_registerStatusCallback, _data, _reply, 0);
+_reply.readException();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+}
+/**
+ * Remove a previously registered callback interface.
+ */
+@Override public void unregisterStatusCallback(de.blinkt.openvpn.api.IOpenVPNStatusCallback cb) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+_data.writeStrongBinder((((cb!=null))?(cb.asBinder()):(null)));
+mRemote.transact(Stub.TRANSACTION_unregisterStatusCallback, _data, _reply, 0);
+_reply.readException();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+}
+/** Remove a profile by UUID */
+@Override public void removeProfile(java.lang.String profileUUID) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+_data.writeString(profileUUID);
+mRemote.transact(Stub.TRANSACTION_removeProfile, _data, _reply, 0);
+_reply.readException();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+}
+/** Request a socket to be protected as a VPN socket would be. Useful for creating
+ * a helper socket for an app controlling OpenVPN
+ * Before calling this function you should make sure OpenVPN for Android may actually
+ * this function by checking if prepareVPNService returns null; */
+@Override public boolean protectSocket(android.os.ParcelFileDescriptor fd) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+boolean _result;
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+if ((fd!=null)) {
+_data.writeInt(1);
+fd.writeToParcel(_data, 0);
+}
+else {
+_data.writeInt(0);
+}
+mRemote.transact(Stub.TRANSACTION_protectSocket, _data, _reply, 0);
+_reply.readException();
+_result = (0!=_reply.readInt());
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+return _result;
+}
+/** Use a profile with all certificates etc. embedded */
+@Override public de.blinkt.openvpn.api.APIVpnProfile addNewVPNProfile(java.lang.String name, boolean userEditable, java.lang.String config) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+de.blinkt.openvpn.api.APIVpnProfile _result;
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+_data.writeString(name);
+_data.writeInt(((userEditable)?(1):(0)));
+_data.writeString(config);
+mRemote.transact(Stub.TRANSACTION_addNewVPNProfile, _data, _reply, 0);
+_reply.readException();
+if ((0!=_reply.readInt())) {
+_result = de.blinkt.openvpn.api.APIVpnProfile.CREATOR.createFromParcel(_reply);
+}
+else {
+_result = null;
+}
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+return _result;
+}
+}
+static final int TRANSACTION_getProfiles = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+static final int TRANSACTION_startProfile = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
+static final int TRANSACTION_addVPNProfile = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
+static final int TRANSACTION_startVPN = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
+static final int TRANSACTION_prepare = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
+static final int TRANSACTION_prepareVPNService = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
+static final int TRANSACTION_disconnect = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
+static final int TRANSACTION_pause = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
+static final int TRANSACTION_resume = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);
+static final int TRANSACTION_registerStatusCallback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 9);
+static final int TRANSACTION_unregisterStatusCallback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 10);
+static final int TRANSACTION_removeProfile = (android.os.IBinder.FIRST_CALL_TRANSACTION + 11);
+static final int TRANSACTION_protectSocket = (android.os.IBinder.FIRST_CALL_TRANSACTION + 12);
+static final int TRANSACTION_addNewVPNProfile = (android.os.IBinder.FIRST_CALL_TRANSACTION + 13);
+}
+public java.util.List<de.blinkt.openvpn.api.APIVpnProfile> getProfiles() throws android.os.RemoteException;
+public void startProfile(java.lang.String profileUUID) throws android.os.RemoteException;
+/** Use a profile with all certificates etc. embedded,
+ * old version which does not return the UUID of the addded profile, see
+ * below for a version that return the UUID on add */
+public boolean addVPNProfile(java.lang.String name, java.lang.String config) throws android.os.RemoteException;
+/** start a profile using a config as inline string. Make sure that all needed data is inlined,
+ * e.g., using <ca>...</ca> or <auth-user-data>...</auth-user-data>
+ * See the OpenVPN manual page for more on inlining files */
+public void startVPN(java.lang.String inlineconfig) throws android.os.RemoteException;
+/** This permission framework is used to avoid confused deputy style attack to the VPN
+ * calling this will give null if the app is allowed to use the external API and an Intent
+ * that can be launched to request permissions otherwise */
+public android.content.Intent prepare(java.lang.String packagename) throws android.os.RemoteException;
+/** Used to trigger to the Android VPN permission dialog (VPNService.prepare()) in advance,
+ * if this return null OpenVPN for ANdroid already has the permissions otherwise you can start the returned Intent
+ * to let OpenVPN for Android request the permission */
+public android.content.Intent prepareVPNService() throws android.os.RemoteException;
+/* Disconnect the VPN */
+public void disconnect() throws android.os.RemoteException;
+/* Pause the VPN (same as using the pause feature in the notifcation bar) */
+public void pause() throws android.os.RemoteException;
+/* Resume the VPN (same as using the pause feature in the notifcation bar) */
+public void resume() throws android.os.RemoteException;
+/**
+ * Registers to receive OpenVPN Status Updates
+ */
+public void registerStatusCallback(de.blinkt.openvpn.api.IOpenVPNStatusCallback cb) throws android.os.RemoteException;
+/**
+ * Remove a previously registered callback interface.
+ */
+public void unregisterStatusCallback(de.blinkt.openvpn.api.IOpenVPNStatusCallback cb) throws android.os.RemoteException;
+/** Remove a profile by UUID */
+public void removeProfile(java.lang.String profileUUID) throws android.os.RemoteException;
+/** Request a socket to be protected as a VPN socket would be. Useful for creating
+ * a helper socket for an app controlling OpenVPN
+ * Before calling this function you should make sure OpenVPN for Android may actually
+ * this function by checking if prepareVPNService returns null; */
+public boolean protectSocket(android.os.ParcelFileDescriptor fd) throws android.os.RemoteException;
+/** Use a profile with all certificates etc. embedded */
+public de.blinkt.openvpn.api.APIVpnProfile addNewVPNProfile(java.lang.String name, boolean userEditable, java.lang.String config) throws android.os.RemoteException;
+}
diff --git a/app/gen/de/blinkt/openvpn/api/IOpenVPNStatusCallback.java b/app/gen/de/blinkt/openvpn/api/IOpenVPNStatusCallback.java
new file mode 100644
index 0000000..fde3f75
--- /dev/null
+++ b/app/gen/de/blinkt/openvpn/api/IOpenVPNStatusCallback.java
@@ -0,0 +1,107 @@
+/*
+ * This file is auto-generated. DO NOT MODIFY.
+ * Original file: /home/fil/workspace/RepWifiApp/src/de/blinkt/openvpn/api/IOpenVPNStatusCallback.aidl
+ */
+package de.blinkt.openvpn.api;
+/**
+ * Example of a callback interface used by IRemoteService to send
+ * synchronous notifications back to its clients. Note that this is a
+ * one-way interface so the server does not block waiting for the client.
+ */
+public interface IOpenVPNStatusCallback extends android.os.IInterface
+{
+/** Local-side IPC implementation stub class. */
+public static abstract class Stub extends android.os.Binder implements de.blinkt.openvpn.api.IOpenVPNStatusCallback
+{
+private static final java.lang.String DESCRIPTOR = "de.blinkt.openvpn.api.IOpenVPNStatusCallback";
+/** Construct the stub at attach it to the interface. */
+public Stub()
+{
+this.attachInterface(this, DESCRIPTOR);
+}
+/**
+ * Cast an IBinder object into an de.blinkt.openvpn.api.IOpenVPNStatusCallback interface,
+ * generating a proxy if needed.
+ */
+public static de.blinkt.openvpn.api.IOpenVPNStatusCallback asInterface(android.os.IBinder obj)
+{
+if ((obj==null)) {
+return null;
+}
+android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
+if (((iin!=null)&&(iin instanceof de.blinkt.openvpn.api.IOpenVPNStatusCallback))) {
+return ((de.blinkt.openvpn.api.IOpenVPNStatusCallback)iin);
+}
+return new de.blinkt.openvpn.api.IOpenVPNStatusCallback.Stub.Proxy(obj);
+}
+@Override public android.os.IBinder asBinder()
+{
+return this;
+}
+@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
+{
+switch (code)
+{
+case INTERFACE_TRANSACTION:
+{
+reply.writeString(DESCRIPTOR);
+return true;
+}
+case TRANSACTION_newStatus:
+{
+data.enforceInterface(DESCRIPTOR);
+java.lang.String _arg0;
+_arg0 = data.readString();
+java.lang.String _arg1;
+_arg1 = data.readString();
+java.lang.String _arg2;
+_arg2 = data.readString();
+java.lang.String _arg3;
+_arg3 = data.readString();
+this.newStatus(_arg0, _arg1, _arg2, _arg3);
+return true;
+}
+}
+return super.onTransact(code, data, reply, flags);
+}
+private static class Proxy implements de.blinkt.openvpn.api.IOpenVPNStatusCallback
+{
+private android.os.IBinder mRemote;
+Proxy(android.os.IBinder remote)
+{
+mRemote = remote;
+}
+@Override public android.os.IBinder asBinder()
+{
+return mRemote;
+}
+public java.lang.String getInterfaceDescriptor()
+{
+return DESCRIPTOR;
+}
+/**
+ * Called when the service has a new status for you.
+ */
+@Override public void newStatus(java.lang.String uuid, java.lang.String state, java.lang.String message, java.lang.String level) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+_data.writeString(uuid);
+_data.writeString(state);
+_data.writeString(message);
+_data.writeString(level);
+mRemote.transact(Stub.TRANSACTION_newStatus, _data, null, android.os.IBinder.FLAG_ONEWAY);
+}
+finally {
+_data.recycle();
+}
+}
+}
+static final int TRANSACTION_newStatus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+}
+/**
+ * Called when the service has a new status for you.
+ */
+public void newStatus(java.lang.String uuid, java.lang.String state, java.lang.String message, java.lang.String level) throws android.os.RemoteException;
+}
diff --git a/app/gen/fil/libre/repwifiapp/R.java b/app/gen/fil/libre/repwifiapp/R.java
index 581ff29..4874e0a 100644
--- a/app/gen/fil/libre/repwifiapp/R.java
+++ b/app/gen/fil/libre/repwifiapp/R.java
@@ -11,10 +11,6 @@ public final class R {
public static final class array {
public static final int debug_priority=0x7f050001;
public static final int debug_priority_names=0x7f050000;
- public static final int pref_example_list_titles=0x7f050002;
- public static final int pref_example_list_values=0x7f050003;
- public static final int pref_sync_frequency_titles=0x7f050004;
- public static final int pref_sync_frequency_values=0x7f050005;
}
public static final class attr {
}
@@ -33,83 +29,123 @@ public final class R {
public static final int checkmark=0x7f020002;
public static final int checkmark_frame=0x7f020003;
public static final int divider_shape=0x7f020004;
- public static final int ic_launcher_bis=0x7f020005;
- public static final int ic_stat_discon=0x7f020006;
- public static final int ic_stat_repwifi=0x7f020007;
- public static final int radio_button=0x7f020008;
- public static final int radio_frame=0x7f020009;
- public static final int repwifi_button=0x7f02000a;
- public static final int repwifi_checkbox=0x7f02000b;
- public static final int repwifi_progbar=0x7f02000c;
- public static final int repwifi_radiobutton=0x7f02000d;
- public static final int rw_prog_0=0x7f02000e;
- public static final int rw_prog_1=0x7f02000f;
- public static final int rw_prog_2=0x7f020010;
- public static final int rw_prog_3=0x7f020011;
+ public static final int fil_logo=0x7f020005;
+ public static final int ic_launcher_bis=0x7f020006;
+ public static final int ic_stat_discon=0x7f020007;
+ public static final int ic_stat_repwifi=0x7f020008;
+ public static final int radio_button=0x7f020009;
+ public static final int radio_frame=0x7f02000a;
+ public static final int repwifi_button=0x7f02000b;
+ public static final int repwifi_checkbox=0x7f02000c;
+ public static final int repwifi_progbar=0x7f02000d;
+ public static final int repwifi_radiobutton=0x7f02000e;
+ public static final int rw_prog_0=0x7f02000f;
+ public static final int rw_prog_1=0x7f020010;
+ public static final int rw_prog_2=0x7f020011;
+ public static final int rw_prog_3=0x7f020012;
}
public static final class id {
- public static final int btn_back=0x7f0a001d;
- public static final int btn_delete=0x7f0a0015;
- public static final int btn_disconnect=0x7f0a001c;
- public static final int btn_hidden_ssid=0x7f0a0010;
- public static final int btn_manage_nets=0x7f0a0011;
- public static final int btn_next_hidden_ssid=0x7f0a000a;
- public static final int btn_rescan=0x7f0a0018;
- public static final int btn_scan=0x7f0a000f;
- public static final int btn_select_hidden_ssid=0x7f0a0006;
- public static final int chk_show_pass=0x7f0a0004;
- public static final int chk_show_pass_details=0x7f0a0014;
- public static final int img_logo=0x7f0a0012;
- public static final int layout=0x7f0a000b;
- public static final int layout_selnets=0x7f0a0016;
- public static final int line=0x7f0a0007;
- public static final int login_form=0x7f0a0001;
- public static final int menu_config=0x7f0a0025;
- public static final int menu_credits=0x7f0a0026;
- public static final int menu_settings=0x7f0a0024;
- public static final int pref_autoconnect=0x7f0a0021;
- public static final int pref_autostart=0x7f0a0023;
- public static final int pref_debug_prio=0x7f0a001e;
- public static final int pref_dns1=0x7f0a001f;
- public static final int pref_dns2=0x7f0a0020;
- public static final int pref_progbar=0x7f0a0022;
- public static final int progbar=0x7f0a000c;
- public static final int scrollview=0x7f0a0019;
- public static final int sign_in_button=0x7f0a0005;
- public static final int table_networks=0x7f0a001a;
- public static final int txt_credits=0x7f0a0000;
- public static final int txt_insert_pass=0x7f0a0002;
- public static final int txt_insert_ssid=0x7f0a0008;
- public static final int txt_main=0x7f0a000e;
- public static final int txt_msg=0x7f0a000d;
- public static final int txt_net_details=0x7f0a0013;
- public static final int txt_password=0x7f0a0003;
- public static final int txt_selnets=0x7f0a0017;
- public static final int txt_ssid=0x7f0a0009;
- public static final int txt_status=0x7f0a001b;
+ public static final int btn_back=0x7f0a0016;
+ public static final int btn_delete=0x7f0a0023;
+ public static final int btn_disconnect=0x7f0a002a;
+ public static final int btn_hidden_ssid=0x7f0a001c;
+ public static final int btn_ip_settings=0x7f0a0021;
+ public static final int btn_manage_nets=0x7f0a001d;
+ public static final int btn_next_hidden_ssid=0x7f0a000c;
+ public static final int btn_rescan=0x7f0a0026;
+ public static final int btn_save_ip_settings=0x7f0a0015;
+ public static final int btn_save_vpn_settings=0x7f0a002d;
+ public static final int btn_scan=0x7f0a001b;
+ public static final int btn_select_hidden_ssid=0x7f0a0008;
+ public static final int btn_vpn_settings=0x7f0a0022;
+ public static final int chk_show_pass=0x7f0a0006;
+ public static final int chk_show_pass_details=0x7f0a0020;
+ public static final int chk_use_dhcp=0x7f0a000e;
+ public static final int img_logo=0x7f0a001e;
+ public static final int img_logo_fil=0x7f0a0001;
+ public static final int layout=0x7f0a0017;
+ public static final int layout_selnets=0x7f0a0024;
+ public static final int lbl_gateway=0x7f0a0013;
+ public static final int lbl_ip_settings=0x7f0a000d;
+ public static final int lbl_netmask=0x7f0a0011;
+ public static final int lbl_static_ip=0x7f0a000f;
+ public static final int lbl_vpn_settings=0x7f0a002b;
+ public static final int line=0x7f0a0009;
+ public static final int login_form=0x7f0a0003;
+ public static final int menu_btn_closeapp=0x7f0a0035;
+ public static final int menu_config=0x7f0a0036;
+ public static final int menu_credits=0x7f0a0037;
+ public static final int menu_settings=0x7f0a0034;
+ public static final int pref_autoconnect=0x7f0a0031;
+ public static final int pref_autostart=0x7f0a0033;
+ public static final int pref_debug_prio=0x7f0a002e;
+ public static final int pref_dns1=0x7f0a002f;
+ public static final int pref_dns2=0x7f0a0030;
+ public static final int pref_progbar=0x7f0a0032;
+ public static final int progbar=0x7f0a0018;
+ public static final int scrollview=0x7f0a0027;
+ public static final int sign_in_button=0x7f0a0007;
+ public static final int spin_vpn_profile=0x7f0a002c;
+ public static final int table_networks=0x7f0a0028;
+ public static final int txt_credits=0x7f0a0002;
+ public static final int txt_credits_title=0x7f0a0000;
+ public static final int txt_gateway=0x7f0a0014;
+ public static final int txt_insert_pass=0x7f0a0004;
+ public static final int txt_insert_ssid=0x7f0a000a;
+ public static final int txt_main=0x7f0a001a;
+ public static final int txt_msg=0x7f0a0019;
+ public static final int txt_net_details=0x7f0a001f;
+ public static final int txt_netmask=0x7f0a0012;
+ public static final int txt_password=0x7f0a0005;
+ public static final int txt_selnets=0x7f0a0025;
+ public static final int txt_ssid=0x7f0a000b;
+ public static final int txt_static_ip=0x7f0a0010;
+ public static final int txt_status=0x7f0a0029;
}
public static final class layout {
public static final int activity_credits=0x7f030000;
public static final int activity_input_password=0x7f030001;
public static final int activity_input_ssid=0x7f030002;
- public static final int activity_long_task=0x7f030003;
- public static final int activity_main=0x7f030004;
- public static final int activity_network_details=0x7f030005;
- public static final int activity_select_network=0x7f030006;
- public static final int activity_settings=0x7f030007;
- public static final int activity_show_status=0x7f030008;
+ public static final int activity_ipv4_settings=0x7f030003;
+ public static final int activity_long_task=0x7f030004;
+ public static final int activity_main=0x7f030005;
+ public static final int activity_network_details=0x7f030006;
+ public static final int activity_select_network=0x7f030007;
+ public static final int activity_settings=0x7f030008;
+ public static final int activity_show_status=0x7f030009;
+ public static final int activity_vpn_settings=0x7f03000a;
}
public static final class menu {
public static final int activity_input_ssid=0x7f090000;
- public static final int activity_main=0x7f090001;
+ public static final int activity_ipv4_settings=0x7f090001;
+ public static final int activity_main=0x7f090002;
+ public static final int activity_vpn_settings=0x7f090003;
}
public static final class string {
- public static final int action_sign_in_register=0x7f07002a;
- public static final int action_sign_in_short=0x7f07002b;
+ /**
+ This file is part of RepWifiApp.
+ RepWifiApp is Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
+ French translation is Copyright (C) 2017 Nicola Spanti
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+ */
public static final int app_name=0x7f070000;
public static final int back_main=0x7f07000b;
- public static final int button_text_next=0x7f070005;
- public static final int confirm_kill_backend=0x7f070025;
+ public static final int button_text_next=0x7f070006;
+ public static final int confirm_exit_app=0x7f070025;
+ public static final int confirm_kill_backend=0x7f070026;
public static final int confirm_reset_settings=0x7f070024;
public static final int connect_hidden=0x7f07001c;
public static final int credit_text=0x7f070013;
@@ -117,66 +153,149 @@ public final class R {
public static final int disconnect=0x7f07000c;
public static final int dns1_default=0x7f070021;
public static final int dns2_default=0x7f070022;
- public static final int error_field_required=0x7f070031;
- public static final int error_incorrect_password=0x7f070030;
- public static final int error_invalid_email=0x7f07002e;
- public static final int error_invalid_password=0x7f07002f;
public static final int force_disconnect=0x7f07000d;
- public static final int hello_world=0x7f070009;
+ public static final int hello_world=0x7f070070;
public static final int input_ssid=0x7f07001d;
- public static final int insert_nets_password=0x7f070006;
- public static final int login_progress_signing_in=0x7f07002d;
+ public static final int insert_nets_password=0x7f070007;
public static final int manage_networks=0x7f070011;
+ public static final int menu_closeapp=0x7f070002;
public static final int menu_config=0x7f070014;
public static final int menu_credits=0x7f070001;
- public static final int menu_forgot_password=0x7f07002c;
public static final int menu_settings=0x7f07001f;
+ public static final int msg_autoconnect_error=0x7f070037;
+ public static final int msg_checking_status=0x7f070030;
public static final int msg_confirm_delete_network=0x7f070016;
+ public static final int msg_connect_fail=0x7f070034;
+ public static final int msg_connected_to=0x7f070041;
+ public static final int msg_connecting_to=0x7f07002d;
+ public static final int msg_disconnect_fail=0x7f070044;
+ public static final int msg_disconnected=0x7f070043;
+ public static final int msg_error_ip_format=0x7f070040;
public static final int msg_interface_not_found=0x7f070015;
+ public static final int msg_invalid_gateway=0x7f070066;
+ public static final int msg_invalid_ip=0x7f070064;
+ public static final int msg_invalid_netmask=0x7f070065;
+ public static final int msg_log_save_fail=0x7f07003f;
+ public static final int msg_log_saved=0x7f07003e;
+ public static final int msg_netinfo_delete_fail=0x7f070036;
+ public static final int msg_netinfo_deleted=0x7f070035;
+ public static final int msg_network_list_fail=0x7f07003a;
+ public static final int msg_network_name_empty=0x7f07002c;
+ public static final int msg_network_save_fail=0x7f070033;
+ public static final int msg_network_saved=0x7f070032;
+ public static final int msg_no_network=0x7f07003b;
+ public static final int msg_no_saved_network=0x7f070046;
+ public static final int msg_os_unsupported=0x7f070048;
+ public static final int msg_password_empty=0x7f07002a;
+ public static final int msg_please_wait=0x7f070031;
public static final int msg_root_denied=0x7f07001b;
public static final int msg_root_disabled=0x7f07001a;
+ public static final int msg_scanning_for_nets=0x7f07002f;
+ public static final int msg_select_network_connect=0x7f07003c;
+ public static final int msg_select_network_manage=0x7f07003d;
+ public static final int msg_touch_open=0x7f070047;
+ public static final int msg_vpn_connect_error=0x7f07006e;
+ public static final int msg_vpn_disconnect=0x7f070068;
+ public static final int msg_vpn_disconnect_error=0x7f070067;
+ public static final int msg_vpn_launched=0x7f070069;
+ public static final int msg_vpn_no_permission=0x7f07006d;
+ public static final int msg_vpn_no_profile=0x7f070073;
+ public static final int msg_vpn_wrong_profile=0x7f07006a;
public static final int no=0x7f070018;
- public static final int pref_default_display_name=0x7f070037;
- public static final int pref_description_social_recommendations=0x7f070035;
- /** Example settings for Data & Sync
- */
- public static final int pref_header_data_sync=0x7f070039;
- /** Strings related to Settings
- Example General settings
- */
- public static final int pref_header_general=0x7f070033;
- /** Example settings for Notifications
- */
- public static final int pref_header_notifications=0x7f07003c;
- public static final int pref_ringtone_silent=0x7f07003f;
- public static final int pref_title_add_friends_to_messages=0x7f070038;
- public static final int pref_title_display_name=0x7f070036;
- public static final int pref_title_new_message_notifications=0x7f07003d;
- public static final int pref_title_ringtone=0x7f07003e;
- public static final int pref_title_social_recommendations=0x7f070034;
- public static final int pref_title_sync_frequency=0x7f07003a;
- public static final int pref_title_system_sync_settings=0x7f07003b;
- public static final int pref_title_vibrate=0x7f070040;
- /** Strings related to login
- */
- public static final int prompt_email=0x7f070028;
- public static final int prompt_password=0x7f070029;
public static final int receiver_description=0x7f070023;
- public static final int rescan=0x7f070004;
+ public static final int rescan=0x7f070005;
public static final int retry=0x7f070019;
- public static final int scan_networks=0x7f070002;
+ public static final int scan_networks=0x7f070003;
public static final int select_saved_net=0x7f070020;
- public static final int show_password=0x7f070007;
- public static final int summary_kill_backend=0x7f070026;
- public static final int title_activity_connect=0x7f070008;
+ public static final int show_password=0x7f070008;
+ public static final int summary_advanced_settings=0x7f07005a;
+ public static final int summary_autoconnect=0x7f070051;
+ public static final int summary_dns1=0x7f07004e;
+ public static final int summary_dns2=0x7f07004f;
+ public static final int summary_general_settings=0x7f07005b;
+ public static final int summary_kill_backend=0x7f070027;
+ public static final int summary_progbar=0x7f070053;
+ public static final int summary_restore_default=0x7f070057;
+ public static final int summary_start_at_boot=0x7f070055;
+ public static final int summary_vpn_settings=0x7f070072;
+ public static final int text_gateway=0x7f070060;
+ public static final int text_ip_address=0x7f070042;
+ public static final int text_ipv4_settings=0x7f07005d;
+ public static final int text_netinfo_last_used=0x7f070038;
+ public static final int text_password=0x7f070039;
+ public static final int text_presented_by=0x7f070028;
+ public static final int text_static_ip=0x7f07005e;
+ public static final int text_status=0x7f070045;
+ public static final int text_subnet_mask=0x7f07005f;
+ public static final int text_use_dhcp=0x7f07005c;
+ public static final int text_vpn_package_missing=0x7f07006c;
+ public static final int title_activity_connect=0x7f070009;
public static final int title_activity_credits=0x7f070012;
- public static final int title_activity_input_password=0x7f070027;
+ /**
+ This file is part of RepWifiApp.
+ RepWifiApp is Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
+ French translation is Copyright (C) 2017 Nicola Spanti
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+ */
+ public static final int title_activity_input_password=0x7f070074;
public static final int title_activity_input_ssid=0x7f07001e;
+ public static final int title_activity_ipv4_settings=0x7f070061;
public static final int title_activity_long_task=0x7f07000e;
public static final int title_activity_manage_networks=0x7f07000f;
- public static final int title_activity_select_network=0x7f070003;
- public static final int title_activity_settings=0x7f070032;
+ public static final int title_activity_select_network=0x7f070004;
+ /**
+ This file is part of RepWifiApp.
+ RepWifiApp is Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
+ French translation is Copyright (C) 2017 Nicola Spanti
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+ */
+ public static final int title_activity_settings=0x7f070075;
public static final int title_activity_show_status=0x7f07000a;
+ public static final int title_activity_vpn_settings=0x7f07006f;
+ public static final int title_advanced_settings=0x7f070058;
+ public static final int title_autoconnect=0x7f070050;
+ public static final int title_dns_1=0x7f07004c;
+ public static final int title_dns_2=0x7f07004d;
+ public static final int title_dump_logs=0x7f07004a;
+ public static final int title_general_settings=0x7f070059;
+ public static final int title_input_password=0x7f070029;
+ public static final int title_input_ssid=0x7f07002b;
+ public static final int title_log_prio=0x7f070049;
+ public static final int title_progbar=0x7f070052;
+ public static final int title_reset_backend=0x7f07004b;
+ public static final int title_restore_default=0x7f070056;
+ public static final int title_scanning=0x7f07002e;
+ public static final int title_start_at_boot=0x7f070054;
+ public static final int title_vpn_settings=0x7f07006b;
+ public static final int txt_back=0x7f070063;
+ public static final int txt_save=0x7f070071;
+ public static final int txt_save_ip_settings=0x7f070062;
public static final int yes=0x7f070017;
}
public static final class style {
diff --git a/app/res/drawable/fil_logo.png b/app/res/drawable/fil_logo.png
new file mode 100644
index 0000000..d862888
--- /dev/null
+++ b/app/res/drawable/fil_logo.png
Binary files differ
diff --git a/app/res/layout/activity_credits.xml b/app/res/layout/activity_credits.xml
index 04280d4..d114ce1 100644
--- a/app/res/layout/activity_credits.xml
+++ b/app/res/layout/activity_credits.xml
@@ -1,16 +1,44 @@
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
- android:background="@color/ThemeDark"
- android:orientation="vertical" >
+ android:background="@color/black"
+ android:padding="15dp" >
+
+ <TextView
+ android:id="@+id/txt_credits_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:padding="2dp"
+ android:text="@string/text_presented_by"
+ android:textColor="@color/ThemeLight"
+ android:textColorLink="@color/ThemeLight"
+ android:textIsSelectable="true"
+ android:textSize="9pt" />
+
+ <ImageView
+ android:id="@+id/img_logo_fil"
+ android:layout_width="100dp"
+ android:layout_height="110dp"
+ android:layout_below="@id/txt_credits_title"
+ android:layout_centerHorizontal="true"
+ android:layout_margin="1dp"
+ android:contentDescription="fil\&apos;s logo"
+ android:src="@drawable/fil_logo" >
+ </ImageView>
<TextView
android:id="@+id/txt_credits"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
+ android:layout_below="@id/img_logo_fil"
+ android:layout_centerHorizontal="true"
+ android:padding="15dp"
android:scrollbars="vertical"
+ android:fadeScrollbars="false"
android:textColor="@color/ThemeLight"
android:textColorLink="@color/ThemeLight"
+ android:textIsSelectable="true"
android:textSize="7pt" />
-</LinearLayout> \ No newline at end of file
+</RelativeLayout> \ No newline at end of file
diff --git a/app/res/layout/activity_ipv4_settings.xml b/app/res/layout/activity_ipv4_settings.xml
new file mode 100644
index 0000000..5c0887c
--- /dev/null
+++ b/app/res/layout/activity_ipv4_settings.xml
@@ -0,0 +1,126 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/black"
+ android:padding="15dp"
+ tools:context=".Ipv4SettingsActivity" >
+
+ <TextView
+ android:id="@+id/lbl_ip_settings"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="10dp"
+ android:background="@color/black"
+ android:text="@string/text_ipv4_settings"
+ android:textColor="@color/ThemeLight"
+ android:textSize="12pt" />
+
+ <CheckBox
+ android:id="@+id/chk_use_dhcp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/lbl_ip_settings"
+ android:layout_margin="10dp"
+ android:text="@string/text_use_dhcp"
+ android:textColor="@color/ThemeLight"
+ android:textSize="9pt" />
+
+ <TextView
+ android:id="@+id/lbl_static_ip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/chk_use_dhcp"
+ android:layout_margin="10dp"
+ android:background="@color/black"
+ android:text="@string/text_ip_address"
+ android:textColor="@color/ThemeLight"
+ android:textSize="9pt" />
+
+ <EditText
+ android:id="@+id/txt_static_ip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/chk_use_dhcp"
+ android:layout_margin="10dp"
+ android:layout_toRightOf="@id/lbl_static_ip"
+ android:background="@drawable/button_bg"
+ android:inputType="text"
+ android:padding="5pt"
+ android:textColor="@color/ThemeLight"
+ android:textSize="9pt" />
+
+ <TextView
+ android:id="@+id/lbl_netmask"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/txt_static_ip"
+ android:layout_margin="10dp"
+ android:background="@color/black"
+ android:text="@string/text_subnet_mask"
+ android:textColor="@color/ThemeLight"
+ android:textSize="9pt" />
+
+ <EditText
+ android:id="@+id/txt_netmask"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/txt_static_ip"
+ android:layout_margin="10dp"
+ android:layout_toRightOf="@id/lbl_netmask"
+ android:background="@drawable/button_bg"
+ android:inputType="text"
+ android:padding="5pt"
+ android:textColor="@color/ThemeLight"
+ android:textSize="9pt" />
+
+ <TextView
+ android:id="@+id/lbl_gateway"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/txt_netmask"
+ android:layout_margin="10dp"
+ android:background="@color/black"
+ android:text="@string/text_gateway"
+ android:textColor="@color/ThemeLight"
+ android:textSize="9pt" />
+
+ <EditText
+ android:id="@+id/txt_gateway"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/txt_netmask"
+ android:layout_margin="10dp"
+ android:layout_toRightOf="@id/lbl_gateway"
+ android:background="@drawable/button_bg"
+ android:inputType="text"
+ android:padding="5pt"
+ android:textColor="@color/ThemeLight"
+ android:textSize="9pt" />
+
+ <Button
+ android:id="@+id/btn_save_ip_settings"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/txt_gateway"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="25dp"
+ android:background="@drawable/repwifi_button"
+ android:onClick="btnSaveClick"
+ android:text="@string/txt_save_ip_settings"
+ android:textColor="@color/ThemeLight" />
+
+ <Button
+ android:id="@+id/btn_back"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/btn_save_ip_settings"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="15dp"
+ android:background="@drawable/repwifi_button"
+ android:onClick="btnBackClick"
+ android:text="@string/txt_back"
+ android:textColor="@color/ThemeLight" />
+
+
+</RelativeLayout> \ No newline at end of file
diff --git a/app/res/layout/activity_long_task.xml b/app/res/layout/activity_long_task.xml
index a17ba32..46d0a12 100644
--- a/app/res/layout/activity_long_task.xml
+++ b/app/res/layout/activity_long_task.xml
@@ -22,6 +22,7 @@
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:padding="10dp"
+ android:textIsSelectable="false"
android:textColor="@color/ThemeLight" />
</RelativeLayout> \ No newline at end of file
diff --git a/app/res/layout/activity_network_details.xml b/app/res/layout/activity_network_details.xml
index 6442585..225e59d 100644
--- a/app/res/layout/activity_network_details.xml
+++ b/app/res/layout/activity_network_details.xml
@@ -13,6 +13,7 @@
android:layout_margin="10dp"
android:background="@color/black"
android:textColor="@color/ThemeLight"
+ android:textIsSelectable="true"
android:textSize="7pt" />
<CheckBox
@@ -25,13 +26,37 @@
android:textSize="10pt" />
<Button
- android:id="@+id/btn_delete"
+ android:id="@+id/btn_ip_settings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/chk_show_pass_details"
android:layout_centerHorizontal="true"
android:layout_marginTop="15dp"
android:background="@drawable/repwifi_button"
+ android:onClick="btnIpSettingsClick"
+ android:text="@string/text_ipv4_settings"
+ android:textColor="@color/ThemeLight" />
+
+ <Button
+ android:id="@+id/btn_vpn_settings"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/btn_ip_settings"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="15dp"
+ android:background="@drawable/repwifi_button"
+ android:onClick="btnVpnSettingsClick"
+ android:text="@string/title_activity_vpn_settings"
+ android:textColor="@color/ThemeLight" />
+
+ <Button
+ android:id="@+id/btn_delete"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/btn_vpn_settings"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="15dp"
+ android:background="@drawable/repwifi_button"
android:onClick="btnDeleteClick"
android:text="@string/delete"
android:textColor="@color/ThemeLight" />
diff --git a/app/res/layout/activity_vpn_settings.xml b/app/res/layout/activity_vpn_settings.xml
new file mode 100644
index 0000000..4378baa
--- /dev/null
+++ b/app/res/layout/activity_vpn_settings.xml
@@ -0,0 +1,55 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/black"
+ android:padding="15dp"
+ tools:context=".Ipv4SettingsActivity" >
+
+ <TextView
+ android:id="@+id/lbl_vpn_settings"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="10dp"
+ android:background="@color/black"
+ android:textColor="@color/ThemeLight"
+ android:textIsSelectable="false"
+ android:textSize="9pt" />
+
+ <Spinner
+ android:id="@+id/spin_vpn_profile"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/lbl_vpn_settings"
+ android:layout_margin="10dp"
+ android:background="@drawable/button_bg"
+ android:inputType="text"
+ android:padding="1pt"
+ android:textColor="@color/ThemeLight"
+ android:textSize="10pt" />
+
+ <Button
+ android:id="@+id/btn_save_vpn_settings"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/spin_vpn_profile"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="25dp"
+ android:background="@drawable/repwifi_button"
+ android:onClick="btnSaveClick"
+ android:text="@string/txt_save"
+ android:textColor="@color/ThemeLight" />
+
+ <Button
+ android:id="@+id/btn_back"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/btn_save_vpn_settings"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="15dp"
+ android:background="@drawable/repwifi_button"
+ android:onClick="btnBackClick"
+ android:text="@string/txt_back"
+ android:textColor="@color/ThemeLight" />
+
+</RelativeLayout> \ No newline at end of file
diff --git a/app/res/menu/activity_ipv4_settings.xml b/app/res/menu/activity_ipv4_settings.xml
new file mode 100644
index 0000000..77f358b
--- /dev/null
+++ b/app/res/menu/activity_ipv4_settings.xml
@@ -0,0 +1,9 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/menu_settings"
+ android:orderInCategory="100"
+ android:showAsAction="never"
+ android:title="@string/menu_settings"/>
+
+</menu> \ No newline at end of file
diff --git a/app/res/menu/activity_main.xml b/app/res/menu/activity_main.xml
index e9a1624..430a0b0 100644
--- a/app/res/menu/activity_main.xml
+++ b/app/res/menu/activity_main.xml
@@ -4,14 +4,20 @@
android:textColor="@color/ThemeLight" >
<item
- android:id="@+id/menu_config"
+ android:id="@+id/menu_btn_closeapp"
android:orderInCategory="1"
android:showAsAction="never"
android:textColor="@color/ThemeLight"
+ android:title="@string/menu_closeapp"/>
+ <item
+ android:id="@+id/menu_config"
+ android:orderInCategory="2"
+ android:showAsAction="never"
+ android:textColor="@color/ThemeLight"
android:title="@string/menu_config"/>
<item
android:id="@+id/menu_credits"
- android:orderInCategory="2"
+ android:orderInCategory="3"
android:showAsAction="never"
android:textColor="@color/ThemeLight"
android:title="@string/menu_credits"/>
diff --git a/app/res/menu/activity_vpn_settings.xml b/app/res/menu/activity_vpn_settings.xml
new file mode 100644
index 0000000..77f358b
--- /dev/null
+++ b/app/res/menu/activity_vpn_settings.xml
@@ -0,0 +1,9 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/menu_settings"
+ android:orderInCategory="100"
+ android:showAsAction="never"
+ android:title="@string/menu_settings"/>
+
+</menu> \ No newline at end of file
diff --git a/app/res/values-fr/strings.xml b/app/res/values-fr/strings.xml
index 0801a44..ad561bf 100644
--- a/app/res/values-fr/strings.xml
+++ b/app/res/values-fr/strings.xml
@@ -2,26 +2,27 @@
<resources>
<!--
- RepWifiApp is Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
- French translation is Copyright (C) 2017 Nicola Spanti
+ This file is part of RepWifiApp.
+ RepWifiApp is Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
+ French translation is Copyright (C) 2017 Nicola Spanti
- This file is part of RepWifiApp.
- RepWifiApp is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
- RepWifiApp is distributed in the hope that it will be useful,
+ 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with RepWifiApp. If not, see <http://www.gnu.org/licenses/>.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<string name="app_name">RepWifi</string>
<string name="menu_credits">Info et crédits</string>
+ <string name="menu_closeapp">Tuer RepWifi</string>
<string name="scan_networks">Scan des réseaux</string>
<string name="title_activity_select_network">Selectionner un réseau</string>
<string name="rescan">Répéter le scan</string>
@@ -29,9 +30,8 @@
<string name="insert_nets_password">Fournisser un mot de passe pour se connecter à :</string>
<string name="show_password">Montrer le mot de passe</string>
<string name="title_activity_connect">ActivitéDeConnexion</string>
- <string name="hello_world">Bonjour le monde !</string>
- <string name="title_activity_show_status">Statur de connexion</string>
- <!--<string name="back_main">Revenir au main</string>-->
+ <string name="title_activity_show_status">Statut de connexion</string>
+ <string name="back_main">Revenir au menu principal</string>
<string name="disconnect">Déconnecter</string>
<string name="force_disconnect">Forcer la déconnection</string>
<string name="title_activity_long_task">ActivitéDeTâcheLongue</string>
@@ -39,7 +39,7 @@
<string name="delete">Supprimer les informations sur le réseau</string>
<string name="manage_networks">Gérer les réseaux</string>
<string name="title_activity_credits">Crédits</string>
- <string name="credit_text">Copyright 2017 Filippo \&quot;Fil\&quot; Bergamo&lt;br/&gt;&lt;br/&gt;Cette app est du logiciel libre.&lt;br/&gt;Elle est sous licence &lt;a href=&quot;https://www.gnu.org/licenses/gpl.txt&quot;&gt;GPL v3&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;Cette app est développé en tant que contribution au &lt;br/&gt;&lt;a href=&quot;https://www.replicant.us&quot;&gt;projet Replicant&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;&lt;b&gt;&lt;u&gt;&lt;big&gt;Merci GNUs:&lt;/big&gt;&lt;/u&gt;&lt;/b&gt;&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Tiberiu - Technoethical&lt;/b&gt;&lt;br/&gt;pour avoir fait le travail initial de porter le Wi-Fi sur Replicant 4.2.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Wolfgang Wiedmeyer&lt;/b&gt;&lt;br/&gt;pour le portage du Wi-Fi libre sur Replicant 6.0 et pour l\'aide sur les scripts.&lt;br/&gt;&lt;br/&gt;Pour reporter des bogues, demander des fonctionnalités, ou n\'importe quelle demande d\'aide, veuillez vous adresser à:&lt;br/&gt;&lt;a href=&quot;https://redmine.replicant.us/projects/replicant/boards&quot;&gt;Le forum de Replicant&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;Le code source est hébergé sur : &lt;br/&gt;&lt;a href=&quot;https://git.replicant.us/contrib/Fil/RepWifiApp/&quot;&gt;https://git.replicant.us/contrib/Fil/RepWifiApp/&lt;/a&gt;&lt;br/&gt;</string>
+ <string name="credit_text">Copyright 2017 Filippo \&quot;Fil\&quot; Bergamo&lt;br/&gt;&lt;br/&gt;Cette app est du logiciel libre.&lt;br/&gt;Elle est sous licence &lt;a href=&quot;https://www.gnu.org/licenses/gpl.txt&quot;&gt;GPL v3&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;Cette app est développé en tant que contribution au &lt;br/&gt;&lt;a href=&quot;https://www.replicant.us&quot;&gt;projet Replicant&lt;/a&gt;&lt;br/&gt;Pour signaler des bogues, demander des fonctionnalités, ou n\'importe quelle autre demande d\'aide, veuillez vous référer à :&lt;br/&gt;&lt;a href=&quot;https://redmine.replicant.us/projects/replicant/boards&quot;&gt;Forum de Replicant&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;Le code source est hébergé sur : &lt;br/&gt;&lt;a href=&quot;https://git.replicant.us/contrib/Fil/RepWifiApp/&quot;&gt;https://git.replicant.us/contrib/Fil/RepWifiApp/&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;&lt;b&gt;&lt;u&gt;&lt;big&gt;Merci GNUs:&lt;/big&gt;&lt;/u&gt;&lt;/b&gt;&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Tiberiu - Technoethical&lt;/b&gt;&lt;br/&gt;pour avoir fait le travail initial de porter le Wi-Fi sur Replicant 4.2.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Wolfgang Wiedmeyer&lt;/b&gt;&lt;br/&gt;pour le portage du Wi-Fi libre sur Replicant 6.0 et pour l\'aide sur les scripts.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Nicola Spanti&lt;/b&gt;&lt;br/&gt;pour la traduction en français.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Nichlas Severinsen&lt;/b&gt;&lt;br/&gt;pour la publication de cette app sur F-Droid.&lt;br/&gt;&lt;br/&gt;</string>
<string name="menu_config">Paramètres</string>
<string name="msg_interface_not_found">Pas d\'adaptateur Wi-Fi trouvé !\nVeuillez connecter un adaptateur Wi-Fi géréet réessayer.</string>
<string name="msg_confirm_delete_network">Êtes vous sûr de vouloir supprimer ce réseau ?</string>
@@ -52,9 +52,87 @@
<string name="input_ssid">Ou.. Fournisser le nom du réseau (SSID)</string>
<string name="title_activity_input_ssid">Fournisser le nom du réseau</string>
<string name="menu_settings">Paramètres</string>
- <string name="select_saved_net">Utiliser le réseau sauvegardé</string>
+ <string name="select_saved_net">Utiliser le réseau enregistré</string>
<string name="receiver_description">RepWifi est attentif à l\'événement de démarrage. Cela lui permet d\'avoir une fonctionnalité de démarrage automatique et une autre lié aux notifications.</string>
<string name="confirm_reset_settings">Êtes vous sûr de vouloir de remettre tous les paramètres aux valeurs par défaut ?</string>
+ <string name="confirm_exit_app">Êtes vous sûr de vouloir tuer RepWifi ? Cela vous déconnectera du Wi-Fi.</string>
<string name="confirm_kill_backend">Êtes vous sûr de vouloir tuer les processus d\'arrière-plan ?</string>
<string name="summary_kill_backend">Des fois les programmes d\'arrière-plan restent coincés dans des états incohérents.\nCliquer sur le boutton restaure le comportement normal en tuant les instances en cours de wpa_supplicant et dhcpcd.</string>
+ <string name="text_presented_by">Fait par :</string>
+ <string name="title_input_password">Saisir le mot de passe</string>
+ <string name="msg_password_empty">Le mot de passe ne peut pas être nul !</string>
+ <string name="title_input_ssid">Saisir les paramètres du réseau</string>
+ <string name="msg_network_name_empty">Le nom du réseau ne peut pas être nul !</string>
+ <string name="msg_connecting_to">Connexion à </string>
+ <string name="title_scanning">Scan...</string>
+ <string name="msg_scanning_for_nets">Scan pour trouver des réseaux...</string>
+ <string name="msg_checking_status">Vérification du statut...</string>
+ <string name="msg_please_wait">Veuillez attendre...</string>
+ <string name="msg_network_saved">Réseau enregistré !</string>
+ <string name="msg_network_save_fail">ÉCHEC à l\'enregistrement du réseau !</string>
+ <string name="msg_connect_fail">ÉCHEC à la connexion !</string>
+ <string name="msg_netinfo_deleted">Informations sur le réseau supprimées !</string>
+ <string name="msg_netinfo_delete_fail">ÉCHEC à la suppresion des informations sur le réseau !</string>
+ <string name="msg_autoconnect_error">Il y a eu une erreur pendant la tentative d\'auto-connexion</string>
+ <string name="text_netinfo_last_used">Dernier utilisé</string>
+ <string name="text_password">Mot de passe</string>
+ <string name="msg_network_list_fail">Impossible d\'avoir la liste des réseaux !</string>
+ <string name="msg_no_network">Aucun réseau trouvé.</string>
+ <string name="msg_select_network_connect">Choisir le réseau auquel vous voulez vous connecter :</string>
+ <string name="msg_select_network_manage">Choisir les informations de réseau à gérer :</string>
+ <string name="msg_log_saved">Journaux enregistrés dans un ficher</string>
+ <string name="msg_log_save_fail">Échec à l\'enregistrement du journal dans un fichier !</string>
+ <string name="msg_error_ip_format">ERREUR :\nMauvais format d\'IP !</string>
+ <string name="msg_connected_to">Connecté à</string>
+ <string name="text_ip_address">Adresse IP</string>
+ <string name="msg_disconnected">Déconnecté.</string>
+ <string name="msg_disconnect_fail">Échec à la déconnexion !</string>
+ <string name="text_status">Statut</string>
+ <string name="msg_no_saved_network">Aucun réseau enregistré</string>
+ <string name="msg_touch_open">Cliquer pour ouvrir.</string>
+ <string name="msg_os_unsupported">VERSION DE SYSTÈME D\'EXPLOITATION NON SUPPORTÉ\nLa version actuelle de Replicant n\'est pas supportée par RepWifi.\nVeuillez mettre à jour à la dernière version aussitôt que possible !</string>
+ <string name="title_log_prio">Priorité du journal</string>
+ <string name="title_dump_logs">Enregistrer les journaux dans un fichier</string>
+ <string name="title_reset_backend">Réinitialiser le moteur en arrière-plan</string>
+ <string name="title_dns_1">Serveur DNS #1</string>
+ <string name="title_dns_2">Serveur DNS #2</string>
+ <string name="summary_dns1">Définir l\'adresse IPv4 du serveur DNS primaire.\nSi c\'est laissé vide, RepWifi va essayer d\'utiliser la passerelle par défaut comme résolveur DNS.</string>
+ <string name="summary_dns2">Définir l\'adresse IPv4 du serveur DNS secondaire.\nSi la première adresse est vide, la valeur de ce champ va être ignorée.</string>
+ <string name="title_autoconnect">Activer l\'auto-connexion</string>
+ <string name="summary_autoconnect">Quand l\'adaptateur Wi-Fi est connecté, RepWifi se connecte automatiquement aux réseaux connus atteignables.\n(Expérimental).</string>
+ <string name="title_progbar">Barre de progression animée</string>
+ <string name="summary_progbar">Affiche une barre de progression animée pendant que des tâches de fond sont réalisées.\nGarder la désactivée pour (à priori) économiser de l\'énergie pour l\'adaptateur Wi-Fi.</string>
+ <string name="title_start_at_boot">Activer le démarrage automatique au démarrage du système</string>
+ <string name="summary_start_at_boot">Si coché, RepWifi démarre automatiquement quand le système démarre.</string>
+ <string name="title_restore_default">Rétablir les paramètres par défaut</string>
+ <string name="summary_restore_default">cliquer pour rétablir les paramètres par défaut\n(ensuite revenez à l\'écran principal pour appliquer la réinitialisation)</string>
+ <string name="title_advanced_settings">Avancé &amp; Débogage</string>
+ <string name="title_general_settings">Options</string>
+ <string name="summary_advanced_settings">définir les options avancées et variables de débogage</string>
+ <string name="summary_general_settings">définir les options générales</string>
+ <string name="text_use_dhcp">Utiliser DHCP</string>
+ <string name="text_ipv4_settings">Paramètres IPv4</string>
+ <string name="text_static_ip">IP statique</string>
+ <string name="text_subnet_mask">Masque de sous-réseau</string>
+ <string name="text_gateway">Passerelle</string>
+ <string name="title_activity_ipv4_settings">ActivitéDesParamètresIpv4</string>
+ <string name="txt_save_ip_settings">Enregistrer les paramètres IP</string>
+ <string name="txt_back">Retour</string>
+ <string name="msg_invalid_ip">Adresse IP invalide !</string>
+ <string name="msg_invalid_netmask">Sous-réseau invalide !</string>
+ <string name="msg_invalid_gateway">Passerelle invalide !</string>
+ <string name="msg_vpn_disconnect_error">ERREUR pendant la déconnexion du VPN !</string>
+ <string name="msg_vpn_disconnect">Déconnecté du VPN</string>
+ <string name="msg_vpn_launched">Démarrage de la connexion au VPN</string>
+ <string name="msg_vpn_wrong_profile">Nom de profil invalide !</string>
+ <string name="title_vpn_settings">Paramètres du VPN</string>
+ <string name="text_vpn_package_missing">Il semble que l\'app VPN nécessaire n\'est pas installée.\nRepWifi a besoin que l\'app &quot;[VPN_EXT_APP]&quot; soit installée, pour pouvoir fournir la fonctionnalité VPN.\nVeuillez installer &quot;[VPN_EXT_APP]&quot; et réessayer.</string>
+ <string name="msg_vpn_no_permission">Permission VPN refusée.\nVous devez accorder à RepWifi la permission d\'utiliser l\'app &quot;[VPN_EXT_APP]&quot; quand cela vous est demandé.\nRepWifi ne sera pas capable de démarrer le VPN tant que vous ne l\'aurez pas fait.</string>
+ <string name="msg_vpn_connect_error">** ERREUR pendant la connexion au VPN **</string>
+ <string name="title_activity_vpn_settings">Paramètres du VPN</string>
+ <string name="hello_world">Bonjour le monde !</string>
+ <string name="txt_save">Enregistrer</string>
+ <string name="summary_vpn_settings">Choisir le nom du profil VPN que vous voulez qui soit lancé automatiquement quand vous vous connecter à ce réseau.\nLaisser vide pour désactiver la connexion automatique au VPN.\nPour utiliser la fonction VPN, l\'app &quot;[VPN_EXT_APP]&quot; doit être installée sur le système.</string>
+ <string name="msg_vpn_no_profile">Aucun profil trouvé.\nVeuillez ajouter un profil VPN dans l\'app [VPN_EXT_APP] avant d\'utiliser cette fonctionnalité.</string>
+
</resources>
diff --git a/app/res/values-fr/strings_activity_input_password.xml b/app/res/values-fr/strings_activity_input_password.xml
index 17f78cd..c27ca7a 100644
--- a/app/res/values-fr/strings_activity_input_password.xml
+++ b/app/res/values-fr/strings_activity_input_password.xml
@@ -2,35 +2,24 @@
<resources>
<!--
- RepWifiApp is Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
- French translation is Copyright (C) 2017 Nicola Spanti
+ This file is part of RepWifiApp.
+ RepWifiApp is Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
+ French translation is Copyright (C) 2017 Nicola Spanti
- This file is part of RepWifiApp.
- RepWifiApp is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
- RepWifiApp is distributed in the hope that it will be useful,
+ 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with RepWifiApp. If not, see <http://www.gnu.org/licenses/>.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<string name="title_activity_input_password">Entrer le mot de passe pour le réseau</string>
- <!-- Strings related to login -->
- <string name="prompt_email">Email</string>
- <string name="prompt_password">Mot de passe</string>
- <string name="action_sign_in_register"><b>S\'identifier</b> ou s\'enregistrer</string>
- <string name="action_sign_in_short">S\'identifier</string>
- <string name="menu_forgot_password">Récupérer un mot de passe perdu</string>
- <string name="login_progress_signing_in">Identification&#8230;</string>
- <string name="error_invalid_email">Cette adresse email est invalide</string>
- <string name="error_invalid_password">Ce mot de passe est trop court</string>
- <string name="error_incorrect_password">Ce mot de passe est incorrect</string>
- <string name="error_field_required">Ce champ est obligatoire</string>
</resources>
diff --git a/app/res/values-fr/strings_activity_settings.xml b/app/res/values-fr/strings_activity_settings.xml
index 6e8610b..260bcb0 100644
--- a/app/res/values-fr/strings_activity_settings.xml
+++ b/app/res/values-fr/strings_activity_settings.xml
@@ -2,62 +2,24 @@
<resources>
<!--
- RepWifiApp is Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
- French translation is Copyright (C) 2017 Nicola Spanti
+ This file is part of RepWifiApp.
+ RepWifiApp is Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
+ French translation is Copyright (C) 2017 Nicola Spanti
- This file is part of RepWifiApp.
- RepWifiApp is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
- RepWifiApp is distributed in the hope that it will be useful,
+ 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.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with RepWifiApp. If not, see <http://www.gnu.org/licenses/>.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<string name="title_activity_settings">Paramètres</string>
- <!-- Strings related to Settings -->
-
-
- <!-- Example General settings -->
- <string name="pref_header_general">Général</string>
- <string name="pref_title_social_recommendations">Activer les recommendations sociales</string>
- <string name="pref_description_social_recommendations">Recommendations pour que les gens puissent vous contacter en se basant sur votre historique de messages</string>
- <string name="pref_title_display_name">Afficher le nom</string>
- <string name="pref_default_display_name">John Smith</string>
- <string name="pref_title_add_friends_to_messages">Ajouter des ami·e·s aux messages</string>
-
- <string-array name="pref_example_list_titles">
- <item>Toujours</item>
- <item>Quand c\'est possible</item>
- <item>Jamais</item>
- </string-array>
-
- <!-- Example settings for Data & Sync -->
- <string name="pref_header_data_sync">Données &amp; synchronisation</string>
- <string name="pref_title_sync_frequency">Fréquence de la synchronisation</string>
-
- <string-array name="pref_sync_frequency_titles">
- <item>15 minutes</item>
- <item>30 minutes</item>
- <item>1 heure</item>
- <item>3 heures</item>
- <item>6 heures</item>
- <item>Jamais</item>
- </string-array>
-
- <string name="pref_title_system_sync_settings">Paramètres de la synchronisation système</string>
-
- <!-- Example settings for Notifications -->
- <string name="pref_header_notifications">Notifications</string>
- <string name="pref_title_new_message_notifications">Nouveaux messages de notifications</string>
- <string name="pref_title_ringtone">Sonnerie</string>
- <string name="pref_ringtone_silent">Muet</string>
- <string name="pref_title_vibrate">Vibrer</string>
</resources>
diff --git a/app/res/values/strings.xml b/app/res/values/strings.xml
index dccbe44..8e8cd36 100644
--- a/app/res/values/strings.xml
+++ b/app/res/values/strings.xml
@@ -3,6 +3,7 @@
<string name="app_name">RepWifi</string>
<string name="menu_credits">Info and Credits</string>
+ <string name="menu_closeapp">Kill RepWifi</string>
<string name="scan_networks">Scan for Networks</string>
<string name="title_activity_select_network">Select Network</string>
<string name="rescan">Repeat Scan</string>
@@ -10,7 +11,6 @@
<string name="insert_nets_password">Insert a Password to connect to:</string>
<string name="show_password">Show password</string>
<string name="title_activity_connect">ConnectActivity</string>
- <string name="hello_world">Hello world!</string>
<string name="title_activity_show_status">Connection status</string>
<string name="back_main">Back to main</string>
<string name="disconnect">Disconnect</string>
@@ -20,7 +20,7 @@
<string name="delete">Delete network info</string>
<string name="manage_networks">Manage Networks</string>
<string name="title_activity_credits">Credits</string>
- <string name="credit_text">Copyright 2017 Filippo \&quot;Fil\&quot; Bergamo&lt;br/&gt;&lt;br/&gt;This app is Free Software.&lt;br/&gt;It\'s licensed under the terms of &lt;a href=&quot;https://www.gnu.org/licenses/gpl.txt&quot;&gt;GPL v3&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;This app is developed as a contribution to &lt;br/&gt;&lt;a href=&quot;http://www.replicant.us&quot;&gt;The Replicant Project&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;&lt;b&gt;&lt;u&gt;&lt;big&gt;Thank GNUs:&lt;/big&gt;&lt;/u&gt;&lt;/b&gt;&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Tiberiu - Technoethical&lt;/b&gt;&lt;br/&gt;for having done the initial job of porting libre WiFi to Replicant 4.2.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Wolfgang Wiedmeyer&lt;/b&gt;&lt;br/&gt;for porting libre WiFi to Replicant 6.0 and for helping with the scripts.&lt;br/&gt;&lt;br/&gt;To report on bugs, request features, or any help request, please refer to:&lt;br/&gt;&lt;a href=&quot;http://redmine.replicant.us/projects/replicant/boards&quot;&gt;Replicant\'s Forum&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;Source code is hosted at: &lt;br/&gt;&lt;a href=&quot;https://git.replicant.us/contrib/Fil/RepWifiApp/&quot;&gt;https://git.replicant.us/contrib/Fil/RepWifiApp/&lt;/a&gt;&lt;br/&gt;</string>
+ <string name="credit_text">Copyright 2017 Filippo \&quot;Fil\&quot; Bergamo&lt;br/&gt;&lt;br/&gt;This app is Free Software.&lt;br/&gt;It\'s licensed under the terms of &lt;a href=&quot;https://www.gnu.org/licenses/gpl.txt&quot;&gt;GPL v3&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;This app is developed as a contribution to &lt;br/&gt;&lt;a href=&quot;http://www.replicant.us&quot;&gt;The Replicant Project&lt;/a&gt;&lt;br/&gt;To report on bugs, request features, or any help request, please refer to:&lt;br/&gt;&lt;a href=&quot;http://redmine.replicant.us/projects/replicant/boards&quot;&gt;Replicant\'s Forum&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;Source code is hosted at: &lt;br/&gt;&lt;a href=&quot;https://git.replicant.us/contrib/Fil/RepWifiApp/&quot;&gt;https://git.replicant.us/contrib/Fil/RepWifiApp/&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;&lt;b&gt;&lt;u&gt;&lt;big&gt;Thank GNUs:&lt;/big&gt;&lt;/u&gt;&lt;/b&gt;&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Tiberiu - Technoethical&lt;/b&gt;&lt;br/&gt;for having done the initial job of porting libre WiFi to Replicant 4.2.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Wolfgang Wiedmeyer&lt;/b&gt;&lt;br/&gt;for porting libre WiFi to Replicant 6.0 and for helping with the scripts.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Nicola Spanti&lt;/b&gt;&lt;br/&gt;for the French translation.&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Nichlas Severinsen&lt;/b&gt;&lt;br/&gt;for publishing this app on F-Droid.&lt;br/&gt;&lt;br/&gt;</string>
<string name="menu_config">Settings</string>
<string name="msg_interface_not_found">WiFi adapter not found!\nPlease plug in a supported WiFi adapter and retry.</string>
<string name="msg_confirm_delete_network">Are you sure you want to delete this network?</string>
@@ -38,7 +38,84 @@
<string name="dns2_default">169.239.202.202</string>
<string name="receiver_description">RepWifi\'s listener for startup event. Provides auto-start and notification features to RepWifi.</string>
<string name="confirm_reset_settings">Are you sure you want to reset all settings to default?</string>
+ <string name="confirm_exit_app">Are you sure you want to kill RepWifi? This will disconnect you from WiFi.</string>
<string name="confirm_kill_backend">Are you sure you want to kill the back-end processes?</string>
<string name="summary_kill_backend">Sometimes back-end programs get stuck in inconsistent states.\nClicking this button restores normal behaviour by killing running instances of wpa_supplicant and dhcpcd."</string>
+ <string name="text_presented_by">Brought to you by:</string>
+ <string name="title_input_password">Input Password</string>
+ <string name="msg_password_empty">Password can\'t be empty!</string>
+ <string name="title_input_ssid">Insert Network\'s parameters</string>
+ <string name="msg_network_name_empty">Network name can\'t be empty!</string>
+ <string name="msg_connecting_to">Connecting to </string>
+ <string name="title_scanning">Scanning...</string>
+ <string name="msg_scanning_for_nets">Scanning for Networks...</string>
+ <string name="msg_checking_status">Checking status...</string>
+ <string name="msg_please_wait">Please wait...</string>
+ <string name="msg_network_saved">Network saved!</string>
+ <string name="msg_network_save_fail">FAILED to save network!</string>
+ <string name="msg_connect_fail">FAILED to connect!</string>
+ <string name="msg_netinfo_deleted">Network Info deleted!</string>
+ <string name="msg_netinfo_delete_fail">FAILED to delete Network Info!</string>
+ <string name="msg_autoconnect_error">An error occurred while trying to auto-connect</string>
+ <string name="text_netinfo_last_used">Last Used</string>
+ <string name="text_password">Password</string>
+ <string name="msg_network_list_fail">Unable to retrieve network list!</string>
+ <string name="msg_no_network">No network found.</string>
+ <string name="msg_select_network_connect">Select the network you want to connect to:</string>
+ <string name="msg_select_network_manage">Select network info to manage:</string>
+ <string name="msg_log_saved">Logs saved to file</string>
+ <string name="msg_log_save_fail">Failed to dump logs!</string>
+ <string name="msg_error_ip_format">ERROR:\nWrong IP format!</string>
+ <string name="msg_connected_to">Connected to</string>
+ <string name="text_ip_address">IP Address</string>
+ <string name="msg_disconnected">Disconnected.</string>
+ <string name="msg_disconnect_fail">FAILED to disconnect!</string>
+ <string name="text_status">Status</string>
+ <string name="msg_no_saved_network">No saved network</string>
+ <string name="msg_touch_open">Touch to open.</string>
+ <string name="msg_os_unsupported">UNSUPPORTED OS VERSION\nThe current version of Replicant is not supported by RepWifi.\nPlease upgrade to the latest version as soon as possible!</string>
+ <string name="title_log_prio">Log priority</string>
+ <string name="title_dump_logs">Dump logs to file</string>
+ <string name="title_reset_backend">Reset back-end engine</string>
+ <string name="title_dns_1">DNS server #1</string>
+ <string name="title_dns_2">DNS server #2</string>
+ <string name="summary_dns1">Set the IPv4 address of the primary DNS server.\nIf left blank, RepWifi will try to use the default gateway as a DNS resolver.</string>
+ <string name="summary_dns2">Set the IPv4 address of the secondary DNS server.\nIf the primary address is blank, this will be ignored.</string>
+ <string name="title_autoconnect">Enable Autoconnect</string>
+ <string name="summary_autoconnect">When the WiFi dongle is attached, RepWifi connects automatically to reachable known networks.\n(Experimental).</string>
+ <string name="title_progbar">Animated progress bar</string>
+ <string name="summary_progbar">Show an animated progress bar while doing long background tasks.\nKeep it disabled to (hopefully) save some extra power for the WiFi dongle.</string>
+ <string name="title_start_at_boot">Enable Start at Boot</string>
+ <string name="summary_start_at_boot">If checked, RepWifi is started automatically on system\'s startup.</string>
+ <string name="title_restore_default">Restore Defaults</string>
+ <string name="summary_restore_default">click to restore default settings\n(then return to main screen to apply the reset)</string>
+ <string name="title_advanced_settings">Advanced &amp; Debug</string>
+ <string name="title_general_settings">Options</string>
+ <string name="summary_advanced_settings">set advanced options and debug variables</string>
+ <string name="summary_general_settings">set general options</string>
+ <string name="text_use_dhcp">Use DHCP</string>
+ <string name="text_ipv4_settings">IPv4 settings</string>
+ <string name="text_static_ip">Static IP</string>
+ <string name="text_subnet_mask">Subnet Mask</string>
+ <string name="text_gateway">Gateway</string>
+ <string name="title_activity_ipv4_settings">Ipv4SettingsActivity</string>
+ <string name="txt_save_ip_settings">Save IP settings</string>
+ <string name="txt_back">Back</string>
+ <string name="msg_invalid_ip">Invalid IP address!</string>
+ <string name="msg_invalid_netmask">Invalid Subnet Mask!</string>
+ <string name="msg_invalid_gateway">Invalid Gateway!</string>
+ <string name="msg_vpn_disconnect_error">ERROR while disconnecting from VPN!</string>
+ <string name="msg_vpn_disconnect">Disconnected from VPN</string>
+ <string name="msg_vpn_launched">Launched VPN connection</string>
+ <string name="msg_vpn_wrong_profile">Invalid profile name!</string>
+ <string name="title_vpn_settings">VPN settings</string>
+ <string name="text_vpn_package_missing">Seems like the required VPN app is not installed.\nRepWifi needs &quot;[VPN_EXT_APP]&quot; to be installed, in order to provide VPN features.\nPlease install &quot;[VPN_EXT_APP]&quot; and retry.</string>
+ <string name="msg_vpn_no_permission">VPN permission denied.\nYou need to grant RepWifi permission to use &quot;[VPN_EXT_APP]&quot; when you are prompted for it.\nRepWifi won\'t be able to start VPN until you do so.</string>
+ <string name="msg_vpn_connect_error">** ERROR while connecting to VPN **</string>
+ <string name="title_activity_vpn_settings">VPN Settings</string>
+ <string name="hello_world">Hello world!</string>
+ <string name="txt_save">Save</string>
+ <string name="summary_vpn_settings">Select the name of a VPN profile that you want to be launched automatically when you connect to this network.\nLeave blank to disable automatic VPN connection.\nTo use VPN capability, &quot;[VPN_EXT_APP]&quot; must be installed in the system.</string>
+ <string name="msg_vpn_no_profile">No profile found.\nPlease add a VPN profile inside [VPN_EXT_APP] before using this feature.</string>
</resources> \ No newline at end of file
diff --git a/app/res/values/strings_activity_input_password.xml b/app/res/values/strings_activity_input_password.xml
index 4770a51..31b8865 100644
--- a/app/res/values/strings_activity_input_password.xml
+++ b/app/res/values/strings_activity_input_password.xml
@@ -3,15 +3,6 @@
<string name="title_activity_input_password">Insert passwrod for network</string>
<!-- Strings related to login -->
- <string name="prompt_email">Email</string>
- <string name="prompt_password">Password</string>
- <string name="action_sign_in_register"><b>Sign in</b> or register</string>
- <string name="action_sign_in_short">Sign in</string>
- <string name="menu_forgot_password">Recover lost password</string>
- <string name="login_progress_signing_in">Signing in&#8230;</string>
- <string name="error_invalid_email">This email address is invalid</string>
- <string name="error_invalid_password">This password is too short</string>
- <string name="error_incorrect_password">This password is incorrect</string>
- <string name="error_field_required">This field is required</string>
+
</resources> \ No newline at end of file
diff --git a/app/res/values/strings_activity_settings.xml b/app/res/values/strings_activity_settings.xml
index d7bab93..dfc25ca 100644
--- a/app/res/values/strings_activity_settings.xml
+++ b/app/res/values/strings_activity_settings.xml
@@ -6,52 +6,9 @@
<!-- Example General settings -->
- <string name="pref_header_general">General</string>
- <string name="pref_title_social_recommendations">Enable social recommendations</string>
- <string name="pref_description_social_recommendations">Recommendations for people to contact based on your message history</string>
- <string name="pref_title_display_name">Display name</string>
- <string name="pref_default_display_name">John Smith</string>
- <string name="pref_title_add_friends_to_messages">Add friends to messages</string>
-
- <string-array name="pref_example_list_titles">
- <item>Always</item>
- <item>When possible</item>
- <item>Never</item>
- </string-array>
- <string-array name="pref_example_list_values">
- <item>1</item>
- <item>0</item>
- <item>-1</item>
- </string-array>
<!-- Example settings for Data & Sync -->
- <string name="pref_header_data_sync">Data &amp; sync</string>
- <string name="pref_title_sync_frequency">Sync frequency</string>
-
- <string-array name="pref_sync_frequency_titles">
- <item>15 minutes</item>
- <item>30 minutes</item>
- <item>1 hour</item>
- <item>3 hours</item>
- <item>6 hours</item>
- <item>Never</item>
- </string-array>
- <string-array name="pref_sync_frequency_values">
- <item>15</item>
- <item>30</item>
- <item>60</item>
- <item>180</item>
- <item>360</item>
- <item>-1</item>
- </string-array>
-
- <string name="pref_title_system_sync_settings">System sync settings</string>
<!-- Example settings for Notifications -->
- <string name="pref_header_notifications">Notifications</string>
- <string name="pref_title_new_message_notifications">New message notifications</string>
- <string name="pref_title_ringtone">Ringtone</string>
- <string name="pref_ringtone_silent">Silent</string>
- <string name="pref_title_vibrate">Vibrate</string>
</resources> \ No newline at end of file
diff --git a/app/res/values/styles.xml b/app/res/values/styles.xml
index 18e186b..2a431aa 100644
--- a/app/res/values/styles.xml
+++ b/app/res/values/styles.xml
@@ -42,7 +42,7 @@
<item name="android:textColor">@color/ThemeLight</item>
<item name="android:cacheColorHint">@color/Anthracite</item>
</style>
-
+
<style name="RepWifi.BorderlessButton" parent="@android:style/Widget.Holo.Button.Borderless">
<item name="android:textColor">@color/ThemeLight</item>
<item name="android:background">@drawable/repwifi_button</item>
diff --git a/app/res/xml/debug_settings.xml b/app/res/xml/debug_settings.xml
index 8aa09f4..f7be0f0 100644
--- a/app/res/xml/debug_settings.xml
+++ b/app/res/xml/debug_settings.xml
@@ -6,10 +6,15 @@
android:entries="@array/debug_priority_names"
android:entryValues="@array/debug_priority"
android:key="debug_priority"
- android:title="Log priority"
+ android:title="@string/title_log_prio"
android:divider="@drawable/divider_shape" />
- <Preference android:title="Reset back-end engine"
+ <Preference android:title="@string/title_dump_logs"
+ android:key="pref_dump_log"
+ android:background="@drawable/button_bg"
+ android:textColor="@color/ThemeLight"/>
+
+ <Preference android:title="@string/title_reset_backend"
android:key="pref_kill_backend"
android:summary="@string/summary_kill_backend"
android:background="@drawable/button_bg"
diff --git a/app/res/xml/general_settings.xml b/app/res/xml/general_settings.xml
index d836b67..bd9fdf9 100644
--- a/app/res/xml/general_settings.xml
+++ b/app/res/xml/general_settings.xml
@@ -5,8 +5,8 @@
android:id="@+id/pref_dns1"
android:defaultValue="@string/dns1_default"
android:key="dns1"
- android:summary="Set the IPv4 address of the primary DNS server.\nIf left blank, RepWifi will try to use the default gateway as a DNS resolver."
- android:title="DNS server #1"
+ android:summary="@string/summary_dns1"
+ android:title="@string/title_dns_1"
android:textColor="@color/ThemeLight"
android:background="@color/ThemeDark"
android:padding="5dp"/>
@@ -16,8 +16,8 @@
android:id="@+id/pref_dns2"
android:defaultValue="@string/dns2_default"
android:key="dns2"
- android:summary="Set the IPv4 address of the secondary DNS server.\nIf the primary address is blank, this will be ignored."
- android:title="DNS server #2"
+ android:summary="@string/summary_dns2"
+ android:title="@string/title_dns_2"
android:textColor="@color/ThemeLight"
android:background="@color/ThemeDark"
android:padding="5dp"/>
@@ -26,26 +26,26 @@
android:id="@+id/pref_autoconnect"
android:defaultValue="false"
android:key="enable_autoconnect"
- android:summary="When the WiFi dongle is attached, RepWifi connects automatically to reachable known networks.\n(Experimental)."
- android:title="Enable Autoconnect" />
-
+ android:summary="@string/summary_autoconnect"
+ android:title="@string/title_autoconnect" />
+
<CheckBoxPreference
android:id="@+id/pref_progbar"
android:defaultValue="true"
android:key="enable_progbar"
- android:summary="Show an animated progress bar while doing long background tasks.\nKeep it disabled to (hopefully) save some extra power for the WiFi dongle."
- android:title="Animated progress bar" />
+ android:summary="@string/summary_progbar"
+ android:title="@string/title_progbar" />
<CheckBoxPreference
android:id="@+id/pref_autostart"
android:defaultValue="false"
android:key="enable_autostart"
- android:summary="If checked, RepWifi is started automatically on system's startup."
- android:title="Enable Start at Boot" />
+ android:summary="@string/summary_start_at_boot"
+ android:title="@string/title_start_at_boot" />
- <Preference android:title="Restore Defaults"
+ <Preference android:title="@string/title_restore_default"
android:key="pref_restore_default"
- android:summary="click to restore default settings\n(then return to main screen to apply the reset)"
+ android:summary="@string/summary_restore_default"
android:background="@drawable/button_bg"
android:textColor="@color/ThemeLight" />
diff --git a/app/res/xml/settings_headers.xml b/app/res/xml/settings_headers.xml
index 50f7436..d33ae33 100644
--- a/app/res/xml/settings_headers.xml
+++ b/app/res/xml/settings_headers.xml
@@ -3,12 +3,12 @@
<header
android:fragment="fil.libre.repwifiapp.activities.SettingsActivity$GeneralSettingFragment"
- android:summary="set general options"
- android:title="Options" />
+ android:summary="@string/summary_general_settings"
+ android:title="@string/title_general_settings" />
<header
android:fragment="fil.libre.repwifiapp.activities.SettingsActivity$DebugSettingFragment"
- android:summary="set advanced options and debug variables"
- android:title="Advanced &amp; Debug" />
+ android:summary="@string/summary_advanced_settings"
+ android:title="@string/title_advanced_settings" />
</preference-headers> \ No newline at end of file
diff --git a/app/src/de/blinkt/openvpn/api/APIVpnProfile.aidl b/app/src/de/blinkt/openvpn/api/APIVpnProfile.aidl
new file mode 100644
index 0000000..f679965
--- /dev/null
+++ b/app/src/de/blinkt/openvpn/api/APIVpnProfile.aidl
@@ -0,0 +1,3 @@
+package de.blinkt.openvpn.api;
+
+parcelable APIVpnProfile;
diff --git a/app/src/de/blinkt/openvpn/api/APIVpnProfile.java b/app/src/de/blinkt/openvpn/api/APIVpnProfile.java
new file mode 100644
index 0000000..6acbf43
--- /dev/null
+++ b/app/src/de/blinkt/openvpn/api/APIVpnProfile.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012-2015 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms.
+ * For full terms see the file https://github.com/schwabe/ics-openvpn/blob/master/doc/LICENSE.txt
+ */
+
+package de.blinkt.openvpn.api;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class APIVpnProfile implements Parcelable {
+
+ public final String mUUID;
+ public final String mName;
+ public final boolean mUserEditable;
+ //public final String mProfileCreator;
+
+ public APIVpnProfile(Parcel in) {
+ mUUID = in.readString();
+ mName = in.readString();
+ mUserEditable = in.readInt() != 0;
+ //mProfileCreator = in.readString();
+ }
+
+ public APIVpnProfile(String uuidString, String name, boolean userEditable, String profileCreator) {
+ mUUID = uuidString;
+ mName = name;
+ mUserEditable = userEditable;
+ //mProfileCreator = profileCreator;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mUUID);
+ dest.writeString(mName);
+ if (mUserEditable)
+ dest.writeInt(0);
+ else
+ dest.writeInt(1);
+ //dest.writeString(mProfileCreator);
+ }
+
+ public static final Creator<APIVpnProfile> CREATOR
+ = new Creator<APIVpnProfile>() {
+ public APIVpnProfile createFromParcel(Parcel in) {
+ return new APIVpnProfile(in);
+ }
+
+ public APIVpnProfile[] newArray(int size) {
+ return new APIVpnProfile[size];
+ }
+ };
+
+
+}
diff --git a/app/src/de/blinkt/openvpn/api/DO_NOT_RENAME b/app/src/de/blinkt/openvpn/api/DO_NOT_RENAME
new file mode 100644
index 0000000..a7b3fe8
--- /dev/null
+++ b/app/src/de/blinkt/openvpn/api/DO_NOT_RENAME
@@ -0,0 +1 @@
+If you create your own remote application remember that these classes are the remote API of ics-openvpn and should be kept as de.blinkt.openvpn.api. \ No newline at end of file
diff --git a/app/src/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl b/app/src/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl
new file mode 100644
index 0000000..273a004
--- /dev/null
+++ b/app/src/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl
@@ -0,0 +1,66 @@
+// IOpenVPNAPIService.aidl
+package de.blinkt.openvpn.api;
+
+import de.blinkt.openvpn.api.APIVpnProfile;
+import de.blinkt.openvpn.api.IOpenVPNStatusCallback;
+
+import android.content.Intent;
+import android.os.ParcelFileDescriptor;
+
+interface IOpenVPNAPIService {
+ List<APIVpnProfile> getProfiles();
+
+ void startProfile (String profileUUID);
+
+ /** Use a profile with all certificates etc. embedded,
+ * old version which does not return the UUID of the addded profile, see
+ * below for a version that return the UUID on add */
+ boolean addVPNProfile (String name, String config);
+
+ /** start a profile using a config as inline string. Make sure that all needed data is inlined,
+ * e.g., using <ca>...</ca> or <auth-user-data>...</auth-user-data>
+ * See the OpenVPN manual page for more on inlining files */
+ void startVPN (String inlineconfig);
+
+ /** This permission framework is used to avoid confused deputy style attack to the VPN
+ * calling this will give null if the app is allowed to use the external API and an Intent
+ * that can be launched to request permissions otherwise */
+ Intent prepare (String packagename);
+
+ /** Used to trigger to the Android VPN permission dialog (VPNService.prepare()) in advance,
+ * if this return null OpenVPN for ANdroid already has the permissions otherwise you can start the returned Intent
+ * to let OpenVPN for Android request the permission */
+ Intent prepareVPNService ();
+
+ /* Disconnect the VPN */
+ void disconnect();
+
+ /* Pause the VPN (same as using the pause feature in the notifcation bar) */
+ void pause();
+
+ /* Resume the VPN (same as using the pause feature in the notifcation bar) */
+ void resume();
+
+ /**
+ * Registers to receive OpenVPN Status Updates
+ */
+ void registerStatusCallback(IOpenVPNStatusCallback cb);
+
+ /**
+ * Remove a previously registered callback interface.
+ */
+ void unregisterStatusCallback(IOpenVPNStatusCallback cb);
+
+ /** Remove a profile by UUID */
+ void removeProfile (String profileUUID);
+
+ /** Request a socket to be protected as a VPN socket would be. Useful for creating
+ * a helper socket for an app controlling OpenVPN
+ * Before calling this function you should make sure OpenVPN for Android may actually
+ * this function by checking if prepareVPNService returns null; */
+ boolean protectSocket(in ParcelFileDescriptor fd);
+
+
+ /** Use a profile with all certificates etc. embedded */
+ APIVpnProfile addNewVPNProfile (String name, boolean userEditable, String config);
+} \ No newline at end of file
diff --git a/app/src/de/blinkt/openvpn/api/IOpenVPNStatusCallback.aidl b/app/src/de/blinkt/openvpn/api/IOpenVPNStatusCallback.aidl
new file mode 100644
index 0000000..1dfa138
--- /dev/null
+++ b/app/src/de/blinkt/openvpn/api/IOpenVPNStatusCallback.aidl
@@ -0,0 +1,13 @@
+package de.blinkt.openvpn.api;
+
+/**
+ * Example of a callback interface used by IRemoteService to send
+ * synchronous notifications back to its clients. Note that this is a
+ * one-way interface so the server does not block waiting for the client.
+ */
+oneway interface IOpenVPNStatusCallback {
+ /**
+ * Called when the service has a new status for you.
+ */
+ void newStatus(String uuid, String state, String message, String level);
+}
diff --git a/app/src/fil/libre/repwifiapp/ActivityLauncher.java b/app/src/fil/libre/repwifiapp/ActivityLauncher.java
index 00a8d50..5e9c31d 100644
--- a/app/src/fil/libre/repwifiapp/ActivityLauncher.java
+++ b/app/src/fil/libre/repwifiapp/ActivityLauncher.java
@@ -1,3 +1,23 @@
+//
+// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
+//
+// This file is part of RepWifiApp.
+//
+// RepWifiApp 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.
+//
+// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>.
+//
+// ********************************************************************
+
package fil.libre.repwifiapp;
import android.app.Activity;
@@ -5,10 +25,12 @@ import android.content.Intent;
import android.widget.Toast;
import fil.libre.repwifiapp.activities.InputPasswordActivity;
import fil.libre.repwifiapp.activities.InputSsidActivity;
+import fil.libre.repwifiapp.activities.Ipv4SettingsActivity;
import fil.libre.repwifiapp.activities.LongTaskActivity;
import fil.libre.repwifiapp.activities.NetworkDetailsActivity;
import fil.libre.repwifiapp.activities.SelectNetworkActivity;
import fil.libre.repwifiapp.activities.ShowStatusActivity;
+import fil.libre.repwifiapp.activities.VpnSettingsActivity;
import fil.libre.repwifiapp.helpers.AccessPointInfo;
import fil.libre.repwifiapp.helpers.ConnectionStatus;
import fil.libre.repwifiapp.helpers.NetworkManager;
@@ -39,6 +61,7 @@ public class ActivityLauncher {
public static final int CONNECT_HIDDEN = 10;
public static final int USB_ATTACHED = 11;
public static final int USB_DETACHED = 12;
+ public static final int VPN_PERMISSION = 13;
}
@@ -59,7 +82,7 @@ public class ActivityLauncher {
}
public void launchLongTaskActivityConnect(AccessPointInfo info) {
-
+
Intent intent = new Intent(currentContext, LongTaskActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.putExtra(ActivityLauncher.EXTRA_REQCODE, RequestCode.CONNECT);
@@ -102,7 +125,7 @@ public class ActivityLauncher {
nets = manager.getKnownNetworks();
if (nets == null || nets.length == 0) {
- Toast toast = Toast.makeText(currentContext, "No saved network", Toast.LENGTH_LONG);
+ Toast toast = Toast.makeText(currentContext, Commons.msgNoSavedNetwork, Toast.LENGTH_LONG);
toast.show();
return;
}
@@ -130,6 +153,24 @@ public class ActivityLauncher {
currentContext.startActivityForResult(intent, RequestCode.DETAILS_SHOW);
}
+
+ public void launchIpSettingsActivity(AccessPointInfo info) {
+
+ Intent intent = new Intent(currentContext, Ipv4SettingsActivity.class);
+ // intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
+ intent.putExtra(EXTRA_APINFO, info);
+ currentContext.startActivity(intent);
+
+ }
+
+ public void launchVpnSettingsActivity(AccessPointInfo info) {
+
+ Intent intent = new Intent(currentContext, VpnSettingsActivity.class);
+ // intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
+ intent.putExtra(EXTRA_APINFO, info);
+ currentContext.startActivity(intent);
+
+ }
public void launchInputSsidActivity() {
@@ -139,5 +180,6 @@ public class ActivityLauncher {
currentContext.startActivityForResult(intent, RequestCode.CONNECT_HIDDEN);
}
+
}
diff --git a/app/src/fil/libre/repwifiapp/Commons.java b/app/src/fil/libre/repwifiapp/Commons.java
index 200381f..1603a76 100644
--- a/app/src/fil/libre/repwifiapp/Commons.java
+++ b/app/src/fil/libre/repwifiapp/Commons.java
@@ -20,6 +20,12 @@
package fil.libre.repwifiapp;
+import java.io.File;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Locale;
+import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
@@ -30,39 +36,33 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
+import android.os.Environment;
import android.preference.PreferenceManager;
import fil.libre.repwifiapp.activities.MainActivity;
import fil.libre.repwifiapp.helpers.ConnectionStatus;
+import fil.libre.repwifiapp.helpers.Engine;
import fil.libre.repwifiapp.helpers.Engine6p0;
import fil.libre.repwifiapp.helpers.IEngine;
import fil.libre.repwifiapp.helpers.NetworkManager;
import fil.libre.repwifiapp.helpers.Utils;
+import fil.libre.repwifiapp.helpers.WpaCli;
+import fil.libre.repwifiapp.helpers.WpaSupplicant;
public abstract class Commons {
private static Context currentContext;
- public Context getContext() {
+ public static Context getContext() {
return currentContext;
}
- // ------------- Enviromnet Constants -----------------
+ // ------------- Environment Constants -----------------
public static final int EXCOD_ROOT_DISABLED = 255;
public static final int EXCOD_ROOT_DENIED = 1;
public static final int WAIT_ON_USB_ATTACHED = 1500;
+ public static final int WAIT_FOR_GATEWAY = 4000;
public static final String BSSID_NOT_AVAILABLE = "[BSSID-NOT-AVAILABLE]";
- public static final String v4p2 = "4.2";
public static final String v6p0 = "6.0";
- public static final String SCAN_FILE_HDR = "bssid / frequency / signal level / flags / ssid";
- public static final String INTERFACE_NAME = "wlan0";
- public static final String WORKDIR = "/data/misc/wifi";
- public static final String PID_FILE = WORKDIR + "/pidfile";
- public static final String SOCKET_DIR = WORKDIR + "/sockets/";
- public static final String SOFTAP_FILE = WORKDIR + "/softap.conf";
- public static final String P2P_CONF = WORKDIR + "/p2p_supplicant.conf";
- public static final String WPA_CONF = WORKDIR + "/wpa_supplicant.conf";
- public static final String ENTROPY_FILE = WORKDIR + "/entropy.bin";
- public static final String OVERLAY_FILE = "/system/etc/wifi/wpa_supplicant_overlay.conf";
// ---------------------------------------------
// ------------- Shared Engines -----------------------
@@ -76,12 +76,45 @@ public abstract class Commons {
public static int colorBlack;
public static String dns1Default = "";
public static String dns2Default = "";
+ private static String APP_DATA_FOLDER;
+ public static String msgNoSavedNetwork;
+
+ public static String getNetworkStorageFile() {
+ if (APP_DATA_FOLDER == null) {
+ return null;
+ } else {
+ return APP_DATA_FOLDER + "/repwifi_storage.conf";
+ }
+ }
+
+ @SuppressLint("SimpleDateFormat")
+ public static String getLogDumpFile() {
+
+ File f = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
+ if (f == null || !f.exists()) {
+ return null;
+ }
+
+ String basefolder;
+ try {
+ basefolder = f.getCanonicalPath();
+ } catch (Exception e) {
+ Utils.logError("Exception while resolving canonical path for log dump file.", e);
+ return null;
+ }
+
+ DateFormat dateFormat = new SimpleDateFormat("yyyyMMddhhmmss", Locale.getDefault());
+ String ts = dateFormat.format(Calendar.getInstance().getTime());
+ return basefolder + "/repwifi_log_dump." + ts + ".log";
+ }
+
+ // --------------------------------------------------------
private static final int NOTIFICATION_ID = 1;
public static void updateNotification(Context context) {
- ConnectionStatus status = connectionEngine.getConnectionStatus();
+ ConnectionStatus status = WpaCli.getConnectionStatus();
Notification.Builder builder = new Notification.Builder(context);
@@ -104,7 +137,7 @@ public abstract class Commons {
builder.setSmallIcon(iconId);
builder.setContentTitle(msg);
- builder.setContentText("Touch to open.");
+ builder.setContentText(currentContext.getString(R.string.msg_touch_open));
Notification n = builder.build();
n.flags |= Notification.FLAG_NO_CLEAR;
@@ -124,12 +157,13 @@ public abstract class Commons {
AlertDialog.Builder dlgAlert = new AlertDialog.Builder(context,
R.style.Theme_RepWifiDialogTheme);
dlgAlert.setMessage(msg);
- dlgAlert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int whichButton) {
- return;
- }
- });
+ dlgAlert.setPositiveButton(currentContext.getString(android.R.string.ok),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int whichButton) {
+ return;
+ }
+ });
dlgAlert.setCancelable(false);
AlertDialog diag = dlgAlert.create();
@@ -180,9 +214,8 @@ public abstract class Commons {
if (silent) {
- if (connectionEngine != null) {
- connectionEngine.killBackEndProcesses();
- }
+ Engine.killDhcpcd();
+ WpaSupplicant.kill();
} else {
@@ -252,55 +285,6 @@ public abstract class Commons {
// ----------------------------------------------------
- // ----------------- Application Files --------------------
- private static String APP_DATA_FOLDER;
-
- public static String getNetworkStorageFile() {
- if (APP_DATA_FOLDER == null) {
- return null;
- } else {
- return APP_DATA_FOLDER + "/repwifi_storage.conf";
- }
- }
-
- public static String getTempFile() {
- return APP_DATA_FOLDER + "/file.tmp";
- }
-
- public static String getScriptScan() {
- return APP_DATA_FOLDER + "/scan_app.sh";
- }
-
- public static String getScriptScanRes() {
- return APP_DATA_FOLDER + "/get_scan_results_app.sh";
- }
-
- public static String getScriptDhcpcd() {
- return APP_DATA_FOLDER + "/run_dhcpcd.sh";
- }
-
- public static String getOldSelectScript() {
- return WORKDIR + "/select_network.sh";
- }
-
- public static String getScanFile() {
- return APP_DATA_FOLDER + "/scanres.txt";
- }
-
- public static String getStatusFile() {
- return APP_DATA_FOLDER + "/tmpStatus";
- }
-
- public static String getGwFile() {
- return APP_DATA_FOLDER + "/gw.txt";
- }
-
- public static String getTempOutFile() {
- return APP_DATA_FOLDER + "/tmpout.txt";
- }
-
- // --------------------------------------------------------
-
// ----------- Initialization methods ---------------------------
public static boolean init(Context context) {
@@ -310,6 +294,8 @@ public abstract class Commons {
colorThemeDark = currentContext.getResources().getColor(R.color.ThemeDark);
colorThemeLight = currentContext.getResources().getColor(R.color.ThemeLight);
+ msgNoSavedNetwork = currentContext.getResources().getString(
+ R.string.msg_no_saved_network);
colorBlack = currentContext.getResources().getColor(R.color.black);
APP_DATA_FOLDER = currentContext.getExternalFilesDir(null).getAbsolutePath();
dns1Default = currentContext.getResources().getString(R.string.dns1_default);
@@ -333,7 +319,7 @@ public abstract class Commons {
String vers = android.os.Build.VERSION.RELEASE;
if (!vers.startsWith(Commons.v6p0)) {
- showMessage("UNSUPPORTED OS VERSION\nThe current version of Replicant is not supported by RepWifi.\nPlease upgrade to the latest version as soon as possible!");
+ showMessage(currentContext.getString(R.string.msg_os_unsupported));
}
}
diff --git a/app/src/fil/libre/repwifiapp/RepWifiIntentReceiver.java b/app/src/fil/libre/repwifiapp/RepWifiIntentReceiver.java
index 3f507ec..ba26bb3 100644
--- a/app/src/fil/libre/repwifiapp/RepWifiIntentReceiver.java
+++ b/app/src/fil/libre/repwifiapp/RepWifiIntentReceiver.java
@@ -7,7 +7,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
-import android.util.Log;
public class RepWifiIntentReceiver extends BroadcastReceiver {
@@ -16,11 +15,9 @@ public class RepWifiIntentReceiver extends BroadcastReceiver {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context
.getApplicationContext());
if (!prefs.getBoolean("enable_autostart", false)) {
- Log.d("RepWifi", "autostart is false");
return;
}
- Log.d("RepWifi", "Autostart is true");
String a = intent.getAction();
if (a.equals(Intent.ACTION_BOOT_COMPLETED) || a.equals(Intent.ACTION_REBOOT)) {
diff --git a/app/src/fil/libre/repwifiapp/activities/InputPasswordActivity.java b/app/src/fil/libre/repwifiapp/activities/InputPasswordActivity.java
index 6f04d1c..32922c6 100644
--- a/app/src/fil/libre/repwifiapp/activities/InputPasswordActivity.java
+++ b/app/src/fil/libre/repwifiapp/activities/InputPasswordActivity.java
@@ -49,7 +49,7 @@ public class InputPasswordActivity extends Activity implements OnCheckedChangeLi
CheckBox c = (CheckBox) findViewById(R.id.chk_show_pass);
c.setOnCheckedChangeListener(this);
- setTitle("Input password");
+ setTitle(getResources().getString(R.string.title_input_password));
TextView v = (TextView) findViewById(R.id.txt_insert_pass);
@@ -81,7 +81,7 @@ public class InputPasswordActivity extends Activity implements OnCheckedChangeLi
String pass = txpass.getText().toString();
if (pass.length() == 0) {
- Commons.showMessage("Password can't be empty!", this);
+ Commons.showMessage(getString(R.string.msg_password_empty), this);
}
this.apinfo.setPassword(pass);
diff --git a/app/src/fil/libre/repwifiapp/activities/InputSsidActivity.java b/app/src/fil/libre/repwifiapp/activities/InputSsidActivity.java
index 4f3f74c..8b7c60c 100644
--- a/app/src/fil/libre/repwifiapp/activities/InputSsidActivity.java
+++ b/app/src/fil/libre/repwifiapp/activities/InputSsidActivity.java
@@ -39,7 +39,7 @@ public class InputSsidActivity extends Activity {
super.onCreate(icicle);
setContentView(R.layout.activity_input_ssid);
- setTitle("Insert Network's parameters");
+ setTitle(getString(R.string.title_input_ssid));
}
@@ -85,7 +85,7 @@ public class InputSsidActivity extends Activity {
String ssid = txssid.getText().toString();
if (ssid.length() == 0) {
- Commons.showMessage("Network name can't be empty!", this);
+ Commons.showMessage(getString(R.string.msg_network_name_empty), this);
return;
}
diff --git a/app/src/fil/libre/repwifiapp/activities/Ipv4SettingsActivity.java b/app/src/fil/libre/repwifiapp/activities/Ipv4SettingsActivity.java
new file mode 100644
index 0000000..1f15252
--- /dev/null
+++ b/app/src/fil/libre/repwifiapp/activities/Ipv4SettingsActivity.java
@@ -0,0 +1,181 @@
+//
+// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
+//
+// This file is part of RepWifiApp.
+//
+// RepWifiApp 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.
+//
+// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>.
+//
+// ********************************************************************
+
+package fil.libre.repwifiapp.activities;
+
+import fil.libre.repwifiapp.ActivityLauncher;
+import fil.libre.repwifiapp.Commons;
+import fil.libre.repwifiapp.R;
+import fil.libre.repwifiapp.helpers.AccessPointInfo;
+import fil.libre.repwifiapp.helpers.DhcpSettings;
+import android.nfc.FormatException;
+import android.os.Bundle;
+import android.app.Activity;
+import android.content.Intent;
+import android.view.Menu;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.EditText;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+
+public class Ipv4SettingsActivity extends Activity implements OnCheckedChangeListener {
+
+ private AccessPointInfo currentNetwork;
+ private DhcpSettings currentSettings;
+
+ private EditText txtIp;
+ private EditText txtGw;
+ private EditText txtMask;
+ private CheckBox chkDhcp;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_ipv4_settings);
+
+ chkDhcp = (CheckBox) findViewById(R.id.chk_use_dhcp);
+ txtIp = (EditText) findViewById(R.id.txt_static_ip);
+ txtMask = (EditText) findViewById(R.id.txt_netmask);
+ txtGw = (EditText) findViewById(R.id.txt_gateway);
+
+ chkDhcp.setOnCheckedChangeListener(this);
+
+ Intent intent = getIntent();
+ if (!intent.hasExtra(ActivityLauncher.EXTRA_APINFO)) {
+ this.setResult(RESULT_CANCELED);
+ this.finish();
+ return;
+ }
+
+ this.currentNetwork = (AccessPointInfo) intent.getExtras().getSerializable(
+ ActivityLauncher.EXTRA_APINFO);
+ if (this.currentNetwork == null) {
+ this.setResult(RESULT_CANCELED);
+ this.finish();
+ return;
+ }
+
+ this.currentNetwork = Commons.storage.getSavedNetwork(currentNetwork);
+
+ loadNetwork();
+
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ // getMenuInflater().inflate(R.menu.activity_manage_networks, menu);
+ return true;
+ }
+
+ private void loadNetwork() {
+
+ setTitle(this.currentNetwork.getSsid());
+ currentSettings = this.currentNetwork.getDhcpConfiguration();
+ loadSettings();
+
+ }
+
+ private void loadSettings() {
+
+ if (currentSettings.useDhcp) {
+
+ chkDhcp.setChecked(true);
+
+ txtIp.setText("");
+ txtIp.setEnabled(false);
+
+ txtMask.setText("");
+ txtMask.setEnabled(false);
+
+ txtGw.setText("");
+ txtGw.setEnabled(false);
+
+ } else {
+ chkDhcp.setChecked(false);
+
+ txtIp.setText(currentSettings.getStaticIP());
+ txtIp.setEnabled(true);
+
+ txtMask.setText(currentSettings.getSubnetMaskString());
+ txtMask.setEnabled(true);
+
+ txtGw.setText(currentSettings.getDefaultGateway());
+ txtGw.setEnabled(true);
+ }
+
+ }
+
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+
+ if (buttonView == findViewById(R.id.chk_use_dhcp)) {
+ currentSettings.useDhcp = isChecked;
+ loadSettings();
+
+ }
+
+ }
+
+ public void btnSaveClick(View v) throws FormatException {
+
+ if (chkDhcp.isChecked()) {
+ currentSettings.useDhcp = true;
+
+ } else {
+
+ String ip = txtIp.getText().toString();
+ String mask = txtMask.getText().toString();
+ String gw = txtGw.getText().toString();
+
+ if (!DhcpSettings.isValidAddress(ip)) {
+ Commons.showMessage(getString(R.string.msg_invalid_ip),this);
+ return;
+ }
+
+ if (!DhcpSettings.isValidMaks(mask)) {
+ Commons.showMessage(getString(R.string.msg_invalid_netmask),this);
+ return;
+ }
+
+ if (!DhcpSettings.isValidAddress(gw)) {
+ Commons.showMessage(getString(R.string.msg_invalid_gateway),this);
+ return;
+ }
+
+ currentSettings = new DhcpSettings(chkDhcp.isChecked(), ip, mask, gw);
+
+ }
+
+ currentNetwork.setDhcpConfiguration(currentSettings);
+ if (Commons.storage.save(currentNetwork)) {
+ Commons.showMessage(getString(R.string.msg_network_saved),this);
+ } else {
+ Commons.showMessage(getString(R.string.msg_network_save_fail),this);
+ }
+
+ }
+
+ public void btnBackClick(View v) {
+ finish();
+ }
+
+}
diff --git a/app/src/fil/libre/repwifiapp/activities/LongTaskActivity.java b/app/src/fil/libre/repwifiapp/activities/LongTaskActivity.java
index e0b4184..a5292d2 100644
--- a/app/src/fil/libre/repwifiapp/activities/LongTaskActivity.java
+++ b/app/src/fil/libre/repwifiapp/activities/LongTaskActivity.java
@@ -1,3 +1,24 @@
+//
+// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
+//
+// This file is part of RepWifiApp.
+//
+// RepWifiApp 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.
+//
+// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>.
+//
+// ********************************************************************
+
+
package fil.libre.repwifiapp.activities;
import fil.libre.repwifiapp.ActivityLauncher;
@@ -99,21 +120,21 @@ public class LongTaskActivity extends Activity {
// Extract AccessPointInfo
input = intent.getExtras().getSerializable(ActivityLauncher.EXTRA_APINFO);
currentNetwork = (AccessPointInfo) input;
- setTitle("Connecting to " + currentNetwork.getSsid() + "...");
- setMessage("Connecting to " + currentNetwork.getSsid() + "...");
+ setTitle(getString(R.string.msg_connecting_to) + " " + currentNetwork.getSsid() + "...");
+ setMessage(getString(R.string.msg_connecting_to) + " " + currentNetwork.getSsid() + "...");
break;
case ActivityLauncher.RequestCode.NETWORKS_GET:
- setTitle("Scanning...");
- setMessage("Scanning for Networks...");
+ setTitle(getString(R.string.title_scanning));
+ setMessage(getString(R.string.msg_scanning_for_nets));
case ActivityLauncher.RequestCode.STATUS_GET:
- setTitle("Checking status...");
- setMessage("Checking status...");
+ setTitle(getString(R.string.msg_checking_status));
+ setMessage(getString(R.string.msg_checking_status));
default:
- setTitle("Please wait...");
- setMessage("Please wait...");
+ setTitle(getString(R.string.msg_please_wait));
+ setMessage(getString(R.string.msg_please_wait));
break;
}
diff --git a/app/src/fil/libre/repwifiapp/activities/MainActivity.java b/app/src/fil/libre/repwifiapp/activities/MainActivity.java
index 6e667bf..7a22416 100644
--- a/app/src/fil/libre/repwifiapp/activities/MainActivity.java
+++ b/app/src/fil/libre/repwifiapp/activities/MainActivity.java
@@ -20,7 +20,6 @@
package fil.libre.repwifiapp.activities;
-import java.io.IOException;
import java.net.SocketException;
import fil.libre.repwifiapp.ActivityLauncher;
import fil.libre.repwifiapp.Commons;
@@ -29,8 +28,10 @@ import fil.libre.repwifiapp.ActivityLauncher.RequestCode;
import fil.libre.repwifiapp.helpers.AccessPointInfo;
import fil.libre.repwifiapp.helpers.ConnectionStatus;
import fil.libre.repwifiapp.helpers.NetworkManager;
+import fil.libre.repwifiapp.helpers.OpenVpnManager;
import fil.libre.repwifiapp.helpers.RootCommand;
import fil.libre.repwifiapp.helpers.Utils;
+import fil.libre.repwifiapp.helpers.WpaSupplicant;
import android.os.Bundle;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -59,8 +60,16 @@ public class MainActivity extends MenuEnabledActivity {
return;
}
+ if (! Commons.storage.updateStorageVersion()){
+ Utils.logError("Failed to convert storage file to new version!");
+ }
+
setImage();
setUsbDeviceMonitor();
+ setVersionOnTitle();
+
+ OpenVpnManager.initialize(this);
+
}
@Override
@@ -149,11 +158,6 @@ public class MainActivity extends MenuEnabledActivity {
handleFinishedConnecting(conres, i);
break;
- case RequestCode.STATUS_GET:
- ConnectionStatus status = (ConnectionStatus) intent.getExtras().getSerializable(
- ActivityLauncher.EXTRA_CONSTATUS);
- handleResultGetStatus(status);
- break;
case RequestCode.NETWORKS_GET:
AccessPointInfo[] nets = (AccessPointInfo[]) intent.getExtras().getSerializable(
@@ -182,6 +186,7 @@ public class MainActivity extends MenuEnabledActivity {
}
break;
+
default:
break;
@@ -190,6 +195,23 @@ public class MainActivity extends MenuEnabledActivity {
}
+ private void setVersionOnTitle() {
+
+ try {
+
+ String vers = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
+ if (vers == null) {
+ return;
+ }
+
+ setTitle(getTitle() + " - v." + vers);
+
+ } catch (Exception e) {
+ Utils.logError("Error while setting version on MainActivity's title.", e);
+ }
+
+ }
+
private void setImage() {
ImageView img = (ImageView) findViewById(R.id.img_logo);
@@ -197,7 +219,7 @@ public class MainActivity extends MenuEnabledActivity {
try {
Drawable d = Drawable.createFromStream(getAssets().open("repwifi-logo-0.png"), null);
img.setImageDrawable(d);
- } catch (IOException e) {
+ } catch (Exception e) {
Utils.logError("Error while loading logo image", e);
}
@@ -224,6 +246,7 @@ public class MainActivity extends MenuEnabledActivity {
}
private boolean checkConditions() {
+
return (checkRootEnabled() && checkInterface(true));
}
@@ -233,7 +256,7 @@ public class MainActivity extends MenuEnabledActivity {
String msg = "";
try {
- res = Commons.connectionEngine.isInterfaceAvailable(Commons.INTERFACE_NAME);
+ res = Commons.connectionEngine.isInterfaceAvailable(WpaSupplicant.INTERFACE_NAME);
} catch (SocketException e) {
Utils.logError("SocketException during isInterfaceAvailable()", e);
msg = "Error while retrieving interface list!";
@@ -258,7 +281,7 @@ public class MainActivity extends MenuEnabledActivity {
int excode = -1;
try {
- excode = su.execute();
+ excode = su.testRootAccess();
} catch (Exception e) {
Utils.logError("Error while trying to get first Super User access.", e);
excode = -1;
@@ -304,7 +327,7 @@ public class MainActivity extends MenuEnabledActivity {
if (i.needsPassword()) {
- // try to fetch network's password from storage
+ // try to fetch network's configuration from storage
AccessPointInfo fromStorage = Commons.storage.getSavedNetwork(i);
if (fromStorage == null) {
@@ -327,12 +350,6 @@ public class MainActivity extends MenuEnabledActivity {
launcher.launchLongTaskActivityConnect(i);
}
- private void handleResultGetStatus(ConnectionStatus status) {
- if (status != null && status.isConnected()) {
- launcher.launchStatusActivity(status);
- }
- }
-
private void handleFinishedConnecting(boolean connectionResult, AccessPointInfo info) {
if (connectionResult && info.needsPassword()) {
@@ -345,13 +362,13 @@ public class MainActivity extends MenuEnabledActivity {
// Save network
if (Commons.storage.save(info)) {
- Toast toast2 = Toast.makeText(getApplicationContext(), "Network Saved!",
- Toast.LENGTH_LONG);
+ Toast toast2 = Toast.makeText(getApplicationContext(),
+ getString(R.string.msg_network_saved), Toast.LENGTH_LONG);
toast2.show();
} else {
- Toast toast2 = Toast.makeText(getApplicationContext(), "FAILED to save network!",
- Toast.LENGTH_LONG);
+ Toast toast2 = Toast.makeText(getApplicationContext(),
+ getString(R.string.msg_network_save_fail), Toast.LENGTH_LONG);
toast2.show();
}
@@ -360,8 +377,8 @@ public class MainActivity extends MenuEnabledActivity {
} else {
// alert that connection failed
- Toast toast = Toast.makeText(getApplicationContext(), "FAILED to connect!",
- Toast.LENGTH_LONG);
+ Toast toast = Toast.makeText(getApplicationContext(),
+ getString(R.string.msg_connect_fail), Toast.LENGTH_LONG);
toast.show();
}
}
@@ -371,9 +388,9 @@ public class MainActivity extends MenuEnabledActivity {
NetworkManager manager = new NetworkManager(Commons.getNetworkStorageFile());
String msg = "";
if (manager.remove(info)) {
- msg = "Network info deleted!";
+ msg = getString(R.string.msg_netinfo_deleted);
} else {
- msg = "FAILED to delete network info!";
+ msg = getString(R.string.msg_netinfo_delete_fail);
}
Toast toast = Toast.makeText(this, msg, Toast.LENGTH_LONG);
@@ -437,7 +454,7 @@ public class MainActivity extends MenuEnabledActivity {
} catch (Exception e) {
Utils.logError("Error while autoconnecting", e);
- Commons.showMessage("An error occured while trying to auto-connect", this);
+ Commons.showMessage(getString(R.string.msg_autoconnect_error), this);
}
}
diff --git a/app/src/fil/libre/repwifiapp/activities/MenuEnabledActivity.java b/app/src/fil/libre/repwifiapp/activities/MenuEnabledActivity.java
index 0edfcf0..f5c8516 100644
--- a/app/src/fil/libre/repwifiapp/activities/MenuEnabledActivity.java
+++ b/app/src/fil/libre/repwifiapp/activities/MenuEnabledActivity.java
@@ -1,20 +1,60 @@
+//
+// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
+//
+// This file is part of RepWifiApp.
+//
+// RepWifiApp 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.
+//
+// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>.
+//
+// ********************************************************************
+
package fil.libre.repwifiapp.activities;
+import java.lang.reflect.Field;
+import fil.libre.repwifiapp.Commons;
import fil.libre.repwifiapp.R;
+import fil.libre.repwifiapp.helpers.RootCommand;
import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
import android.content.Intent;
import android.view.Menu;
import android.view.MenuItem;
+import android.view.ViewConfiguration;
public class MenuEnabledActivity extends Activity {
@Override
+ protected void onCreate(android.os.Bundle savedInstanceState) {
+ try {
+ ViewConfiguration config = ViewConfiguration.get(this);
+ Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
+ if (menuKeyField != null) {
+ menuKeyField.setAccessible(true);
+ menuKeyField.setBoolean(config, false);
+ }
+ } catch (Exception ignored) {
+ }
+ super.onCreate(savedInstanceState);
+ };
+
+ @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
-
+
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
@@ -27,6 +67,10 @@ public class MenuEnabledActivity extends Activity {
case R.id.menu_config:
launchSettingsActivity();
break;
+
+ case R.id.menu_btn_closeapp:
+ CloseApplication(false);
+ break;
default:
break;
@@ -46,4 +90,46 @@ public class MenuEnabledActivity extends Activity {
// intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);
}
+
+ protected void CloseApplication(boolean silent) {
+
+ if (silent) {
+
+ Commons.connectionEngine.disconnect();
+ Commons.killBackEnd(this, true);
+ super.onDestroy();
+ RootCommand.executeRootCmd("am force-stop " + getPackageName());
+
+ } else {
+
+ String msg = getString(R.string.confirm_exit_app);
+ AlertDialog.Builder dlgAlert = new AlertDialog.Builder(this,
+ R.style.Theme_RepWifiDialogTheme);
+ dlgAlert.setMessage(msg);
+ dlgAlert.setPositiveButton(this.getString(android.R.string.ok),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int whichButton) {
+ CloseApplication(true);
+ return;
+ }
+ });
+ dlgAlert.setNegativeButton(getString(android.R.string.cancel),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int whichButton) {
+ return;
+ }
+ });
+
+ dlgAlert.setCancelable(false);
+ AlertDialog diag = dlgAlert.create();
+
+ diag.show();
+ return;
+
+ }
+
+ }
+
}
diff --git a/app/src/fil/libre/repwifiapp/activities/NetworkDetailsActivity.java b/app/src/fil/libre/repwifiapp/activities/NetworkDetailsActivity.java
index 325d546..f2a8944 100644
--- a/app/src/fil/libre/repwifiapp/activities/NetworkDetailsActivity.java
+++ b/app/src/fil/libre/repwifiapp/activities/NetworkDetailsActivity.java
@@ -22,6 +22,7 @@ package fil.libre.repwifiapp.activities;
import java.util.Date;
import fil.libre.repwifiapp.ActivityLauncher;
+import fil.libre.repwifiapp.Commons;
import fil.libre.repwifiapp.R;
import fil.libre.repwifiapp.helpers.AccessPointInfo;
import android.os.Bundle;
@@ -69,6 +70,12 @@ public class NetworkDetailsActivity extends Activity implements OnCheckedChangeL
}
@Override
+ protected void onStart() {
+ super.onStart();
+ currentNetwork = Commons.storage.getSavedNetwork(currentNetwork);
+ };
+
+ @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
// getMenuInflater().inflate(R.menu.activity_manage_networks, menu);
@@ -88,17 +95,26 @@ public class NetworkDetailsActivity extends Activity implements OnCheckedChangeL
if (lastused > 0) {
Date ts = new Date(lastused);
String formstring = "dd-MMM-yyyy kk:mm:ss";
- v.append("\nLast Used: " + DateFormat.format(formstring, ts));
+ v.append("\n" + getString(R.string.text_netinfo_last_used) + ": "
+ + DateFormat.format(formstring, ts));
}
if (showPassword) {
- v.append("\n\nPassword:\n" + this.currentNetwork.getPassword());
+ v.append("\n\n" + getString(R.string.text_password) + ":\n" + this.currentNetwork.getPassword());
} else {
v.append("\n\n\n");
}
}
+ public void btnIpSettingsClick(View v){
+ new ActivityLauncher(this).launchIpSettingsActivity(currentNetwork);
+ }
+
+ public void btnVpnSettingsClick(View v){
+ new ActivityLauncher(this).launchVpnSettingsActivity(currentNetwork);
+ }
+
public void btnDeleteClick(View v) {
String msg = getResources().getString(R.string.msg_confirm_delete_network);
diff --git a/app/src/fil/libre/repwifiapp/activities/SelectNetworkActivity.java b/app/src/fil/libre/repwifiapp/activities/SelectNetworkActivity.java
index 341fb68..51baed8 100644
--- a/app/src/fil/libre/repwifiapp/activities/SelectNetworkActivity.java
+++ b/app/src/fil/libre/repwifiapp/activities/SelectNetworkActivity.java
@@ -48,7 +48,7 @@ public class SelectNetworkActivity extends Activity implements OnClickListener {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select_network);
- setTitle("Select network");
+ setTitle(getString(R.string.title_activity_select_network));
getNetworks();
@@ -135,17 +135,17 @@ public class SelectNetworkActivity extends Activity implements OnClickListener {
if (info == null) {
Utils.logError("Unable to retrieve network list!");
- writeOut("Unable to retrieve network list!");
+ writeOut(getString(R.string.msg_network_list_fail));
return;
}
if (info.length == 0) {
- writeOut("No network found.");
+ writeOut(getString(R.string.msg_no_network));
toggleBtnRescan(true);
return;
}
- writeOut("Select the network you want to connect to:");
+ writeOut(getString(R.string.msg_select_network_connect));
toggleBtnRescan(false);
for (AccessPointInfo i : info) {
@@ -162,7 +162,7 @@ public class SelectNetworkActivity extends Activity implements OnClickListener {
return;
}
- writeOut("Select network info to manage:");
+ writeOut(getString(R.string.msg_select_network_manage));
toggleBtnRescan(false);
for (AccessPointInfo i : info) {
diff --git a/app/src/fil/libre/repwifiapp/activities/SettingsActivity.java b/app/src/fil/libre/repwifiapp/activities/SettingsActivity.java
index 6f14748..36e0e1f 100644
--- a/app/src/fil/libre/repwifiapp/activities/SettingsActivity.java
+++ b/app/src/fil/libre/repwifiapp/activities/SettingsActivity.java
@@ -1,9 +1,31 @@
+//
+// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
+//
+// This file is part of RepWifiApp.
+//
+// RepWifiApp 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.
+//
+// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>.
+//
+// ********************************************************************
+
+
package fil.libre.repwifiapp.activities;
import org.apache.http.conn.util.InetAddressUtils;
import java.util.List;
import fil.libre.repwifiapp.Commons;
import fil.libre.repwifiapp.R;
+import fil.libre.repwifiapp.helpers.Utils;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.Preference;
@@ -31,6 +53,7 @@ public class SettingsActivity extends PreferenceActivity {
addPreferencesFromResource(R.xml.debug_settings);
setConfirmKillBackend();
+ setDumpFileClick();
}
@@ -48,6 +71,24 @@ public class SettingsActivity extends PreferenceActivity {
}
+ private void setDumpFileClick() {
+ Preference pref = getPreferenceScreen().findPreference("pref_dump_log");
+ pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+
+ @Override
+ public boolean onPreferenceClick(Preference p) {
+ if (Utils.dumpLogcatToFile(Commons.getLogDumpFile())) {
+ Commons.showMessage(getString(R.string.msg_log_saved) + ": \n" + Commons.getLogDumpFile(),
+ getActivity());
+
+ } else {
+ Commons.showMessage(getString(R.string.msg_log_save_fail), getActivity());
+ }
+ return true;
+ }
+ });
+ }
+
}
public static class GeneralSettingFragment extends PreferenceFragment {
@@ -76,7 +117,7 @@ public class SettingsActivity extends PreferenceActivity {
|| InetAddressUtils.isIPv4Address((String) newValue)) {
return true;
} else {
- Commons.showMessage("ERROR:\nWrong IP format!", getActivity());
+ Commons.showMessage(getString(R.string.msg_error_ip_format), getActivity());
return false;
}
}
diff --git a/app/src/fil/libre/repwifiapp/activities/ShowStatusActivity.java b/app/src/fil/libre/repwifiapp/activities/ShowStatusActivity.java
index 0fb8992..21bfc4c 100644
--- a/app/src/fil/libre/repwifiapp/activities/ShowStatusActivity.java
+++ b/app/src/fil/libre/repwifiapp/activities/ShowStatusActivity.java
@@ -23,9 +23,14 @@ package fil.libre.repwifiapp.activities;
import fil.libre.repwifiapp.ActivityLauncher;
import fil.libre.repwifiapp.Commons;
import fil.libre.repwifiapp.R;
+import fil.libre.repwifiapp.ActivityLauncher.RequestCode;
+import fil.libre.repwifiapp.helpers.AccessPointInfo;
import fil.libre.repwifiapp.helpers.ConnectionStatus;
+import fil.libre.repwifiapp.helpers.OpenVpnManager;
import fil.libre.repwifiapp.helpers.Utils;
+import android.content.Intent;
import android.os.Bundle;
+import android.os.RemoteException;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
@@ -35,6 +40,8 @@ public class ShowStatusActivity extends MenuEnabledActivity {
private ConnectionStatus status;
+ // private AccessPointInfo info;
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -45,14 +52,45 @@ public class ShowStatusActivity extends MenuEnabledActivity {
ActivityLauncher.EXTRA_CONSTATUS);
}
- showStatus(false);
+ try {
+ showStatus(false);
+ } catch (Exception e) {
+ Utils.logError("Exception on showStatus", e);
+ }
}
@Override
public void onRestart() {
super.onRestart();
- showStatus(true);
+ try {
+ showStatus(true);
+ } catch (Exception e) {
+ Utils.logError("Exception on showStatus", e);
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+
+ switch (requestCode) {
+
+ case RequestCode.VPN_PERMISSION:
+
+ if (resultCode == RESULT_OK) {
+ endLaunchVpn(true);
+ } else {
+ endLaunchVpn(false);
+ }
+
+ break;
+
+ default:
+
+ break;
+
+ }
+
}
private void setMessage(String msg) {
@@ -60,7 +98,7 @@ public class ShowStatusActivity extends MenuEnabledActivity {
view.setText(msg);
}
- private void showStatus(boolean refresh) {
+ private void showStatus(boolean refresh) throws Exception {
if (refresh || status == null) {
this.status = Commons.connectionEngine.getConnectionStatus();
@@ -71,12 +109,14 @@ public class ShowStatusActivity extends MenuEnabledActivity {
} else if (this.status.isConnected()) {
Utils.logDebug("StatusActivity isConnected,showing buttons");
- setMessage("Connected to " + status.SSID + "\n\n" + "IP Address: " + status.IP + "\n");
+ setMessage(getString(R.string.msg_connected_to) + " " + status.SSID + "\n\n"
+ + getString(R.string.text_ip_address) + ": " + status.IP + "\n");
toggleBtnDisconnect(true);
-
+ beginLauncVpn();
+
} else {
Utils.logDebug("StatusActivity status Else");
- setMessage("Status:\n" + status.status);
+ setMessage(getString(R.string.text_status) + ":\n" + status.status);
toggleBtnDisconnect(false);
}
@@ -103,21 +143,144 @@ public class ShowStatusActivity extends MenuEnabledActivity {
public void onBtnDisconnectClick(View v) {
+ disconnectVpn();
+
boolean res = Commons.connectionEngine.disconnect();
String msg = "";
if (res) {
- msg = "Disconnected.";
+ msg = getString(R.string.msg_disconnected);
} else {
- msg = "FAILED to disconnect!";
+ msg = getString(R.string.msg_disconnect_fail);
}
Toast toast = Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT);
toast.show();
- showStatus(true);
+ try {
+ showStatus(true);
+ } catch (Exception e) {
+ Utils.logError("Exception on showStatus", e);
+ }
+
+ }
+
+ private void disconnectVpn() {
+
+ if (! OpenVpnManager.isVpnConnected()){
+ return;
+ }
+
+ if (OpenVpnManager.disconnect()) {
+ Toast t = Toast.makeText(this, getString(R.string.msg_vpn_disconnect),
+ Toast.LENGTH_LONG);
+ t.show();
+
+ } else {
+ Commons.showMessage(getString(R.string.msg_vpn_disconnect_error), this);
+ }
+
+ }
+
+ private void beginLauncVpn() throws Exception {
+
+ if (OpenVpnManager.isVpnConnected()){
+ // already connected;
+ return;
+ }
+
+ if (!OpenVpnManager.isExternalAppInstalled(this)) {
+ Utils.logDebug("External VPN app not installed.");
+ return;
+ }
+
+ if (getVpnNameIfAny() == null){
+ Utils.logDebug("No vpn profile set. Exiting beginLaunchVpn()");
+ return;
+ }
+
+ // first, we make sure we have permission to use the vpn service.
+ Intent pi;
+
+ try {
+ pi = OpenVpnManager.askApiPermissionsGetIntent();
+ } catch (RemoteException e) {
+ Utils.logError("Exception while asking for VPN permission", e);
+ Toast t = Toast.makeText(getApplicationContext(), getString(R.string.msg_vpn_connect_error), Toast.LENGTH_LONG);
+ t.show();
+ return;
+
+ }
+
+ if (pi == null){
+ // no need to ask for permission
+ Utils.logDebug("No need for vpn permission: going to endLaunchVpn.");
+ endLaunchVpn(true);
+
+ } else{
+ // launch the intent to ask permission
+ Utils.logDebug("Need to ask for vpn permission. Starting intent..");
+ startActivityForResult(pi, ActivityLauncher.RequestCode.VPN_PERMISSION);
+ }
}
+ private void endLaunchVpn(boolean permissionGranted) {
+
+ try {
+
+ if (!permissionGranted) {
+ // warn user that permission must be granted
+ Utils.logDebug("User rejected vpn permission.");
+ String msg = getString(R.string.msg_vpn_no_permission).replace(
+ OpenVpnManager.PLACEHOLDER_APPNAME, OpenVpnManager.APP_COMMON_NAME);
+ Commons.showMessage(msg, this);
+ return;
+ }
+
+ String profname = getVpnNameIfAny();
+
+ // check if profile exists
+ String profUuid = OpenVpnManager.getUuidFromName(profname);
+ if (profUuid == null){
+ // warn user that selected profile doesn't exist
+ Commons.showMessage(getString(R.string.msg_vpn_wrong_profile), this);
+ return;
+ }
+
+ if (OpenVpnManager.startVpn(profUuid)){
+ Toast t = Toast.makeText(this, getString(R.string.msg_vpn_launched), Toast.LENGTH_LONG);
+ t.show();
+ } else {
+ Commons.showMessage(getString(R.string.msg_vpn_connect_error),this);
+ }
+
+ } catch (Exception e) {
+ Utils.logError("Exception while endLaunchVpn", e);
+
+ }
+
+ }
+
+ private String getVpnNameIfAny(){
+
+ if (status == null) {
+ return null;
+ }
+
+ AccessPointInfo i = status.getNetworkDetails();
+ if (i == null) {
+ return null;
+ }
+
+ String profname = i.getVpnProfileName();
+ if (profname == null || profname.isEmpty()) {
+ return null;
+ } else {
+ return profname;
+ }
+
+ }
+
public void onBtnMainClick(View v) {
finish();
}
@@ -126,5 +289,5 @@ public class ShowStatusActivity extends MenuEnabledActivity {
public void onBackPressed() {
moveTaskToBack(true);
}
-
+
}
diff --git a/app/src/fil/libre/repwifiapp/activities/VpnSettingsActivity.java b/app/src/fil/libre/repwifiapp/activities/VpnSettingsActivity.java
new file mode 100644
index 0000000..b9dab93
--- /dev/null
+++ b/app/src/fil/libre/repwifiapp/activities/VpnSettingsActivity.java
@@ -0,0 +1,201 @@
+//
+// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
+//
+// This file is part of RepWifiApp.
+//
+// RepWifiApp 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.
+//
+// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>.
+//
+// ********************************************************************
+
+package fil.libre.repwifiapp.activities;
+
+import java.util.List;
+import fil.libre.repwifiapp.ActivityLauncher;
+import fil.libre.repwifiapp.Commons;
+import fil.libre.repwifiapp.R;
+import fil.libre.repwifiapp.ActivityLauncher.RequestCode;
+import fil.libre.repwifiapp.helpers.AccessPointInfo;
+import fil.libre.repwifiapp.helpers.OpenVpnManager;
+import fil.libre.repwifiapp.helpers.Utils;
+import android.os.Bundle;
+import android.app.Activity;
+import android.content.Intent;
+import android.view.Menu;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+public class VpnSettingsActivity extends Activity {
+
+ private AccessPointInfo currentNetwork;
+ private Spinner spinProfile;
+ private TextView summaryView;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_vpn_settings);
+
+ String title = getString(R.string.title_activity_vpn_settings);
+
+ Intent intent = getIntent();
+ if (!intent.hasExtra(ActivityLauncher.EXTRA_APINFO)) {
+ this.setResult(RESULT_CANCELED);
+ this.finish();
+ return;
+ }
+
+ this.currentNetwork = (AccessPointInfo) intent.getExtras().getSerializable(
+ ActivityLauncher.EXTRA_APINFO);
+ if (this.currentNetwork == null) {
+ this.setResult(RESULT_CANCELED);
+ this.finish();
+ return;
+ }
+
+ this.currentNetwork = Commons.storage.getSavedNetwork(currentNetwork);
+ this.spinProfile = (Spinner)findViewById(R.id.spin_vpn_profile);
+ this.summaryView = (TextView)findViewById(R.id.lbl_vpn_settings);
+ String summary = getString(R.string.summary_vpn_settings).replace(OpenVpnManager.PLACEHOLDER_APPNAME, OpenVpnManager.APP_COMMON_NAME);
+ summaryView.setText(summary);
+
+ title += " " + currentNetwork.getSsid();
+ this.setTitle(title);
+
+ if (!checkExternalApp()){
+ toggleSettingsEnabled(false);
+ } else {
+ initVpnManager();
+ }
+
+ }
+
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+
+ switch (requestCode) {
+
+ case RequestCode.VPN_PERMISSION:
+
+ if (resultCode != RESULT_OK) {
+ toggleSettingsEnabled(false);
+ Utils.logDebug("User rejected vpn permission.");
+ String msg = getString(R.string.msg_vpn_no_permission).replace(
+ OpenVpnManager.PLACEHOLDER_APPNAME, OpenVpnManager.APP_COMMON_NAME);
+ Commons.showMessage(msg, this);
+ return;
+ }
+
+ break;
+
+ default:
+
+ break;
+
+ }
+
+ }
+
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ return true;
+ }
+
+ private void initVpnManager(){
+
+ try {
+
+ Intent intentAllow = OpenVpnManager.askApiPermissionsGetIntent();
+ if (intentAllow != null){
+ startActivityForResult(intentAllow, ActivityLauncher.RequestCode.VPN_PERMISSION);
+ }
+
+ List<String> profiles = OpenVpnManager.getExistingProfiles();
+ if (profiles.size() == 0){
+ String msg = getString(R.string.msg_vpn_no_profile).replace(OpenVpnManager.PLACEHOLDER_APPNAME, OpenVpnManager.APP_COMMON_NAME);
+ Commons.showMessage(msg, this);
+ toggleSettingsEnabled(false);
+ return;
+ }
+ Spinner spin = (Spinner)findViewById(R.id.spin_vpn_profile);
+
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_dropdown_item,profiles);
+ adapter.insert("",0);
+ spin.setAdapter(adapter);
+ spin.setSelection(adapter.getPosition(currentNetwork.getVpnProfileName()));
+
+ } catch (Exception e) {
+ Utils.logError("Exception while creating openvpnmanager",e);
+ Commons.showMessage(getString(R.string.msg_vpn_connect_error));
+ toggleSettingsEnabled(false);
+ }
+
+ }
+
+ private boolean checkExternalApp(){
+
+ if (! OpenVpnManager.isExternalAppInstalled(this)){
+ String msg = getString(R.string.text_vpn_package_missing).replace(OpenVpnManager.PLACEHOLDER_APPNAME, OpenVpnManager.APP_COMMON_NAME);
+ Commons.showMessage(msg, this);
+ toggleSettingsEnabled(false);
+ return false;
+ } else {
+ return true;
+ }
+
+ }
+
+ private void toggleSettingsEnabled(boolean enabled){
+
+ spinProfile.setEnabled(enabled);
+
+ Button b = (Button)findViewById(R.id.btn_save_vpn_settings);
+ b.setEnabled(enabled);
+
+ }
+
+ public void btnSaveClick(View v){
+
+ String vpnProf = (String)spinProfile.getSelectedItem();
+
+ /*if (! vpnProf.isEmpty()){
+ // check if profile name exists
+ if( OpenVpnManager.getUuidFromName(vpnProf) == null){
+ Commons.showMessage(getString(R.string.msg_vpn_wrong_profile), this);
+ return;
+ }
+
+ }*/
+
+ // save profile
+ currentNetwork.setVpnProfileName(vpnProf);
+ Commons.storage.save(currentNetwork);
+
+ terminate();
+
+ }
+
+ public void btnBackClick(View v){
+ terminate();
+ }
+
+ private void terminate(){
+ finish();
+ }
+
+}
diff --git a/app/src/fil/libre/repwifiapp/helpers/AccessPointInfo.java b/app/src/fil/libre/repwifiapp/helpers/AccessPointInfo.java
index d6e2eb3..eee569d 100644
--- a/app/src/fil/libre/repwifiapp/helpers/AccessPointInfo.java
+++ b/app/src/fil/libre/repwifiapp/helpers/AccessPointInfo.java
@@ -20,25 +20,38 @@
package fil.libre.repwifiapp.helpers;
-import java.io.File;
+import org.json.JSONException;
+import org.json.JSONObject;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
-import fil.libre.repwifiapp.Commons;
public class AccessPointInfo implements Serializable {
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 2L;
private static final int MAX_SSID_LENGTH = 32;
-
+ protected static final String SCAN_FILE_HDR = "bssid / frequency / signal level / flags / ssid";
+
+ private static final String JSONKEY_BSSID = "BSSID";
+ private static final String JSONKEY_SSID = "SSID";
+ private static final String JSONKEY_LASTUSED = "LastUsed";
+ private static final String JSONKEY_AUTH = "Auth";
+ private static final String JSONKEY_PSK = "PSK";
+ private static final String JSONKEY_VPN_PROFILE = "VpnProfile";
+ private static final String JSONKEY_DHCPSETS = "DhcpSettings";
+
private String _ssid;
private String _bssid;
private String _auth;
private String _level;
private String _freq;
private String _password;
+ private String _vpnProfileName = null;
private boolean _isHidden = false;
private long _lastTimeUsed;
+ private DhcpSettings _dhcpsets;
public AccessPointInfo(String ssid, String bssid, String authType, String level, String freq) {
@@ -50,6 +63,23 @@ public class AccessPointInfo implements Serializable {
}
+ private AccessPointInfo(){
+ // for inner use;
+ }
+
+ public void setDhcpConfiguration(DhcpSettings sets) {
+ this._dhcpsets = sets;
+ }
+
+ public DhcpSettings getDhcpConfiguration() {
+
+ if (this._dhcpsets == null) {
+ return DhcpSettings.getDefault();
+ } else {
+ return this._dhcpsets;
+ }
+ }
+
public String getSsid() {
return this._ssid;
}
@@ -78,12 +108,42 @@ public class AccessPointInfo implements Serializable {
this._bssid = bssid;
}
+ public String getVpnProfileName(){
+ if (_vpnProfileName == null){
+ return "";
+ } else {
+ return _vpnProfileName;
+ }
+ }
+
+ public void setVpnProfileName(String profileName){
+ _vpnProfileName = profileName;
+ }
+
public String getAuthType() {
+ if (_auth == null){
+ return "";
+ }
return this._auth;
}
- public String getSignlalStrength() {
- return this._level;
+ public int getSignlalStrength() {
+ // return this._level;
+
+ if (this._level == null || this._level.isEmpty()) {
+ return 0;
+ }
+
+ int retval = 0;
+
+ try {
+ retval = Integer.parseInt(this._level);
+ } catch (NumberFormatException e) {
+ retval = 0;
+ }
+
+ return retval;
+
}
public String getFrequency() {
@@ -116,6 +176,9 @@ public class AccessPointInfo implements Serializable {
}
public String getPassword() {
+ if (_password == null){
+ return "";
+ }
return this._password;
}
@@ -170,19 +233,18 @@ public class AccessPointInfo implements Serializable {
}
- public static AccessPointInfo[] parseScanResult(String scanResultFile) {
+ public static AccessPointInfo[] parseScanResult(String scanResultContent) {
try {
- Utils.logDebug("AccesPointInfo trying to parse file: " + scanResultFile);
-
- File f = new File(scanResultFile);
- if (!f.exists()) {
- Utils.logError("AccessPointInfo.parseScanResult(): The provided scan result file doesn't exist");
+ if (scanResultContent == null) {
return null;
}
- String[] lines = Utils.readFileLines(scanResultFile);
+ Utils.logDebug("AccesPointInfo trying to parse file scan content:\n"
+ + scanResultContent);
+
+ String[] lines = scanResultContent.split("\n");
List<AccessPointInfo> nets = new ArrayList<AccessPointInfo>();
if (lines == null) {
@@ -190,7 +252,7 @@ public class AccessPointInfo implements Serializable {
}
for (String l : lines) {
- if (l.startsWith(Commons.SCAN_FILE_HDR)) {
+ if (l.startsWith(SCAN_FILE_HDR)) {
// strip off the header
continue;
}
@@ -211,6 +273,8 @@ public class AccessPointInfo implements Serializable {
}
+ sortInfosBySignalStrength(nets);
+
AccessPointInfo[] a = new AccessPointInfo[nets.size()];
a = nets.toArray(a);
return a;
@@ -222,4 +286,85 @@ public class AccessPointInfo implements Serializable {
}
+ public JSONObject toJson(){
+
+ try {
+
+ JSONObject j = new JSONObject();
+
+ j.put(JSONKEY_BSSID, getBssid());
+ j.put(JSONKEY_SSID, getSsid());
+ j.put(JSONKEY_PSK, getPassword());
+ j.put(JSONKEY_AUTH, getAuthType());
+ j.put(JSONKEY_LASTUSED, getLastTimeUsed());
+ j.put(JSONKEY_VPN_PROFILE, getVpnProfileName());
+
+ DhcpSettings sets = getDhcpConfiguration();
+ if (sets != null){
+ JSONObject dhcpj = sets.toJson();
+ if (dhcpj != null){
+ j.put(JSONKEY_DHCPSETS, dhcpj);
+ }
+
+ }
+
+ return j;
+
+ } catch (JSONException e) {
+ Utils.logError("Exception while converting AccessPointInfo to JSON.", e);
+ return null;
+ }
+
+ }
+
+ public static AccessPointInfo fromJsonObject(JSONObject json){
+
+ if (json == null || json.isNull(JSONKEY_BSSID) || json.isNull(JSONKEY_SSID)){
+ return null;
+ }
+
+ AccessPointInfo info = new AccessPointInfo();
+
+ try {
+ info._bssid = json.getString(JSONKEY_BSSID);
+ info._ssid = json.getString(JSONKEY_SSID);
+ info._auth = json.getString(JSONKEY_AUTH);
+ info._lastTimeUsed = json.getLong(JSONKEY_LASTUSED);
+
+ if (json.has(JSONKEY_PSK) && ! json.isNull(JSONKEY_PSK)){
+ info._password = json.getString(JSONKEY_PSK);
+ }
+
+ if ( json.has(JSONKEY_VPN_PROFILE) && ! json.isNull(JSONKEY_VPN_PROFILE)){
+ info._vpnProfileName = json.getString(JSONKEY_VPN_PROFILE);
+ }
+
+ if (json.has(JSONKEY_DHCPSETS) && ! json.isNull(JSONKEY_DHCPSETS)){
+ info._dhcpsets = DhcpSettings.fromJsonObject(json.getJSONObject(JSONKEY_DHCPSETS));
+ }
+
+ return info;
+
+ } catch (JSONException e) {
+ Utils.logError("Exception while parsing json object to AccessPointInfo", e);
+ return null;
+ }
+
+
+
+
+ }
+
+ private static void sortInfosBySignalStrength(List<AccessPointInfo> toSort) {
+
+ Collections.sort(toSort, new Comparator<AccessPointInfo>() {
+ public int compare(AccessPointInfo o1, AccessPointInfo o2) {
+ if (o1.getSignlalStrength() == o2.getSignlalStrength())
+ return 0;
+ return o1.getSignlalStrength() < o2.getSignlalStrength() ? -1 : 1;
+ }
+ });
+
+ }
+
}
diff --git a/app/src/fil/libre/repwifiapp/helpers/ConnectionStatus.java b/app/src/fil/libre/repwifiapp/helpers/ConnectionStatus.java
index c26dae9..e271dbe 100644
--- a/app/src/fil/libre/repwifiapp/helpers/ConnectionStatus.java
+++ b/app/src/fil/libre/repwifiapp/helpers/ConnectionStatus.java
@@ -20,6 +20,7 @@
package fil.libre.repwifiapp.helpers;
+import fil.libre.repwifiapp.Commons;
import java.io.Serializable;
public class ConnectionStatus implements Serializable {
@@ -37,7 +38,7 @@ public class ConnectionStatus implements Serializable {
public String SSID;
public String BSSID;
public String IP;
-
+
private static final String F_SEP = "=";
private static final String KeyStatus = "wpa_state";
private static final String KeySSID = "ssid";
@@ -100,4 +101,9 @@ public class ConnectionStatus implements Serializable {
}
}
+ public AccessPointInfo getNetworkDetails(){
+ AccessPointInfo i = new AccessPointInfo(SSID, BSSID, "","", "");
+ return Commons.storage.getSavedNetwork(i);
+ }
+
}
diff --git a/app/src/fil/libre/repwifiapp/helpers/DhcpSettings.java b/app/src/fil/libre/repwifiapp/helpers/DhcpSettings.java
new file mode 100644
index 0000000..c0587a3
--- /dev/null
+++ b/app/src/fil/libre/repwifiapp/helpers/DhcpSettings.java
@@ -0,0 +1,205 @@
+//
+// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
+//
+// This file is part of RepWifiApp.
+//
+// RepWifiApp 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.
+//
+// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>.
+//
+// ********************************************************************
+
+package fil.libre.repwifiapp.helpers;
+
+import org.apache.http.conn.util.InetAddressUtils;
+import org.json.JSONException;
+import org.json.JSONObject;
+import java.io.Serializable;
+import android.nfc.FormatException;
+
+public class DhcpSettings implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ public boolean useDhcp;
+ private String _staticIP;
+ private int _mask;
+ private String _defGw;
+
+ private static final String JSONKEY_DHCP = "DHCP";
+ private static final String JSONKEY_STATIC_IP = "StaticIP";
+ private static final String JSONKEY_GW = "Gateway";
+
+ public DhcpSettings(boolean useDhcp, String staticIP, String subnetMask, String defaultGateway)
+ throws FormatException {
+ this(useDhcp, staticIP, Utils.netmaskStringToInt(subnetMask), defaultGateway);
+ }
+
+ public DhcpSettings(boolean useDhcp, String staticIP, int subnetMask, String defaultGatweay)
+ throws FormatException {
+
+ this.useDhcp = useDhcp;
+
+ if (!useDhcp) {
+
+ if (!validateParams(staticIP, defaultGatweay, subnetMask)) {
+ throw new FormatException("Invalid dhcp parameters!");
+ }
+
+ this._staticIP = staticIP;
+ this._mask = subnetMask;
+ this._defGw = defaultGatweay;
+
+ }
+
+ }
+
+ private DhcpSettings(){
+ // inner use
+ }
+
+ public static DhcpSettings parseSavedSettings(String staticIPwithMask, String defaultGateway){
+
+ try {
+
+ String[] ipm = staticIPwithMask.split("/");
+ String ip = ipm[0];
+ int mask = Integer.parseInt(ipm[1]);
+
+ return new DhcpSettings(false, ip, mask, defaultGateway);
+
+
+ } catch (Exception e) {
+ Utils.logError("Exception while parsing DhcpSettings for saved network. Reverting to dhcp.", e);
+ return null;
+ }
+
+ }
+
+ public static DhcpSettings getDefault(){
+ try {
+ return new DhcpSettings(true, null, 24, null);
+ } catch (FormatException e) {
+ //no format exception can happen.
+ return null;
+ }
+ }
+
+ private boolean validateParams(String ip, String gateway, int mask) {
+
+ if (isValidAddress(ip) && isValidAddress(gateway) && isValidMask(mask)) {
+ return true;
+ } else {
+ return false;
+ }
+
+ }
+
+ public static boolean isValidAddress(String ipAddress){
+ return InetAddressUtils.isIPv4Address(ipAddress);
+ }
+
+ public static boolean isValidMaks(String mask){
+ int m = Utils.netmaskStringToInt(mask);
+ return isValidMask(m);
+ }
+
+ public static boolean isValidMask(int mask){
+ if (mask >= 8 && mask <= 32){
+ return true;
+ }else{
+ return false;
+ }
+ }
+
+ public String getStaticIP() {
+ if (_staticIP == null){
+ return "";
+ }
+ return _staticIP;
+ }
+
+ public String getStaticIPwithMask() {
+ return getStaticIP() + "/" + String.valueOf(getSubnetMaskInt());
+ }
+
+ public int getSubnetMaskInt() {
+ return _mask;
+ }
+
+ public String getSubnetMaskString(){
+ String v = Utils.netmaskIntToString(_mask);
+ if (v == null){
+ return "";
+ }
+ return v;
+ }
+
+ public String getDefaultGateway() {
+ if (_defGw == null){
+ return "";
+ }
+ return _defGw;
+ }
+
+ public JSONObject toJson(){
+
+ JSONObject j = new JSONObject();
+
+ try {
+ j.put(JSONKEY_DHCP, useDhcp);
+ j.put(JSONKEY_GW, getDefaultGateway());
+ j.put(JSONKEY_STATIC_IP, getStaticIPwithMask());
+
+ return j;
+
+ } catch (JSONException e) {
+ Utils.logError("Exception while converting DhcpSettings to JSON.", e);
+ return null;
+ }
+
+
+ }
+
+ public static DhcpSettings fromJsonObject(JSONObject json){
+
+ if (json == null){
+ return null;
+ }
+
+ DhcpSettings sets = new DhcpSettings();
+
+ try {
+
+ sets.useDhcp = json.getBoolean(JSONKEY_DHCP);
+
+ if (json.has(JSONKEY_GW) && ! json.isNull(JSONKEY_GW)){
+ sets._defGw = json.getString(JSONKEY_GW);
+ }
+
+ if (json.has(JSONKEY_STATIC_IP) && !json.isNull(JSONKEY_STATIC_IP)){
+
+ String[] splt = json.getString(JSONKEY_STATIC_IP).split("/");
+ sets._staticIP = splt[0];
+ sets._mask = Integer.parseInt(splt[1]);
+
+ }
+
+ return sets;
+
+ } catch (Exception e) {
+ Utils.logError("Exception while parsing json object to DhcpSettings", e);
+ return null;
+ }
+
+ }
+
+}
diff --git a/app/src/fil/libre/repwifiapp/helpers/Engine.java b/app/src/fil/libre/repwifiapp/helpers/Engine.java
index 68d8745..225d993 100644
--- a/app/src/fil/libre/repwifiapp/helpers/Engine.java
+++ b/app/src/fil/libre/repwifiapp/helpers/Engine.java
@@ -22,167 +22,33 @@ package fil.libre.repwifiapp.helpers;
import java.net.NetworkInterface;
import java.net.SocketException;
-import java.util.ArrayList;
import java.util.Enumeration;
-import fil.libre.repwifiapp.Commons;
public abstract class Engine implements IEngine {
-
- protected String getCmdWpaSup() {
- return "wpa_supplicant -B -dd -i" + Commons.INTERFACE_NAME + " -C" + Commons.SOCKET_DIR
- + " -P" + Commons.PID_FILE + " -I" + Commons.OVERLAY_FILE + " -e"
- + Commons.ENTROPY_FILE;
- }
-
- protected String getCmdWpaCli() {
- return "wpa_cli -p" + Commons.SOCKET_DIR + " -P" + Commons.PID_FILE + " -i"
- + Commons.INTERFACE_NAME;
- }
-
- protected abstract String getCmdWpaStart();
-
- public boolean deleteFileIfExists(String filePath) {
-
- if (filePath == null) {
- return false;
- }
-
- if (filePath.contains("*")) {
- // it's safer to reject bulk rm'ing
- return false;
- }
-
- if (filePath.contains(" -r ")) {
- // only file rm'ing acceppted
- return false;
- }
-
- // needs root (it only gets used by the 4p2 engine, working in
- // /data/misc/wifi)
- return executeRootCmd("if [ -e \"" + filePath + "\" ]; then rm \"" + filePath + "\"; fi");
-
- }
-
- public boolean chmodFile(String filePath, String mod) {
- // needs root (chmod)
- return executeRootCmd("chmod " + mod + " \"" + filePath + "\"");
- }
-
- @Override
- public boolean killBackEndProcesses() {
-
- // needs root (for killall)
-
- Utils.logDebug("killing wpa_supplicant..:");
- if (executeRootCmd("killall -SIGINT wpa_supplicant")) {
- Utils.logDebug("Killed wpa_supplicant");
- } else {
- Utils.logDebug("Wpa_supplicant NOT killed.");
- }
-
- Utils.logDebug("killing dhcpcd..");
- if (executeRootCmd("killall -SIGINT dhcpcd")) {
- Utils.logDebug("Killed dhcpcd");
- } else {
- Utils.logDebug("dhcpcd NOT killed.");
- }
-
- return true;
-
- }
-
- @Override
- public boolean clearWorkingDir() {
-
- // needs root (to work within /data/misc/wifi)
-
- Utils.logDebug("clearWorkingDir():");
-
- if (executeRootCmd("rm -r " + Commons.SOCKET_DIR)) {
- Utils.logDebug("removed socket dir");
- }
-
- if (executeRootCmd("rm " + Commons.ENTROPY_FILE)) {
- Utils.logDebug("removed entropy file");
- }
-
- if (executeRootCmd("rm " + Commons.PID_FILE)) {
- Utils.logDebug("removed pidfile");
- }
-
- if (executeRootCmd("rm " + Commons.SOFTAP_FILE)) {
- Utils.logDebug("removed softap file");
- }
-
- if (executeRootCmd("rm " + Commons.WPA_CONF)) {
- Utils.logDebug("removed wpa conf file");
- }
-
- if (executeRootCmd("rm " + Commons.P2P_CONF)) {
- Utils.logDebug("removed p2p conf file");
- }
-
- return true;
-
- }
-
- @Override
- public boolean startWpaSupplicant() {
-
- Utils.logDebug("startWpaSupplicant():");
-
- // needs root (for wpa_supplicant)
- if (executeRootCmd(getCmdWpaSup())) {
- return true;
- } else {
- Utils.logDebug("Failed to start wpa");
- return false;
- }
-
- }
-
+
@Override
public AccessPointInfo[] getAvailableNetworks() {
Utils.logDebug("getAvailableNetworks():");
- // killPreviousConnections();
-
- // Is it really necessary???
- // seems that clearing /data/misc/wifi is NOT necessary
- // so, commented out - Fil 2017-03-24
- /*
- * if (! clearWorkingDir()){ Utils.logError("Failed clearing dir");
- * return null; }
- */
-
- if (!startWpaSupplicant()) {
+ if (!WpaSupplicant.start()) {
Utils.logError("Failed starting wpa_supplicant");
return null;
}
- if (!createScanScripts()) {
- Utils.logError("Failed creating scripts");
- return null;
- }
-
- if (!scanNetworks()) {
+ if (!WpaCli.scanNetworks()) {
Utils.logError("failed scanning networks");
return null;
}
- if (!getScanResults()) {
+ String scanRes = WpaCli.getScanResults();
+
+ if (scanRes == null) {
Utils.logError("failed getting scan results");
return null;
}
- // chmod 664 scan_file to make it readable
- /*
- * if (!chmodFile(Commons.getScanFile(), "664")){
- * Utils.logError("failed chmodding scan_file"); return null; }
- */
-
- AccessPointInfo[] a = AccessPointInfo.parseScanResult(Commons.getScanFile());
+ AccessPointInfo[] a = AccessPointInfo.parseScanResult(scanRes);
if (a == null) {
Utils.logError("Unable to parse scan file into AccessPointInfo array");
return a;
@@ -200,30 +66,8 @@ public abstract class Engine implements IEngine {
@Override
public boolean disconnect() {
- // needs root (for wpa_cli)
-
- if (!isWpaSupplicantRunning()) {
- return true;
- }
-
- try {
+ return WpaCli.disconnect();
- RootCommand su = new RootCommand(getCmdWpaCli() + " disconnect");
- if (su.execute() == 0) {
- String out = su.getOutput();
- if (out != null && out.trim().replace("\n", "").equals("OK")) {
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
-
- } catch (Exception e) {
- Utils.logError("Error while enabling network", e);
- return false;
- }
}
/***
@@ -231,51 +75,12 @@ public abstract class Engine implements IEngine {
*/
@Override
public ConnectionStatus getConnectionStatus() {
-
- Utils.logDebug("called getConnecitonStatus()");
- if (!isWpaSupplicantRunning()) {
- // wpa_supplicant is not running.
- // unable to determin status.
- Utils.logDebug("wpa not running, cannot get connection status.");
- return null;
-
- }
-
- try {
-
- RootCommand su = new RootCommand(getCmdWpaCli() + " status");
- if (su.execute() == 0) {
- String out = su.getOutput();
- if (out == null || out.trim().equals("")) {
- return null;
- } else {
- return ConnectionStatus.parseWpaCliOutput(out);
- }
- } else {
- return null;
- }
-
- } catch (Exception e) {
- Utils.logError("Error while executing wpa_cli status", e);
- return null;
- }
-
+ return WpaCli.getConnectionStatus();
}
@Override
public boolean isInterfaceAvailable(String ifaceName) throws SocketException {
- /*
- * String[]ifaces = getAvailableInterfaces(); if(ifaces == null ||
- * ifaces.length == 0){ return false; }
- *
- * for(String name : ifaces){
- *
- * if (name.equals(ifaceName)){ return true; } }
- *
- * return false;
- */
-
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface nif = interfaces.nextElement();
@@ -288,182 +93,40 @@ public abstract class Engine implements IEngine {
}
- @Override
- public String[] getAvailableInterfaces() {
-
- try {
-
- // No need for root for "ip link"
- // tested 2017-03-24 - Fil
- ShellCommand cmd = new ShellCommand("ip link");
- if (cmd.execute() == 0) {
-
- String out = cmd.getOutput();
- if (out == null || out.contains("\n") == false) {
- Utils.logDebug("No out from ip link");
- return null;
- }
-
- ArrayList<String> list = new ArrayList<String>();
-
- String[] lines = out.split("\n");
- for (String l : lines) {
-
- String[] fields = l.split(":");
- if (fields.length != 3) {
- continue;
- }
-
- String interfName = fields[1].trim();
- list.add(interfName);
-
- }
-
- String[] retArr = new String[list.size()];
- retArr = list.toArray(retArr);
-
- return retArr;
-
- } else {
- return null;
- }
-
- } catch (Exception e) {
- Utils.logError("Error while querying ip link", e);
- return null;
- }
-
- }
-
public boolean runDhcpcd() {
-
// needs root
- return executeRootCmd("dhcpcd " + Commons.INTERFACE_NAME);
-
- }
-
+ // option -w avoids dhcpcd forking to background,
+ // in order to keep control over its exit code, and be able to wait for it.
+ // option -A avoids ARP IP checking, we use it to save some seconds in the connection process.
+ return RootCommand.executeRootCmd("dhcpcd -w -A " + WpaSupplicant.INTERFACE_NAME);
+
+ }
+
+ public boolean runDhcpcd(DhcpSettings dhcpConfig) {
+
+ if (dhcpConfig == null || dhcpConfig.useDhcp){
+ Utils.logDebug("running dhchpc without dhcp settings, reverting to dhcp");
+ return runDhcpcd();
+ }
+
+ Utils.logDebug("Running dhcpcd with custom ip settings");
+ String cmdMask = "dhcpcd -w -A -S ip_address=%s -S routers=%s %s";
+ String cmd = String.format(cmdMask,
+ dhcpConfig.getStaticIPwithMask(),
+ dhcpConfig.getDefaultGateway(),
+ WpaSupplicant.INTERFACE_NAME);
+
+ return RootCommand.executeRootCmd(cmd);
+
+ }
+
+ public static boolean killDhcpcd(){
+ return RootCommand.executeRootCmd("killall -SIGINT dhcpcd");
+ }
+
public boolean interfaceUp() {
// needs root (tested)
- return executeRootCmd("ifconfig " + Commons.INTERFACE_NAME + " up");
- }
-
- /*
- * protected boolean executeCmd(String cmd){
- *
- * try {
- *
- * ShellCommand c = new ShellCommand(cmd); if ( c.execute() == 0){ return
- * true; }else { return false; }
- *
- * } catch (Exception e) { Utils.logError("Error executing \"" + cmd +
- * "\"",e); return false; }
- *
- * }
- */
-
- protected boolean executeRootCmd(String cmd) {
-
- try {
-
- RootCommand c = new RootCommand(cmd);
- if (c.execute() == 0) {
- return true;
- } else {
- return false;
- }
-
- } catch (Exception e) {
- Utils.logError("Error executing \"" + cmd + "\"", e);
- return false;
- }
- }
-
- protected boolean isWpaSupplicantRunning() {
-
- boolean retval = false;
-
- try {
-
- RootCommand su = new RootCommand("pidof wpa_supplicant");
- if (su.execute() == 0) {
-
- if (su.getOutput().trim().equals("")) {
- retval = false;
- } else {
- retval = true;
- }
-
- } else {
- retval = false;
- }
-
- } catch (Exception e) {
- Utils.logError("Exception during isWpaSupplicantRunning()", e);
- retval = false;
- }
-
- return retval;
-
- }
-
- protected boolean scanNetworks() {
-
- // needs root (for wpa_supplicant and wpa_cli)
- return executeRootCmd("bash " + Commons.getScriptScan());
-
- }
-
- protected boolean getScanResults() {
-
- // needs root (for wpa_supplicant and wpa_cli)
- boolean res = executeRootCmd("bash " + Commons.getScriptScanRes());
- if (!res) {
- return false;
- }
- return res;
-
- }
-
- protected boolean createScanScripts() {
-
- try {
-
- String scan = getCmdWpaCli() + " scan\n" + "if [ $? -ne 0 ]; then\n" + "exit 1\n"
- + "fi\n" + "sleep 2s\n";
-
- String scanRes = "if [ -e \"" + Commons.getScanFile() + "\" ]; then\n" + " rm \""
- + Commons.getScanFile() + "\"\n" + "fi\n" + getCmdWpaCli()
- + " scan_results > \"" + Commons.getScanFile() + "\"\n"
- + "if [ $? -ne 0 ]; then\n" + " exit 1\n" + "fi\n";
-
- if (!Utils.writeFile(Commons.getScriptScan(), scan, true)) {
-
- Exception e = Utils.getLastException();
- if (e != null) {
- Utils.logError("Error while writing scan script.", e);
- }
-
- return false;
- }
-
- if (!Utils.writeFile(Commons.getScriptScanRes(), scanRes, true)) {
-
- Exception e = Utils.getLastException();
- if (e != null) {
- Utils.logError("Error while writing getScanResults script.", e);
- }
-
- return false;
- }
-
- return true;
-
- } catch (Exception e) {
-
- Utils.logError("Error while creating the scanning script.", e);
- return false;
- }
-
+ return RootCommand.executeRootCmd("ifconfig " + WpaSupplicant.INTERFACE_NAME + " up");
}
}
diff --git a/app/src/fil/libre/repwifiapp/helpers/Engine6p0.java b/app/src/fil/libre/repwifiapp/helpers/Engine6p0.java
index d4ff0f7..3eff6c8 100644
--- a/app/src/fil/libre/repwifiapp/helpers/Engine6p0.java
+++ b/app/src/fil/libre/repwifiapp/helpers/Engine6p0.java
@@ -26,16 +26,9 @@ import fil.libre.repwifiapp.Commons;
public class Engine6p0 extends Engine {
@Override
- protected String getCmdWpaStart() {
- return "wpa_supplicant -B -dd -i" + Commons.INTERFACE_NAME + " -C" + Commons.SOCKET_DIR
- + " -P" + Commons.PID_FILE + " -I" + Commons.OVERLAY_FILE + " -e"
- + Commons.ENTROPY_FILE;
- }
-
- @Override
public boolean connect(AccessPointInfo info) {
- killBackEndProcesses();
+ WpaSupplicant.kill();
if (info == null) {
Utils.logDebug("Engine's connect() received a null AccessPointInfo");
@@ -62,81 +55,81 @@ public class Engine6p0 extends Engine {
// launch wpa_supplicant specifying our custom configuration and the
// socket file
- if (!executeRootCmd(getCmdWpaStart())) {
+ if (!WpaSupplicant.start()) {
Utils.logDebug("Unable to run wpa start");
return false;
}
// create new network and get network id
- String netID = createNetworkGetId();
+ String netID = WpaCli.createNetworkGetId();
if (netID == null) {
Utils.logDebug("Unable to fetch network id");
return false;
}
// set network SSID
- if (!setNetworkSSID(info.getSsid(), netID)) {
+ if (!WpaCli.setNetworkSSID(info.getSsid(), netID)) {
Utils.logDebug("Failed to set network ssid");
return false;
}
- if (info.isHidden() && !setNetworkScanSSID(netID)) {
+ if (info.isHidden() && !WpaCli.setNetworkScanSSID(netID)) {
Utils.logDebug("Failed to set scan_ssid 1 for hidden network.");
return false;
}
// set password (if any)
- if (!setNetworkPSK(info, netID)) {
+ if (!WpaCli.setNetworkPSK(info, netID)) {
Utils.logDebug("Failed to set network psk");
return false;
}
// select the network we just created
- if (!selectNetwork(netID)) {
+ if (!WpaCli.selectNetwork(netID)) {
Utils.logDebug("Unable to wpa_cli select network");
return false;
}
// enable the newtork
- if (!enableNetwork(netID)) {
+ if (!WpaCli.enableNetwork(netID)) {
Utils.logDebug("Unable to wpa_cli enable_newtork");
return false;
}
-
- // try to reassociate to Access Point
- /*
- * if (! reassociate()){
- * Utils.logDebug("Unable to wpa_cli reassociate"); return false; }
- */
+
+ // kill previous dhchcd instances
+ if (!RootCommand.executeRootCmd("killall -SIGINT dhcpcd")){
+ Utils.logError("Unable to kill previous instances of dhcpcd");
+ }
// get DHCP
Utils.logDebug("Attempt to run dhcpcd..");
- if (!runDhcpcd()) {
+ if (!runDhcpcd(info.getDhcpConfiguration())) {
Utils.logDebug("Failed to run dhcpcd");
return false;
}
// try to fetch gateway
- String gw = getGateway();
- if (gw == null || gw.trim().length() < 7) {
+ String gw = getGateWayTimeout(Commons.WAIT_FOR_GATEWAY);
+ if (gw == null || !InetAddressUtils.isIPv4Address(gw)) {
// failed to get gateway
Utils.logDebug("Failed to get gateway");
return false;
}
- if (!executeRootCmd("ndc network create 1")) {
+ if (!RootCommand.executeRootCmd("ndc network create 1")) {
Utils.logDebug("Failed to wpa_cli network create 1 ");
return false;
}
- if (!executeRootCmd("ndc network interface add 1 " + Commons.INTERFACE_NAME)) {
+ if (!RootCommand.executeRootCmd("ndc network interface add 1 "
+ + WpaSupplicant.INTERFACE_NAME)) {
Utils.logDebug("Failed to add interface.");
return false;
}
// set route to gateway for all traffic
- if (!executeRootCmd("ndc network route add 1 " + Commons.INTERFACE_NAME + " 0.0.0.0/0 "
- + gw)) {
+ if (!RootCommand.executeRootCmd("ndc network route add 1 " + WpaSupplicant.INTERFACE_NAME
+ + " 0.0.0.0/0 " + gw)) {
Utils.logDebug("Failed to add route to gateway");
return false;
}
@@ -147,7 +140,7 @@ public class Engine6p0 extends Engine {
}
// use network
- if (!executeRootCmd("ndc network default set 1")) {
+ if (!RootCommand.executeRootCmd("ndc network default set 1")) {
Utils.logDebug("Failed to set network as default");
return false;
}
@@ -156,163 +149,9 @@ public class Engine6p0 extends Engine {
}
- private String createNetworkGetId() {
-
- try {
-
- RootCommand su = new RootCommand(getCmdWpaCli() + " add_network");
- if (su.execute() == 0) {
- String out = su.getOutput();
- if (out == null || out.trim().equals("")) {
- return null;
- } else {
- return out.replace("\n", "");
- }
- } else {
- return null;
- }
-
- } catch (Exception e) {
- Utils.logError("Error while creating network", e);
- return null;
- }
-
- }
-
private boolean destroyNetwork() {
// needs root (tested)
- return executeRootCmd("ndc network destroy 1");
- }
-
- private boolean setNetworkSSID(String ssid, String networkID) {
-
- try {
-
- // needs root (wpa_cli)
- RootCommand su = new RootCommand(getCmdWpaCli() + " set_network " + networkID
- + " ssid '\"" + ssid + "\"'");
- if (su.execute() == 0) {
- String out = su.getOutput();
- if (out != null && out.trim().replace("\n", "").equals("OK")) {
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
-
- } catch (Exception e) {
- Utils.logError("Error while setting network SSID", e);
- return false;
- }
-
- }
-
- private boolean setNetworkPSK(AccessPointInfo info, String networkID) {
-
- try {
-
- // needs root (wpa_cli)
-
- String cmdSetPass = null;
- if (info.needsPassword()) {
- cmdSetPass = getCmdWpaCli() + " set_network " + networkID + " psk '\""
- + info.getPassword() + "\"'";
- } else {
- cmdSetPass = getCmdWpaCli() + " set_network " + networkID + " key_mgmt NONE";
- }
-
- RootCommand su = new RootCommand(cmdSetPass);
- if (su.execute() == 0) {
- String out = su.getOutput();
- if (out != null && out.trim().replace("\n", "").equals("OK")) {
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
-
- } catch (Exception e) {
- Utils.logError("Error while setting network PSK", e);
- return false;
- }
-
- }
-
- private boolean setNetworkScanSSID(String networkID) {
-
- try {
-
- // needs root (wpa_cli)
- RootCommand su = new RootCommand(getCmdWpaCli() + " set_network " + networkID
- + " scan_ssid 1");
- if (su.execute() == 0) {
- String out = su.getOutput();
- if (out != null && out.trim().replace("\n", "").equals("OK")) {
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
-
- } catch (Exception e) {
- Utils.logError("Error while setting network SSID", e);
- return false;
- }
- }
-
- private boolean selectNetwork(String networkID) {
-
- try {
-
- // needs root (wpa_cli)
- RootCommand su = new RootCommand(getCmdWpaCli() + " select_network " + networkID);
- if (su.execute() == 0) {
- String out = su.getOutput();
- if (out != null && out.trim().replace("\n", "").equals("OK")) {
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
-
- } catch (Exception e) {
- Utils.logError("Error while selecting network", e);
- return false;
- }
-
- }
-
- private boolean enableNetwork(String networkID) {
-
- try {
-
- // needs root (wpa_cli)
-
- RootCommand su = new RootCommand(getCmdWpaCli() + " enable_network " + networkID);
- if (su.execute() == 0) {
- String out = su.getOutput();
- if (out != null && out.trim().replace("\n", "").equals("OK")) {
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
-
- } catch (Exception e) {
- Utils.logError("Error while enabling network", e);
- return false;
- }
-
+ return RootCommand.executeRootCmd("ndc network destroy 1");
}
private boolean setDns(String[] dnss, String gateway) {
@@ -343,7 +182,42 @@ public class Engine6p0 extends Engine {
cmd += " " + dnss[0];
}
- return executeRootCmd(cmd);
+ return RootCommand.executeRootCmd(cmd);
+ }
+
+ private String getGateWayTimeout(int timeoutMillis) {
+
+ String gw = getGateway();
+ if (gw != null && !gw.trim().isEmpty()) {
+ return gw;
+ }
+
+ Utils.logDebug("Gateway not available.. going into wait loop..");
+
+ // gateway not (yet) available
+ // waits for a maximum of timeoutMillis milliseconds
+ // to let the interface being registered.
+ int msWaited = 0;
+ while (msWaited < timeoutMillis) {
+
+ try {
+ Thread.sleep(100);
+ } catch (Exception e) {
+ return null;
+ }
+ msWaited += 100;
+
+ gw = getGateway();
+ if (gw != null && !gw.trim().isEmpty()) {
+ Utils.logDebug("Gateway found after wait loop!");
+ return gw;
+ }
+ }
+
+ // unable to get gateway
+ Utils.logError("Gateway not found after wait loop.");
+ return null;
+
}
private String getGateway() {
@@ -351,7 +225,7 @@ public class Engine6p0 extends Engine {
try {
// doesn't need root (tested)
- RootCommand cmd = new RootCommand("ip route show dev " + Commons.INTERFACE_NAME);
+ ShellCommand cmd = new ShellCommand("ip route show dev " + WpaSupplicant.INTERFACE_NAME);
if (cmd.execute() != 0) {
Utils.logDebug("command failed show route");
return null;
@@ -390,7 +264,8 @@ public class Engine6p0 extends Engine {
private boolean clearAddrs() {
// needs root (tested)
- return executeRootCmd("ndc interface clearaddrs " + Commons.INTERFACE_NAME);
+ return RootCommand.executeRootCmd("ndc interface clearaddrs "
+ + WpaSupplicant.INTERFACE_NAME);
}
} \ No newline at end of file
diff --git a/app/src/fil/libre/repwifiapp/helpers/IEngine.java b/app/src/fil/libre/repwifiapp/helpers/IEngine.java
index 037cf62..26ebddb 100644
--- a/app/src/fil/libre/repwifiapp/helpers/IEngine.java
+++ b/app/src/fil/libre/repwifiapp/helpers/IEngine.java
@@ -24,12 +24,6 @@ import java.net.SocketException;
public interface IEngine {
- public boolean startWpaSupplicant();
-
- public boolean killBackEndProcesses();
-
- public boolean clearWorkingDir();
-
public AccessPointInfo[] getAvailableNetworks();
public boolean connect(AccessPointInfo info);
@@ -40,6 +34,4 @@ public interface IEngine {
public boolean isInterfaceAvailable(String ifaceName) throws SocketException;
- public String[] getAvailableInterfaces();
-
}
diff --git a/app/src/fil/libre/repwifiapp/helpers/NetworkManager.java b/app/src/fil/libre/repwifiapp/helpers/NetworkManager.java
index db27f7e..96805a6 100644
--- a/app/src/fil/libre/repwifiapp/helpers/NetworkManager.java
+++ b/app/src/fil/libre/repwifiapp/helpers/NetworkManager.java
@@ -20,13 +20,16 @@
package fil.libre.repwifiapp.helpers;
+import org.json.JSONArray;
+import org.json.JSONObject;
import java.io.File;
import java.util.ArrayList;
public class NetworkManager {
+ private static final String VERSION_NOTE = "RepWifiStorageVersion: 2.0\n";
private static final String F_SEP = "\t";
- private static final int NET_MAX_AGE = 365; // Expressed in days
+ private static final int NET_MAX_AGE = 1095; // Expressed in days
private String _knownNetworksFile = null;
@@ -34,7 +37,7 @@ public class NetworkManager {
this._knownNetworksFile = networksFilePath;
}
- private AccessPointInfo searchInFile(AccessPointInfo i) {
+ private AccessPointInfo getSavedInfo(AccessPointInfo i) {
if (i == null) {
return null;
@@ -63,12 +66,16 @@ public class NetworkManager {
// then return the best match (only ssid), if any
if (toTest.getSsid().equals(ssid)) {
+ i.setPassword(toTest.getPassword());
+ i.setDhcpConfiguration(toTest.getDhcpConfiguration());
+ i.setVpnProfileName(toTest.getVpnProfileName());
+
if (toTest.getBssid().equals(bssid)) {
- i.setPassword(toTest.getPassword());
+ // complete match, return.
return i;
} else {
- i.setPassword(toTest.getPassword());
+ // probable match
ret = i;
}
@@ -82,11 +89,6 @@ public class NetworkManager {
private boolean saveOrRemove(AccessPointInfo info, boolean save) {
- String iText = InfoToString(info);
- if (iText == null) {
- return false;
- }
-
AccessPointInfo[] existingNets = getKnownNetworks();
ArrayList<AccessPointInfo> newlist = new ArrayList<AccessPointInfo>();
@@ -151,7 +153,7 @@ public class NetworkManager {
}
- private AccessPointInfo getFromString(String savedString) {
+ private AccessPointInfo getFromStringOld(String savedString) {
if (savedString == null || savedString.trim().equals("")) {
return null;
@@ -168,11 +170,25 @@ public class NetworkManager {
String pass = fields[2];
String lastUsed = fields[3];
String auth = null;
+ String ipWmask = null;
+ String gw = null;
+ boolean useDhcp = true;
+ String vpnProfile = null;
if (fields.length > 4) {
auth = fields[4];
}
+ if (fields.length > 6) {
+ ipWmask = fields[5];
+ gw = fields[6];
+ useDhcp = false;
+ }
+
+ if (fields.length > 7) {
+ vpnProfile = fields[7];
+ }
+
long lastusedmillis = 0;
try {
lastusedmillis = Long.parseLong(lastUsed);
@@ -189,69 +205,129 @@ public class NetworkManager {
AccessPointInfo i = new AccessPointInfo(ssid, bssid, auth, null, null);
i.setPassword(pass);
i.setLastTimeUsed(lastusedmillis);
+ i.setVpnProfileName(vpnProfile);
+
+ if (!useDhcp) {
+ DhcpSettings s = DhcpSettings.parseSavedSettings(ipWmask, gw);
+ i.setDhcpConfiguration(s);
+ }
return i;
}
- private String InfoToString(AccessPointInfo info) {
+ private boolean saveList(AccessPointInfo[] list) {
- if (info == null) {
- return null;
- }
+ try {
- String bssid = info.getBssid();
- String ssid = info.getSsid();
- String pass = info.getPassword();
- String tsLastUsed = "" + info.getLastTimeUsed();
- String auth = info.getAuthType();
+ JSONArray jarr = new JSONArray();
+ for (AccessPointInfo i : list) {
- if (bssid == null || bssid.trim().equals("")) {
- return null;
- }
+ JSONObject jo = i.toJson();
+ if (jo == null) {
+ return false;
+ }
- if (ssid == null || ssid.trim().equals("")) {
- return null;
- }
+ jarr.put(jo);
- if (pass == null || pass.trim().equals("")) {
- return null;
- }
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append(VERSION_NOTE);
+ sb.append("\n");
+
+ sb.append(jarr.toString(2));
+
+ return Utils.writeFile(_knownNetworksFile, sb.toString(), true);
- if (auth == null) {
- auth = "";
+ } catch (Exception e) {
+ Utils.logError("Exception while saving AccessPointInfo array to JSON-formatted file.",
+ e);
+ return false;
}
- String iText = info.getBssid() + F_SEP + info.getSsid() + F_SEP + info.getPassword()
- + F_SEP + tsLastUsed + F_SEP + auth;
- return iText;
+ /*
+ * if (list == null) { return false; }
+ *
+ * String[] lines = new String[list.length];
+ *
+ * for (int i = 0; i < list.length; i++) {
+ *
+ * String storeString = InfoToString(list[i]); if (storeString == null)
+ * { return false; } lines[i] = storeString;
+ *
+ * }
+ *
+ * return Utils.writeFileLines(this._knownNetworksFile, lines, true);
+ */
}
- private boolean saveList(AccessPointInfo[] list) {
+ public boolean updateStorageVersion() {
- if (list == null) {
- return false;
+ String[] lines = Utils.readFileLines(_knownNetworksFile);
+ if (lines.length == 0) {
+ return true;
}
- String[] lines = new String[list.length];
+ if (lines[0].trim().equals(VERSION_NOTE)) {
+ return true;
- for (int i = 0; i < list.length; i++) {
+ } else {
- String storeString = InfoToString(list[i]);
- if (storeString == null) {
- return false;
+ AccessPointInfo[] infos = getKnownNetworksOld();
+ if (infos == null || infos.length == 0) {
+ return true;
}
- lines[i] = storeString;
+ return saveList(infos);
}
- return Utils.writeFileLines(this._knownNetworksFile, lines, true);
-
}
public AccessPointInfo[] getKnownNetworks() {
+ try {
+
+ String fconts = Utils.readFile(_knownNetworksFile);
+ if (fconts == null) {
+ return null;
+ }
+
+ if (!fconts.startsWith(VERSION_NOTE)) {
+ // wrong version, try to convert it
+ if (updateStorageVersion()) {
+ return getKnownNetworks();
+ } else {
+ return null;
+ }
+ }
+
+ JSONArray jarr = new JSONArray(fconts.replace(VERSION_NOTE, ""));
+ ArrayList<AccessPointInfo> list = new ArrayList<AccessPointInfo>();
+
+ int count = 0;
+ for (int i = 0; i < jarr.length(); i++) {
+ AccessPointInfo info = AccessPointInfo.fromJsonObject(jarr.getJSONObject(i));
+ if (info == null) {
+ continue;
+ }
+ count += 1;
+ list.add(info);
+ }
+
+ AccessPointInfo[] arr = new AccessPointInfo[count];
+ return list.toArray(arr);
+
+ } catch (Exception e) {
+ Utils.logError("Exception while parsing JSON content from storage file.", e);
+ return null;
+ }
+
+ }
+
+ public AccessPointInfo[] getKnownNetworksOld() {
+
ArrayList<AccessPointInfo> list = new ArrayList<AccessPointInfo>();
File f = new File(this._knownNetworksFile);
@@ -266,7 +342,7 @@ public class NetworkManager {
for (String l : lines) {
- AccessPointInfo info = getFromString(l);
+ AccessPointInfo info = getFromStringOld(l);
if (info != null) {
list.add(info);
}
@@ -282,7 +358,7 @@ public class NetworkManager {
public boolean isKnown(AccessPointInfo info) {
- AccessPointInfo i = searchInFile(info);
+ AccessPointInfo i = getSavedInfo(info);
if (i == null) {
return false;
} else {
@@ -300,7 +376,7 @@ public class NetworkManager {
}
public AccessPointInfo getSavedNetwork(AccessPointInfo i) {
- return searchInFile(i);
+ return getSavedInfo(i);
}
}
diff --git a/app/src/fil/libre/repwifiapp/helpers/OpenVpnManager.java b/app/src/fil/libre/repwifiapp/helpers/OpenVpnManager.java
new file mode 100644
index 0000000..5de2501
--- /dev/null
+++ b/app/src/fil/libre/repwifiapp/helpers/OpenVpnManager.java
@@ -0,0 +1,237 @@
+//
+// Copyright 2017 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
+//
+// This file is part of RepWifiApp.
+// This file is based upon the example file included in
+// de.blinkt.openvpn package by Arne Schwabe.
+//
+// RepWifiApp 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.
+//
+// RepWifiApp 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 RepWifiApp. If not, see <http://www.gnu.org/licenses/>.
+//
+// ********************************************************************
+
+package fil.libre.repwifiapp.helpers;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.IBinder;
+import android.os.RemoteException;
+import java.util.ArrayList;
+import java.util.List;
+import de.blinkt.openvpn.api.APIVpnProfile;
+import de.blinkt.openvpn.api.IOpenVPNAPIService;
+
+public class OpenVpnManager {
+
+ public static final String SERVICE_PACKAGE_NAME = "de.blinkt.openvpn";
+ public static final String APP_COMMON_NAME = "OpenVPN for Android";
+ public static final String PLACEHOLDER_APPNAME = "[VPN_EXT_APP]";
+
+ private static boolean VpnIsConnected;
+ private static OpenVpnManager _currentInstance;
+
+ protected IOpenVPNAPIService _vpnSvc;
+
+ private Activity _caller;
+ private ServiceConnection _svcConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ _vpnSvc = IOpenVPNAPIService.Stub.asInterface(service);
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ _vpnSvc = null;
+ }
+ };
+
+ private OpenVpnManager(Activity c) throws Exception {
+ this._caller = c;
+ bindService();
+ }
+
+ private void bindService() throws Exception {
+
+ Intent intentGetService = new Intent(IOpenVPNAPIService.class.getName());
+ intentGetService.setPackage(SERVICE_PACKAGE_NAME);
+ if (!_caller.bindService(intentGetService, _svcConnection, Context.BIND_AUTO_CREATE)) {
+ throw new Exception("FAILED to bind to OpenVPN service!");
+ }
+
+ }
+
+ private void unbindService() {
+ _caller.unbindService(_svcConnection);
+ }
+
+ private Intent askApiPermissionsGetIntentInternal() throws RemoteException {
+ return _vpnSvc.prepare(_caller.getPackageName());
+ }
+
+ private boolean startVpnInternal(String profileUuid) {
+
+ if (profileUuid == null) {
+ Utils.logError("Invoked startVpn with null uuid");
+ return false;
+ }
+
+ if (_vpnSvc == null) {
+ Utils.logError("Invoked startVpn but inner service is null.");
+ return false;
+ }
+
+ try {
+
+ _vpnSvc.startProfile(profileUuid);
+ VpnIsConnected = true;
+ return true;
+
+ } catch (RemoteException e) {
+ Utils.logError("Exception while starting vpn.", e);
+ return false;
+ }
+ }
+
+ private boolean disconnectInternal() {
+
+ if (_vpnSvc == null) {
+ Utils.logDebug("Attempted to disconnect from VPN, but inner service is null");
+ VpnIsConnected = false;
+ return true;
+ }
+
+ try {
+ _vpnSvc.disconnect();
+ VpnIsConnected = false;
+ return true;
+ } catch (RemoteException e) {
+ Utils.logError("Exception while disconnecting from vpn.", e);
+ return false;
+ }
+ }
+
+ private List<String> getExistingProfilesInternal(){
+
+ try {
+ List<APIVpnProfile> list = _vpnSvc.getProfiles();
+
+ List<String> ret = new ArrayList<String>();
+ for (APIVpnProfile vp : list) {
+ ret.add(vp.mName);
+ }
+
+ return ret;
+
+ } catch (RemoteException e) {
+ Utils.logError("Exception while retrieving profiles from vpn service.", e);
+ return null;
+ }
+
+ }
+
+ private String getUuidFromNameInternal(String profileName) {
+
+ if (_vpnSvc == null) {
+ Utils.logError("Called getUuidFromName but inner service is null!");
+ return null;
+ }
+
+ try {
+ List<APIVpnProfile> list = _vpnSvc.getProfiles();
+
+ for (APIVpnProfile vp : list) {
+ if (vp.mName.equals(profileName)) {
+ return vp.mUUID;
+ }
+ }
+
+ return null;
+
+ } catch (RemoteException e) {
+ Utils.logError("Exception while retrieving profiles from vpn service.", e);
+ return null;
+ }
+ }
+
+ public void close() {
+ if (_vpnSvc != null) {
+ unbindService();
+
+ }
+
+ }
+
+ public static void initialize(Activity caller){
+
+ if (_currentInstance != null){
+ return;
+ }
+
+ try {
+ _currentInstance = new OpenVpnManager(caller);
+ } catch (Exception e) {
+ Utils.logError("Exception while initializing vpn manager.",e);
+ }
+ }
+
+ public static boolean isExternalAppInstalled(Activity caller) {
+
+ try {
+
+ ApplicationInfo i;
+ i = caller.getPackageManager().getApplicationInfo(SERVICE_PACKAGE_NAME, 0);
+ return (i != null);
+
+ } catch (NameNotFoundException e) {
+ return false;
+ }
+
+ }
+
+ public static boolean startVpn(String profileUuid){
+ if (_currentInstance == null){
+ return false;
+ }
+ return _currentInstance.startVpnInternal(profileUuid);
+ }
+
+ public static boolean disconnect(){
+ if (_currentInstance == null){
+ return false;
+ }
+ return _currentInstance.disconnectInternal();
+ }
+
+ public static boolean isVpnConnected(){
+ return VpnIsConnected;
+ }
+
+ public static String getUuidFromName(String profileName){
+ if (_currentInstance == null){
+ return null;
+ }
+ return _currentInstance.getUuidFromNameInternal(profileName);
+ }
+
+ public static List<String> getExistingProfiles(){
+ return _currentInstance.getExistingProfilesInternal();
+ }
+
+ public static Intent askApiPermissionsGetIntent() throws RemoteException{
+ return _currentInstance.askApiPermissionsGetIntentInternal();
+ }
+
+}
diff --git a/app/src/fil/libre/repwifiapp/helpers/RootCommand.java b/app/src/fil/libre/repwifiapp/helpers/RootCommand.java
index 9d9f7d3..bd859c8 100644
--- a/app/src/fil/libre/repwifiapp/helpers/RootCommand.java
+++ b/app/src/fil/libre/repwifiapp/helpers/RootCommand.java
@@ -22,71 +22,89 @@ package fil.libre.repwifiapp.helpers;
import java.io.DataOutputStream;
import java.io.InputStream;
-import fil.libre.repwifiapp.Commons;
+
public class RootCommand extends ShellCommand {
+ // protected static final String CMD_WRAPPING = "export TEMPOUT=\"$(%s)\";echo \"$TEMPOUT\";exit $?";
+ protected static final String CMD_WRAPPING = "TEMPOUT=\"$(%s)\";ec=$?;echo \"$TEMPOUT\";exit $ec";
+
public RootCommand(String commandText) {
super(commandText);
this._cmdTxt = commandText;
}
+
+ public static boolean executeRootCmd(String cmd) {
+
+ try {
+ RootCommand c = new RootCommand(cmd);
+ if (c.execute() == 0) {
+ return true;
+ } else {
+ return false;
+ }
+
+ } catch (Exception e) {
+ Utils.logError("Error executing \"" + cmd + "\"", e);
+ return false;
+ }
+ }
+
@Override
public int execute() throws Exception {
+ if (this._cmdTxt == null) {
+ return EXITCODE_INVALID_INPUT;
+ }
+
Process su = Runtime.getRuntime().exec("su");
DataOutputStream stdin = new DataOutputStream(su.getOutputStream());
InputStream os = su.getInputStream();
InputStream es = su.getErrorStream();
- if (this._cmdTxt != null) {
-
- Utils.logDebug("SU:EXEC: " + this._cmdTxt);
+ Utils.logDebug("SU:EXEC: " + this._cmdTxt);
- this._cmdTxt += " > " + Commons.getTempOutFile();
-
- stdin.writeBytes(this._cmdTxt + "\n");
- stdin.flush();
- }
+ String wrappedCmd = String.format(CMD_WRAPPING, this._cmdTxt);
+
+ stdin.writeBytes(wrappedCmd + "\n");
+ stdin.flush();
StringBuilder sb = new StringBuilder();
sb.append(getStringFromStream(es));
sb.append(getStringFromStream(os));
- this._cmdOut = sb.toString();
-
- stdin.writeBytes("exit\n");
- stdin.flush();
-
int res = su.waitFor();
// re-read the output, in case it was empty when first tried
sb.append(getStringFromStream(es));
sb.append(getStringFromStream(os));
+ this._cmdOut = sb.toString();
+
Utils.logDebug("OUT: " + getOutput());
return res;
}
+
+ public int testRootAccess() throws Exception {
- @Override
- public String getOutput() {
+ Process su = Runtime.getRuntime().exec("su");
- String[] lastOut = Utils.readFileLines(Commons.getTempOutFile());
- if (lastOut == null) {
- return this._cmdOut;
- }
+ DataOutputStream stdin = new DataOutputStream(su.getOutputStream());
- String fout = "";
+ Utils.logDebug("Testing root access: executing simple \"su\"");
+ stdin.writeBytes("exit\n");
+ stdin.flush();
- for (String s : lastOut) {
- fout += s + "\n";
- }
+ int res = su.waitFor();
- return fout;
+ Utils.logDebug("Simple \"su\" exitcode: " + res);
+
+ return res;
}
diff --git a/app/src/fil/libre/repwifiapp/helpers/ShellCommand.java b/app/src/fil/libre/repwifiapp/helpers/ShellCommand.java
index fbeb719..f232ac7 100644
--- a/app/src/fil/libre/repwifiapp/helpers/ShellCommand.java
+++ b/app/src/fil/libre/repwifiapp/helpers/ShellCommand.java
@@ -5,6 +5,8 @@ import java.io.InputStream;
public class ShellCommand {
+ public static final int EXITCODE_INVALID_INPUT = -9;
+
protected String _cmdOut = "";
protected String _cmdTxt = "";
@@ -15,12 +17,13 @@ public class ShellCommand {
public int execute() throws Exception {
if (this._cmdTxt == null) {
- return -9;
+ return EXITCODE_INVALID_INPUT;
}
Utils.logDebug("EXEC: " + this._cmdTxt);
Process cmd = Runtime.getRuntime().exec(this._cmdTxt);
+
InputStream os = cmd.getInputStream();
InputStream es = cmd.getErrorStream();
@@ -47,6 +50,11 @@ public class ShellCommand {
protected String getStringFromStream(InputStream s) throws IOException {
+ java.util.Scanner sc = new java.util.Scanner(s,"UTF-8").useDelimiter("\\A");
+ return sc.hasNext() ? sc.next() : "";
+
+ /*
+
StringBuilder sb = new StringBuilder();
while ((s.available() > 0)) {
int b = s.read();
@@ -57,7 +65,7 @@ public class ShellCommand {
}
}
- return sb.toString();
+ return sb.toString();*/
}
@@ -65,17 +73,6 @@ public class ShellCommand {
return this._cmdOut;
- /*
- * String[] lastOut = Utils.readFileLines(Commons.getTempOutFile()); if
- * (lastOut == null){ return this._cmdOut; }
- *
- * String fout = "";
- *
- * for (String s : lastOut){ fout += s + "\n"; }
- *
- * return fout;
- */
-
}
}
diff --git a/app/src/fil/libre/repwifiapp/helpers/Utils.java b/app/src/fil/libre/repwifiapp/helpers/Utils.java
index 8cd90bf..ad10c1a 100644
--- a/app/src/fil/libre/repwifiapp/helpers/Utils.java
+++ b/app/src/fil/libre/repwifiapp/helpers/Utils.java
@@ -63,63 +63,50 @@ public class Utils {
Log.d(APP_NAME, msg);
}
- public static boolean writeFile(String filePath, String text, boolean overwrite) {
-
- FileWriter writer = null;
- boolean retval = false;
+ public static boolean writeFileLines(String filePath, String[] lines, boolean overwrite) {
- try {
+ if (lines == null) {
+ return false;
+ }
- writer = new FileWriter(filePath, (!overwrite));
- writer.write(text);
+ if (lines.length == 0) {
+ return true;
+ }
- retval = true;
+ StringBuilder sb = new StringBuilder();
- } catch (Exception e) {
- _lastException = e;
- retval = false;
- } finally {
+ for (String l : lines) {
- if (writer != null) {
- try {
- writer.close();
- } catch (IOException e) {
- logError("error while closing filewriter", e);
- }
+ if (l == null) {
+ return false;
}
+ sb.append(l + "\n");
}
- return retval;
+ return writeFile(filePath, sb.toString(), overwrite);
}
- public static boolean writeFileLines(String filePath, String[] lines, boolean overwrite) {
+ public static boolean writeFile(String filePath, String content, boolean overwrite) {
- if (lines == null) {
+ if (content == null) {
return false;
}
FileWriter writer = null;
- boolean retval = false;
try {
writer = new FileWriter(filePath, (!overwrite));
+ writer.write(content);
- if (lines.length == 0) {
- writer.write("");
- }
-
- for (String l : lines) {
- writer.write(l + "\n");
- }
-
- retval = true;
+ return true;
} catch (Exception e) {
_lastException = e;
- retval = false;
+ return false;
+
} finally {
if (writer != null) {
@@ -132,8 +119,6 @@ public class Utils {
}
- return retval;
-
}
public static String[] readFileLines(String filePath) {
@@ -152,7 +137,6 @@ public class Utils {
BufferedReader bufr = null;
List<String> lines = new ArrayList<String>();
- String[] ret = null;
try {
@@ -165,11 +149,13 @@ public class Utils {
}
String[] ar = new String[lines.size()];
- ret = lines.toArray(ar);
+
+ return lines.toArray(ar);
} catch (Exception e) {
logError("Error while reading file " + filePath, e);
- ret = null;
+ return null;
+
} finally {
try {
if (bufr != null) {
@@ -187,10 +173,61 @@ public class Utils {
}
}
- return ret;
-
}
+ public static String readFile(String filePath){
+
+ if (filePath == null) {
+ return null;
+ }
+
+ File f = new File(filePath);
+ if (!f.exists()) {
+ logError("File doesn't exist: " + filePath);
+ return null;
+ }
+
+ FileReader fr = null;
+ BufferedReader bufr = null;
+
+ StringBuilder sb = new StringBuilder();
+
+ try {
+
+ fr = new FileReader(filePath);
+ bufr = new BufferedReader(fr);
+ String line = "";
+
+ while ((line = bufr.readLine()) != null) {
+ sb.append(line);
+ sb.append("\n");
+ }
+
+ return sb.toString();
+
+ } catch (Exception e) {
+ logError("Error while reading file " + filePath, e);
+ return null;
+
+ } finally {
+ try {
+ if (bufr != null) {
+ bufr.close();
+ }
+ } catch (IOException ex) {
+ logError("error while closing filereader", ex);
+ }
+ try {
+ if (fr != null) {
+ fr.close();
+ }
+ } catch (IOException exc) {
+ logError("error while closing filereader", exc);
+ }
+ }
+
+ }
+
public static long daysToMilliseconds(int days) {
return (days * MILLIS_IN_DAY);
}
@@ -199,4 +236,120 @@ public class Utils {
return (milliseconds / MILLIS_IN_DAY);
}
+ public static boolean dumpLogcatToFile(String filePath) {
+
+ if (filePath == null) {
+ return false;
+ }
+
+ try {
+
+ String cmd1 = "logcat -d | grep " + APP_NAME + ">" + filePath;
+ String cmd2 = "logcat -d | grep " + Commons.getContext().getPackageName() + ">>"
+ + filePath;
+ String SEP_LOG = "\n\n---------- [REPWIFI_LOG_SEPARATOR] ----------\n\n";
+
+ RootCommand c1 = new RootCommand(cmd1);
+ RootCommand c2 = new RootCommand(cmd2);
+
+ if (c1.execute() != 0) {
+ return false;
+ }
+
+ if (!writeFile(filePath, SEP_LOG, false)) {
+ return false;
+ }
+
+ if (c2.execute() != 0) {
+ return false;
+ }
+
+ return true;
+
+ } catch (Exception e) {
+ logError("Exception during log dump.", e);
+ return false;
+ }
+
+ }
+
+ public static String netmaskIntToString(int mask) {
+
+ if (mask < 8 || mask > 32) {
+ return null;
+ }
+
+ StringBuilder sb = new StringBuilder(32);
+ StringBuilder sb2 = new StringBuilder(15);
+
+ for (int i = 0; i < mask; i++) {
+ sb.append("1");
+ }
+
+ for (int i = 0; i < 32 - mask; i++) {
+ sb.append("0");
+ }
+
+ for (int i = 0; i < 3; i++) {
+ String bitString = sb.substring((i * 8), (i * 8) + 8);
+ int ibyte = Integer.parseInt(bitString, 2);
+ sb2.append(ibyte);
+ sb2.append(".");
+ }
+ String bitString = sb.substring(24, 32);
+ int ibyte = Integer.parseInt(bitString, 2);
+ sb2.append(ibyte);
+
+ return sb2.toString();
+
+ }
+
+ public static int netmaskStringToInt(String mask) {
+
+ if (mask == null) {
+ return -1;
+ }
+
+ String[] octs = mask.split("\\.");
+ if (octs.length != 4) {
+ return -1;
+ }
+
+ int intmask = 0;
+ boolean prevIsZero = false;
+ for (String o : octs) {
+
+ int intval = 0;
+
+ try {
+ intval = Integer.parseInt(o, 10);
+ } catch (NumberFormatException e) {
+ return -1;
+ }
+
+ String b = Integer.toBinaryString(intval);
+ if (b.length() != 8 && b.contains("1")) {
+ //invalid mask! has ones after a zero
+ return -1;
+ }
+ for (int i = 0; i < b.length(); i++) {
+ if (b.charAt(i) == '0') {
+ prevIsZero = true;
+
+ } else if (prevIsZero) {
+ // invalid mask
+ return -1;
+
+ } else {
+ intmask += 1;
+ }
+
+ }
+
+ }
+
+ return intmask;
+
+ }
+
}
diff --git a/app/src/fil/libre/repwifiapp/helpers/WpaCli.java b/app/src/fil/libre/repwifiapp/helpers/WpaCli.java
new file mode 100644
index 0000000..8bd6561
--- /dev/null
+++ b/app/src/fil/libre/repwifiapp/helpers/WpaCli.java
@@ -0,0 +1,263 @@
+package fil.libre.repwifiapp.helpers;
+
+public abstract class WpaCli {
+
+ private static final int SCAN_WAIT_INTERVAL = 3;
+ private static final String BASE_COMMAND = "wpa_cli -p" + WpaSupplicant.SOCKET_DIR + " -P"
+ + WpaSupplicant.PID_FILE + " -i" + WpaSupplicant.INTERFACE_NAME;
+
+ public static String createNetworkGetId() {
+
+ try {
+
+ RootCommand su = new RootCommand(BASE_COMMAND + " add_network");
+ if (su.execute() == 0) {
+ String out = su.getOutput();
+ if (out == null || out.trim().equals("")) {
+ return null;
+ } else {
+ return out.replace("\n", "");
+ }
+ } else {
+ return null;
+ }
+
+ } catch (Exception e) {
+ Utils.logError("Error while creating network", e);
+ return null;
+ }
+
+ }
+
+ public static boolean setNetworkSSID(String ssid, String networkID) {
+
+ try {
+
+ // needs root (wpa_cli)
+ RootCommand su = new RootCommand(BASE_COMMAND + " set_network " + networkID
+ + " ssid '\"" + ssid + "\"'");
+ if (su.execute() == 0) {
+ String out = su.getOutput();
+ if (out != null && out.trim().replace("\n", "").equals("OK")) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ } catch (Exception e) {
+ Utils.logError("Error while setting network SSID", e);
+ return false;
+ }
+
+ }
+
+ public static boolean setNetworkPSK(AccessPointInfo info, String networkID) {
+
+ try {
+
+ // needs root (wpa_cli)
+
+ String cmdSetPass = null;
+ if (info.needsPassword()) {
+ cmdSetPass = BASE_COMMAND + " set_network " + networkID + " psk '\""
+ + info.getPassword() + "\"'";
+ } else {
+ cmdSetPass = BASE_COMMAND + " set_network " + networkID + " key_mgmt NONE";
+ }
+
+ RootCommand su = new RootCommand(cmdSetPass);
+ if (su.execute() == 0) {
+ String out = su.getOutput();
+ if (out != null && out.trim().replace("\n", "").equals("OK")) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ } catch (Exception e) {
+ Utils.logError("Error while setting network PSK", e);
+ return false;
+ }
+
+ }
+
+ public static boolean setNetworkScanSSID(String networkID) {
+
+ try {
+
+ // needs root (wpa_cli)
+ RootCommand su = new RootCommand(BASE_COMMAND + " set_network " + networkID
+ + " scan_ssid 1");
+ if (su.execute() == 0) {
+ String out = su.getOutput();
+ if (out != null && out.trim().replace("\n", "").equals("OK")) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ } catch (Exception e) {
+ Utils.logError("Error while setting network SSID", e);
+ return false;
+ }
+ }
+
+ public static boolean selectNetwork(String networkID) {
+
+ try {
+
+ // needs root (wpa_cli)
+ RootCommand su = new RootCommand(BASE_COMMAND + " select_network " + networkID);
+ if (su.execute() == 0) {
+ String out = su.getOutput();
+ if (out != null && out.trim().replace("\n", "").equals("OK")) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ } catch (Exception e) {
+ Utils.logError("Error while selecting network", e);
+ return false;
+ }
+
+ }
+
+ public static boolean enableNetwork(String networkID) {
+
+ try {
+
+ // needs root (wpa_cli)
+
+ RootCommand su = new RootCommand(BASE_COMMAND + " enable_network " + networkID);
+ if (su.execute() == 0) {
+ String out = su.getOutput();
+ if (out != null && out.trim().replace("\n", "").equals("OK")) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ } catch (Exception e) {
+ Utils.logError("Error while enabling network", e);
+ return false;
+ }
+
+ }
+
+ public static boolean scanNetworks() {
+
+ // needs root (for wpa_supplicant and wpa_cli)
+ return RootCommand.executeRootCmd(BASE_COMMAND
+ + " scan; if [ $? -ne 0 ]; then exit 1; fi; sleep " + SCAN_WAIT_INTERVAL);
+
+ }
+
+ public static String getScanResults() {
+
+ try {
+
+ RootCommand su = new RootCommand(BASE_COMMAND
+ + " scan_results; if [ $? -ne 0 ]; then exit 1; fi ");
+ if (su.execute() == 0) {
+ String out = su.getOutput();
+ if (out == null || out.trim().equals("")) {
+ return null;
+ } else {
+ return out;
+ }
+ } else {
+ return null;
+ }
+
+ } catch (Exception e) {
+ Utils.logError("Error while executing wpa_cli status", e);
+ return null;
+ }
+
+ /*
+ * // needs root (for wpa_supplicant and wpa_cli) boolean res =
+ * RootCommand.executeRootCmd(); if (!res) { return false; } return res;
+ */
+
+ }
+
+ /***
+ * returns null if unable to determine connection status for any reason.
+ */
+ public static ConnectionStatus getConnectionStatus() {
+
+ Utils.logDebug("called getConnecitonStatus()");
+ if (!WpaSupplicant.isRunning()) {
+ // wpa_supplicant is not running.
+ // unable to determine status.
+ Utils.logDebug("wpa not running, cannot get connection status.");
+ return null;
+
+ }
+
+ try {
+
+ RootCommand su = new RootCommand(BASE_COMMAND + " status");
+ if (su.execute() == 0) {
+ String out = su.getOutput();
+ if (out == null || out.trim().equals("")) {
+ return null;
+ } else {
+ return ConnectionStatus.parseWpaCliOutput(out);
+ }
+ } else {
+ return null;
+ }
+
+ } catch (Exception e) {
+ Utils.logError("Error while executing wpa_cli status", e);
+ return null;
+ }
+
+ }
+
+ public static boolean disconnect() {
+
+ // needs root (for wpa_cli)
+
+ if (!WpaSupplicant.isRunning()) {
+ return true;
+ }
+
+ try {
+
+ RootCommand su = new RootCommand(BASE_COMMAND + " disconnect");
+ if (su.execute() == 0) {
+ String out = su.getOutput();
+ if (out != null && out.trim().replace("\n", "").equals("OK")) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ } catch (Exception e) {
+ Utils.logError("Error while enabling network", e);
+ return false;
+ }
+ }
+
+}
diff --git a/app/src/fil/libre/repwifiapp/helpers/WpaSupplicant.java b/app/src/fil/libre/repwifiapp/helpers/WpaSupplicant.java
new file mode 100644
index 0000000..1dfe449
--- /dev/null
+++ b/app/src/fil/libre/repwifiapp/helpers/WpaSupplicant.java
@@ -0,0 +1,65 @@
+package fil.libre.repwifiapp.helpers;
+
+
+public abstract class WpaSupplicant {
+
+ public static final String INTERFACE_NAME = "wlan0";
+ public static final String WORKDIR = "/data/misc/wifi";
+ public static final String PID_FILE = WORKDIR + "/pidfile";
+ public static final String SOCKET_DIR = WORKDIR + "/sockets/";
+ public static final String SOFTAP_FILE = WORKDIR + "/softap.conf";
+ public static final String P2P_CONF = WORKDIR + "/p2p_supplicant.conf";
+ public static final String WPA_CONF = WORKDIR + "/wpa_supplicant.conf";
+ public static final String ENTROPY_FILE = WORKDIR + "/entropy.bin";
+ public static final String OVERLAY_FILE = "/system/etc/wifi/wpa_supplicant_overlay.conf";
+
+ protected static final String BASE_COMMNAD = "wpa_supplicant -B -dd -i" + INTERFACE_NAME + " -C" + SOCKET_DIR + " -P" + PID_FILE
+ + " -I" + OVERLAY_FILE + " -e" + ENTROPY_FILE;
+
+ public static boolean start() {
+
+ Utils.logDebug("startWpaSupplicant():");
+
+ // needs root (for wpa_supplicant)
+ if (RootCommand.executeRootCmd(BASE_COMMNAD)) {
+ return true;
+ } else {
+ Utils.logDebug("Failed to start wpa");
+ return false;
+ }
+
+ }
+
+ public static boolean kill(){
+ return RootCommand.executeRootCmd("killall -SIGINT wpa_supplicant");
+ }
+
+ public static boolean isRunning() {
+
+ boolean retval = false;
+
+ try {
+
+ RootCommand su = new RootCommand("pidof wpa_supplicant");
+ if (su.execute() == 0) {
+
+ if (su.getOutput().trim().equals("")) {
+ retval = false;
+ } else {
+ retval = true;
+ }
+
+ } else {
+ retval = false;
+ }
+
+ } catch (Exception e) {
+ Utils.logError("Exception during isWpaSupplicantRunning()", e);
+ retval = false;
+ }
+
+ return retval;
+
+ }
+
+}