diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 447661f4..f90a3794 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -119,6 +119,8 @@ + + diff --git a/app/src/main/java/com/emanuelef/remote_capture/ActionReceiver.java b/app/src/main/java/com/emanuelef/remote_capture/ActionReceiver.java new file mode 100644 index 00000000..3249a77c --- /dev/null +++ b/app/src/main/java/com/emanuelef/remote_capture/ActionReceiver.java @@ -0,0 +1,55 @@ +/* + * This file is part of PCAPdroid. + * + * PCAPdroid 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. + * + * PCAPdroid 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 PCAPdroid. If not, see . + * + * Copyright 2022 - Emanuele Faranda + */ + +package com.emanuelef.remote_capture; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import androidx.core.app.NotificationManagerCompat; + +import com.emanuelef.remote_capture.model.AppDescriptor; +import com.emanuelef.remote_capture.model.Blocklist; + +public class ActionReceiver extends BroadcastReceiver { + public static final String EXTRA_UNBLOCK_APP = "unblock_app"; + private static final String TAG = "TAG"; + + @Override + public void onReceive(Context context, Intent intent) { + String unblock_app = intent.getStringExtra(EXTRA_UNBLOCK_APP); + + if((unblock_app != null) && !unblock_app.isEmpty()) { + Log.d(TAG, "unblock_app: " + unblock_app); + Blocklist blocklist = PCAPdroid.getInstance().getBlocklist(); + blocklist.removeApp(unblock_app); + blocklist.saveAndReload(); + + // remove notification + NotificationManagerCompat man = NotificationManagerCompat.from(context); + man.cancel(CaptureService.NOTIFY_ID_APP_BLOCKED); + + AppDescriptor app = AppsResolver.resolve(context.getPackageManager(), unblock_app, 0); + String label = (app != null) ? app.getName() : unblock_app; + Utils.showToastLong(context, R.string.app_unblocked, label); + } + } +} diff --git a/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java b/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java index dcd2e3db..0a10cf9c 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java +++ b/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java @@ -59,6 +59,7 @@ import androidx.preference.PreferenceManager; import com.emanuelef.remote_capture.activities.CaptureCtrl; import com.emanuelef.remote_capture.activities.ConnectionsActivity; +import com.emanuelef.remote_capture.activities.FirewallActivity; import com.emanuelef.remote_capture.activities.MainActivity; import com.emanuelef.remote_capture.fragments.ConnectionsFragment; import com.emanuelef.remote_capture.model.AppDescriptor; @@ -98,9 +99,9 @@ public class CaptureService extends VpnService implements Runnable { private static final String NOTIFY_CHAN_MALWARE_DETECTION = "Malware detection"; private static final String NOTIFY_CHAN_OTHER = "Other"; private static final int VPN_MTU = 10000; - private static final int NOTIFY_ID_VPNSERVICE = 1; - private static final int NOTIFY_ID_LOW_MEMORY = 2; - private static final int NOTIFY_ID_APP_BLOCKED = 3; + public static final int NOTIFY_ID_VPNSERVICE = 1; + public static final int NOTIFY_ID_LOW_MEMORY = 2; + public static final int NOTIFY_ID_APP_BLOCKED = 3; private static CaptureService INSTANCE; final ReentrantLock mLock = new ReentrantLock(); final Condition mCaptureStopped = mLock.newCondition(); @@ -485,16 +486,26 @@ public class CaptureService extends VpnService implements Runnable { AppDescriptor app = appsResolver.getByPackage(packageName, 0); String label = (app != null) ? app.getName() : packageName; + PendingIntent pi = PendingIntent.getActivity(CaptureService.this, 0, + new Intent(CaptureService.this, FirewallActivity.class), Utils.getIntentFlags(0)); + + PendingIntent unblockIntent = PendingIntent.getBroadcast(CaptureService.this, 0, + new Intent(CaptureService.this, ActionReceiver.class) + .putExtra(ActionReceiver.EXTRA_UNBLOCK_APP, packageName), Utils.getIntentFlags(PendingIntent.FLAG_UPDATE_CURRENT)); + // Notify the user NotificationManagerCompat man = NotificationManagerCompat.from(context); if(man.areNotificationsEnabled()) { Notification notification = new NotificationCompat.Builder(CaptureService.this, NOTIFY_CHAN_OTHER) + .setContentIntent(pi) .setSmallIcon(R.drawable.ic_logo) .setColor(ContextCompat.getColor(CaptureService.this, R.color.colorPrimary)) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setCategory(NotificationCompat.CATEGORY_STATUS) .setContentTitle(getString(R.string.app_blocked)) .setContentText(getString(R.string.app_blocked_info, label)) + .setAutoCancel(true) + .addAction(R.drawable.ic_check_solid, getString(R.string.action_unblock), unblockIntent) .build(); man.notify(NOTIFY_ID_APP_BLOCKED, notification); diff --git a/app/src/main/java/com/emanuelef/remote_capture/fragments/AppsFragment.java b/app/src/main/java/com/emanuelef/remote_capture/fragments/AppsFragment.java index 7abc2fd1..792282e3 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/fragments/AppsFragment.java +++ b/app/src/main/java/com/emanuelef/remote_capture/fragments/AppsFragment.java @@ -181,9 +181,7 @@ public class AppsFragment extends Fragment implements ConnectionsListener { else return super.onContextItemSelected(item); - blocklist.save(); - if(CaptureService.isServiceActive()) - CaptureService.requireInstance().reloadBlocklist(); + blocklist.saveAndReload(); // refresh the item mAdapter.notifyItemChanged(app); diff --git a/app/src/main/java/com/emanuelef/remote_capture/fragments/ConnectionsFragment.java b/app/src/main/java/com/emanuelef/remote_capture/fragments/ConnectionsFragment.java index 850cdc4e..b5709290 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/fragments/ConnectionsFragment.java +++ b/app/src/main/java/com/emanuelef/remote_capture/fragments/ConnectionsFragment.java @@ -557,11 +557,8 @@ public class ConnectionsFragment extends Fragment implements ConnectionsListener } else if(whitelist_changed) { whitelist.save(); CaptureService.reloadMalwareWhitelist(); - } else if(blocklist_changed) { - blocklist.save(); - if(CaptureService.isServiceActive()) - CaptureService.requireInstance().reloadBlocklist(); - } + } else if(blocklist_changed) + blocklist.saveAndReload(); return true; } diff --git a/app/src/main/java/com/emanuelef/remote_capture/model/Blocklist.java b/app/src/main/java/com/emanuelef/remote_capture/model/Blocklist.java index 1261e321..6217edf5 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/model/Blocklist.java +++ b/app/src/main/java/com/emanuelef/remote_capture/model/Blocklist.java @@ -5,6 +5,8 @@ import android.os.SystemClock; import android.util.ArrayMap; import android.util.Log; +import com.emanuelef.remote_capture.CaptureService; + import java.util.Iterator; import java.util.Map; @@ -69,4 +71,11 @@ public class Blocklist extends MatchList { mUidToGrace.remove(uid); super.addApp(uid); } + + public void saveAndReload() { + save(); + + if(CaptureService.isServiceActive()) + CaptureService.requireInstance().reloadBlocklist(); + } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 26154924..e3574845 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -383,6 +383,7 @@ Block newly installed apps App blocked The %1$s app has been blocked by the firewall + The %1$s app has been unblocked This view may contain sensitive information, like your passwords and access tokens.\n\nNever give out this information to anyone, it may be a scam attempt Cancel Show data