diff --git a/NetGuard b/NetGuard
deleted file mode 160000
index f86b828..0000000
--- a/NetGuard
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit f86b8287a9e8f0fd44b8e62f3d252e3fc2f9b9da
diff --git a/NetGuard/ADBLOCKING.md b/NetGuard/ADBLOCKING.md
new file mode 100644
index 0000000..f3169e5
--- /dev/null
+++ b/NetGuard/ADBLOCKING.md
@@ -0,0 +1,105 @@
+Ad Blocking with NetGuard
+-------------------------
+
+Instructions (you need to follow **all** the steps):
+
+1. Download/install the latest NetGuard version [from GitHub](https://github.com/M66B/NetGuard/releases) (ad blocking is not possible with the Play store version because Google does not allow ad blocking apps in the Play store)
+1. Enable the setting *'Filter traffic'* in the advanced options (three dot menu > Settings > Advanced options > Filter traffic; default is disabled except always enabled in Android 5.0 and earlier)
+1. Enable the setting *'Block domain names'* in the advanced options (three dot menu > Settings > Advanced options > Block domain names; default is enabled)
+1. Import or download [a hosts file](https://en.wikipedia.org/wiki/Hosts_(file)) using the NetGuard backup settings (three dot menu > Settings > Backup > Download hosts file)
+1. Disable browser compression (in Chrome: three dot menu > Settings > Lite mode > Off)
+1. Wait at least 10 minutes to let the Android DNS cache time out (clear via Chrome: [chrome://net-internals/#dns](chrome://net-internals/#dns))
+1. Test to see if ad blocking works by opening [this page](http://www.netguard.me/test)
+1. Enjoy ad blocking, but don't forget to support application developers and website authors in other ways
+
+
+
+Troubleshooting:
+
+Because of routing bugs, some devices/Android versions require:
+
+* the advanced option *Manage system applications* to be enabled and/or
+* the network option *Subnet routing* to be disabled and/or
+* two (not just one) DNS server addresses to be set in the advanced options, for example 8.8.8.8 and 8.8.4.4 or more privacy friendly [these](https://dns.watch/)
+* disabling of private DNS
+
+
+
+Note that:
+
+* applications, like web browsers, may cache data, so you may need to clear caches
+* applications, browsers mostly, that have a *"data saver"*-like feature that proxies requests through their servers (eg. Opera w/ Turbo, Opera Max, Puffin, Chrome w/ data saver, UC Browser, Yandex w/ Turbo, Apus Browser, KK Browser, Onavo Extend, Maxthon) will not have ads blocked as NetGuard cannot see those domain requests
+* applications, browsers mostly, can have a private DNS feature (Chrome: three-dots menu, Settings, Privacy, Use secure DNS, turn off) **
+* applications, including browser, can be system apps, which require managing system apps in the advanced settings to be enabled
+* the Android always-on VPN setting *Block connections without VPN* will result in stop sending domain names to the VPN after some time
+* YouTube ads are not domain-based, and thus cannot be blocked with NetGuard
+* NetGuard ignores the IP addresses in the hosts file, because it does not route blocked domains to localhost
+* When NetGuard imports the hosts file, it automatically discards any duplicates entries, so duplicate entries are not a problem and have no performance impact after the file is imported
+* you can check the number of hosts (domains) imported by pulling the NetGuard notification down using two fingers if your version of Android supports that functionality
+* wildcards are not supported due to performance and battery usage reasons
+* it is not possible to edit the hosts file (change/add/delete domain names) with NetGuard
+* you can disable ad blocking by disabling the setting *'Block domain names'* in the advanced options
+* you cannot exclude a single app from ad blocking because Android resolves domain names on behalf of all apps
+* **ad blocking is provided as-is**, see also [here](https://forum.xda-developers.com/showpost.php?p=71805655&postcount=4668)
+* **ad blocking is not available when NetGuard was installed from the Google Play store!** (disable automatic updates of NetGuard in the Play store application)
+
+** Some browsers (and also apps) now use DNS over TLS (DoT) or DNS over
+HTTPS (DoH). If one of the two protocols is active in the browser,
+NetGuard cannot "see" the outgoing DNS requests (due to encryption).
+They still flow through NetGuard, but are not treated as DNS requests,
+but as normal connections (via port 853 or 443). It is therefore not
+sufficient to disable Private DNS within Android, but you must also
+check the settings for DoT and DoH (especially for browsers).
+
+
+
+The NetGuard version from GitHub:
+
+* is signed with the same signature as the version from the Google Play store, so any purchases will be restored (this will not happen with for example the F-Droid version)
+* will automatically notify you if there are updates available via GitHub (this can be switched off in NetGuard's settings)
+
+
+
+Which hosts (ad servers) will be blocked depends on the hosts file being used.
+NetGuard downloads the [StevenBlack hosts file](https://github.com/StevenBlack/hosts) by default.
+
+
+
+Automation:
+
+You can automatically download a hosts file by sending this service intent with your favorite automation tool, like Tasker:
+
+`eu.faircode.netguard.DOWNLOAD_HOSTS_FILE`
+
+For example using [adb](https://developer.android.com/studio/command-line/adb.html) from the command line:
+
+`adb shell am startservice -a eu.faircode.netguard.DOWNLOAD_HOSTS_FILE`
+
+
+
+Apart from using a hosts file, you can block most in-app ads by blocking this address in the access list of Google Play services:
+
+*googleads.g.doubleclick.net/443*
+
+You'll need to enable filtering and (temporarily) logging for this (you can do this by using the *Configure* button; check both options)
+and you'll need to wait until the address appears (you can speed this up by opening some apps with in-app ads).
+Note that ads are likely being cached, so this may not take effect immediately.
+
+
+
+An alternate way to block advertisements is by using special DNS servers, like these:
+
+* [AdGuard DNS](https://adguard.com/en/adguard-dns/overview.html) - Free
+* [Alternate DNS](https://alternate-dns.com/) - 14 day free trial
+* [NoAd](https://noad.zone/) - Not working as of 2017 June 03
+
+Be sure to read the privacy policies of these services as they might log your DNS requests.
+
+You can set DNS server addresses for all connection types in NetGuard's *Advanced options*.
+Note that when you set two DNS server addresses, the default (operating system/network provider) DNS servers will not be used anymore.
+
+Feel free to let me know about other servers or request to add them in alphabetic order by doing a pull request.
+
+
+
+**Please do not mention this feature in Google Play store comments, since Google does not allow ad blocking applications in the Google Play store.**
diff --git a/NetGuard/FAQ-de.txt b/NetGuard/FAQ-de.txt
new file mode 100644
index 0000000..21ea20d
--- /dev/null
+++ b/NetGuard/FAQ-de.txt
@@ -0,0 +1,500 @@
+Häufig gestellte Fragen (FAQ)
+
+(0) Wie verwende ich NetGuard?
+
+ Aktivieren Sie die NetGuard-Firewall über den Schalter in der Aktionsleiste von NetGuard
+ Erlauben (grünlich*) oder verweigern (rötlich*) Sie den Wi-Fi- oder mobilen Internetzugang über die Symbole neben den Anwendungsnamen in der Anwendungsliste des NetGuard
+
+Über Einstellungen > Standardeinstellungen können Sie vom Modus "Blockieren/Blacklist" (Deaktivieren von "Wi-Fi blockieren" und "Mobile blockieren" und anschließendes Blockieren unerwünschter Anwendungen in der Anwendungsliste des NetGuard) in den Modus "Zulassen/Whitelist" (Aktivieren von "Wi-Fi blockieren" und "Mobile blockieren" und anschließendes Zulassen gewünschter Anwendungen in der Anwendungsliste des NetGuard) wechseln.
+
+* Je nach dem von Ihnen verwendeten Thema können die Symbole wie folgt aussehen:
+
+ Erlaubt (Internetzugang erlaubt): grünlich (teal) / blau / lila / grau
+ Blockiert (Internetzugang verweigert): rötlich (lachsfarben) / orange / gelb / gelb
+
+(1) Kann NetGuard meine Privatsphäre vollständig schützen?
+
+Nein - nichts kann Ihre Privatsphäre vollständig schützen. NetGuard tut sein Bestes, ist aber durch die Tatsache eingeschränkt, dass es den Android-VPN-Dienst verwenden muss. Dies ist der Kompromiss, der erforderlich ist, um eine Firewall zu entwickeln, die keinen Root-Zugriff erfordert. Die Firewall kann nur gestartet werden, wenn Android den Start "erlaubt". Sie bietet also keinen Schutz beim frühen Hochfahren (obwohl Sie Ihr Netzwerk vor dem Neustart deaktivieren können). Außerdem muss der Android-VPN-Dienst neu gestartet werden, um neue Regeln anzuwenden, wenn sich die Konnektivität geändert hat oder wenn der Bildschirm ein- oder ausgeschaltet wird. Das ist jedoch viel besser als gar nichts.
+
+In den erweiterten Optionen können Sie Seamless VPN Handover on reload aktivieren, um zu verhindern, dass Datenverkehr verloren geht, wenn der Android VPN-Dienst neu gestartet wird. Dies funktioniert jedoch nicht bei allen Android-Versionen/Varianten und führt dazu, dass NetGuard hängen bleibt und alle Verbindungen blockiert.
+
+Unter Android N und höher kann NetGuard als Always-On VPN konfiguriert werden. Aktivieren Sie unter Android O nicht die Unteroption "Verbindungen ohne VPN blockieren", siehe Frage 51) für weitere Informationen dazu.
+
+Um sich besser zu schützen, denken Sie daran, Wi-Fi und mobile Daten vor dem Neustart zu deaktivieren und sie erst beim Neustart zu aktivieren, nachdem der Firewall-Dienst gestartet wurde (und das Schlüsselsymbol in der Statusleiste sichtbar ist).
+
+Vielen Dank @pulser
+
+(2) Kann ich eine andere VPN-Anwendung verwenden, während ich NetGuard nutze?
+
+Wenn die VPN-Anwendung den VPN-Dienst nutzt, dann nicht, denn NetGuard muss diesen Dienst nutzen. Android erlaubt immer nur einer Anwendung, diesen Dienst zu nutzen.
+
+NetGuard ist eine Firewall-Anwendung, es ist also nicht beabsichtigt, VPN-Unterstützung hinzuzufügen. NetGuard unterstützt jedoch einen SOCKS5-Proxy zur Verkettung von VPN-Anwendungen. Eine mögliche Lösung, die von der Community beigesteuert wurde, finden Sie hier.
+
+3) Kann ich NetGuard auf jeder Android-Version verwenden?
+
+Nein, die minimal erforderliche Android-Version ist 5.1 (Lollipop).
+
+(4) Verbraucht NetGuard zusätzliche Akkuleistung?
+
+In der Standardeinstellung verbraucht NetGuard kaum Akkuleistung. Alle Einstellungen, die zusätzlichen Akkuverbrauch verursachen, wie IP-Filterung und Protokollierung, sind mit einer Warnung versehen. Wenn NetGuard sehr viel Strom verbraucht, überprüfen Sie bitte Ihre Einstellungen.
+
+Der Akkuverbrauch bei aktivierter IP-Filterung hängt von der Qualität der Implementierung Ihres Android-VPN-Dienstes und der Leistungsfähigkeit des Prozessors Ihres Geräts ab. Im Allgemeinen kann der Akkuverbrauch auf älteren Geräten inakzeptabel sein, während er auf modernen Geräten mit einem effizienten Prozessor kaum auffällt.
+
+Die Benachrichtigung über die Netzwerkgeschwindigkeitsgrafik verbraucht zusätzliche Akkuleistung. Deshalb wird die Benachrichtigung nur angezeigt, wenn der Bildschirm eingeschaltet ist. Sie können die Aktualisierungshäufigkeit in den Einstellungen verringern, um den Akkuverbrauch zu reduzieren.
+
+Beachten Sie, dass Android oft fälschlicherweise den Akkuverbrauch anderer Anwendungen dem NetGuard zuordnet, da der Netzwerkverkehr anderer Anwendungen durch den NetGuard fließt. Das bedeutet, dass es so aussehen kann, als würde NetGuard viel Akkuleistung verbrauchen, aber in Wirklichkeit ist der Gesamtakkuverbrauch aller Apps immer noch derselbe.
+
+(6) Sendet NetGuard meinen Internetverkehr an einen externen (VPN-)Server?
+
+Nein, je nach Betriebsmodus geschieht grundsätzlich eines von zwei Dingen mit Ihrem Internetverkehr:
+
+ Wenn die IP-Filterung deaktiviert ist, wird der blockierte Internetverkehr an den lokalen VPN-Dienst weitergeleitet, der dann als Sinkhole fungiert (d.h. den gesamten blockierten Verkehr verwirft).
+ Wenn die IP-Filterung aktiviert ist, wird sowohl der blockierte als auch der erlaubte Internetverkehr in den lokalen VPN-Dienst geleitet und nur der erlaubte Verkehr wird an das vorgesehene Ziel weitergeleitet (und nicht an einen VPN-Server).
+
+Der Android-VPN-Dienst wird verwendet, um den gesamten Internetverkehr lokal zu NetGuard zu leiten, so dass für die Erstellung dieser Firewall-Anwendung kein Root-Recht erforderlich ist. NetGuard ist im Gegensatz zu allen anderen No-Root-Firewall-Anwendungen zu 100 % Open Source, so dass Sie im Zweifelsfall den Quellcode selbst überprüfen können.
+
+(7) Warum werden Anwendungen ohne Internetzulassung angezeigt?
+
+Die Internetzugangsberechtigung kann bei jedem Anwendungsupdate ohne Zustimmung des Benutzers erteilt werden. Indem NetGuard alle Anwendungen anzeigt, können Sie den Internetzugang kontrollieren, noch bevor ein solches Update erfolgt.
+
+(8) Was muss ich aktivieren, damit die Google Play™ Store-App funktioniert?
+
+Sie müssen 3 Pakete (Anwendungen) aktivieren (verwenden Sie die Suche in NetGuard, um sie schnell zu finden):
+
+ com.android.vending (Play Store)
+ com.google.android.gms (Play-Dienste)
+ com.android.providers.downloads (Download-Manager)
+
+Da die Google Play™ Store-App dazu neigt, von sich aus nach Updates zu suchen oder sie sogar herunterzuladen (auch wenn kein Konto damit verknüpft ist), kann man sie in Schach halten, indem man "Bei eingeschaltetem Bildschirm zulassen" für alle 3 Pakete aktiviert. Klicken Sie auf den Pfeil nach unten auf der linken Seite eines Anwendungsnamens und aktivieren Sie diese Option, aber lassen Sie die Netzwerksymbole auf rot stehen (daher blockiert). Das kleine menschliche Symbol wird für diese Pakete angezeigt.
+
+Beachten Sie, dass NetGuard die Installation eines Google-Dienstes nicht erfordert.
+
+(9) Warum wird der VPN-Dienst neu gestartet?
+
+Der VPN-Dienst wird neu gestartet, wenn Sie den Bildschirm ein- oder ausschalten und wenn sich die Konnektivität ändert (Wi-Fi, Mobilfunk), um die Regeln mit den Bedingungen "Zulassen, wenn der Bildschirm eingeschaltet ist" und "Blockieren, wenn Roaming" anzuwenden.
+
+Siehe hier für weitere Details.
+
+(10) Werden Sie ein Tasker-Plug-in anbieten?
+
+Nein, denn wenn es Tasker erlaubt ist, den NetGuard zu deaktivieren, kann jede Anwendung den NetGuard deaktivieren. Es ist keine gute Idee, einer Sicherheitsanwendung zu erlauben, von anderen Anwendungen deaktiviert zu werden.
+
+
+(13) Wie kann ich den laufenden NetGuard-Eintrag auf dem Benachrichtigungsbildschirm entfernen?
+
+ Klicken Sie lange auf die NetGuard-Benachrichtigung
+ Tippen Sie auf das "i"-Symbol
+ Je nach den Software-Anpassungen Ihres Geräts und/oder ROM-Herstellers werden Sie entweder zu
+ zum Bildschirm "App-Info", wo Sie das Häkchen bei "Benachrichtigungen anzeigen" entfernen und dem nächsten Dialog zustimmen können
+ zum Bildschirm "App-Benachrichtigungen", wo Sie den Schieberegler "Blockieren" auf "Ein" stellen können
+
+Beachten Sie, dass unabhängig davon, ob Sie eine Dialogwarnung erhalten oder nicht, dieser Vorgang auch alle Informations- oder Warnbenachrichtigungen von NetGuard deaktiviert, wie z. B. die Benachrichtigung über eine neu installierte Anwendung.
+
+Um zu erfahren, warum diese Benachrichtigung überhaupt notwendig ist, lesen Sie bitte Frage 24.
+
+Einige Android-Versionen zeigen eine zusätzliche Benachrichtigung an, die ein Schlüsselsymbol enthalten kann. Diese Benachrichtigung kann leider nicht entfernt werden.
+
+(14) Warum kann ich nicht OK wählen, um die VPN-Verbindungsanfrage zu bestätigen?
+
+Möglicherweise befindet sich eine weitere (unsichtbare) Anwendung über dem Dialog für die VPN-Verbindungsanfrage. Einige bekannte (den Bildschirm verdunkelnde) Anwendungen, die dies verursachen können, sind Lux Brightness, Night Mode und Twilight. Um dieses Problem zumindest vorübergehend zu vermeiden, schließen Sie alle Anwendungen und/oder Dienste, die im Hintergrund ausgeführt werden können.
+
+(15) Werden F-Droid-Builds unterstützt?
+
+F-Droid-Builds werden nicht unterstützt, da ich keine Kontrolle darüber habe, ob und wann die F-Droid-Version von NetGuard aktualisiert wird, so dass ich keine rechtzeitigen Updates garantieren kann, z. B. wenn es ein kritisches oder Sicherheitsproblem gibt.
+
+Da F-Droid-Builds und GitHub-Versionen unterschiedlich signiert sind, muss ein F-Droid-Build zuerst deinstalliert werden, um auf eine GitHub-Version aktualisieren zu können.
+
+(16) Warum werden einige Anwendungen abgeblendet angezeigt?
+
+Deaktivierte Anwendungen und Anwendungen ohne Internetzugang werden abgeblendet dargestellt.
+
+(17) Warum verbraucht der NetGuard so viel Speicher?
+
+Das tut er nicht. NetGuard weist keinen Speicher zu, außer ein wenig für die Anzeige der Elemente der Benutzeroberfläche und für die Pufferung des Datenverkehrs. Bei einigen Android-Varianten scheint die Verbindung mit der Google Play™ Store-App fast 150 MB zu verbrauchen. Sie wird für In-App-Spenden benötigt und wird fälschlicherweise NetGuard statt der Google Play™ Store-App zugewiesen.
+
+(18) Warum kann ich NetGuard nicht in der Google Play™-Store-App finden?
+
+NetGuard erfordert mindestens Android 5.1 und ist daher in der Google Play™ Store-App auf Geräten mit früheren Android-Versionen nicht verfügbar.
+
+(18) Warum kann ich NetGuard nicht in der Google Play™ Store-App finden?
+
+NetGuard erfordert mindestens Android 5.1 und ist daher in der Google Play™ Store-App auf Geräten mit früheren Android-Versionen nicht verfügbar.
+
+(19) Warum hat die Anwendung XYZ immer noch Internetzugang?
+
+Wenn Sie den Internetzugang für eine Anwendung sperren, gibt es keine Möglichkeit, dies zu umgehen. Anwendungen können jedoch über andere (System-)Anwendungen/Komponenten auf das Internet zugreifen. So erhalten beispielsweise die Google Play-Dienste eingehende Push-Nachrichten und Werbung für die meisten Anwendungen, einschließlich WhatsApp und Facebook Messenger. Sie können dies verhindern, indem Sie den Internetzugang auch für die andere Anwendung/Komponente blockieren. Sie können Systemanwendungen und -komponenten wie Google Play Services blockieren, indem Sie die erweiterte NetGuard-Option Systemanwendungen verwalten aktivieren. Dies lässt sich am besten diagnostizieren, indem Sie das globale Zugriffsprotokoll überprüfen (Drei-Punkte-Menü, Protokoll anzeigen).
+
+Beachten Sie, dass einige Anwendungen immer wieder versuchen, auf das Internet zuzugreifen, was durch das Senden eines Verbindungsanforderungspakets geschieht. Dieses Paket geht in das VPN-Sinkhole, wenn der Internetzugang für die Anwendung blockiert ist. Dieses Paket besteht aus weniger als 100 Bytes und wird von Android als ausgehender Datenverkehr gezählt und ist auch in der Geschwindigkeitsanzeige sichtbar.
+
+(20) Kann ich den NetGuard "grün" machen/bewerben?
+
+Nein. Wenn Sie den NetGuard auf "grün" stellen oder anderweitig in den Ruhezustand versetzen, werden die Regeln nicht angewendet, wenn sich die Konnektivität von Wi-Fi/Mobilfunk, Bildschirm ein/aus und Roaming/nicht Roaming ändert.
+
+(21) Wirkt sich der Dämmerungsmodus auf den NetGuard aus?
+
+Ich bin mir nicht sicher, denn aus der Dokumentation zum Dämmerungsmodus geht nicht hervor, ob der Android-VPN-Dienst davon betroffen ist.
+
+Um sicher zu gehen, können Sie die Akku-Optimierung für NetGuard wie folgt manuell deaktivieren:
+
+Android-Einstellungen > Akku > Drei-Punkte-Menü > Akku-Optimierungen > Dropdown > Alle Apps > NetGuard > Nicht optimieren > Fertig
+
+Die Vorgehensweise kann von Gerät zu Gerät unterschiedlich sein.
+
+Das Deaktivieren des Standby-Modus für NetGuard kann nicht von NetGuard aus erfolgen, da NetGuard laut Google kein Anwendungstyp ist, der dies tun darf.
+
+(22) Kann ich mit dem NetGuard Tethering (Android-Hotspot) oder Wi-Fi-Anrufe nutzen?
+
+Ja, aber Sie müssen das Subnetz-Routing und Tethering in den NetGuard-Netzwerkeinstellungen aktivieren. Ob dies funktioniert, hängt von Ihrer Android-Version ab, da einige Android-Versionen einen Fehler aufweisen, der die Zusammenarbeit zwischen Tethering und dem VPN-Dienst verhindert.
+
+Einige Geräte schalten das Wi-Fi in den Ruhezustand, so dass Tethering nicht funktioniert, wenn der Bildschirm ausgeschaltet ist. Dieses Verhalten kann in den erweiterten Wi-Fi-Einstellungen von Android deaktiviert werden.
+
+(24) Kann man die Benachrichtigung aus der Statusleiste entfernen?
+
+Android kann Hintergrunddienste jederzeit beenden. Dies kann nur verhindert werden, indem ein Hintergrunddienst in einen Vordergrunddienst umgewandelt wird. Android verlangt eine ständige Benachrichtigung für alle Vordergrunddienste, um Sie auf einen möglichen Batterieverbrauch aufmerksam zu machen (siehe Frage 4). Die Benachrichtigung kann also nicht entfernt werden, ohne Instabilität zu verursachen. Allerdings wird die Benachrichtigung als niedrige Priorität markiert, was dazu führen sollte, dass sie an das Ende der Liste verschoben wird.
+
+Das Schlüsselsymbol und/oder die Benachrichtigung "VPN läuft", die von Android und nicht von NetGuard angezeigt wird, kann leider nicht entfernt werden. In der Google-Dokumentation steht: "Eine vom System verwaltete Benachrichtigung wird während der Lebensdauer einer VPN-Verbindung angezeigt".
+
+Android 8 Oreo und höher zeigen eine Benachrichtigung "... läuft im Hintergrund" an, die alle im Hintergrund laufenden Apps auflistet. Sie können diese Benachrichtigung nicht deaktivieren, aber Sie können das Symbol wie folgt aus der Statusleiste entfernen:
+
+ Öffnen Sie Einstellungen > Apps & Benachrichtigungen > App-Info
+ Öffnen Sie die Einstellungen (drei Punkte); Wählen Sie "System anzeigen".
+ Wählen Sie "Android-System".
+ Wählen Sie "App-Benachrichtigungen".
+ Wählen Sie "Im Hintergrund laufende Apps".
+ Wählen Sie "Wichtigkeit" und wählen Sie "Niedrig".
+
+(25) Können Sie eine Funktion "Alle auswählen" hinzufügen?
+
+Die Funktion "Alle auswählen" ist nicht erforderlich, da Sie in den Einstellungen von Netguard vom Modus "Blockieren" (Blacklist) auf "Zulassen" (Whitelist) umschalten können. Siehe auch Frage 0.
+
+(27) Wie lese ich das Protokoll des blockierten Datenverkehrs?
+
+Die Spalten haben die folgenden Bedeutungen:
+
+ Zeit (tippen Sie auf einen Protokolleintrag, um das Datum zu sehen)
+ Anwendungssymbol (tippen Sie auf einen Protokolleintrag, um den Anwendungsnamen zu sehen)
+ UID der Anwendung
+ Wi-Fi / mobile Verbindung, grün=erlaubt, rot=geblockt
+ Interaktiver Status (Bildschirm an oder aus)
+ Protokoll (siehe unten) und Paketflags (siehe unten)
+ Quell- und Zielport (tippen Sie auf einen Protokolleintrag, um einen Zielport zu suchen)
+ Quell- und Ziel-IPv4- oder IPv6-Adresse (tippen Sie auf einen Protokolleintrag, um eine Ziel-IP-Adresse nachzuschlagen)
+ Name der Organisation, der die IP-Adresse gehört (muss über das Menü aktiviert werden)
+
+Protokolle:
+
+ HOPO (IPv6 Hop-by-Hop-Option)
+ ICMP
+ IGMP
+ ESP (IPSec)
+ TCP
+ UDP
+ Nummer = eines der Protokolle in dieser Liste
+ 4 = IPv4
+ 6 = IPv6
+
+Paket-Flags:
+
+ S = SYN
+ A = ACK
+ P = PSH
+ F = FIN
+ R = RST
+
+Eine ausführliche Erklärung finden Sie hier.
+
+Nur TCP-, UDP- und ICMP-Ping-Datenverkehr kann durch den Android VPN-Dienst geleitet werden. Alle anderen Daten werden verworfen und im globalen Datenverkehrsprotokoll als blockiert angezeigt. Dies ist auf einem Android-Gerät fast nie ein Problem.
+
+(28) Warum wird den Google-Konnektivitätsdiensten standardmäßig der Internetzugang gestattet?
+
+Die Systemanwendung der Google-Konnektivitätsdienste prüft, ob das aktuelle Netzwerk wirklich mit dem Internet verbunden ist. Dies wird wahrscheinlich durch eine kurze Verbindung zu einem Google-Server erreicht.
+
+Wenn dies nicht der Fall ist, erscheint ein '!' im Wi-Fi- oder Mobil-Symbol in der Systemstatusleiste.
+
+Neuere Android-Versionen scheinen die Konnektivität nicht von Mobil auf Wi-Fi umzuschalten, wenn das Wi-Fi-Netzwerk nicht wirklich verbunden ist, obwohl eine Verbindung zum Wi-Fi-Netzwerk besteht (oder umgekehrt). Unter Android 6.0 und höher erhalten Sie möglicherweise eine Benachrichtigung, in der Sie gefragt werden, ob Sie die Verbindung aufrechterhalten möchten oder nicht. Um eine schlechte Benutzererfahrung zu vermeiden, enthält NetGuard eine vordefinierte Regel, um die Google-Konnektivitätsdienste standardmäßig zuzulassen.
+
+Sie können alle vordefinierten Regeln hier finden.
+
+Sie können vordefinierte Regeln außer Kraft setzen.
+
+(29) Warum erhalte ich die Meldung "Das von Ihnen angeforderte Element ist nicht zum Kauf verfügbar"?
+
+Sie können nur Pro-Funktionen erwerben, wenn Sie NetGuard aus dem Google Play Store installiert haben.
+
+(30) Kann ich auch AFWall+ auf demselben Gerät ausführen?
+
+Sofern Sie NetGuard nicht nur testen, gibt es derzeit keinen Grund, beide zu verwenden, da sie dieselbe Funktion (Firewall) abdecken, wenn auch mit unterschiedlichen Grundvoraussetzungen (AFWall+ benötigt ein gerootetes Gerät) und Vorgehensweisen (AFWall+ verwendet iptables, während NetGuard ein VPN verwendet).
+
+Außerdem müssen Sie die Zugriffsregeln für jede Anwendung zwischen AFWall+ und NetGuard synchron halten, da die Anwendung sonst nicht auf das Netzwerk zugreifen kann.
+
+Einige Hinweise zur Einrichtung von AFWall+ für den gleichzeitigen Einsatz mit NetGuard:
+
+ Wenn Sie keine Filterung in NetGuard verwenden, benötigen die Anwendungen direkten Internetzugang (Wi-Fi und/oder mobil) in AFWall+
+ Wenn Sie die Filterung verwenden, benötigt NetGuard einen Internetzugang (Wi-Fi und/oder mobil) in AFWall+
+ Wenn Sie die Filterung verwenden, müssen Sie NetGuard in AFWall+ wieder zulassen, wenn Sie NetGuard deinstallieren/neu installieren.
+ Wenn Sie die Filterung verwenden, benötigen die Anwendungen einen VPN-Internetzugang (aktivieren Sie das Kontrollkästchen, um diese Option in den AFWall+-Einstellungen anzuzeigen).
+
+Diese Frage wurde von der Community gestellt. Es gibt keine Unterstützung für die Verwendung von NetGuard und AFWall+ zusammen.
+
+(31) Warum können einige Anwendungen nur als Gruppe konfiguriert werden?
+
+Für viele Zwecke, einschließlich des Netzwerkzugriffs, gruppiert Android Anwendungen nach UID und nicht nach Paket/Anwendungsname. Insbesondere Systemanwendungen haben oft dieselbe UID, obwohl sie einen anderen Paket- und Anwendungsnamen haben; diese werden vom ROM-Hersteller bei der Erstellung so eingerichtet. Diesen Anwendungen kann nur als Gruppe der Zugang zum Internet erlaubt/gesperrt werden.
+
+(32) Warum ist der Akku-/Netzwerkverbrauch von NetGuard so hoch?
+
+Das liegt daran, dass Android die Batterie- und Netzwerknutzung zählt, die normalerweise für andere Anwendungen gegen NetGuard im IP-Filtermodus gezählt wird. Der gesamte Akkuverbrauch ist etwas höher, wenn der IP-Filtermodus aktiviert ist. Der IP-Filtermodus ist bei Android-Versionen vor 5.0 immer aktiviert, bei späteren Android-Versionen ist er optional.
+
+(33) Können Sie Profile hinzufügen?
+
+Profile sind unpraktisch, da sie manuell bedient werden müssen. Bedingungen wie "Wenn der Bildschirm eingeschaltet ist" sind dagegen praktisch, weil sie automatisch funktionieren. Daher werden keine Profile hinzugefügt, aber Sie können gerne neue Bedingungen vorschlagen; diese müssen jedoch allgemein verwendbar sein, um aufgenommen zu werden.
+
+Als Abhilfe können Sie die Export-/Importfunktion verwenden, um bestimmte Einstellungen unter bestimmten Umständen anzuwenden. Alternativ können Sie auch den Sperrmodus als Profil verwenden.
+
+(34) Können Sie eine Bedingung "wenn im Vordergrund" oder "wenn aktiv" hinzufügen?
+
+Aktuelle Android-Versionen erlauben es einer Anwendung nicht, abzufragen, ob andere Anwendungen im Vordergrund/Hintergrund oder aktiv/inaktiv sind, ohne eine zusätzliche, die Privatsphäre verletzende Berechtigung zu besitzen und auf Kosten eines zusätzlichen Batterieverbrauchs (da eine regelmäßige Abfrage erforderlich ist). Daher kann dies nicht ohne erhebliche Nachteile, wie diesen, hinzugefügt werden. Sie können stattdessen die Bedingung "wenn der Bildschirm eingeschaltet ist" verwenden.
+
+(35) Warum startet das VPN nicht?
+
+NetGuard "bittet" Android, den lokalen VPN-Dienst zu starten, aber einige Android-Versionen enthalten einen Fehler, der den (automatischen) Start des VPN verhindert. Manchmal wird dies durch ein Update von NetGuard verursacht. Leider kann dieser Fehler nicht von NetGuard behoben werden. Sie können versuchen, Ihr Gerät neu zu starten und/oder die VPN-Berechtigungen von NetGuard über die Android-Einstellungen zu widerrufen. Manchmal hilft es auch, NetGuard zu deinstallieren und neu zu installieren (exportieren Sie vorher unbedingt Ihre Einstellungen!).
+
+(36) Können Sie einen PIN- oder Passwortschutz hinzufügen?
+
+Da das Ausschalten des VPN-Dienstes über die Android-Einstellungen nicht verhindert werden kann, ist es wenig sinnvoll, einen PIN- oder Passwortschutz hinzuzufügen.
+
+(37) Warum sind die Profi-Funktionen so teuer?
+
+Die richtige Frage lautet: "Warum gibt es so viele Steuern und Gebühren":
+
+ Mehrwertsteuer: 25% (abhängig von Ihrem Land)
+ Google-Gebühr: 30%
+ Einkommenssteuer: 50%
+
+Was für den Entwickler übrig bleibt, ist also nur ein Bruchteil dessen, was Sie bezahlen.
+
+Obwohl NetGuard wirklich viel Arbeit macht, müssen nur einige der Komfort- und erweiterten Funktionen gekauft werden, was bedeutet, dass NetGuard im Grunde kostenlos ist und Sie nichts bezahlen müssen, um Ihren Datenverbrauch zu reduzieren, die Akkulaufzeit zu erhöhen und Ihre Privatsphäre zu schützen.
+
+Beachten Sie auch, dass die meisten kostenlosen Anwendungen am Ende nicht nachhaltig zu sein scheinen, während NetGuard ordnungsgemäß gewartet und unterstützt wird, und dass kostenlose Anwendungen einen Haken haben können, wie z. B. das Senden von datenschutzrelevanten Informationen an das Internet.
+
+Siehe hier für weitere Informationen.
+
+(38) Warum hat NetGuard aufgehört zu laufen?
+
+Vergewissern Sie sich zunächst, dass Sie in den Android-Einstellungen die Akku-Optimierung für NetGuard deaktiviert haben.
+
+Auf den meisten Geräten läuft der NetGuard im Hintergrund mit seinem Dienst im Vordergrund weiter. Auf einigen Geräten (insbesondere einigen Samsung-Modellen), auf denen viele Anwendungen um den Speicher konkurrieren, kann Android NetGuard als letzte Möglichkeit noch stoppen. Einige Android-Versionen, insbesondere von Huawei (siehe hier für einen Fix) oder Xiaomi (siehe hier für einen Fix) stoppen Apps und Dienste zu aggressiv. Dies kann leider nicht von NetGuard behoben werden und kann als Mangel des Gerätes und/oder als Fehler in Android angesehen werden. In der Tat leiden viele Apps unter diesem Problem, siehe die Website Don't kill my app! für weitere Informationen und Lösungen. Sie können dieses Problem umgehen, indem Sie in den erweiterten Optionen des NetGuard den Watchdog aktivieren, der alle 10-15 Minuten überprüft.
+
+(39) Wie unterscheidet sich eine VPN-basierte Firewall von einer iptables-basierten Firewall?
+
+Siehe diese Stack Exchange-Frage.
+
+(40) Kann man Zeitpläne hinzufügen?
+
+Abgesehen davon, dass es nicht trivial ist, Zeitpläne hinzuzufügen, sind sie - meiner Meinung nach - keine gute Idee, da Zeit keine gute Regelbedingung ist. Eine Regelbedingung wie Wenn der Bildschirm eingeschaltet ist ist eine bessere und einfachere Bedingung. Daher werden keine Zeitpläne hinzugefügt, aber Sie können gerne andere neue Bedingungen vorschlagen.
+
+(41) Können Sie Wildcards / Adress-/Portbereiche hinzufügen?
+
+Wildcards zum Zulassen/Blockieren von Adressen und Adress-/Anschlussbereichen hätten erhebliche Auswirkungen auf die Leistung und Benutzerfreundlichkeit und werden daher nicht hinzugefügt. Wildcard-Regeln und Adress-/Port-Bereiche müssten für jeden einzelnen Verbindungsversuch überprüft werden. Da NetGuard im Gegensatz zu anderen No-Root-Firewalls Domänennamen anstelle von IP-Adressen blockiert, gibt es kaum einen Bedarf für Wildcards.
+
+(42) Warum wird die Berechtigung ... benötigt?
+
+ INTERNET ('Voller Netzwerkzugriff'): um erlaubten (gefilterten) Datenverkehr an das Internet weiterzuleiten
+ ACCESS_NETWORK_STATE ("Netzwerkverbindungen anzeigen"): um zu prüfen, ob das Gerät über Wi-Fi mit dem Internet verbunden ist
+ READ_PHONE_STATE ('Device ID & call information'): um Änderungen im Mobilfunknetz zu erkennen, siehe hier für weitere Details
+ ACCESS_WIFI_STATE ("Wi-Fi-Verbindungsinformationen"): zur Erkennung von Änderungen im Wi-Fi-Netzwerk
+ RECEIVE_BOOT_COMPLETED ('Run at startup'): zum Starten der Firewall beim Booten des Geräts
+ WAKE_LOCK ("Gerät am Schlafen hindern"): zum zuverlässigen Neuladen von Regeln im Hintergrund bei Änderungen der Konnektivität
+ VIBRATE: um eine Vibrationsrückmeldung beim Antippen des Widgets zu geben
+ FOREGROUND_SERVICE ('Vordergrunddienst'): zur Ausführung eines Vordergrunddienstes unter Android 9 Pie und höher
+ QUERY_ALL_PACKAGES: zum Auflisten aller Apps unter Android 11 und höher
+ BILLING: zur Verwendung der In-App-Abrechnung
+
+(43) Ich erhalte die Meldung "Diese App führt dazu, dass Ihr Gerät langsam läuft".
+
+Diese Meldung wird vom Smart Manager angezeigt, aber eigentlich ist es die Smart Manager-Anwendung selbst, die Verzögerungen und Lags verursacht. Einige Links:
+
+ Smart Manager beschwert sich über LastPass
+ Smart Manager deaktivieren?
+(44) Ich erhalte keine Benachrichtigungen beim Zugriff
+
+Um eine hohe Anzahl von Benachrichtigungen in der Statusleiste zu vermeiden, wird die Benachrichtigung bei Zugriff nur einmal pro Domainname und Anwendung durchgeführt. Zugriffe auf Domänennamen, die im Zugriffsprotokoll der Anwendung angezeigt werden (Drilldown in den NetGuard-Anwendungseinstellungen), werden nicht erneut benachrichtigt, selbst wenn Sie die Benachrichtigung bei Zugriff gerade aktiviert haben. Um wieder für alle Domainnamen benachrichtigt zu werden, können Sie das Anwendungszugriffsprotokoll über das Mülleimer-Symbol löschen. Wenn Sie alle Anwendungsprotokolle löschen möchten, können Sie Ihre Einstellungen exportieren und importieren.
+
+Ein weiterer Grund, warum Sie keine Benachrichtigungen erhalten, könnte ein aktivierter Energiesparmodus sein, z. B. bei Samsung-Geräten. Auch wenn Sie die CPU-Frequenz in diesem Modus nicht einschränken.
+
+(45) Verarbeitet NetGuard eingehende Verbindungen?
+
+Der Android VPN-Dienst behandelt nur ausgehende Verbindungen (von Anwendungen zum Internet), eingehende Verbindungen werden also normalerweise nicht behandelt.
+
+Wenn Sie eine Serveranwendung auf Android ausführen möchten, sollten Sie beachten, dass die Verwendung von Portnummern unter 1024 Root-Berechtigungen erfordert und dass einige Android-Versionen Routing-Fehler enthalten, die dazu führen, dass eingehender Datenverkehr fälschlicherweise in das VPN geleitet wird.
+
+(46) Kann ich eine Rückerstattung erhalten?
+
+Wenn eine gekaufte Pro-Funktion nicht wie beschrieben funktioniert und dies nicht durch ein Problem in den kostenlosen Funktionen verursacht wird und ich das Problem nicht zeitnah beheben kann, können Sie eine Rückerstattung erhalten. In allen anderen Fällen ist eine Rückerstattung nicht möglich. In keinem Fall kann es eine Rückerstattung für ein Problem im Zusammenhang mit den kostenlosen Funktionen geben, da für diese nichts bezahlt wurde und sie ohne Einschränkung bewertet werden können. Ich übernehme die Verantwortung als Verkäufer, das zu liefern, was versprochen wurde, und ich erwarte, dass Sie die Verantwortung übernehmen, sich über das zu informieren, was Sie kaufen.
+
+(48) Warum werden einige Domänennamen blockiert, obwohl sie als erlaubt eingestellt sind?
+
+NetGuard blockiert den Datenverkehr auf der Grundlage der IP-Adressen, mit denen eine Anwendung versucht, eine Verbindung herzustellen. Wenn mehr als ein Domänenname auf dieselbe IP-Adresse verweist, können sie nicht unterschieden werden. Wenn Sie für 2 Domänen, die auf dieselbe IP-Adresse aufgelöst werden, unterschiedliche Regeln festlegen, werden beide blockiert.
+
+Danke @pulser
+
+Ein weiteres mögliches Problem ist, dass Android den DNS-TTL-Wert nicht beachtet und seine eigenen Caching-Regeln anwendet. Dies könnte dazu führen, dass NetGuard einen DNS-Eintrag zu früh oder zu spät aus seinem eigenen Cache löscht, was dazu führt, dass eine IP-Adresse nicht oder falsch erkannt wird. Sie können versuchen, dieses Problem zu umgehen, indem Sie den DNS-TTL-Wert von NetGuard ändern. Dieser Wert wird als minimaler DNS TTL-Wert verwendet, um das Verhalten von Android zu imitieren.
+
+NetGuard blockiert den Datenverkehr auch, wenn der Android-VPN-Dienst neu gestartet wird, um neue Regeln anzuwenden, z. B. wenn sich die Konnektivität ändert oder wenn der Bildschirm ein- oder ausgeschaltet wird.
+
+(49) Verschlüsselt NetGuard meinen Internetverkehr / verbirgt es meine IP-Adresse?
+
+NetGuard ist eine Firewall-Anwendung, die den Internetverkehr auf Ihrem Gerät filtert (siehe auch diese Frage). Sie ist also nicht dazu gedacht - und tut es auch nicht -, Ihren Internetverkehr zu verschlüsseln oder Ihre IP-Adresse zu verbergen.
+
+(50) Wird NetGuard beim Booten automatisch gestartet?
+
+Ja, NetGuard wird beim Hochfahren automatisch gestartet, wenn Sie Ihr Gerät mit aktiviertem NetGuard ausgeschaltet haben und NetGuard nicht auf einem externen Speicher installiert ist.
+
+Einige Geräte, z. B. OnePlus- und Mi-Geräte, können verhindern, dass bestimmte Apps nach dem Neustart automatisch gestartet werden. Dies kann in den Android-Einstellungen deaktiviert werden.
+
+(51) Warum blockiert der NetGuard den gesamten Internetverkehr?
+
+Vergewissern Sie sich, dass Sie NetGuard auf die Doze-Ausnahmeliste gesetzt haben (Android 6 Marshmallow oder höher) und dass Android NetGuard erlaubt, das Internet im Hintergrund zu nutzen (siehe auch diese Frage).
+
+Stellen Sie sicher, dass Sie NetGuard nicht im Erlaubnismodus (Whitelist) betreiben (überprüfen Sie die Standardeinstellungen von NetGuard).
+
+Stellen Sie sicher, dass Sie die Always-On-VPN-Unteroption "Verbindungen ohne VPN blockieren" nicht aktiviert haben (Android 8 Oreo oder höher). Dadurch wird auch die Auflösung von Domainnamen blockiert (ist das ein Fehler oder eine Funktion?).
+
+Einige Internetanbieter blockieren alle DNS-Anfragen, außer über ihre eigenen DNS-Server. Wenn Sie also benutzerdefinierte DNS-Server konfiguriert haben, versuchen Sie, dies rückgängig zu machen.
+
+Einige Android-Versionen, darunter LineageOS und /e/ für einige Geräte, enthalten einen Fehler, der dazu führt, dass der gesamte Internetverkehr blockiert wird. Meistens können Sie diesen Fehler umgehen, indem Sie die Filterung in den erweiterten Optionen von NetGuard aktivieren. Wenn dies das Problem nicht löst, kann es leider nicht von NetGuard behoben oder umgangen werden. Bitte schauen Sie hier für eine Lösung.
+
+(52) Was ist der Lockdown-Modus?
+
+Im Sperrmodus wird der gesamte Datenverkehr für alle Anwendungen blockiert, mit Ausnahme von Anwendungen, für die die Bedingung "Im Sperrmodus zulassen" aktiviert ist. Sie können diesen Modus verwenden, um die Nutzung des Akkus oder des Netzes einzuschränken, z. B. wenn Ihr Akku fast leer ist oder Ihr Datenkontingent fast erschöpft ist.
+
+Beachten Sie, dass der Sperrmodus nur angewendet werden kann, wenn die entsprechende Option auch unter "Netzwerkoptionen" eingestellt ist (eine für den Wi-Fi-Modus, eine für mobile Daten), so dass die Sperrung nur in einem der beiden Netzwerkmodi und nicht im anderen erfolgen kann (z. B. Sperren, wenn mobile Daten aktiv sind, aber nicht, wenn Wi-Fi gerade verwendet wird).
+
+Beachten Sie auch, dass Systemanwendungen in diesem Modus nur blockiert werden, wenn die Verwaltung von Systemanwendungen in den erweiterten Einstellungen aktiviert ist.
+
+Sie können den Sperrmodus im Hauptmenü, über ein Widget oder über eine Einstellungs-Kachel aktivieren/deaktivieren (Android 7 Nougat oder höher).
+
+(53) Die Übersetzung in meiner Sprache fehlt / ist falsch / unvollständig
+
+Sie können hier Übersetzungen beisteuern (die Registrierung ist kostenlos). Wenn deine Sprache fehlt, kontaktiere mich bitte, damit ich sie hinzufügen kann.
+
+(54) Wie kann ich alle TCP-Verbindungen durch das Tor-Netzwerk tunneln?
+
+Tor mit NetGuard wird nur im XDA NetGuard Forum unterstützt. Es gibt keinen persönlichen Support für Tor mit NetGuard, da ich Tor selbst nicht benutze.
+
+Installiere zunächst Orbot, den Android-Client für Tor, starte ihn, drücke auf Start, während er sich verbindet, öffne die Einstellungen und stelle sicher, dass er so eingestellt ist, dass er beim Start des Gerätes automatisch startet.
+
+In den Netzwerkoptionen von NetGuard aktiviere Subnetz-Routing und in den erweiterten Optionen SOCKS5-Proxy verwenden mit der Adresse 127.0.0.1 und dem Port 9050 (das ist der Standard-Port, wenn du ihn in Orbot geändert hast, dann ändere ihn auch hier).
+
+Das sollte ausreichen. Wenn der Test fehlschlägt (z.B. keine Verbindung), können Sie die App-Details von Orbot öffnen, das Häkchen bei Regeln und Bedingungen anwenden entfernen und es erneut versuchen.
+
+Wie man testet: Öffne Firefox (oder einen anderen nicht-proxyfähigen Browser) mit der Adresse https://ipleak.net/ und du solltest eine andere IP-Adresse als deine normale sehen, und unten im Feld Tor Exit Node etwas anderes als Unknown.
+
+Sei dir bewusst, dass alle anderen Tor-Hinweise (https://www.torproject.org/docs/faq.html.en) immer noch gelten, wie z.B. dass das Tor-Netzwerk nicht erreichbar ist, deine Aktivitäten in deinem Land aktiv überwacht/gezielt werden, Online-Dienste (z.B. Gmail, Google Play Store) sich nicht anmelden können oder du gezwungen bist, endlose Capchas zu lösen, wenn du auf Seiten zugreifst, die Cloudflare's CDN-Dienste nutzen.
+
+(55) Warum verbindet sich NetGuard mit Amazon / ipinfo.io / 216.239.34.21?
+
+NetGuard stellt eine Verbindung zu Amazon / ipinfo.io her, um die Namen und Organisationen für IP-Adressen anzuzeigen. Wenn Sie dies nicht wünschen, deaktivieren Sie einfach die Anzeige von Namen und Organisationen über das Drei-Punkte-Menü in der globalen Protokollansicht.
+
+(56) Warum lässt der NetGuard den gesamten Internetverkehr zu?
+
+NetGuard kann jede einzelne Anwendung blockieren, sogar Systemanwendungen und -komponenten.
+
+NetGuard lässt standardmäßig jeglichen Datenverkehr zu, um schwer zu findende Probleme zu vermeiden. Sie müssen den Datenverkehr selbst selektiv blockieren, indem Sie auf das Mobil- oder Wi-Fi-Symbol tippen.
+
+Beachten Sie, dass NetGuard den Datenverkehr zu einer Anwendung zulässt, wenn der Bildschirm eingeschaltet ist und die Bedingung "wenn Bildschirm eingeschaltet" aktiviert ist.
+
+(57) Warum verbraucht der NetGuard so viele Daten?
+
+Im Grunde genommen verbraucht NetGuard selbst keine Daten. Bei vielen Android-Versionen werden jedoch die Daten anderer Anwendungen, die durch NetGuard fließen, fälschlicherweise dem NetGuard statt den Anwendungen zugerechnet. In diesem Fall ist der Datenverbrauch anderer Anwendungen bei aktiviertem NetGuard gleich Null.
+
+Der gesamte Datenverbrauch Ihres Geräts ist mit und ohne NetGuard gleich.
+
+(58) Warum dauert das Laden der Anwendungsliste so lange?
+
+Die Anwendungsliste wird von Android bereitgestellt, daher hängt die Ladegeschwindigkeit hauptsächlich von der Leistung Ihres Geräts und der Effizienz Ihrer Android-Version ab. So kann z. B. Speicherknappheit zu längeren Ladezeiten führen, da Speicher freigegeben werden muss, z. B. durch das Pausieren anderer Anwendungen.
+
+Es ist bekannt, dass die Einschränkung von Systemanwendungen und Systemkomponenten unter bestimmten Umständen dazu führt, dass die Anwendungsliste langsam oder gar nicht geladen wird. Die genauen Umstände sind nicht bekannt.
+
+(59) Können Sie mir helfen, meinen Kauf wiederherzustellen?
+
+Google verwaltet alle Käufe, so dass ich als Entwickler keine Kontrolle über die Käufe habe. Daher kann ich Ihnen nur einige Ratschläge geben:
+
+ Stellen Sie sicher, dass Sie eine aktive Internetverbindung haben.
+ Stellen Sie sicher, dass Sie den Google Play Store / die Play-Dienste nicht blockiert haben.
+ Vergewissern Sie sich, dass Sie mit dem richtigen Google-Konto angemeldet sind und dass mit Ihrem Google-Konto alles in Ordnung ist.
+ Stellen Sie sicher, dass Sie NetGuard über das richtige Google-Konto installiert haben, wenn Sie mehrere Google-Konten auf Ihrem Gerät eingerichtet haben
+ Öffnen Sie die Play Store-App und warten Sie mindestens eine Minute, um ihr Zeit zu geben, sich mit den Google-Servern zu synchronisieren.
+ Öffnen Sie NetGuard und navigieren Sie zum Bildschirm mit den Profi-Funktionen; NetGuard wird die Einkäufe erneut überprüfen
+
+Sie können auch versuchen, den Cache der Play Store-App über die Einstellungen der Android-Apps zu löschen.
+
+Beachten Sie dies:
+
+ Einkäufe werden in der Google-Cloud gespeichert und können nicht verloren gehen.
+ Es gibt keine zeitliche Begrenzung für Einkäufe, sie können also nicht verfallen
+ Google gibt keine Details (Name, E-Mail, etc.) über Käufer an Entwickler weiter.
+ Eine Anwendung wie NetGuard kann nicht auswählen, welches Google-Konto verwendet werden soll.
+ Es kann eine Weile dauern, bis die Play Store-App einen Kauf mit einem anderen Gerät synchronisiert hat
+ Play Store-Einkäufe können nicht ohne den Play Store verwendet werden, was nach den Play Store-Regeln ebenfalls nicht zulässig ist
+
+Wenn Sie das Problem mit dem Kauf nicht lösen können, müssen Sie sich mit Google in Verbindung setzen.
+
+(60) Warum funktionieren IP (Wi-Fi) Anrufe/SMS/MMS nicht?
+
+Bitte lesen Sie dazu den Abschnitt über die Kompatibilität (wenn Sie ein mobiles Gerät verwenden, müssen Sie möglicherweise die Desktop-Version anfordern, um diesen Abschnitt zu sehen).
+
+(61) Hilfe, NetGuard ist abgestürzt!
+
+NetGuard stürzt selten ab ("unerwartet gestoppt"), aber wenn es abgestürzt ist (was etwas anderes ist, als von Android gestoppt zu werden, siehe diese FAQ), dann liegt es meist an Fehlern in Ihrer Android-Version (entweder in der Implementierung des Android-VPN-Dienstes oder im Android-Linux-Kernel). Ich bin gerne bereit, die Ursache eines Absturzes zu überprüfen und wenn möglich zu beheben, aber dazu benötige ich ein Logcat, das von Ihrem PC mit dem Absturzprotokoll aufgezeichnet wurde. Da Logcats meist recht umfangreich sind, benötige ich auch den genauen Zeitpunkt des Absturzes. Wenn Sie nicht wissen, wie Sie ein Logcat von Ihrem PC erfassen können, verwenden Sie bitte Ihre Lieblingssuchmaschine, um eine der zahlreichen Anleitungen zu finden.
+
+(62) Wie kann ich das Problem "Es gab ein Problem beim Parsen des Pakets" lösen?
+
+Wahrscheinliche Ursachen sind, dass die heruntergeladene APK-Datei beschädigt ist (was durch einen Virenscanner verursacht werden könnte) oder dass Sie versuchen, NetGuard auf einer nicht unterstützten Android-Version zu installieren.
+
+(63) Warum ist der gesamte DNS-Verkehr erlaubt?
+
+NetGuard blockiert im Gegensatz zu allen anderen Android-Firewalls echte Domainnamen. Hierfür muss eine Liste von Domainnamen und IP-Adressen erstellt werden. Zu diesem Zweck lässt NetGuard jeglichen DNS-Verkehr zu, auch wenn der Domainname in der Hosts-Datei aufgeführt ist. Das bedeutet jedoch nicht, dass der Verkehr zur aufgelösten IP-Adresse erlaubt ist.
+
+Wenn Sie dem System (Google) oder den DNS-Servern Ihres Providers nicht trauen, können Sie in den erweiterten Einstellungen alternative DNS-Server festlegen. Achten Sie darauf, die Adressen einzugeben und zu bestätigen und zwei DNS-Serveradressen festzulegen. Wenn Sie nur eine DNS-Serveradresse eingeben, wird diese zusätzlich zu den Standard-DNS-Serveradressen verwendet.
+
+(64) Können Sie DNS über TLS/HTTP hinzufügen?
+
+Wenn Sie DNS-over-HTTP- (DoH) oder DNS-over-TLS- (DoT) Anfragen abfangen wollen, um Domänennamen aufzulösen, ist dies nicht möglich, da der DoH/DoT-Verkehr verschlüsselt ist, was ja der Sinn von DoH/DoT ist.
+
+Bitte lesen Sie hier, wie Sie DoH/DoT trotzdem mit NetGuard nutzen können.
+
+(65) Warum kann sich NetGuard nicht selbst blockieren?
+
+Zunächst einmal, wenn NetGuard sich selbst blockieren kann, sollten Sie darauf vertrauen, dass NetGuard sich wirklich selbst blockiert, was im Grunde dasselbe ist, wie darauf zu vertrauen, dass NetGuard sich nicht mit dem Internet verbindet, wenn es nicht benötigt wird.
+
+Beachten Sie, dass NetGuard sich mit dem Internet verbinden muss, um den Datenverkehr anderer Anwendungen an das Internet weiterzuleiten und um Informationen über IP-Adressen nachzuschlagen, siehe auch diese FAQ.
+
+NetGuard konnte sich in älteren Versionen selbst blockieren, aber das erforderte den Aufruf von VpnService.protect für jede einzelne Verbindung. Da es in einer typischen Android-Umgebung viele Verbindungen von vielen Apps gibt, führte dies zu einer Verschwendung von Batteriestrom und zu Abstürzen auf einigen Android-Versionen mit Fehlern in dieser Funktion.
+
+Da das Blockieren von NetGuard mit sich selbst nichts Nützliches gebracht hat, wurde das Blockieren von NetGuard mit sich selbst entfernt, um Batteriestrom zu sparen und Abstürze zu vermeiden.
+
+(66) Warum greift eine blockierte App trotzdem auf das Internet zu?
+
+Gesperrte Anwendungen können nicht auf das Internet zugreifen. Hierfür gibt es keine Ausnahmen. Der gesamte App- und Systemverkehr fließt durch den Android-VPN-Dienst, was für Unternehmen mit hohen Sicherheitsanforderungen ein Muss ist. Das bedeutet auch, dass alle Apps gleich behandelt werden und dass das globale Zugriffsprotokoll (Protokoll anzeigen im Drei-Punkte-Überlaufmenü) den gesamten Datenverkehr anzeigt.
+
+Allerdings:
+
+ Apps können lokal zwischengespeicherte Inhalte anzeigen
+ Eingehende (Push-)Nachrichten werden von der Systemkomponente Google Play-Dienste und nicht von Apps empfangen, insbesondere wenn die App im Hintergrund läuft oder der Bildschirm ausgeschaltet ist.
+ Ebenso wird Werbung meist von der Systemkomponente Google Play-Dienste empfangen.
+ Downloads werden oft durch den Download-Manager und nicht durch Apps durchgeführt.
+
+Wenn Sie Google Play-Dienste oder den Download-Manager blockieren möchten, müssen Sie die Verwaltung von System-Apps in den erweiterten Einstellungen aktivieren.
+
+Wenn Sie sicherstellen möchten, dass Push-Nachrichten immer empfangen werden, können Sie Regeln und Bedingungen für Google Play-Dienste anwenden deaktivieren.
+
+Um es klar zu sagen: In den meisten Fällen können Sie Anzeigen nicht durch das Blockieren von Apps blockieren. Sie können jedoch mit NetGuard Werbung für alle Apps blockieren, wie das geht, erfahren Sie hier.
+
+(67) Wer ist "nobody"?
+
+"nobody" ist die übliche Bezeichnung für ein Benutzerkonto, das keine Dateien besitzt, in keiner privilegierten Gruppe ist und keine anderen Fähigkeiten hat als die, die jeder andere Benutzer hat.
+
+NetGuard wird nur für Telefone und Tablets unterstützt, also nicht für andere Gerätetypen wie Fernsehgeräte oder Fahrzeuge.
+
+Wenn Sie die Antwort auf Ihre Frage nicht gefunden haben, können Sie Ihre Fragen in diesem Forum stellen oder mich über dieses Kontaktformular kontaktieren.
+
diff --git a/NetGuard/FAQ.md b/NetGuard/FAQ.md
new file mode 100644
index 0000000..96f7868
--- /dev/null
+++ b/NetGuard/FAQ.md
@@ -0,0 +1,751 @@
+NetGuard
+========
+
+Please scroll down if you want to ask a question, request a feature, or report a bug.
+
+[Deutsche Übersetzung](https://raw.githubusercontent.com/M66B/NetGuard/master/FAQ-de.txt)
+
+Frequently Asked Questions (FAQ)
+--------------------------------
+
+
+**(0) How do I use NetGuard?**
+
+* Enable the NetGuard firewall using the switch in NetGuard's action bar
+* Allow (greenish\*) or deny (reddish\*) Wi-Fi or mobile internet access using the icons next to an application name in NetGuard's applications list
+
+You can use *Settings > Defaults* to change from block/blacklist mode (disable *Block Wi-Fi* and *Block mobile*, and then block unwanted applications in NetGuard's applications list) to allow/whitelist mode (enable *Block Wi-Fi* and *Block mobile*, and then allow desired applications in NetGuard's applications list).
+
+\* Depending on the theme you use, the icons may be:
+* Allowed (internet access permitted): greenish (teal) / blue / purple / gray
+* Blocked (internet access denied): reddish (salmon) / orange / yellow / amber
+
+
+**(1) Can NetGuard completely protect my privacy?**
+
+No - nothing can completely protect your privacy.
+NetGuard will do its best, but it is limited by the fact it must use the Android VPN service.
+This is the trade-off required to make a firewall which does not require root access.
+The firewall can only start when Android "allows" it to start,
+so it will not offer protection during early boot-up (although you can disable your network before rebooting).
+Also, the Android VPN service needs to be restarted to apply new rules when connectivity has changed or when the screen is being turned on or off.
+It will, however, be much better than nothing.
+
+In the advanced options you can enable *Seamless VPN handover on reload* to prevent traffic from leaking when the Android VPN service is being restarted.
+However, this does not work properly on all Android versions/variants causing NetGuard to hang and block all connections.
+
+On Android N and later NetGuard can be configured as [Always-On VPN](https://developer.android.com/guide/topics/connectivity/vpn#always-on).
+On Android O **do not** enable the sub option '*Block connections without VPN*', see [question 51](#user-content-faq51)) for more information on this.
+
+To protect yourself more, remember to disable Wi-Fi and mobile data before rebooting,
+and only enable them on reboot, after the firewall service has started (and the key icon is visible in the status bar).
+
+Thanks @[pulser](https://github.com/pulser/)
+
+
+**(2) Can I use another VPN application while using NetGuard**
+
+If the VPN application is using the [VPN service](http://developer.android.com/reference/android/net/VpnService.html),
+then no, because NetGuard needs to use this service. Android allows only one application at a time to use this service.
+
+NetGuard is a firewall application, so there is no intention to add VPN support.
+However, NetGuard supports a [SOCKS5 proxy](https://en.wikipedia.org/wiki/SOCKS) to chain VPN applications.
+You can find one possible community contributed solution [here](https://itsignacioportal.github.io/netguard-pdnsf-any-vpn-combo/).
+
+
+**(3) Can I use NetGuard on any Android version?**
+
+No, the minimum required Android version is 5.1 (Lollipop )
+
+
+**(4) Will NetGuard use extra battery power?**
+
+By default NetGuard will hardly use any battery power.
+All settings resulting in extra battery usage, like IP filtering and logging, have a warning.
+If NetGuard uses a lot of battery power, please double check your settings.
+
+The battery usage when IP filtering is enabled depends on the quality of your Android VPN service implementation and the efficiency of the processor of your device.
+Generally the battery usage on older devices might be unacceptable, yet hardly noticeable on modern devices with an efficient processor.
+
+The network speed graph notification will use extra battery power.
+This is why the notification is shown only when the screen is on.
+You can decrease the update frequency using the settings to reduce the battery usage.
+
+Note that Android often incorrectly contribute battery usage of other apps to NetGuard,
+because the network traffic of other apps is flowing through NetGuard.
+This means that it might look like NetGuard is using a lot of battery power,
+but that in fact the total battery usage of all apps is still the same.
+
+
+**(6) Will NetGuard send my internet traffic to an external (VPN) server?**
+
+No, depending on the mode of operation basically one of two things will happen with your internet traffic:
+
+* When IP filtering is disabled, blocked internet traffic will be routed into the local VPN service, which will operate as a sinkhole (in effect dropping all blocked traffic)
+* When IP filtering is enabled, both blocked and allowed internet traffic will be routed into the local VPN service and only allowed traffic will be forwarded to the intended destination (and not to a VPN server)
+
+The [Android VPN service](http://developer.android.com/reference/android/net/VpnService.html) is being used to locally route all internet traffic to NetGuard so no root is required to build this firewall application.
+NetGuard, unlike all other no-root firewalls applications, is 100% open source, so when you are in doubt you can check [the source code](https://github.com/M66B/NetGuard/) yourself.
+
+
+**(7) Why are applications without internet permission shown?**
+
+Internet permission can be granted with each application update without user consent.
+By showing all applications, NetGuard allows you to control internet access even *before* such an update occurs.
+
+
+**(8) What do I need to enable for the Google Play™ store app to work?**
+
+You need 3 packages (applications) enabled (use search in NetGuard to find them quickly):
+
+* com.android.vending (Play store)
+* com.google.android.gms (Play services)
+* com.android.providers.downloads (Download manager)
+
+Since the Google Play™ store app has a tendency to check for updates or even download them all by itself (even if no account is associated),
+one can keep it in check by enabling "*Allow when screen is on*" for all 3 of these packages.
+Click on the down arrow on the left side of an application name and check that option,
+but leave the network icons set to red (hence blocked). The little human icon will appear for those packages.
+
+Note that NetGuard does *not* require any Google service to be installed.
+
+
+**(9) Why is the VPN service being restarted?**
+
+The VPN service will be restarted when you turn the screen on or off and when connectivity changes (Wi-Fi, mobile)
+to apply the rules with the conditions *'Allow when screen is on'* and *'Block when roaming'*.
+
+See [here](http://forum.xda-developers.com/showpost.php?p=65723629&postcount=1788) for more details.
+
+
+**(10) Will you provide a Tasker plug-in?**
+
+No, because if Tasker is allowed to disable NetGuard, any application can disable NetGuard.
+Allowing a security application to be disabled by other applications is not a good idea.
+
+
+**(13) How can I remove the ongoing NetGuard entry in the notification screen?**
+
+* Long click the NetGuard notification
+* Tap the 'i' icon
+* Depending on your device and/or ROM manufacturer's software customizations, you can be directed to either:
+ * the **App Info** screen and you can uncheck '*Show notifications*' and agree to the next dialog
+ * the **App Notifications** screen and you can toggle the '*Block*' slider to on
+
+Note that, whether or not you get a dialog warning to agree upon,
+this operation will also disable any information or warning notifications from NetGuard,
+such as the new application installed notification.
+
+To read about the need for the notification in the first place, see [question 24](#user-content-faq24).
+
+Some Android versions display an additional notification, which might include a key icon.
+This notification, unfortunately, cannot be removed.
+
+
+**(14) Why can't I select OK to approve the VPN connection request?**
+
+There might be another (invisible) application on top of the VPN connection request dialog.
+Some known (screen dimming) applications which can cause this are *Lux Brightness*, *Night Mode*, and *Twilight*.
+To avoid this problem, at least temporarily, close all applications and/or services which may be running in the background.
+
+
+**(15) Are F-Droid builds supported?**
+
+F-Droid builds are not supported because I have no control over if and when the F-Droid version of NetGuard will be updated,
+so I cannot guarantee timely updates, for example if there is a critical or security issue.
+
+Because F-Droid builds and GitHub releases are signed differently, an F-Droid build needs to be uninstalled first to be able to update to a GitHub release.
+
+
+**(16) Why are some applications shown dimmed?**
+
+Disabled applications and applications without internet permission are shown dimmed.
+
+
+**(17) Why is NetGuard using so much memory?**
+
+It isn't. NetGuard doesn't allocate any memory, except a little for displaying the user interface elements and for buffering traffic.
+It appears, on some Android variants, that the Google Play™ store app connection uses almost 150 MB. It is needed for in-app donations,
+and is incorrectly attributed to NetGuard instead to the Google Play™ store app.
+
+
+**(18) Why can't I find NetGuard in the Google Play™ store app?**
+
+NetGuard requires at least Android 5.1, so it is not available in the Google Play™ store app on devices running prior Android versions.
+
+
+**(19) Why does application XYZ still have internet access?**
+
+If you block internet access for an application, there is no way around it.
+However, applications could access the internet through other (system) applications/components.
+For example, Google Play services receives incoming push messages and ads for most applications, including WhatsApp and Facebook messenger.
+You can prevent this by blocking internet access for the other application/component as well.
+You can block system applications and components, like Google Play services, by enabling the advanced NetGuard option *Manage system apps*.
+This can best be diagnosed by checking the global access log (three dot menu, *Show log*).
+
+Note that some applications keep trying to access the internet, which is done by sending a connection request packet.
+This packet goes into the VPN sinkhole when internet access for the application is blocked.
+This packet consists of less than 100 bytes and is counted by Android as outgoing traffic
+and will be visible in the speed graph notification as well.
+
+
+**(20) Can I Greenify/hibernate NetGuard?**
+
+No. [Greenifying](https://play.google.com/store/apps/details?id=com.oasisfeng.greenify)
+or otherwise hibernating NetGuard will result in rules not being applied
+when connectivity changes from Wi-Fi/mobile, screen on/off, and roaming/not roaming.
+
+
+**(21) Does doze mode affect NetGuard?**
+
+I am not sure, because the [doze mode documentation](http://developer.android.com/training/monitoring-device-state/doze-standby.html)
+is not clear if the [Android VPN service](http://developer.android.com/reference/android/net/VpnService.html) will be affected.
+
+To be sure, you can disable battery optimizations for NetGuard manually like this:
+
+```
+Android settings > Battery > three dot menu > Battery optimizations > Dropdown > All apps > NetGuard > Don't optimize > Done
+```
+
+The procedure to accomplish this can vary between devices.
+
+Disabling doze mode for NetGuard cannot be done from within NetGuard
+because, according to Google, NetGuard is [not an application type allowed to do this](http://developer.android.com/training/monitoring-device-state/doze-standby.html#whitelisting-cases).
+
+
+**(22) Can I tether (use the Android hotspot) / use Wi-Fi calling while using NetGuard?**
+
+Yes, but you'll need to enable subnet routing and tethering in the NetGuard network settings.
+Whether or not it works depends on your Android version
+because some Android versions have a bug preventing tethering and the VPN service working together.
+
+Some devices hibernate Wi-Fi, preventing tethering from working when the screen is off.
+This behavior can be disabled in the Android enhanced/advanced Wi-Fi settings.
+
+
+**(24) Can you remove the notification from the status bar?**
+
+Android can kill background services at any time.
+This can only be prevented by turning a background service into a foreground service.
+Android requires an ongoing notification for all foreground services
+to make you aware of potential battery usage (see [question 4](#user-content-faq4)).
+So, the notification cannot be removed without causing instability.
+However, the notification is being marked as low priority,
+which should result in moving it to the bottom of the list.
+
+The key icon and/or the VPN running notification,
+which is shown by Android and not by NetGuard, unfortunately, cannot be removed.
+The [Google documentation](http://developer.android.com/reference/android/net/VpnService.html) states:
+*"A system-managed notification is shown during the lifetime of a VPN connection"*.
+
+Android 8 Oreo and later display a notification "*... running in the background*" listing all apps running in the background.
+You can't disable this notification, but you can remove the icon from the status bar like this:
+
+* Open Settings > Apps & notifications > App info
+* Open settings (three dots); Select "Show system"
+* Select "Android System"
+* Select "App notifications"
+* Select "Apps running in background"
+* Select "Importance" and select "Low"
+
+
+**(25) Can you add a 'Select All' function?**
+
+There is no need for a 'Select All' function
+because you can switch from block (blacklist) to allow (whitelist) mode using Netguard's settings.
+See also [question 0](#user-content-faq0).
+
+
+**(27) How do I read the blocked traffic log?**
+
+The columns have the following meanings:
+
+1. Time (tap on a log entry to see the date)
+1. Application icon (tap on a log entry to see the application name)
+1. Application UID
+1. Wi-Fi / mobile connection, green=allowed, red=blocked
+1. Interactive state (screen on or off)
+1. Protocol (see below) and packet flags (see below)
+1. Source and destination port (tap on a log entry to lookup a destination port)
+1. Source and destination IPv4 or IPv6 address (tap on a log entry to lookup a destination IP address)
+1. Organization name owning the IP address (needs to be enabled via the menu)
+
+Protocols:
+
+* HOPO ([IPv6 Hop-by-Hop Option](https://en.m.wikipedia.org/wiki/IPv6_packet#Hop-by-hop_options_and_destination_options))
+* ICMP
+* IGMP
+* ESP (IPSec)
+* TCP
+* UDP
+* Number = one of the protocols in [this list](https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers)
+* 4 = IPv4
+* 6 = IPv6
+
+Packet flags:
+
+* S = SYN
+* A = ACK
+* P = PSH
+* F = FIN
+* R = RST
+
+For a detailed explanation see [here](https://en.wikipedia.org/wiki/Transmission_Control_Protocol).
+
+Only TCP, UDP, and ICMP ping traffic can be routed through the Android VPN service.
+All other traffic will be dropped and will be shown as blocked in the global traffic log.
+This is almost never a problem on an Android device.
+
+
+**(28) Why is Google connectivity services allowed internet access by default?**
+
+The Google connectivity services system application checks if the current network is really connected to the internet.
+This is probably accomplished by briefly connecting to some Google server.
+
+If this is not the case, there will be an '!' in the Wi-Fi or mobile icon in the system status bar.
+
+Recent Android versions seem not to switch connectivity from mobile to Wi-Fi when the Wi-Fi network is not really connected,
+even though there is a connection to the Wi-Fi network (or the other way around). On Android 6.0 and later you might get a notification asking you if you want to keep this connection on or not.
+To prevent a bad user experience, NetGuard includes a predefined rule to default allow the Google connectivity services.
+
+You can find all predefined rules [here](https://github.com/M66B/NetGuard/blob/master/app/src/main/res/xml/predefined.xml).
+
+You can override predefined rules.
+
+
+**(29) Why do I get 'The item you requested is not available for purchase'?**
+
+You can only purchase pro features when you have installed NetGuard from the Google Play store.
+
+
+**(30) Can I also run AFWall+ on the same device?**
+
+Unless you are just testing NetGuard, there is no current reason to use them both, since they cover the same function (firewall),
+although with different base needs (AFWall+ needs a rooted device) and ways of doing their thing (AFWall+ uses iptables whereas NetGuard uses a VPN).
+
+Also you need to keep per application access rules _always_ in sync between AFWall+ and NetGuard,
+else the application will not be able to access the network,
+hence bringing another level of complexity when setting and assuring everything work as expected.
+
+Some pointers on how to set up AFWall+ to be used simultaneously with NetGuard:
+* if not using filtering in NetGuard, applications _need_ direct internet access (Wi-Fi and/or mobile) in AFWall+
+* if using filtering, NetGuard will _need_ internet access (Wi-Fi and/or mobile) in AFWall+
+* if using filtering, when you un/reinstall NetGuard, remember to re-allow NetGuard in AFWall+
+* if using filtering, applications _need_ VPN internet access (check the box to show that option in AFWall+ settings)
+
+This question was community contributed. There is no support on using NetGuard and AFWall+ together.
+
+
+**(31) Why can some applications be configured as a group only?**
+
+For many purposes, including network access, Android groups applications on UID and not on package/application name.
+Especially system applications often have the same UID, despite having a different package and application name; these are set up like this by the ROM manufacturer at build time.
+These applications can only be allowed/blocked access to the internet as a group.
+
+
+**(32) Why is the battery/network usage of NetGuard so high?**
+
+This is because Android counts battery and network usage which is normally counted for other applications
+against NetGuard in IP filtering mode. The total battery usage is slightly higher when IP filtering mode is enabled.
+IP filtering mode is always enabled on Android versions prior to 5.0, and optionally enabled on later Android versions.
+
+
+**(33) Can you add profiles?**
+
+Profiles are inconvenient because they need to be operated manually.
+Conditions like '*When screen is on*' are, on the other hand, convenient because they work automatically.
+Therefore profiles will not be added, but you are welcome to propose new conditions;
+however, they need to be generally usable to be included.
+
+As a workaround you can use the export/import function to apply specific settings in specific circumstances.
+Alternatively, you can use lockdown mode as a profile.
+
+
+**(34) Can you add a condition 'when on foreground' or 'when active'?**
+
+Recent Android versions do not allow an application to query if other applications are in the foreground/background or active/inactive
+without holding an [additional privacy violating permission](https://developer.android.com/reference/android/Manifest.permission.html#PACKAGE_USAGE_STATS)
+and at the expense of extra battery usage (because periodic polling is required).
+As a result, this cannot be added without significant disadvantages, like [this one](http://www.xda-developers.com/working-as-intended-an-exploration-into-androids-accessibility-lag/).
+You can use the condition '*when screen is on*' instead.
+
+
+**(35) Why does the VPN not start?**
+
+NetGuard "asks" Android to start the local VPN service,
+but some Android versions contain a bug which prevents the VPN from starting (automatically).
+Sometimes this is caused by updating NetGuard.
+Unfortunately this cannot be fixed by NetGuard.
+You can try to restart your device and/or revoke the VPN permissions from NetGuard using the Android settings.
+Sometimes it helps to uninstall and install NetGuard again (be sure to export your settings first!).
+
+
+**(36) Can you add PIN or password protection?**
+
+Since turning off the VPN service using the Android settings cannot be prevented,
+there is little use in adding PIN or password protection.
+
+
+**(37) Why are the pro features so expensive?**
+
+The right question is "*why are there so many taxes and fees*":
+
+* VAT: 25% (depending on your country)
+* Google fee: 30%
+* Income tax: 50%
+
+So, what is left for the developer is just a fraction of what you pay.
+
+Despite NetGuard being *really* a lot of work, only some of the convenience and advanced features need to be purchased,
+which means that NetGuard is basically free to use
+and that you don't need to pay anything to reduce your data usage, increase battery life, and increase your privacy.
+
+Also note that most free applications will appear not to be sustainable in the end, whereas NetGuard is properly maintained and supported,
+and that free applications may have a catch, like sending privacy sensitive information to the internet.
+
+See [here](http://forum.xda-developers.com/showpost.php?p=67892427&postcount=3030) for some more information.
+
+
+**(38) Why did NetGuard stop running?**
+
+First of all, please make sure you disabled battery optimizations for NetGuard in the Android settings.
+
+On most devices, NetGuard will keep running in the background with its foreground service.
+On some devices (in particular some Samsung models), where there are lots of applications competing for memory, Android may still stop NetGuard as a last resort.
+Some Android versions, in particular of Huawei (see [here](https://www.forbes.com/sites/bensin/2016/07/04/push-notifications-not-coming-through-to-your-huawei-phone-heres-how-to-fix-it/) for a fix) or Xiaomi (see [here](https://www.forbes.com/sites/bensin/2016/11/17/how-to-fix-push-notifications-on-xiaomis-miui-8-for-real/) for a fix) stop apps and services too aggressively.
+Unfortunately this cannot be fixed by NetGuard, and can be considered a shortcoming of the device and/or as a bug in Android.
+As a matter of fact lots of apps suffer from this, see the website [Don't kill my app!](https://dontkillmyapp.com/) for more information and solutions.
+You can workaround this problem by enabling the watchdog in the NetGuard advanced options to check every 10-15 minutes.
+
+
+**(39) How does a VPN based firewall differ from a iptables based firewall?**
+
+See this [Stack Exchange question](http://android.stackexchange.com/questions/152087/any-security-difference-between-root-based-firewall-afwall-and-non-root-based).
+
+
+**(40) Can you add schedules?**
+
+Besides not being trivial to add, schedules - in my opinion - are not a good idea, since time is not a good rule condition.
+A rule condition like *When screen is on* is a better and more straightforward condition.
+Therefore schedules will not be added, but you are welcome to propose other new conditions.
+
+
+**(41) Can you add wildcards / address/port ranges?**
+
+Wildcards to allow/block addresses and address/port ranges would have a significant performance and usability impact and therefore will not be added.
+Wildcards rules and address/port ranges would need to be checked for each and every connection attempt.
+Since NetGuard blocks, unlike any other no-root firewall, domain names instead of IP addresses there is hardly a need for wildcards.
+
+
+**(42) Why is permission ... needed?**
+
+* INTERNET ('*Full network access*'): to forward allowed (filtered) traffic to the internet
+* ACCESS_NETWORK_STATE ('*View network connections*'): to check if the device is connected to the internet through Wi-Fi
+* READ_PHONE_STATE ('*Device ID & call information*'): to detect mobile network changes, see [here](http://forum.xda-developers.com/showpost.php?p=64107371&postcount=489) for more details
+* ACCESS_WIFI_STATE ('*Wi-Fi connection information*'): to detect Wi-Fi network changes
+* RECEIVE_BOOT_COMPLETED ('*Run at startup*'): to start the firewall when booting the device
+* WAKE_LOCK ('*Prevent device from sleeping*'): to reliably reload rules in the background on connectivity changes
+* VIBRATE: to provide vibration feedback on widget tap
+* FOREGROUND_SERVICE ('foreground service'): to run a foreground service on Android 9 Pie and later
+* QUERY_ALL_PACKAGES: to list all apps on Android 11 and later
+* BILLING: to use in-app billing
+
+
+**(43) I get 'This app is causing your device to run slowly'**
+
+This message is displayed by the *Smart Manager*,
+but actually it is the 'Smart' Manager application itself which is causing delays and lags.
+Some links:
+
+* [Smart Manager complaining about LastPass](https://www.reddit.com/r/GalaxyS6/comments/3htu2y/smart_manager_cmoplaining_about_lastpass/)
+* [Disable Smart Manager?](http://forums.androidcentral.com/samsung-galaxy-s4/595483-disable-smart-manager.html)
+
+
+**(44) I don't get notifications on access**
+
+To prevent a high number of status bar notifications, notify on access is done only once per domain name per application.
+Access to domain names shown in the application access log (drill down in the NetGuard application settings) will not be notified again,
+even if you just enabled notify on access.
+To get notified for all domain names again, you can clear the application access log using the trashcan icon.
+If you want to clear all applications logs, you can export and import your settings.
+
+Another reason why you don't get notifications could be an applied "Power Saving Mode" for example on Samsung devices. Even if you do not restrict CPU frequency in this mode.
+
+
+**(45) Does NetGuard handle incoming connections?**
+
+The Android VPN service handles outgoing connections only (from applications to the internet), so incoming connections are normally left alone.
+
+If you want to run a server application on Android, then be aware that using port numbers below 1024 require root permissions
+and that some Android versions contain routing bugs, causing inbound traffic incorrectly being routed into the VPN.
+
+
+**(46) Can I get a refund?**
+
+If a purchased pro feature doesn't work [as described](https://www.netguard.me/)
+and this isn't caused by a problem in the free features
+and I cannot fix the problem in a timely manner, you can get a refund.
+In all other cases there is no refund possible.
+In no circumstances there can be a refund for any problem related to the free features,
+since there wasn't paid anything for them and because they can be evaluated without any limitation.
+I take my responsibility as seller to deliver what has been promised
+and I expect that you take responsibility for informing yourself of what you are buying.
+
+
+**(48) Why are some domain names blocked while they are set to be allowed?**
+
+NetGuard blocks traffic based on the IP addresses an application is trying to connect to.
+If more than one domain name is on the same IP, they cannot be distinguished.
+If you set different rules for 2 domains which resolve to the same IP, both will be blocked.
+
+Thanks @[pulser](https://github.com/pulser/)
+
+Another potential problem is that Android doesn't honor the DNS TTL value and applies its own caching rules.
+This could result in NetGuard too early or too late purging a DNS record from its own cache,
+resulting in not recognizing an IP address or recognizing a wrong IP address.
+You can try to workaround this by changing the DNS TTL value setting of NetGuard.
+This value is used as a minimum DNS TTL value in an attempt to mimick the behavior of Android.
+
+NetGuard will also block traffic while restarting the Android VPN service to apply new rules,
+for example when connectivity changes or when the screen is turned on or off.
+
+
+**(49) Does NetGuard encrypt my internet traffic / hide my IP address?**
+
+NetGuard is a firewall application that filters internet traffic on your device (see also [this question](#user-content-faq6)),
+so it is not meant to - and does not - encrypt your internet traffic or hide your IP address.
+
+
+**(50) Will NetGuard automatically start on boot?**
+
+Yes, NetGuard will automatically be started on boot if you powered off your device with NetGuard enabled and NetGuard is not installed on external storage.
+
+Some devices, for example OnePlus and Mi devices, can prevent certain apps from auto-starting after reboot.
+This can be disabled in the Android settings.
+
+
+**(51) Why does NetGuard block all internet traffic?!**
+
+Make sure you have put NetGuard on the doze exception list (Android 6 Marshmallow or later)
+and that Android allows NetGuard to use the internet in the background (see also [this question](#user-content-faq21)).
+
+Make sure you are not running NetGuard in allow (whitelist) mode (check the NetGuard default settings).
+
+Make sure you didn't enable the Always-On VPN sub option '*Block connections without VPN*' (Android 8 Oreo or later).
+This will block resolving domain names too (is it a bug or feature?).
+
+Some internet providers block all DNS requests except via their own DNS servers.
+So, if you configured custom DNS servers, try to undo this.
+
+Some Android versions, including LineageOS and /e/ for some devices, contain a bug resulting in all internet traffic being blocked.
+Mostly, you can workaround this bug by enabling filtering in NetGuard's *Advanced options*.
+If this doesn't solve the issue, the problem can unfortunately not be fixed or worked around by NetGuard.
+Please [see here](https://forum.xda-developers.com/t/app-6-0-netguard-no-root-firewall.3233012/post-84457527) for a fix.
+
+
+**(52) What is lockdown mode?**
+
+In lockdown mode, all traffic for all applictions will be blocked,
+except for applications with the condition *'Allow in lockdown mode'* enabled.
+You can use this mode to limit battery usage or network usage,
+for example, when your battery is almost empty or when your data allotment is almost exhausted.
+
+Note that Lockdown mode applies only if the corresponding option is also set in "Network options"
+(one for Wi-Fi mode, one for Mobile data), allowing to have lockdown in only one of the two network modes
+and not in the other (eg. Lock down if mobile data are active, but not if Wi-Fi is currently used).
+
+Note also that system applications will only be blocked in this mode
+when managing system applications is enabled in the advanced settings.
+
+You can enable/disable lockdown mode in the main menu, using a widget, or using a settings tile (Android 7 Nougat or later).
+
+
+**(53) The translation in my language is missing / incorrect / incomplete**
+
+You can contribute translations [here](https://crowdin.com/project/netguard) (registration is free).
+If your language is missing, please contact me to have it added.
+
+
+**(54) How to tunnel all TCP connections through the Tor network?**
+
+Tor with NetGuard is only supported in the [XDA NetGuard forum](http://forum.xda-developers.com/showthread.php?t=3233012).
+There is no personal support on Tor with NetGuard, because I don't use Tor myself.
+
+First, install [Orbot](market://details?id=org.torproject.android), the Android client for Tor,
+run it, press _Start_, while it connects open its _Settings_ and make sure it's setup to auto-start
+on device start.
+
+In NetGuard's _Network options_ enable _Subnet routing_ and in _Advanced options_ toggle on
+_Use SOCKS5 proxy_ with address 127.0.0.1 and port as 9050 (this is the default port, if you changed
+this in Orbot make the adjustment here also).
+
+This should be enough, if testing fails (eg. no connection at all) you can open the app details
+for Orbot, uncheck _Apply rules and conditions_ and retry.
+
+How to test: open Firefox (or another non-proxy enabled browser) to the address https://ipleak.net/
+and you should see a different IP address from your regular one, and below in the _Tor Exit Node_
+field something else besides _Unknown_.
+
+**Be aware** that all the other Tor caveats (https://www.torproject.org/docs/faq.html.en) still apply,
+like having the Tor network unreacheable, your activity actively monitored/targeted in your country,
+online services (eg. Gmail, Google Play store) failing to login or being forced to solve endless capchas
+when accessing sites that use Cloudflare's CDN services.
+
+
+**(55) Why does NetGuard connect to Amazon / ipinfo.io / 216.239.34.21?**
+
+NetGuard connects to Amazon / [ipinfo.io](https://ipinfo.io/) to show the names and organizations for IP addresses.
+If you don't want this, just disable showing names and organizations using the three dot menu in the global log view.
+
+
+**(56) Why does NetGuard allow all internet traffic?!**
+
+NetGuard can block each and every application, even system applications and components.
+
+NetGuard, by default, allows all traffic to prevent hard to find problems. You need to selectively block traffic yourself by tapping on the mobile or Wi-Fi icons.
+
+Be aware that NetGuard will allow traffic to an application when the screen is on and the condition *'when screen on'* is enabled.
+
+
+**(57) Why does NetGuard use so much data?**
+
+Basically, NetGuard doesn't use data itself.
+However, many Android versions incorrectly account data of other applications flowing through NetGuard to NetGuard instead of to the applications.
+The data usage of other applications will be zero with NetGuard enabled in this case.
+
+The total data usage of your device will be the same with and without NetGuard.
+
+
+**(58) Why does loading the application list take a long time?**
+
+The application list is provided by Android, so the loading speed depends mostly on the power of your device and on the efficiency of your Android version.
+For example shortage of memory could lead to increased loading times, because memory needs to be freed, for example by pausing other applications.
+
+In some circumstances, restricting system apps and system components is known to cause the application list to load slowly or not at all. The exact circumstances are unknown.
+
+
+**(59) Can you help me restore my purchase?**
+
+Google manages all purchases, so as a developer I have no control over purchases.
+So, the only thing I can do, is give some advice:
+
+* Make sure you have an active internet connection
+* Make sure you didn't block Google Play store / Play services
+* Make sure you are logged in with the right Google account and that there is nothing wrong with your Google account
+* Make sure you installed NetGuard via the right Google account if you configured multiple Google accounts on your device
+* Open the Play store app and wait at least a minute to give it time to synchronize with the Google servers
+* Open NetGuard and navigate to the pro features screen; NetGuard will check the purchases again
+
+You can also try to clear the cache of the Play store app via the Android apps settings.
+
+Note that:
+
+* Purchases are stored in the Google cloud and cannot get lost
+* There is no time limit on purchases, so they cannot expire
+* Google does not expose details (name, e-mail, etc) about buyers to developers
+* An app like NetGuard cannot select which Google account to use
+* It may take a while until the Play store app has synchronized a purchase to another device
+* Play Store purchases cannot be used without the Play Store, which is also not allowed by Play Store rules
+
+If you cannot solve the problem with the purchase, you will have to contact Google about it.
+
+
+**(60) Why does IP (Wi-Fi) calling/SMS/MMS not work?**
+
+Please see the [compatibility section](https://github.com/M66B/NetGuard/#compatibility) about this
+(you might need to request the desktop version to see this section if you are using a mobile device).
+
+
+**(61) Help, NetGuard crashed!**
+
+NetGuard rarely crashes ("unexpectedly stopped"), but if it crashed (which is something different than being stopped by Android, see [this FAQ](#user-content-faq38)),
+then it is mostly caused by bugs in your Android version
+(either in the [Android VPN service](https://developer.android.com/reference/android/net/VpnService.html) implementation or in the [Android Linux kernel](https://developer.android.com/guide/platform/index.html#linux-kernel)).
+I am happy to check what the cause of a crash is and I will fix it whenever possible, but I need a logcat captured from your PC with the crash log for this.
+Since logcats are mostly quite large, I will need the exact time of the crash as well.
+If you don't know how to capture a logcat from your PC, please use your favorite search engine to find one of the numerous guides.
+
+
+**(62) How can I solve 'There was a problem parsing the package' ?**
+
+Likely causes are that the downloaded APK file is damaged (which could be caused by a virus scanner)
+or that you are trying to install NetGuard on a not supported Android version.
+
+
+**(63) Why is all DNS traffic allowed?**
+
+NetGuard blocks unlike any other Android firewall on real domain names.
+For this a list of domain names and IP address needs to be built.
+For this purpose, NetGuard allows all DNS traffic, even if the domain name is listed in the hosts file.
+However, this doesn't mean traffic to the resolved IP address is allowed.
+
+If you don't trust the system (Google's) or your provider's DNS servers, you can set alternative DNS servers in the advanced settings.
+Be sure to enter and confirm the addresses and to set two DNS server addresses.
+If you enter just one DNS server address, it will be used in addition to the default DNS server addresses.
+
+
+**(64) Can you add DNS over TLS/HTTP?**
+
+If you mean to intercept [DNS over HTTP](https://en.wikipedia.org/wiki/DNS_over_HTTPS) (DoH)
+or [DNS over TLS](https://en.wikipedia.org/wiki/DNS_over_TLS) (DoT) requests to resolve domain names,
+this is not possible because DoH/DoT traffic is encrypted, which is the whole point of DoH/DoT.
+
+Please [see here](https://github.com/Ch4t4r/Nebulo/blob/master/docs/NONVPNMODE.md) about how you can use DoH/DoT with NetGuard anyway.
+
+
+
+
+**(65) Why can NetGuard not block itself?**
+
+First of all, if NetGuard could block itself, you should trust that NetGuard really blocks itself,
+which is basically the same as trusting that NetGuard doesn't connect to the internet when not needed.
+
+Note that NetGuard needs to connect to the internet to forward traffic of other apps to the internet and to lookup information on IP addresses,
+see also [this FAQ](#user-content-faq55).
+
+NetGuard could block itself in older versions,
+but this required calling [VpnService.protect](https://developer.android.com/reference/android/net/VpnService.html#protect(int)) for each and every connection.
+Since there are lots of connections of lots of apps in a typical Android environment,
+this resulted in wasting battery power and in crashes on some Android versions with bugs in this function.
+
+So, because blocking NetGuard with itself didn't added anything useful
+and to save on battery power and to prevent crashes blocking NetGuard with itself was removed.
+
+
+
+
+**(66) Why is a blocked app still accessing the internet?**
+
+Blocked apps cannot access the internet. There are no exceptions to this.
+All app and system traffic flows through the [Android VPN service](https://developer.android.com/guide/topics/connectivity/vpn),
+which is a *must* for companies with high security requirements.
+This also means that all apps will be treated in the same way
+and that the global access log (*Show log* in the three-dots overflow menu) will show all traffic.
+
+However:
+
+* Apps can show locally cached content
+* Incoming (push) messages are received by the system component Google Play services and not apps, especially when the app is in the background or when the screen is turned off
+* Similarly, advertisements are mostly received by the system component Google Play services
+* Downloads are often performed by the download manager and not apps
+
+If you like to block Google Play services or the download manager, you'll need to enable managing system apps in the advanced settings.
+
+If you like to make sure that push messages will always be received, you can disable *Apply rules and conditions* for Google Play services.
+
+To be clear: in most cases **you cannot block ads by blocking apps**.
+However, you can block ads for all apps with NetGuard, please see [here](https://github.com/M66B/NetGuard/blob/master/ADBLOCKING.md) about how to.
+
+
+
+
+**(67) Who is 'nobody'?**
+
+["nobody" is the conventional name of a user account](https://en.wikipedia.org/wiki/Nobody_(username))
+which owns no files, is in no privileged groups, and has no abilities except those which every other user has.
+
+
+
+**NetGuard is supported for phones and tablets only, so not for other device types like televisions or vehicles.**
+
+**If you didn't find the answer to your question, you can ask your questions [in this forum](http://forum.xda-developers.com/showthread.php?t=3233012) or contact me by using [this contact form](https://contact.faircode.eu/)**.
diff --git a/NetGuard/FUNDING.yml b/NetGuard/FUNDING.yml
new file mode 100644
index 0000000..6fea02d
--- /dev/null
+++ b/NetGuard/FUNDING.yml
@@ -0,0 +1 @@
+github: [M66B]
diff --git a/NetGuard/LICENSE b/NetGuard/LICENSE
new file mode 100644
index 0000000..733c072
--- /dev/null
+++ b/NetGuard/LICENSE
@@ -0,0 +1,675 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ {one line to give the program's name and a brief idea of what it does.}
+ Copyright (C) {year} {name of author}
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ {project} Copyright (C) {year} {fullname}
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+ .
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
+
diff --git a/NetGuard/README.md b/NetGuard/README.md
new file mode 100644
index 0000000..210b3e7
--- /dev/null
+++ b/NetGuard/README.md
@@ -0,0 +1,411 @@
+# NetGuard
+
+# Edits in NetGuard Code
+The NetGuard code has been taken from https://github.com/M66B/NetGuard
+The compilation of the code was problematic and the problem was solved by modifiying the following lines of code in app --> Gradle Scripts --> build.gradle (Module :app)
+
+Add the following lines:
+
+ storeFile file("my.keystore")
+ storePassword "store_password"
+ keyAlias "my_key_alias"
+ keyPassword "key_password"
+
+and comment out the following lines:
+
+ // def keystorePropertiesFile = rootProject.file("keystore.properties")
+ // def keystoreProperties = new Properties()
+ // keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
+
+ // storeFile file(keystoreProperties['storeFile'])
+ // storePassword keystoreProperties['storePassword']
+ // keyAlias keystoreProperties['keyAlias']
+ // keyPassword keystoreProperties['keyPassword']
+
+# The readme file from this point onwards is the original readme file.
+*NetGuard* provides simple and advanced ways to block access to the internet - no root required.
+Applications and addresses can individually be allowed or denied access to your Wi-Fi and/or mobile connection.
+
+
+
+**WARNING: there is an app in the Samsung Galaxy app store "*Play Music - MP3 Music player*"
+with the same package name as NetGuard, which will be installed as update without your confirmation.
+This app is probably malicious and was reported to Samsung on December 8, 2021.**
+
+
+
+Blocking access to the internet can help:
+
+* reduce your data usage
+* save your battery
+* increase your privacy
+
+NetGuard is the first free and open source no-root firewall for Android.
+
+Features:
+
+* Simple to use
+* No root required
+* 100% open source
+* No calling home
+* No tracking or analytics
+* Actively developed and supported
+* Android 5.1 and later supported
+* IPv4/IPv6 TCP/UDP supported
+* Tethering supported
+* Optionally allow when screen on
+* Optionally block when roaming
+* Optionally block system applications
+* Optionally forward ports, also to external addresses (not available if installed from the Play store)
+* Optionally notify when an application accesses the internet
+* Optionally record network usage per application per address
+* Optionally [block ads using a hosts file](https://github.com/M66B/NetGuard/blob/master/ADBLOCKING.md) (not available if installed from the Play store)
+* Material design theme with light and dark theme
+
+PRO features:
+
+* Log all outgoing traffic; search and filter access attempts; export PCAP files to analyze traffic
+* Allow/block individual addresses per application
+* New application notifications; configure NetGuard directly from the notification
+* Display network speed graph in a status bar notification
+* Select from five additional themes in both light and dark version
+
+There is no other no-root firewall offering all these features.
+
+Requirements:
+
+* Android 5.1 or later
+* A [compatible device](#compatibility)
+
+Downloads:
+
+* [GitHub](https://github.com/M66B/NetGuard/releases)
+* [Google Play](https://play.google.com/store/apps/details?id=eu.faircode.netguard)
+
+Certificate fingerprints:
+
+* MD5: B6:4A:E8:08:1C:3C:9C:19:D6:9E:29:00:46:89:DA:73
+* SHA1: EF:46:F8:13:D2:C8:A0:64:D7:2C:93:6B:9B:96:D1:CC:CC:98:93:78
+* SHA256: E4:A2:60:A2:DC:E7:B7:AF:23:EE:91:9C:48:9E:15:FD:01:02:B9:3F:9E:7C:9D:82:B0:9C:0B:39:50:00:E4:D4
+
+Usage:
+
+* Enable the firewall using the switch in the action bar
+* Allow/deny Wi-Fi/mobile internet access using the icons along the right side of the application list
+
+You can use the settings menu to change from blacklist mode (allow all in *Settings* but block unwanted applications in list) to whitelist mode (block all in *Settings* but allow favorite applications in list).
+
+* Red/orange/yellow/amber = internet access denied
+* Teal/blue/purple/grey = internet access allowed
+
+
+
+
+
+
+For more screenshots, see [here](https://github.com/M66B/NetGuard/tree/master/screenshots).
+
+Compatibility
+-------------
+
+The only way to build a no-root firewall on Android is to use the Android VPN service.
+Android doesn't allow chaining of VPN services, so you cannot use NetGuard together with other VPN based applications.
+See also [this FAQ](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq2).
+
+NetGuard can be used on rooted devices too and even offers more features than most root firewalls.
+
+Some older Android versions, especially Samsung's Android versions, have a buggy VPN implementation,
+which results in Android refusing to start the VPN service in certain circumstances,
+like when there is no internet connectivity yet (when starting up your device)
+or when incorrectly requiring manual approval of the VPN service again (when starting up your device).
+NetGuard will try to workaround this and remove the error message when it succeeds, else you are out of luck.
+
+Some LineageOS versions have a broken Android VPN implementation, causing all traffic to be blocked,
+please see [this FAQ](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq51) for more information.
+
+NetGuard is not supported for apps installed in a [work profile](https://developer.android.com/work/managed-profiles),
+or in a [Secure Folder](https://www.samsung.com/uk/support/mobile-devices/what-is-the-secure-folder-and-how-do-i-use-it/) (Samsung),
+or as second instance (MIUI), or as Parallel app (OnePlus), or as Xiaomi dual app
+because the Android VPN service too often does not work correctly in this situation, which can't be fixed by NetGuard.
+
+Filtering mode cannot be used on [CopperheadOS](https://copperhead.co/android/).
+
+NetGuard will not work or crash when the package *com.android.vpndialogs* has been removed or otherwise is unavailable.
+Removing this package is possible with root permissions only.
+If you disable this package, you can enable it with this command again:
+
+```
+adb shell pm enable --user 0 com.android.vpndialogs
+```
+
+NetGuard is supported for phones and tablets only, so not for other device types like on a television or in a car.
+
+Android does not allow incoming connections (not the same as incoming traffic) and the Android VPN service has no support for this either.
+Therefore managing incoming connections for servers running on your device is not supported.
+
+Wi-Fi or IP calling will not work if your provider uses [IPsec](https://en.wikipedia.org/wiki/IPsec) to encrypt your phone calls, SMS messages and/or MMS messages,
+unless there was made an exception in NetGuard for your provider (currently for T-Mobile and Verizon).
+I am happy to add exceptions for other providers, but I need the [MCC](https://en.wikipedia.org/wiki/Mobile_country_code) codes, [MNC](https://en.wikipedia.org/wiki/MNC) codes and [IP address](https://en.wikipedia.org/wiki/IP_address) ranges your provider is using.
+As an alternative you can enable the option '*Disable on call*', which is available since version 2.113.
+
+
+
+Frequently Asked Questions (FAQ)
+--------------------------------
+
+
+[**(0) How do I use NetGuard?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq0)
+
+
+[**(1) Can NetGuard completely protect my privacy?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq1)
+
+
+[**(2) Can I use another VPN application while using NetGuard?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq2)
+
+
+[**(3) Can I use NetGuard on any Android version?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq3)
+
+
+[**(4) Will NetGuard use extra battery power?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq4)
+
+
+[**(6) Will NetGuard send my internet traffic to an external (VPN) server?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq6)
+
+
+[**(7) Why are applications without internet permission shown?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq7)
+
+
+[**(8) What do I need to enable for the Google Play™ store app to work?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq8)
+
+
+[**(9) Why is the VPN service being restarted?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq9)
+
+
+[**(10) Will you provide a Tasker plug-in?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq10)
+
+
+[**(13) How can I remove the ongoing NetGuard entry in the notification screen?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq13)
+
+
+[**(14) Why can't I select OK to approve the VPN connection request?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq14)
+
+
+[**(15) Are F-Droid builds supported?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq15)
+
+
+[**(16) Why are some applications shown dimmed?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq16)
+
+
+[**(17) Why is NetGuard using so much memory?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq17)
+
+
+[**(18) Why can't I find NetGuard in the Google Play™ store app?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq18)
+
+
+[**(19) Why does application XYZ still have internet access?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq19)
+
+
+[**(20) Can I Greenify/hibernate NetGuard?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq20)
+
+
+[**(21) Does doze mode affect NetGuard?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq21)
+
+
+[**(22) Can I tether (use the Android hotspot) / use Wi-Fi calling while using NetGuard?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq22)
+
+
+[**(24) Can you remove the notification from the status bar?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq24)
+
+
+[**(25) Can you add a 'select all'?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq25)
+
+
+[**(27) How do I read the blocked traffic log?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq27)
+
+
+[**(28) Why is Google connectivity services allowed internet access by default?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq28)
+
+
+[**(29) Why do I get 'The item you requested is not available for purchase'?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq29)
+
+
+[**(30) Can I also run AFWall+ on the same device?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq30)
+
+
+[**(31) Why can some applications be configured as a group only?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq31)
+
+
+[**(32) Why is the battery/network usage of NetGuard so high**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq32)
+
+
+[**(33) Can you add profiles?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq33)
+
+
+[**(34) Can you add the condition 'when on foreground'?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq34)
+
+
+[**(35) Why does the VPN not start?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq35)
+
+
+[**(36) Can you add PIN or password protection?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq36)
+
+
+[**(37) Why are the pro features so expensive?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq37)
+
+
+[**(38) Why did NetGuard stop running?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq38)
+
+
+[**(39) How does a VPN based firewall differ from a iptables based firewall?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq39)
+
+
+[**(40) Can you add schedules?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq40)
+
+
+[**(41) Can you add wildcards?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq41)
+
+
+[**(42) Why is permission ... needed?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq42)
+
+
+[**(43) I get 'This app is causing your device to run slowly'**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq43)
+
+
+[**(44) I don't get notifications on access**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq44)
+
+
+[**(45) Does NetGuard handle incoming connections?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq45)
+
+
+[**(46) Can I get a refund?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq46)
+
+
+[**(47) Why are there in application advertisements?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq47)
+
+
+[**(48) Why are some domain names blocked while they are set to be allowed?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq48)
+
+
+[**(49) Does NetGuard encrypt my internet traffic / hide my IP address?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq49)
+
+
+[**(50) Will NetGuard automatically start on boot?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq50)
+
+
+[**(51) NetGuard blocks all internet traffic!**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq51)
+
+
+[**(52) What is lockdown mode?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq52)
+
+
+[**(53) The translation in my language is missing / incorrect / incomplete!**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq53)
+
+
+[**(54) How to tunnel all TCP connections through the Tor network?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq54)
+
+
+[**(55) Why does NetGuard connect to Amazon / ipinfo.io?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq55)
+
+
+[**(56) NetGuard allows all internet traffic!**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq56)
+
+
+[**(57) Why does NetGuard use so much data?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq57)
+
+
+[**(58) Why does loading the application list take a long time?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq58)
+
+
+[**(59) Can you help me restore my purchase?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq59)
+
+
+[**(60) Why does IP (Wi-Fi) calling/SMS/MMS not work?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq60)
+
+
+[**(61) Help, NetGuard crashed!**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq61)
+
+
+[**(62) How can I solve 'There was a problem parsing the package' ?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq62)
+
+
+[**(63) Why is all DNS traffic allowed?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq63)
+
+
+[**(64) Can you add DNS over TLS?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq64)
+
+
+[**(65) Why can NetGuard not block itself?**](https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq65)
+
+Support
+-------
+
+For questions, feature requests and bug reports, please [use this XDA-Developers forum thread](http://forum.xda-developers.com/showthread.php?t=3233012).
+
+There is support on the latest version of NetGuard only.
+
+There is no support on things that are not directly related to NetGuard.
+
+There is no support on building and developing things by yourself.
+
+**NetGuard is supported for phones and tablets only, so not for other device types like on a television or in a car.**
+
+Contributing
+------------
+
+*Building*
+
+Building is simple, if you install the right tools:
+
+* [Android Studio](http://developer.android.com/sdk/)
+* [Android NDK](http://developer.android.com/tools/sdk/ndk/)
+
+The native code is built as part of the Android Studio project.
+
+It is expected that you can solve build problems yourself, so there is no support on building.
+If you cannot build yourself, there are prebuilt versions of NetGuard available [here](https://github.com/M66B/NetGuard/releases).
+
+*Translating*
+
+* Translations to other languages are welcomed
+* You can translate online [here](https://crowdin.com/project/netguard/)
+* If your language is not listed, please send a message to marcel(plus)netguard(at)faircode(dot)eu
+* You can see the status of all translations [here](https://crowdin.com/project/netguard).
+
+Please note that by contributing you agree to the license below, including the copyright, without any additional terms or conditions.
+
+Attribution
+-----------
+
+NetGuard uses:
+
+* [Glide](https://bumptech.github.io/glide/)
+* [Android Support Library](https://developer.android.com/tools/support-library/)
+
+License
+-------
+
+[GNU General Public License version 3](http://www.gnu.org/licenses/gpl.txt)
+
+Copyright (c) 2015-2018 Marcel Bokhorst ([M66B](https://contact.faircode.eu/))
+
+All rights reserved
+
+This file is part of NetGuard.
+
+NetGuard 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 discretion) any later version.
+
+NetGuard 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 NetGuard. If not, see [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
+
+Trademarks
+----------
+
+*Android is a trademark of Google Inc. Google Play is a trademark of Google Inc*
diff --git a/NetGuard/app/.gitignore b/NetGuard/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/NetGuard/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/NetGuard/app/CMakeLists.txt b/NetGuard/app/CMakeLists.txt
new file mode 100644
index 0000000..ff27ce0
--- /dev/null
+++ b/NetGuard/app/CMakeLists.txt
@@ -0,0 +1,23 @@
+
+cmake_minimum_required(VERSION 3.4.1)
+
+add_library( netguard
+ SHARED
+ src/main/jni/netguard/netguard.c
+ src/main/jni/netguard/session.c
+ src/main/jni/netguard/ip.c
+ src/main/jni/netguard/tcp.c
+ src/main/jni/netguard/udp.c
+ src/main/jni/netguard/icmp.c
+ src/main/jni/netguard/dns.c
+ src/main/jni/netguard/dhcp.c
+ src/main/jni/netguard/pcap.c
+ src/main/jni/netguard/util.c )
+
+include_directories( src/main/jni/netguard/ )
+
+find_library( log-lib
+ log )
+
+target_link_libraries( netguard
+ ${log-lib} )
diff --git a/NetGuard/app/build.gradle b/NetGuard/app/build.gradle
new file mode 100644
index 0000000..1d20916
--- /dev/null
+++ b/NetGuard/app/build.gradle
@@ -0,0 +1,100 @@
+apply plugin: 'com.android.application'
+
+def keystorePropertiesFile = rootProject.file("keystore.properties")
+def keystoreProperties = new Properties()
+keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
+
+android {
+ compileSdkVersion = 31
+
+ defaultConfig {
+ applicationId = "eu.faircode.netguard"
+ versionName = "2.303"
+ minSdkVersion 22
+ targetSdkVersion 31
+ versionCode = 2022111001
+ archivesBaseName = "NetGuard-v$versionName"
+
+ externalNativeBuild {
+ cmake {
+ cppFlags ""
+ arguments "-DANDROID_PLATFORM=android-22"
+ // https://developer.android.com/ndk/guides/cmake.html
+ }
+ }
+
+ //ndkVersion "21.4.7075529"
+ ndk {
+ // https://developer.android.com/ndk/guides/abis.html#sa
+ abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
+ }
+ }
+ signingConfigs {
+ release {
+ storeFile file(keystoreProperties['storeFile'])
+ storePassword keystoreProperties['storePassword']
+ keyAlias keystoreProperties['keyAlias']
+ keyPassword keystoreProperties['keyPassword']
+ }
+ }
+
+
+ externalNativeBuild {
+ cmake {
+ path "CMakeLists.txt"
+ }
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled = true
+ proguardFiles.add(file('proguard-rules.pro'))
+ signingConfig signingConfigs.release
+ buildConfigField "boolean", "PLAY_STORE_RELEASE", "false"
+ buildConfigField "String", "HOSTS_FILE_URI", "\"https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts\""
+ buildConfigField "String", "GITHUB_LATEST_API", "\"https://api.github.com/repos/M66B/NetGuard/releases/latest\""
+ }
+ play {
+ minifyEnabled = true
+ signingConfig signingConfigs.release
+ proguardFiles.add(file('proguard-rules.pro'))
+ buildConfigField "boolean", "PLAY_STORE_RELEASE", "true"
+ buildConfigField "String", "HOSTS_FILE_URI", "\"\""
+ buildConfigField "String", "GITHUB_LATEST_API", "\"\""
+ }
+ debug {
+ minifyEnabled = true
+ proguardFiles.add(file('proguard-rules.pro'))
+ buildConfigField "boolean", "PLAY_STORE_RELEASE", "false"
+ buildConfigField "String", "HOSTS_FILE_URI", "\"https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts\""
+ buildConfigField "String", "GITHUB_LATEST_API", "\"https://api.github.com/repos/M66B/NetGuard/releases/latest\""
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_7
+ targetCompatibility JavaVersion.VERSION_1_7
+ }
+
+ lint {
+ disable 'MissingTranslation'
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+ // https://developer.android.com/jetpack/androidx/releases/
+ implementation 'androidx.appcompat:appcompat:1.3.1'
+ implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
+ implementation 'androidx.recyclerview:recyclerview:1.2.1'
+ implementation 'androidx.preference:preference:1.1.1'
+ implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
+ annotationProcessor 'androidx.annotation:annotation:1.2.0'
+
+ // https://bumptech.github.io/glide/
+ implementation('com.github.bumptech.glide:glide:4.11.0') {
+ exclude group: "com.android.support"
+ }
+ annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
+}
diff --git a/NetGuard/app/proguard-rules.pro b/NetGuard/app/proguard-rules.pro
new file mode 100644
index 0000000..adf6d1a
--- /dev/null
+++ b/NetGuard/app/proguard-rules.pro
@@ -0,0 +1,62 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /home/marcel/Android/Sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+#Line numbers
+-renamesourcefileattribute SourceFile
+-keepattributes SourceFile,LineNumberTable
+
+#NetGuard
+-keepnames class eu.faircode.netguard.** { *; }
+
+#JNI
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+#JNI callbacks
+-keep class eu.faircode.netguard.Allowed { *; }
+-keep class eu.faircode.netguard.Packet { *; }
+-keep class eu.faircode.netguard.ResourceRecord { *; }
+-keep class eu.faircode.netguard.Usage { *; }
+-keep class eu.faircode.netguard.ServiceSinkhole {
+ void nativeExit(java.lang.String);
+ void nativeError(int, java.lang.String);
+ void logPacket(eu.faircode.netguard.Packet);
+ void dnsResolved(eu.faircode.netguard.ResourceRecord);
+ boolean isDomainBlocked(java.lang.String);
+ int getUidQ(int, int, java.lang.String, int, java.lang.String, int);
+ eu.faircode.netguard.Allowed isAddressAllowed(eu.faircode.netguard.Packet);
+ void accountUsage(eu.faircode.netguard.Usage);
+}
+
+#AndroidX
+-keep class androidx.appcompat.widget.** { *; }
+-keep class androidx.appcompat.app.AppCompatViewInflater { (...); }
+-keepclassmembers class * implements android.os.Parcelable { static ** CREATOR; }
+
+#Glide
+-keep public class * implements com.bumptech.glide.module.GlideModule
+-keep public class * extends com.bumptech.glide.module.AppGlideModule
+-keep enum com.bumptech.glide.** {*;}
+#-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
+# **[] $VALUES;
+# public *;
+#}
+
+#AdMob
+-dontwarn com.google.android.gms.internal.**
diff --git a/NetGuard/app/src/main/AndroidManifest.xml b/NetGuard/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..6682150
--- /dev/null
+++ b/NetGuard/app/src/main/AndroidManifest.xml
@@ -0,0 +1,287 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl b/NetGuard/app/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl
new file mode 100644
index 0000000..2a492f7
--- /dev/null
+++ b/NetGuard/app/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.vending.billing;
+
+import android.os.Bundle;
+
+/**
+ * InAppBillingService is the service that provides in-app billing version 3 and beyond.
+ * This service provides the following features:
+ * 1. Provides a new API to get details of in-app items published for the app including
+ * price, type, title and description.
+ * 2. The purchase flow is synchronous and purchase information is available immediately
+ * after it completes.
+ * 3. Purchase information of in-app purchases is maintained within the Google Play system
+ * till the purchase is consumed.
+ * 4. An API to consume a purchase of an inapp item. All purchases of one-time
+ * in-app items are consumable and thereafter can be purchased again.
+ * 5. An API to get current purchases of the user immediately. This will not contain any
+ * consumed purchases.
+ *
+ * All calls will give a response code with the following possible values
+ * RESULT_OK = 0 - success
+ * RESULT_USER_CANCELED = 1 - user pressed back or canceled a dialog
+ * RESULT_BILLING_UNAVAILABLE = 3 - this billing API version is not supported for the type requested
+ * RESULT_ITEM_UNAVAILABLE = 4 - requested SKU is not available for purchase
+ * RESULT_DEVELOPER_ERROR = 5 - invalid arguments provided to the API
+ * RESULT_ERROR = 6 - Fatal error during the API action
+ * RESULT_ITEM_ALREADY_OWNED = 7 - Failure to purchase since item is already owned
+ * RESULT_ITEM_NOT_OWNED = 8 - Failure to consume since item is not owned
+ */
+interface IInAppBillingService {
+ /**
+ * Checks support for the requested billing API version, package and in-app type.
+ * Minimum API version supported by this interface is 3.
+ * @param apiVersion the billing version which the app is using
+ * @param packageName the package name of the calling app
+ * @param type type of the in-app item being purchased "inapp" for one-time purchases
+ * and "subs" for subscription.
+ * @return RESULT_OK(0) on success, corresponding result code on failures
+ */
+ int isBillingSupported(int apiVersion, String packageName, String type);
+
+ /**
+ * Provides details of a list of SKUs
+ * Given a list of SKUs of a valid type in the skusBundle, this returns a bundle
+ * with a list JSON strings containing the productId, price, title and description.
+ * This API can be called with a maximum of 20 SKUs.
+ * @param apiVersion billing API version that the Third-party is using
+ * @param packageName the package name of the calling app
+ * @param skusBundle bundle containing a StringArrayList of SKUs with key "ITEM_ID_LIST"
+ * @return Bundle containing the following key-value pairs
+ * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
+ * failure as listed above.
+ * "DETAILS_LIST" with a StringArrayList containing purchase information
+ * in JSON format similar to:
+ * '{ "productId" : "exampleSku", "type" : "inapp", "price" : "$5.00",
+ * "title : "Example Title", "description" : "This is an example description" }'
+ */
+ Bundle getSkuDetails(int apiVersion, String packageName, String type, in Bundle skusBundle);
+
+ /**
+ * Returns a pending intent to launch the purchase flow for an in-app item by providing a SKU,
+ * the type, a unique purchase token and an optional developer payload.
+ * @param apiVersion billing API version that the app is using
+ * @param packageName package name of the calling app
+ * @param sku the SKU of the in-app item as published in the developer console
+ * @param type the type of the in-app item ("inapp" for one-time purchases
+ * and "subs" for subscription).
+ * @param developerPayload optional argument to be sent back with the purchase information
+ * @return Bundle containing the following key-value pairs
+ * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
+ * failure as listed above.
+ * "BUY_INTENT" - PendingIntent to start the purchase flow
+ *
+ * The Pending intent should be launched with startIntentSenderForResult. When purchase flow
+ * has completed, the onActivityResult() will give a resultCode of OK or CANCELED.
+ * If the purchase is successful, the result data will contain the following key-value pairs
+ * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
+ * failure as listed above.
+ * "INAPP_PURCHASE_DATA" - String in JSON format similar to
+ * '{"orderId":"12999763169054705758.1371079406387615",
+ * "packageName":"com.example.app",
+ * "productId":"exampleSku",
+ * "purchaseTime":1345678900000,
+ * "purchaseToken" : "122333444455555",
+ * "developerPayload":"example developer payload" }'
+ * "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that
+ * was signed with the private key of the developer
+ * TODO: change this to app-specific keys.
+ */
+ Bundle getBuyIntent(int apiVersion, String packageName, String sku, String type,
+ String developerPayload);
+
+ /**
+ * Returns the current SKUs owned by the user of the type and package name specified along with
+ * purchase information and a signature of the data to be validated.
+ * This will return all SKUs that have been purchased in V3 and managed items purchased using
+ * V1 and V2 that have not been consumed.
+ * @param apiVersion billing API version that the app is using
+ * @param packageName package name of the calling app
+ * @param type the type of the in-app items being requested
+ * ("inapp" for one-time purchases and "subs" for subscription).
+ * @param continuationToken to be set as null for the first call, if the number of owned
+ * skus are too many, a continuationToken is returned in the response bundle.
+ * This method can be called again with the continuation token to get the next set of
+ * owned skus.
+ * @return Bundle containing the following key-value pairs
+ * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
+ * failure as listed above.
+ * "INAPP_PURCHASE_ITEM_LIST" - StringArrayList containing the list of SKUs
+ * "INAPP_PURCHASE_DATA_LIST" - StringArrayList containing the purchase information
+ * "INAPP_DATA_SIGNATURE_LIST"- StringArrayList containing the signatures
+ * of the purchase information
+ * "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the
+ * next set of in-app purchases. Only set if the
+ * user has more owned skus than the current list.
+ */
+ Bundle getPurchases(int apiVersion, String packageName, String type, String continuationToken);
+
+ /**
+ * Consume the last purchase of the given SKU. This will result in this item being removed
+ * from all subsequent responses to getPurchases() and allow re-purchase of this item.
+ * @param apiVersion billing API version that the app is using
+ * @param packageName package name of the calling app
+ * @param purchaseToken token in the purchase information JSON that identifies the purchase
+ * to be consumed
+ * @return 0 if consumption succeeded. Appropriate error values for failures.
+ */
+ int consumePurchase(int apiVersion, String packageName, String purchaseToken);
+}
diff --git a/NetGuard/app/src/main/ic_launcher-web.png b/NetGuard/app/src/main/ic_launcher-web.png
new file mode 100644
index 0000000..68fe670
Binary files /dev/null and b/NetGuard/app/src/main/ic_launcher-web.png differ
diff --git a/NetGuard/app/src/main/ic_launcher_foreground.xcf b/NetGuard/app/src/main/ic_launcher_foreground.xcf
new file mode 100644
index 0000000..342fd91
Binary files /dev/null and b/NetGuard/app/src/main/ic_launcher_foreground.xcf differ
diff --git a/NetGuard/app/src/main/ic_launcher_round-web.png b/NetGuard/app/src/main/ic_launcher_round-web.png
new file mode 100644
index 0000000..8e09478
Binary files /dev/null and b/NetGuard/app/src/main/ic_launcher_round-web.png differ
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityDns.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityDns.java
new file mode 100644
index 0000000..04832cb
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityDns.java
@@ -0,0 +1,256 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.util.Xml;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.widget.ListView;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+public class ActivityDns extends AppCompatActivity {
+ private static final String TAG = "NetGuard.DNS";
+
+ private static final int REQUEST_EXPORT = 1;
+
+ private boolean running;
+ private AdapterDns adapter = null;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ Util.setTheme(this);
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.resolving);
+
+ getSupportActionBar().setTitle(R.string.setting_show_resolved);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ ListView lvDns = findViewById(R.id.lvDns);
+ adapter = new AdapterDns(this, DatabaseHelper.getInstance(this).getDns());
+ lvDns.setAdapter(adapter);
+
+ running = true;
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.dns, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ PackageManager pm = getPackageManager();
+ menu.findItem(R.id.menu_export).setEnabled(getIntentExport().resolveActivity(pm) != null);
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_refresh:
+ refresh();
+ return true;
+
+ case R.id.menu_cleanup:
+ cleanup();
+ return true;
+
+ case R.id.menu_clear:
+ Util.areYouSure(this, R.string.menu_clear, new Util.DoubtListener() {
+ @Override
+ public void onSure() {
+ clear();
+ }
+ });
+ return true;
+
+ case R.id.menu_export:
+ export();
+ return true;
+ }
+ return false;
+ }
+
+ private void refresh() {
+ updateAdapter();
+ }
+
+ private void cleanup() {
+ new AsyncTask() {
+ @Override
+ protected Long doInBackground(Object... objects) {
+ Log.i(TAG, "Cleanup DNS");
+ DatabaseHelper.getInstance(ActivityDns.this).cleanupDns();
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Object result) {
+ ServiceSinkhole.reload("DNS cleanup", ActivityDns.this, false);
+ updateAdapter();
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ private void clear() {
+ new AsyncTask() {
+ @Override
+ protected Long doInBackground(Object... objects) {
+ Log.i(TAG, "Clear DNS");
+ DatabaseHelper.getInstance(ActivityDns.this).clearDns();
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Object result) {
+ ServiceSinkhole.reload("DNS clear", ActivityDns.this, false);
+ updateAdapter();
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ private void export() {
+ startActivityForResult(getIntentExport(), REQUEST_EXPORT);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ Log.i(TAG, "onActivityResult request=" + requestCode + " result=" + requestCode + " ok=" + (resultCode == RESULT_OK));
+ if (requestCode == REQUEST_EXPORT) {
+ if (resultCode == RESULT_OK && data != null)
+ handleExport(data);
+ }
+ }
+
+ private Intent getIntentExport() {
+ Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("*/*"); // text/xml
+ intent.putExtra(Intent.EXTRA_TITLE, "netguard_dns_" + new SimpleDateFormat("yyyyMMdd").format(new Date().getTime()) + ".xml");
+ return intent;
+ }
+
+ private void handleExport(final Intent data) {
+ new AsyncTask() {
+ @Override
+ protected Throwable doInBackground(Object... objects) {
+ OutputStream out = null;
+ try {
+ Uri target = data.getData();
+ Log.i(TAG, "Writing URI=" + target);
+ out = getContentResolver().openOutputStream(target);
+ xmlExport(out);
+ return null;
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ return ex;
+ } finally {
+ if (out != null)
+ try {
+ out.close();
+ } catch (IOException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Throwable ex) {
+ if (running) {
+ if (ex == null)
+ Toast.makeText(ActivityDns.this, R.string.msg_completed, Toast.LENGTH_LONG).show();
+ else
+ Toast.makeText(ActivityDns.this, ex.toString(), Toast.LENGTH_LONG).show();
+ }
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ private void xmlExport(OutputStream out) throws IOException {
+ XmlSerializer serializer = Xml.newSerializer();
+ serializer.setOutput(out, "UTF-8");
+ serializer.startDocument(null, true);
+ serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+ serializer.startTag(null, "netguard");
+
+ DateFormat df = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss Z", Locale.US); // RFC 822
+
+ try (Cursor cursor = DatabaseHelper.getInstance(this).getDns()) {
+ int colTime = cursor.getColumnIndex("time");
+ int colQName = cursor.getColumnIndex("qname");
+ int colAName = cursor.getColumnIndex("aname");
+ int colResource = cursor.getColumnIndex("resource");
+ int colTTL = cursor.getColumnIndex("ttl");
+ while (cursor.moveToNext()) {
+ long time = cursor.getLong(colTime);
+ String qname = cursor.getString(colQName);
+ String aname = cursor.getString(colAName);
+ String resource = cursor.getString(colResource);
+ int ttl = cursor.getInt(colTTL);
+
+ serializer.startTag(null, "dns");
+ serializer.attribute(null, "time", df.format(time));
+ serializer.attribute(null, "qname", qname);
+ serializer.attribute(null, "aname", aname);
+ serializer.attribute(null, "resource", resource);
+ serializer.attribute(null, "ttl", Integer.toString(ttl));
+ serializer.endTag(null, "dns");
+ }
+ }
+
+ serializer.endTag(null, "netguard");
+ serializer.endDocument();
+ serializer.flush();
+ }
+
+ private void updateAdapter() {
+ if (adapter != null)
+ adapter.changeCursor(DatabaseHelper.getInstance(this).getDns());
+ }
+
+ @Override
+ protected void onDestroy() {
+ running = false;
+ adapter = null;
+ super.onDestroy();
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityForwardApproval.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityForwardApproval.java
new file mode 100644
index 0000000..e269fe4
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityForwardApproval.java
@@ -0,0 +1,130 @@
+package eu.faircode.netguard;
+
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import java.net.InetAddress;
+
+public class ActivityForwardApproval extends Activity {
+ private static final String TAG = "NetGuard.Forward";
+ private static final String ACTION_START_PORT_FORWARD = "eu.faircode.netguard.START_PORT_FORWARD";
+ private static final String ACTION_STOP_PORT_FORWARD = "eu.faircode.netguard.STOP_PORT_FORWARD";
+
+ static {
+ try {
+ System.loadLibrary("netguard");
+ } catch (UnsatisfiedLinkError ignored) {
+ System.exit(1);
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.forwardapproval);
+
+ final int protocol = getIntent().getIntExtra("protocol", 0);
+ final int dport = getIntent().getIntExtra("dport", 0);
+ String addr = getIntent().getStringExtra("raddr");
+ final int rport = getIntent().getIntExtra("rport", 0);
+ final int ruid = getIntent().getIntExtra("ruid", 0);
+ final String raddr = (addr == null ? "127.0.0.1" : addr);
+
+ try {
+ InetAddress iraddr = InetAddress.getByName(raddr);
+ if (rport < 1024 && (iraddr.isLoopbackAddress() || iraddr.isAnyLocalAddress()))
+ throw new IllegalArgumentException("Port forwarding to privileged port on local address not possible");
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ finish();
+ }
+
+ String pname;
+ if (protocol == 6)
+ pname = getString(R.string.menu_protocol_tcp);
+ else if (protocol == 17)
+ pname = getString(R.string.menu_protocol_udp);
+ else
+ pname = Integer.toString(protocol);
+
+ TextView tvForward = findViewById(R.id.tvForward);
+ if (ACTION_START_PORT_FORWARD.equals(getIntent().getAction()))
+ tvForward.setText(getString(R.string.msg_start_forward,
+ pname, dport, raddr, rport,
+ TextUtils.join(", ", Util.getApplicationNames(ruid, this))));
+ else
+ tvForward.setText(getString(R.string.msg_stop_forward, pname, dport));
+
+ Button btnOk = findViewById(R.id.btnOk);
+ Button btnCancel = findViewById(R.id.btnCancel);
+
+ btnOk.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (ACTION_START_PORT_FORWARD.equals(getIntent().getAction())) {
+/*
+am start -a eu.faircode.netguard.START_PORT_FORWARD \
+-n eu.faircode.netguard/eu.faircode.netguard.ActivityForwardApproval \
+--ei protocol 17 \
+--ei dport 53 \
+--es raddr 8.8.4.4 \
+--ei rport 53 \
+--ei ruid 9999 \
+--user 0
+*/
+ Log.i(TAG, "Start forwarding protocol " + protocol + " port " + dport + " to " + raddr + "/" + rport + " uid " + ruid);
+ DatabaseHelper dh = DatabaseHelper.getInstance(ActivityForwardApproval.this);
+ dh.deleteForward(protocol, dport);
+ dh.addForward(protocol, dport, raddr, rport, ruid);
+
+ } else if (ACTION_STOP_PORT_FORWARD.equals(getIntent().getAction())) {
+/*
+am start -a eu.faircode.netguard.STOP_PORT_FORWARD \
+-n eu.faircode.netguard/eu.faircode.netguard.ActivityForwardApproval \
+--ei protocol 17 \
+--ei dport 53 \
+--user 0
+*/
+ Log.i(TAG, "Stop forwarding protocol " + protocol + " port " + dport);
+ DatabaseHelper.getInstance(ActivityForwardApproval.this).deleteForward(protocol, dport);
+ }
+
+ ServiceSinkhole.reload("forwarding", ActivityForwardApproval.this, false);
+
+ finish();
+ }
+ });
+
+ btnCancel.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ finish();
+ }
+ });
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityForwarding.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityForwarding.java
new file mode 100644
index 0000000..db515a8
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityForwarding.java
@@ -0,0 +1,251 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.content.DialogInterface;
+import android.database.Cursor;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.PopupMenu;
+import android.widget.ProgressBar;
+import android.widget.Spinner;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+
+import java.net.InetAddress;
+import java.util.List;
+
+public class ActivityForwarding extends AppCompatActivity {
+ private boolean running;
+ private ListView lvForwarding;
+ private AdapterForwarding adapter;
+ private AlertDialog dialog = null;
+
+ private DatabaseHelper.ForwardChangedListener listener = new DatabaseHelper.ForwardChangedListener() {
+ @Override
+ public void onChanged() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (adapter != null)
+ adapter.changeCursor(DatabaseHelper.getInstance(ActivityForwarding.this).getForwarding());
+ }
+ });
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ Util.setTheme(this);
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.forwarding);
+ running = true;
+
+ getSupportActionBar().setTitle(R.string.setting_forwarding);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+
+ lvForwarding = findViewById(R.id.lvForwarding);
+ adapter = new AdapterForwarding(this, DatabaseHelper.getInstance(this).getForwarding());
+ lvForwarding.setAdapter(adapter);
+
+ lvForwarding.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ Cursor cursor = (Cursor) adapter.getItem(position);
+ final int protocol = cursor.getInt(cursor.getColumnIndex("protocol"));
+ final int dport = cursor.getInt(cursor.getColumnIndex("dport"));
+ final String raddr = cursor.getString(cursor.getColumnIndex("raddr"));
+ final int rport = cursor.getInt(cursor.getColumnIndex("rport"));
+
+ PopupMenu popup = new PopupMenu(ActivityForwarding.this, view);
+ popup.inflate(R.menu.forward);
+ popup.getMenu().findItem(R.id.menu_port).setTitle(
+ Util.getProtocolName(protocol, 0, false) + " " +
+ dport + " > " + raddr + "/" + rport);
+
+ popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem menuItem) {
+ if (menuItem.getItemId() == R.id.menu_delete) {
+ DatabaseHelper.getInstance(ActivityForwarding.this).deleteForward(protocol, dport);
+ ServiceSinkhole.reload("forwarding", ActivityForwarding.this, false);
+ adapter = new AdapterForwarding(ActivityForwarding.this,
+ DatabaseHelper.getInstance(ActivityForwarding.this).getForwarding());
+ lvForwarding.setAdapter(adapter);
+ }
+ return false;
+ }
+ });
+
+ popup.show();
+ }
+ });
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ DatabaseHelper.getInstance(this).addForwardChangedListener(listener);
+ if (adapter != null)
+ adapter.changeCursor(DatabaseHelper.getInstance(ActivityForwarding.this).getForwarding());
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ DatabaseHelper.getInstance(this).removeForwardChangedListener(listener);
+ }
+
+ @Override
+ protected void onDestroy() {
+ running = false;
+ adapter = null;
+ if (dialog != null) {
+ dialog.dismiss();
+ dialog = null;
+ }
+ super.onDestroy();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.forwarding, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_add:
+ LayoutInflater inflater = LayoutInflater.from(this);
+ View view = inflater.inflate(R.layout.forwardadd, null, false);
+ final Spinner spProtocol = view.findViewById(R.id.spProtocol);
+ final EditText etDPort = view.findViewById(R.id.etDPort);
+ final EditText etRAddr = view.findViewById(R.id.etRAddr);
+ final EditText etRPort = view.findViewById(R.id.etRPort);
+ final ProgressBar pbRuid = view.findViewById(R.id.pbRUid);
+ final Spinner spRuid = view.findViewById(R.id.spRUid);
+
+ final AsyncTask task = new AsyncTask>() {
+ @Override
+ protected void onPreExecute() {
+ pbRuid.setVisibility(View.VISIBLE);
+ spRuid.setVisibility(View.GONE);
+ }
+
+ @Override
+ protected List doInBackground(Object... objects) {
+ return Rule.getRules(true, ActivityForwarding.this);
+ }
+
+ @Override
+ protected void onPostExecute(List rules) {
+ ArrayAdapter spinnerArrayAdapter =
+ new ArrayAdapter(ActivityForwarding.this,
+ android.R.layout.simple_spinner_item, rules);
+ spRuid.setAdapter(spinnerArrayAdapter);
+ pbRuid.setVisibility(View.GONE);
+ spRuid.setVisibility(View.VISIBLE);
+ }
+ };
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+
+ dialog = new AlertDialog.Builder(this)
+ .setView(view)
+ .setCancelable(true)
+ .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ try {
+ int pos = spProtocol.getSelectedItemPosition();
+ String[] values = getResources().getStringArray(R.array.protocolValues);
+ final int protocol = Integer.valueOf(values[pos]);
+ final int dport = Integer.parseInt(etDPort.getText().toString());
+ final String raddr = etRAddr.getText().toString();
+ final int rport = Integer.parseInt(etRPort.getText().toString());
+ final int ruid = ((Rule) spRuid.getSelectedItem()).uid;
+
+ InetAddress iraddr = InetAddress.getByName(raddr);
+ if (rport < 1024 && (iraddr.isLoopbackAddress() || iraddr.isAnyLocalAddress()))
+ throw new IllegalArgumentException("Port forwarding to privileged port on local address not possible");
+
+ new AsyncTask() {
+ @Override
+ protected Throwable doInBackground(Object... objects) {
+ try {
+ DatabaseHelper.getInstance(ActivityForwarding.this)
+ .addForward(protocol, dport, raddr, rport, ruid);
+ return null;
+ } catch (Throwable ex) {
+ return ex;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Throwable ex) {
+ if (running)
+ if (ex == null) {
+ ServiceSinkhole.reload("forwarding", ActivityForwarding.this, false);
+ adapter = new AdapterForwarding(ActivityForwarding.this,
+ DatabaseHelper.getInstance(ActivityForwarding.this).getForwarding());
+ lvForwarding.setAdapter(adapter);
+ } else
+ Toast.makeText(ActivityForwarding.this, ex.toString(), Toast.LENGTH_LONG).show();
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ } catch (Throwable ex) {
+ Toast.makeText(ActivityForwarding.this, ex.toString(), Toast.LENGTH_LONG).show();
+ }
+ }
+ })
+ .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ task.cancel(false);
+ dialog.dismiss();
+ }
+ })
+ .setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialogInterface) {
+ dialog = null;
+ }
+ })
+ .create();
+ dialog.show();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityLog.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityLog.java
new file mode 100644
index 0000000..5380108
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityLog.java
@@ -0,0 +1,643 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.CompoundButton;
+import android.widget.FilterQueryProvider;
+import android.widget.ListView;
+import android.widget.PopupMenu;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.SearchView;
+import androidx.appcompat.widget.SwitchCompat;
+import androidx.core.app.NavUtils;
+import androidx.preference.PreferenceManager;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class ActivityLog extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
+ private static final String TAG = "NetGuard.Log";
+
+ private boolean running = false;
+ private ListView lvLog;
+ private AdapterLog adapter;
+ private MenuItem menuSearch = null;
+
+ private boolean live;
+ private boolean resolve;
+ private boolean organization;
+ private InetAddress vpn4 = null;
+ private InetAddress vpn6 = null;
+
+ private static final int REQUEST_PCAP = 1;
+
+ private DatabaseHelper.LogChangedListener listener = new DatabaseHelper.LogChangedListener() {
+ @Override
+ public void onChanged() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ updateAdapter();
+ }
+ });
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ if (!IAB.isPurchased(ActivityPro.SKU_LOG, this)) {
+ startActivity(new Intent(this, ActivityPro.class));
+ finish();
+ }
+
+ Util.setTheme(this);
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.logging);
+ running = true;
+
+ // Action bar
+ View actionView = getLayoutInflater().inflate(R.layout.actionlog, null, false);
+ SwitchCompat swEnabled = actionView.findViewById(R.id.swEnabled);
+
+ getSupportActionBar().setDisplayShowCustomEnabled(true);
+ getSupportActionBar().setCustomView(actionView);
+
+ getSupportActionBar().setTitle(R.string.menu_log);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ // Get settings
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ resolve = prefs.getBoolean("resolve", false);
+ organization = prefs.getBoolean("organization", false);
+ boolean log = prefs.getBoolean("log", false);
+
+ // Show disabled message
+ TextView tvDisabled = findViewById(R.id.tvDisabled);
+ tvDisabled.setVisibility(log ? View.GONE : View.VISIBLE);
+
+ // Set enabled switch
+ swEnabled.setChecked(log);
+ swEnabled.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ prefs.edit().putBoolean("log", isChecked).apply();
+ }
+ });
+
+ // Listen for preference changes
+ prefs.registerOnSharedPreferenceChangeListener(this);
+
+ lvLog = findViewById(R.id.lvLog);
+
+ boolean udp = prefs.getBoolean("proto_udp", true);
+ boolean tcp = prefs.getBoolean("proto_tcp", true);
+ boolean other = prefs.getBoolean("proto_other", true);
+ boolean allowed = prefs.getBoolean("traffic_allowed", true);
+ boolean blocked = prefs.getBoolean("traffic_blocked", true);
+
+ adapter = new AdapterLog(this, DatabaseHelper.getInstance(this).getLog(udp, tcp, other, allowed, blocked), resolve, organization);
+ adapter.setFilterQueryProvider(new FilterQueryProvider() {
+ public Cursor runQuery(CharSequence constraint) {
+ return DatabaseHelper.getInstance(ActivityLog.this).searchLog(constraint.toString());
+ }
+ });
+
+ lvLog.setAdapter(adapter);
+
+ try {
+ vpn4 = InetAddress.getByName(prefs.getString("vpn4", "10.1.10.1"));
+ vpn6 = InetAddress.getByName(prefs.getString("vpn6", "fd00:1:fd00:1:fd00:1:fd00:1"));
+ } catch (UnknownHostException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ lvLog.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ PackageManager pm = getPackageManager();
+ Cursor cursor = (Cursor) adapter.getItem(position);
+ long time = cursor.getLong(cursor.getColumnIndex("time"));
+ int version = cursor.getInt(cursor.getColumnIndex("version"));
+ int protocol = cursor.getInt(cursor.getColumnIndex("protocol"));
+ final String saddr = cursor.getString(cursor.getColumnIndex("saddr"));
+ final int sport = (cursor.isNull(cursor.getColumnIndex("sport")) ? -1 : cursor.getInt(cursor.getColumnIndex("sport")));
+ final String daddr = cursor.getString(cursor.getColumnIndex("daddr"));
+ final int dport = (cursor.isNull(cursor.getColumnIndex("dport")) ? -1 : cursor.getInt(cursor.getColumnIndex("dport")));
+ final String dname = cursor.getString(cursor.getColumnIndex("dname"));
+ final int uid = (cursor.isNull(cursor.getColumnIndex("uid")) ? -1 : cursor.getInt(cursor.getColumnIndex("uid")));
+ int allowed = (cursor.isNull(cursor.getColumnIndex("allowed")) ? -1 : cursor.getInt(cursor.getColumnIndex("allowed")));
+
+ // Get external address
+ InetAddress addr = null;
+ try {
+ addr = InetAddress.getByName(daddr);
+ } catch (UnknownHostException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ String ip;
+ int port;
+ if (addr.equals(vpn4) || addr.equals(vpn6)) {
+ ip = saddr;
+ port = sport;
+ } else {
+ ip = daddr;
+ port = dport;
+ }
+
+ // Build popup menu
+ PopupMenu popup = new PopupMenu(ActivityLog.this, findViewById(R.id.vwPopupAnchor));
+ popup.inflate(R.menu.log);
+
+ // Application name
+ if (uid >= 0)
+ popup.getMenu().findItem(R.id.menu_application).setTitle(TextUtils.join(", ", Util.getApplicationNames(uid, ActivityLog.this)));
+ else
+ popup.getMenu().removeItem(R.id.menu_application);
+
+ // Destination IP
+ popup.getMenu().findItem(R.id.menu_protocol).setTitle(Util.getProtocolName(protocol, version, false));
+
+ // Whois
+ final Intent lookupIP = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.dnslytics.com/whois-lookup/" + ip));
+ if (pm.resolveActivity(lookupIP, 0) == null)
+ popup.getMenu().removeItem(R.id.menu_whois);
+ else
+ popup.getMenu().findItem(R.id.menu_whois).setTitle(getString(R.string.title_log_whois, ip));
+
+ // Lookup port
+ final Intent lookupPort = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.speedguide.net/port.php?port=" + port));
+ if (port <= 0 || pm.resolveActivity(lookupPort, 0) == null)
+ popup.getMenu().removeItem(R.id.menu_port);
+ else
+ popup.getMenu().findItem(R.id.menu_port).setTitle(getString(R.string.title_log_port, port));
+
+ if (prefs.getBoolean("filter", false)) {
+ if (uid <= 0) {
+ popup.getMenu().removeItem(R.id.menu_allow);
+ popup.getMenu().removeItem(R.id.menu_block);
+ }
+ } else {
+ popup.getMenu().removeItem(R.id.menu_allow);
+ popup.getMenu().removeItem(R.id.menu_block);
+ }
+
+ final Packet packet = new Packet();
+ packet.version = version;
+ packet.protocol = protocol;
+ packet.daddr = daddr;
+ packet.dport = dport;
+ packet.time = time;
+ packet.uid = uid;
+ packet.allowed = (allowed > 0);
+
+ // Time
+ popup.getMenu().findItem(R.id.menu_time).setTitle(SimpleDateFormat.getDateTimeInstance().format(time));
+
+ // Handle click
+ popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem menuItem) {
+ switch (menuItem.getItemId()) {
+ case R.id.menu_application: {
+ Intent main = new Intent(ActivityLog.this, ActivityMain.class);
+ main.putExtra(ActivityMain.EXTRA_SEARCH, Integer.toString(uid));
+ startActivity(main);
+ return true;
+ }
+
+ case R.id.menu_whois:
+ startActivity(lookupIP);
+ return true;
+
+ case R.id.menu_port:
+ startActivity(lookupPort);
+ return true;
+
+ case R.id.menu_allow:
+ if (IAB.isPurchased(ActivityPro.SKU_FILTER, ActivityLog.this)) {
+ DatabaseHelper.getInstance(ActivityLog.this).updateAccess(packet, dname, 0);
+ ServiceSinkhole.reload("allow host", ActivityLog.this, false);
+ Intent main = new Intent(ActivityLog.this, ActivityMain.class);
+ main.putExtra(ActivityMain.EXTRA_SEARCH, Integer.toString(uid));
+ startActivity(main);
+ } else
+ startActivity(new Intent(ActivityLog.this, ActivityPro.class));
+ return true;
+
+ case R.id.menu_block:
+ if (IAB.isPurchased(ActivityPro.SKU_FILTER, ActivityLog.this)) {
+ DatabaseHelper.getInstance(ActivityLog.this).updateAccess(packet, dname, 1);
+ ServiceSinkhole.reload("block host", ActivityLog.this, false);
+ Intent main = new Intent(ActivityLog.this, ActivityMain.class);
+ main.putExtra(ActivityMain.EXTRA_SEARCH, Integer.toString(uid));
+ startActivity(main);
+ } else
+ startActivity(new Intent(ActivityLog.this, ActivityPro.class));
+ return true;
+
+ case R.id.menu_copy:
+ ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
+ ClipData clip = ClipData.newPlainText("netguard", dname == null ? daddr : dname);
+ clipboard.setPrimaryClip(clip);
+ return true;
+
+ default:
+ return false;
+ }
+ }
+ });
+
+ // Show
+ popup.show();
+ }
+ });
+
+ live = true;
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (live) {
+ DatabaseHelper.getInstance(this).addLogChangedListener(listener);
+ updateAdapter();
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (live)
+ DatabaseHelper.getInstance(this).removeLogChangedListener(listener);
+ }
+
+ @Override
+ protected void onDestroy() {
+ running = false;
+ adapter = null;
+ PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
+ super.onDestroy();
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences prefs, String name) {
+ Log.i(TAG, "Preference " + name + "=" + prefs.getAll().get(name));
+ if ("log".equals(name)) {
+ // Get enabled
+ boolean log = prefs.getBoolean(name, false);
+
+ // Display disabled warning
+ TextView tvDisabled = findViewById(R.id.tvDisabled);
+ tvDisabled.setVisibility(log ? View.GONE : View.VISIBLE);
+
+ // Check switch state
+ SwitchCompat swEnabled = getSupportActionBar().getCustomView().findViewById(R.id.swEnabled);
+ if (swEnabled.isChecked() != log)
+ swEnabled.setChecked(log);
+
+ ServiceSinkhole.reload("changed " + name, ActivityLog.this, false);
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.logging, menu);
+
+ menuSearch = menu.findItem(R.id.menu_search);
+ SearchView searchView = (SearchView) menuSearch.getActionView();
+ searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ if (adapter != null)
+ adapter.getFilter().filter(getUidForName(query));
+ return true;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String newText) {
+ if (adapter != null)
+ adapter.getFilter().filter(getUidForName(newText));
+ return true;
+ }
+ });
+ searchView.setOnCloseListener(new SearchView.OnCloseListener() {
+ @Override
+ public boolean onClose() {
+ if (adapter != null)
+ adapter.getFilter().filter(null);
+ return true;
+ }
+ });
+
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+
+ // https://gist.github.com/granoeste/5574148
+ File pcap_file = new File(getDir("data", MODE_PRIVATE), "netguard.pcap");
+
+ boolean export = (getPackageManager().resolveActivity(getIntentPCAPDocument(), 0) != null);
+
+ menu.findItem(R.id.menu_protocol_udp).setChecked(prefs.getBoolean("proto_udp", true));
+ menu.findItem(R.id.menu_protocol_tcp).setChecked(prefs.getBoolean("proto_tcp", true));
+ menu.findItem(R.id.menu_protocol_other).setChecked(prefs.getBoolean("proto_other", true));
+ menu.findItem(R.id.menu_traffic_allowed).setEnabled(prefs.getBoolean("filter", false));
+ menu.findItem(R.id.menu_traffic_allowed).setChecked(prefs.getBoolean("traffic_allowed", true));
+ menu.findItem(R.id.menu_traffic_blocked).setChecked(prefs.getBoolean("traffic_blocked", true));
+
+ menu.findItem(R.id.menu_refresh).setEnabled(!menu.findItem(R.id.menu_log_live).isChecked());
+ menu.findItem(R.id.menu_log_resolve).setChecked(prefs.getBoolean("resolve", false));
+ menu.findItem(R.id.menu_log_organization).setChecked(prefs.getBoolean("organization", false));
+ menu.findItem(R.id.menu_pcap_enabled).setChecked(prefs.getBoolean("pcap", false));
+ menu.findItem(R.id.menu_pcap_export).setEnabled(pcap_file.exists() && export);
+
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ final File pcap_file = new File(getDir("data", MODE_PRIVATE), "netguard.pcap");
+
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ Log.i(TAG, "Up");
+ NavUtils.navigateUpFromSameTask(this);
+ return true;
+
+ case R.id.menu_protocol_udp:
+ item.setChecked(!item.isChecked());
+ prefs.edit().putBoolean("proto_udp", item.isChecked()).apply();
+ updateAdapter();
+ return true;
+
+ case R.id.menu_protocol_tcp:
+ item.setChecked(!item.isChecked());
+ prefs.edit().putBoolean("proto_tcp", item.isChecked()).apply();
+ updateAdapter();
+ return true;
+
+ case R.id.menu_protocol_other:
+ item.setChecked(!item.isChecked());
+ prefs.edit().putBoolean("proto_other", item.isChecked()).apply();
+ updateAdapter();
+ return true;
+
+ case R.id.menu_traffic_allowed:
+ item.setChecked(!item.isChecked());
+ prefs.edit().putBoolean("traffic_allowed", item.isChecked()).apply();
+ updateAdapter();
+ return true;
+
+ case R.id.menu_traffic_blocked:
+ item.setChecked(!item.isChecked());
+ prefs.edit().putBoolean("traffic_blocked", item.isChecked()).apply();
+ updateAdapter();
+ return true;
+
+ case R.id.menu_log_live:
+ item.setChecked(!item.isChecked());
+ live = item.isChecked();
+ if (live) {
+ DatabaseHelper.getInstance(this).addLogChangedListener(listener);
+ updateAdapter();
+ } else
+ DatabaseHelper.getInstance(this).removeLogChangedListener(listener);
+ return true;
+
+ case R.id.menu_refresh:
+ updateAdapter();
+ return true;
+
+ case R.id.menu_log_resolve:
+ item.setChecked(!item.isChecked());
+ prefs.edit().putBoolean("resolve", item.isChecked()).apply();
+ adapter.setResolve(item.isChecked());
+ adapter.notifyDataSetChanged();
+ return true;
+
+ case R.id.menu_log_organization:
+ item.setChecked(!item.isChecked());
+ prefs.edit().putBoolean("organization", item.isChecked()).apply();
+ adapter.setOrganization(item.isChecked());
+ adapter.notifyDataSetChanged();
+ return true;
+
+ case R.id.menu_pcap_enabled:
+ item.setChecked(!item.isChecked());
+ prefs.edit().putBoolean("pcap", item.isChecked()).apply();
+ ServiceSinkhole.setPcap(item.isChecked(), ActivityLog.this);
+ return true;
+
+ case R.id.menu_pcap_export:
+ startActivityForResult(getIntentPCAPDocument(), REQUEST_PCAP);
+ return true;
+
+ case R.id.menu_log_clear:
+ new AsyncTask() {
+ @Override
+ protected Object doInBackground(Object... objects) {
+ DatabaseHelper.getInstance(ActivityLog.this).clearLog(-1);
+ if (prefs.getBoolean("pcap", false)) {
+ ServiceSinkhole.setPcap(false, ActivityLog.this);
+ if (pcap_file.exists() && !pcap_file.delete())
+ Log.w(TAG, "Delete PCAP failed");
+ ServiceSinkhole.setPcap(true, ActivityLog.this);
+ } else {
+ if (pcap_file.exists() && !pcap_file.delete())
+ Log.w(TAG, "Delete PCAP failed");
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Object result) {
+ if (running)
+ updateAdapter();
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ return true;
+
+ case R.id.menu_log_support:
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse("https://github.com/M66B/NetGuard/blob/master/FAQ.md#user-content-faq27"));
+ if (getPackageManager().resolveActivity(intent, 0) != null)
+ startActivity(intent);
+ return true;
+
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ private void updateAdapter() {
+ if (adapter != null) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean udp = prefs.getBoolean("proto_udp", true);
+ boolean tcp = prefs.getBoolean("proto_tcp", true);
+ boolean other = prefs.getBoolean("proto_other", true);
+ boolean allowed = prefs.getBoolean("traffic_allowed", true);
+ boolean blocked = prefs.getBoolean("traffic_blocked", true);
+ adapter.changeCursor(DatabaseHelper.getInstance(this).getLog(udp, tcp, other, allowed, blocked));
+ if (menuSearch != null && menuSearch.isActionViewExpanded()) {
+ SearchView searchView = (SearchView) menuSearch.getActionView();
+ adapter.getFilter().filter(getUidForName(searchView.getQuery().toString()));
+ }
+ }
+ }
+
+ private String getUidForName(String query) {
+ if (query != null && query.length() > 0) {
+ for (Rule rule : Rule.getRules(true, ActivityLog.this))
+ if (rule.name != null && rule.name.toLowerCase().contains(query.toLowerCase())) {
+ String newQuery = Integer.toString(rule.uid);
+ Log.i(TAG, "Search " + query + " found " + rule.name + " new " + newQuery);
+ return newQuery;
+ }
+ Log.i(TAG, "Search " + query + " not found");
+ }
+ return query;
+ }
+
+ private Intent getIntentPCAPDocument() {
+ Intent intent;
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ if (Util.isPackageInstalled("org.openintents.filemanager", this)) {
+ intent = new Intent("org.openintents.action.PICK_DIRECTORY");
+ } else {
+ intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse("https://play.google.com/store/apps/details?id=org.openintents.filemanager"));
+ }
+ } else {
+ intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("application/octet-stream");
+ intent.putExtra(Intent.EXTRA_TITLE, "netguard_" + new SimpleDateFormat("yyyyMMdd").format(new Date().getTime()) + ".pcap");
+ }
+ return intent;
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
+ Log.i(TAG, "onActivityResult request=" + requestCode + " result=" + requestCode + " ok=" + (resultCode == RESULT_OK));
+
+ if (requestCode == REQUEST_PCAP) {
+ if (resultCode == RESULT_OK && data != null)
+ handleExportPCAP(data);
+
+ } else {
+ Log.w(TAG, "Unknown activity result request=" + requestCode);
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+
+ private void handleExportPCAP(final Intent data) {
+ new AsyncTask() {
+ @Override
+ protected Throwable doInBackground(Object... objects) {
+ OutputStream out = null;
+ FileInputStream in = null;
+ try {
+ // Stop capture
+ ServiceSinkhole.setPcap(false, ActivityLog.this);
+
+ Uri target = data.getData();
+ if (data.hasExtra("org.openintents.extra.DIR_PATH"))
+ target = Uri.parse(target + "/netguard.pcap");
+ Log.i(TAG, "Export PCAP URI=" + target);
+ out = getContentResolver().openOutputStream(target);
+
+ File pcap = new File(getDir("data", MODE_PRIVATE), "netguard.pcap");
+ in = new FileInputStream(pcap);
+
+ int len;
+ long total = 0;
+ byte[] buf = new byte[4096];
+ while ((len = in.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ total += len;
+ }
+ Log.i(TAG, "Copied bytes=" + total);
+
+ return null;
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ return ex;
+ } finally {
+ if (out != null)
+ try {
+ out.close();
+ } catch (IOException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ if (in != null)
+ try {
+ in.close();
+ } catch (IOException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ // Resume capture
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ActivityLog.this);
+ if (prefs.getBoolean("pcap", false))
+ ServiceSinkhole.setPcap(true, ActivityLog.this);
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Throwable ex) {
+ if (ex == null)
+ Toast.makeText(ActivityLog.this, R.string.msg_completed, Toast.LENGTH_LONG).show();
+ else
+ Toast.makeText(ActivityLog.this, ex.toString(), Toast.LENGTH_LONG).show();
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityMain.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityMain.java
new file mode 100644
index 0000000..948e5cd
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityMain.java
@@ -0,0 +1,1304 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.net.VpnService;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ImageSpan;
+import android.text.style.UnderlineSpan;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.SearchView;
+import androidx.appcompat.widget.SwitchCompat;
+import androidx.core.graphics.drawable.DrawableCompat;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+import androidx.preference.PreferenceManager;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+
+import java.util.List;
+
+public class ActivityMain extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
+ private static final String TAG = "NetGuard.Main";
+
+ private boolean running = false;
+ private ImageView ivIcon;
+ private ImageView ivQueue;
+ private SwitchCompat swEnabled;
+ private ImageView ivMetered;
+ private SwipeRefreshLayout swipeRefresh;
+ private AdapterRule adapter = null;
+ private MenuItem menuSearch = null;
+ private AlertDialog dialogFirst = null;
+ private AlertDialog dialogVpn = null;
+ private AlertDialog dialogDoze = null;
+ private AlertDialog dialogLegend = null;
+ private AlertDialog dialogAbout = null;
+
+ private IAB iab = null;
+
+ private static final int REQUEST_VPN = 1;
+ private static final int REQUEST_INVITE = 2;
+ private static final int REQUEST_LOGCAT = 3;
+ public static final int REQUEST_ROAMING = 4;
+
+ private static final int MIN_SDK = Build.VERSION_CODES.LOLLIPOP_MR1;
+
+ public static final String ACTION_RULES_CHANGED = "eu.faircode.netguard.ACTION_RULES_CHANGED";
+ public static final String ACTION_QUEUE_CHANGED = "eu.faircode.netguard.ACTION_QUEUE_CHANGED";
+ public static final String EXTRA_REFRESH = "Refresh";
+ public static final String EXTRA_SEARCH = "Search";
+ public static final String EXTRA_RELATED = "Related";
+ public static final String EXTRA_APPROVE = "Approve";
+ public static final String EXTRA_LOGCAT = "Logcat";
+ public static final String EXTRA_CONNECTED = "Connected";
+ public static final String EXTRA_METERED = "Metered";
+ public static final String EXTRA_SIZE = "Size";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ Log.i(TAG, "Create version=" + Util.getSelfVersionName(this) + "/" + Util.getSelfVersionCode(this));
+ Util.logExtras(getIntent());
+
+ // Check minimum Android version
+ if (Build.VERSION.SDK_INT < MIN_SDK) {
+ Log.i(TAG, "SDK=" + Build.VERSION.SDK_INT);
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.android);
+ return;
+ }
+
+ // Check for Xposed
+ if (Util.hasXposed(this)) {
+ Log.i(TAG, "Xposed running");
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.xposed);
+ return;
+ }
+
+ Util.setTheme(this);
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ running = true;
+
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean enabled = prefs.getBoolean("enabled", false);
+ boolean initialized = prefs.getBoolean("initialized", false);
+
+ // Upgrade
+ ReceiverAutostart.upgrade(initialized, this);
+
+ if (!getIntent().hasExtra(EXTRA_APPROVE)) {
+ if (enabled)
+ ServiceSinkhole.start("UI", this);
+ else
+ ServiceSinkhole.stop("UI", this, false);
+ }
+
+ // Action bar
+ final View actionView = getLayoutInflater().inflate(R.layout.actionmain, null, false);
+ ivIcon = actionView.findViewById(R.id.ivIcon);
+ ivQueue = actionView.findViewById(R.id.ivQueue);
+ swEnabled = actionView.findViewById(R.id.swEnabled);
+ ivMetered = actionView.findViewById(R.id.ivMetered);
+
+ // Icon
+ ivIcon.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View view) {
+ menu_about();
+ return true;
+ }
+ });
+
+ // Title
+ getSupportActionBar().setTitle(null);
+
+ // Netguard is busy
+ ivQueue.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View view) {
+ int location[] = new int[2];
+ actionView.getLocationOnScreen(location);
+ Toast toast = Toast.makeText(ActivityMain.this, R.string.msg_queue, Toast.LENGTH_LONG);
+ toast.setGravity(
+ Gravity.TOP | Gravity.LEFT,
+ location[0] + ivQueue.getLeft(),
+ Math.round(location[1] + ivQueue.getBottom() - toast.getView().getPaddingTop()));
+ toast.show();
+ return true;
+ }
+ });
+
+ // On/off switch
+ swEnabled.setChecked(enabled);
+ swEnabled.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ Log.i(TAG, "Switch=" + isChecked);
+ prefs.edit().putBoolean("enabled", isChecked).apply();
+
+ if (isChecked) {
+ try {
+ String alwaysOn = Settings.Secure.getString(getContentResolver(), "always_on_vpn_app");
+ Log.i(TAG, "Always-on=" + alwaysOn);
+ if (!TextUtils.isEmpty(alwaysOn))
+ if (getPackageName().equals(alwaysOn)) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q &&
+ prefs.getBoolean("filter", false)) {
+ int lockdown = Settings.Secure.getInt(getContentResolver(), "always_on_vpn_lockdown", 0);
+ Log.i(TAG, "Lockdown=" + lockdown);
+ if (lockdown != 0) {
+ swEnabled.setChecked(false);
+ Toast.makeText(ActivityMain.this, R.string.msg_always_on_lockdown, Toast.LENGTH_LONG).show();
+ return;
+ }
+ }
+ } else {
+ swEnabled.setChecked(false);
+ Toast.makeText(ActivityMain.this, R.string.msg_always_on, Toast.LENGTH_LONG).show();
+ return;
+ }
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ boolean filter = prefs.getBoolean("filter", false);
+ if (filter && Util.isPrivateDns(ActivityMain.this))
+ Toast.makeText(ActivityMain.this, R.string.msg_private_dns, Toast.LENGTH_LONG).show();
+
+ try {
+ final Intent prepare = VpnService.prepare(ActivityMain.this);
+ if (prepare == null) {
+ Log.i(TAG, "Prepare done");
+ onActivityResult(REQUEST_VPN, RESULT_OK, null);
+ } else {
+ // Show dialog
+ LayoutInflater inflater = LayoutInflater.from(ActivityMain.this);
+ View view = inflater.inflate(R.layout.vpn, null, false);
+ dialogVpn = new AlertDialog.Builder(ActivityMain.this)
+ .setView(view)
+ .setCancelable(false)
+ .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (running) {
+ Log.i(TAG, "Start intent=" + prepare);
+ try {
+ // com.android.vpndialogs.ConfirmDialog required
+ startActivityForResult(prepare, REQUEST_VPN);
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ onActivityResult(REQUEST_VPN, RESULT_CANCELED, null);
+ prefs.edit().putBoolean("enabled", false).apply();
+ }
+ }
+ }
+ })
+ .setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialogInterface) {
+ dialogVpn = null;
+ }
+ })
+ .create();
+ dialogVpn.show();
+ }
+ } catch (Throwable ex) {
+ // Prepare failed
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ prefs.edit().putBoolean("enabled", false).apply();
+ }
+
+ } else
+ ServiceSinkhole.stop("switch off", ActivityMain.this, false);
+ }
+ });
+ if (enabled)
+ checkDoze();
+
+ // Network is metered
+ ivMetered.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View view) {
+ int location[] = new int[2];
+ actionView.getLocationOnScreen(location);
+ Toast toast = Toast.makeText(ActivityMain.this, R.string.msg_metered, Toast.LENGTH_LONG);
+ toast.setGravity(
+ Gravity.TOP | Gravity.LEFT,
+ location[0] + ivMetered.getLeft(),
+ Math.round(location[1] + ivMetered.getBottom() - toast.getView().getPaddingTop()));
+ toast.show();
+ return true;
+ }
+ });
+
+ getSupportActionBar().setDisplayShowCustomEnabled(true);
+ getSupportActionBar().setCustomView(actionView);
+
+ // Disabled warning
+ TextView tvDisabled = findViewById(R.id.tvDisabled);
+ tvDisabled.setVisibility(enabled ? View.GONE : View.VISIBLE);
+
+ // Application list
+ RecyclerView rvApplication = findViewById(R.id.rvApplication);
+ rvApplication.setHasFixedSize(false);
+ LinearLayoutManager llm = new LinearLayoutManager(this);
+ llm.setAutoMeasureEnabled(true);
+ rvApplication.setLayoutManager(llm);
+ adapter = new AdapterRule(this, findViewById(R.id.vwPopupAnchor));
+ rvApplication.setAdapter(adapter);
+
+ // Swipe to refresh
+ TypedValue tv = new TypedValue();
+ getTheme().resolveAttribute(R.attr.colorPrimary, tv, true);
+ swipeRefresh = findViewById(R.id.swipeRefresh);
+ swipeRefresh.setColorSchemeColors(Color.WHITE, Color.WHITE, Color.WHITE);
+ swipeRefresh.setProgressBackgroundColorSchemeColor(tv.data);
+ swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ Rule.clearCache(ActivityMain.this);
+ ServiceSinkhole.reload("pull", ActivityMain.this, false);
+ updateApplicationList(null);
+ }
+ });
+
+ // Hint usage
+ final LinearLayout llUsage = findViewById(R.id.llUsage);
+ Button btnUsage = findViewById(R.id.btnUsage);
+ boolean hintUsage = prefs.getBoolean("hint_usage", true);
+ llUsage.setVisibility(hintUsage ? View.VISIBLE : View.GONE);
+ btnUsage.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ prefs.edit().putBoolean("hint_usage", false).apply();
+ llUsage.setVisibility(View.GONE);
+ showHints();
+ }
+ });
+
+ final LinearLayout llFairEmail = findViewById(R.id.llFairEmail);
+ TextView tvFairEmail = findViewById(R.id.tvFairEmail);
+ tvFairEmail.setMovementMethod(LinkMovementMethod.getInstance());
+ Button btnFairEmail = findViewById(R.id.btnFairEmail);
+ boolean hintFairEmail = prefs.getBoolean("hint_fairemail", true);
+ llFairEmail.setVisibility(hintFairEmail ? View.VISIBLE : View.GONE);
+ btnFairEmail.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ prefs.edit().putBoolean("hint_fairemail", false).apply();
+ llFairEmail.setVisibility(View.GONE);
+ }
+ });
+
+ showHints();
+
+ // Listen for preference changes
+ prefs.registerOnSharedPreferenceChangeListener(this);
+
+ // Listen for rule set changes
+ IntentFilter ifr = new IntentFilter(ACTION_RULES_CHANGED);
+ LocalBroadcastManager.getInstance(this).registerReceiver(onRulesChanged, ifr);
+
+ // Listen for queue changes
+ IntentFilter ifq = new IntentFilter(ACTION_QUEUE_CHANGED);
+ LocalBroadcastManager.getInstance(this).registerReceiver(onQueueChanged, ifq);
+
+ // Listen for added/removed applications
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ intentFilter.addDataScheme("package");
+ registerReceiver(packageChangedReceiver, intentFilter);
+
+ // First use
+ if (!initialized) {
+ // Create view
+ LayoutInflater inflater = LayoutInflater.from(this);
+ View view = inflater.inflate(R.layout.first, null, false);
+
+ TextView tvFirst = view.findViewById(R.id.tvFirst);
+ TextView tvEula = view.findViewById(R.id.tvEula);
+ TextView tvPrivacy = view.findViewById(R.id.tvPrivacy);
+ tvFirst.setMovementMethod(LinkMovementMethod.getInstance());
+ tvEula.setMovementMethod(LinkMovementMethod.getInstance());
+ tvPrivacy.setMovementMethod(LinkMovementMethod.getInstance());
+
+ // Show dialog
+ dialogFirst = new AlertDialog.Builder(this)
+ .setView(view)
+ .setCancelable(false)
+ .setPositiveButton(R.string.app_agree, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (running) {
+ prefs.edit().putBoolean("initialized", true).apply();
+ }
+ }
+ })
+ .setNegativeButton(R.string.app_disagree, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (running)
+ finish();
+ }
+ })
+ .setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialogInterface) {
+ dialogFirst = null;
+ }
+ })
+ .create();
+ dialogFirst.show();
+ }
+
+ // Fill application list
+ updateApplicationList(getIntent().getStringExtra(EXTRA_SEARCH));
+
+ // Update IAB SKUs
+ try {
+ iab = new IAB(new IAB.Delegate() {
+ @Override
+ public void onReady(IAB iab) {
+ try {
+ iab.updatePurchases();
+
+ if (!IAB.isPurchased(ActivityPro.SKU_LOG, ActivityMain.this))
+ prefs.edit().putBoolean("log", false).apply();
+ if (!IAB.isPurchased(ActivityPro.SKU_THEME, ActivityMain.this)) {
+ if (!"teal".equals(prefs.getString("theme", "teal")))
+ prefs.edit().putString("theme", "teal").apply();
+ }
+ if (!IAB.isPurchased(ActivityPro.SKU_NOTIFY, ActivityMain.this))
+ prefs.edit().putBoolean("install", false).apply();
+ if (!IAB.isPurchased(ActivityPro.SKU_SPEED, ActivityMain.this))
+ prefs.edit().putBoolean("show_stats", false).apply();
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ } finally {
+ iab.unbind();
+ }
+ }
+ }, this);
+ iab.bind();
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ // Support
+ LinearLayout llSupport = findViewById(R.id.llSupport);
+ TextView tvSupport = findViewById(R.id.tvSupport);
+
+ SpannableString content = new SpannableString(getString(R.string.app_support));
+ content.setSpan(new UnderlineSpan(), 0, content.length(), 0);
+ tvSupport.setText(content);
+
+ llSupport.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(getIntentPro(ActivityMain.this));
+ }
+ });
+
+ // Handle intent
+ checkExtras(getIntent());
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ Log.i(TAG, "New intent");
+ Util.logExtras(intent);
+ super.onNewIntent(intent);
+
+ if (Build.VERSION.SDK_INT < MIN_SDK || Util.hasXposed(this))
+ return;
+
+ setIntent(intent);
+
+ if (Build.VERSION.SDK_INT >= MIN_SDK) {
+ if (intent.hasExtra(EXTRA_REFRESH))
+ updateApplicationList(intent.getStringExtra(EXTRA_SEARCH));
+ else
+ updateSearch(intent.getStringExtra(EXTRA_SEARCH));
+ checkExtras(intent);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ Log.i(TAG, "Resume");
+
+ if (Build.VERSION.SDK_INT < MIN_SDK || Util.hasXposed(this)) {
+ super.onResume();
+ return;
+ }
+
+ DatabaseHelper.getInstance(this).addAccessChangedListener(accessChangedListener);
+ if (adapter != null)
+ adapter.notifyDataSetChanged();
+
+ PackageManager pm = getPackageManager();
+ LinearLayout llSupport = findViewById(R.id.llSupport);
+ llSupport.setVisibility(
+ IAB.isPurchasedAny(this) || getIntentPro(this).resolveActivity(pm) == null
+ ? View.GONE : View.VISIBLE);
+
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ Log.i(TAG, "Pause");
+ super.onPause();
+
+ if (Build.VERSION.SDK_INT < MIN_SDK || Util.hasXposed(this))
+ return;
+
+ DatabaseHelper.getInstance(this).removeAccessChangedListener(accessChangedListener);
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ Log.i(TAG, "Config");
+ super.onConfigurationChanged(newConfig);
+
+ if (Build.VERSION.SDK_INT < MIN_SDK || Util.hasXposed(this))
+ return;
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.i(TAG, "Destroy");
+
+ if (Build.VERSION.SDK_INT < MIN_SDK || Util.hasXposed(this)) {
+ super.onDestroy();
+ return;
+ }
+
+ running = false;
+ adapter = null;
+
+ PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
+
+ LocalBroadcastManager.getInstance(this).unregisterReceiver(onRulesChanged);
+ LocalBroadcastManager.getInstance(this).unregisterReceiver(onQueueChanged);
+ unregisterReceiver(packageChangedReceiver);
+
+ if (dialogFirst != null) {
+ dialogFirst.dismiss();
+ dialogFirst = null;
+ }
+ if (dialogVpn != null) {
+ dialogVpn.dismiss();
+ dialogVpn = null;
+ }
+ if (dialogDoze != null) {
+ dialogDoze.dismiss();
+ dialogDoze = null;
+ }
+ if (dialogLegend != null) {
+ dialogLegend.dismiss();
+ dialogLegend = null;
+ }
+ if (dialogAbout != null) {
+ dialogAbout.dismiss();
+ dialogAbout = null;
+ }
+
+ if (iab != null) {
+ iab.unbind();
+ iab = null;
+ }
+
+ super.onDestroy();
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
+ Log.i(TAG, "onActivityResult request=" + requestCode + " result=" + requestCode + " ok=" + (resultCode == RESULT_OK));
+ Util.logExtras(data);
+
+ if (requestCode == REQUEST_VPN) {
+ // Handle VPN approval
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.edit().putBoolean("enabled", resultCode == RESULT_OK).apply();
+ if (resultCode == RESULT_OK) {
+ ServiceSinkhole.start("prepared", this);
+
+ Toast on = Toast.makeText(ActivityMain.this, R.string.msg_on, Toast.LENGTH_LONG);
+ on.setGravity(Gravity.CENTER, 0, 0);
+ on.show();
+
+ checkDoze();
+ } else if (resultCode == RESULT_CANCELED)
+ Toast.makeText(this, R.string.msg_vpn_cancelled, Toast.LENGTH_LONG).show();
+
+ } else if (requestCode == REQUEST_INVITE) {
+ // Do nothing
+
+ } else if (requestCode == REQUEST_LOGCAT) {
+ // Send logcat by e-mail
+ if (resultCode == RESULT_OK) {
+ Uri target = data.getData();
+ if (data.hasExtra("org.openintents.extra.DIR_PATH"))
+ target = Uri.parse(target + "/logcat.txt");
+ Log.i(TAG, "Export URI=" + target);
+ Util.sendLogcat(target, this);
+ }
+
+ } else {
+ Log.w(TAG, "Unknown activity result request=" + requestCode);
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ if (requestCode == REQUEST_ROAMING)
+ if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
+ ServiceSinkhole.reload("permission granted", this, false);
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences prefs, String name) {
+ Log.i(TAG, "Preference " + name + "=" + prefs.getAll().get(name));
+ if ("enabled".equals(name)) {
+ // Get enabled
+ boolean enabled = prefs.getBoolean(name, false);
+
+ // Display disabled warning
+ TextView tvDisabled = findViewById(R.id.tvDisabled);
+ tvDisabled.setVisibility(enabled ? View.GONE : View.VISIBLE);
+
+ // Check switch state
+ SwitchCompat swEnabled = getSupportActionBar().getCustomView().findViewById(R.id.swEnabled);
+ if (swEnabled.isChecked() != enabled)
+ swEnabled.setChecked(enabled);
+
+ } else if ("whitelist_wifi".equals(name) ||
+ "screen_on".equals(name) ||
+ "screen_wifi".equals(name) ||
+ "whitelist_other".equals(name) ||
+ "screen_other".equals(name) ||
+ "whitelist_roaming".equals(name) ||
+ "show_user".equals(name) ||
+ "show_system".equals(name) ||
+ "show_nointernet".equals(name) ||
+ "show_disabled".equals(name) ||
+ "sort".equals(name) ||
+ "imported".equals(name)) {
+ updateApplicationList(null);
+
+ final LinearLayout llWhitelist = findViewById(R.id.llWhitelist);
+ boolean screen_on = prefs.getBoolean("screen_on", true);
+ boolean whitelist_wifi = prefs.getBoolean("whitelist_wifi", false);
+ boolean whitelist_other = prefs.getBoolean("whitelist_other", false);
+ boolean hintWhitelist = prefs.getBoolean("hint_whitelist", true);
+ llWhitelist.setVisibility(!(whitelist_wifi || whitelist_other) && screen_on && hintWhitelist ? View.VISIBLE : View.GONE);
+
+ } else if ("manage_system".equals(name)) {
+ invalidateOptionsMenu();
+ updateApplicationList(null);
+
+ LinearLayout llSystem = findViewById(R.id.llSystem);
+ boolean system = prefs.getBoolean("manage_system", false);
+ boolean hint = prefs.getBoolean("hint_system", true);
+ llSystem.setVisibility(!system && hint ? View.VISIBLE : View.GONE);
+
+ } else if ("theme".equals(name) || "dark_theme".equals(name))
+ recreate();
+ }
+
+ private DatabaseHelper.AccessChangedListener accessChangedListener = new DatabaseHelper.AccessChangedListener() {
+ @Override
+ public void onChanged() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (adapter != null && adapter.isLive())
+ adapter.notifyDataSetChanged();
+ }
+ });
+ }
+ };
+
+ private BroadcastReceiver onRulesChanged = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.i(TAG, "Received " + intent);
+ Util.logExtras(intent);
+
+ if (adapter != null)
+ if (intent.hasExtra(EXTRA_CONNECTED) && intent.hasExtra(EXTRA_METERED)) {
+ ivIcon.setImageResource(Util.isNetworkActive(ActivityMain.this)
+ ? R.drawable.ic_security_white_24dp
+ : R.drawable.ic_security_white_24dp_60);
+ if (intent.getBooleanExtra(EXTRA_CONNECTED, false)) {
+ if (intent.getBooleanExtra(EXTRA_METERED, false))
+ adapter.setMobileActive();
+ else
+ adapter.setWifiActive();
+ ivMetered.setVisibility(Util.isMeteredNetwork(ActivityMain.this) ? View.VISIBLE : View.INVISIBLE);
+ } else {
+ adapter.setDisconnected();
+ ivMetered.setVisibility(View.INVISIBLE);
+ }
+ } else
+ updateApplicationList(null);
+ }
+ };
+
+ private BroadcastReceiver onQueueChanged = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.i(TAG, "Received " + intent);
+ Util.logExtras(intent);
+ int size = intent.getIntExtra(EXTRA_SIZE, -1);
+ ivIcon.setVisibility(size == 0 ? View.VISIBLE : View.GONE);
+ ivQueue.setVisibility(size == 0 ? View.GONE : View.VISIBLE);
+ }
+ };
+
+ private BroadcastReceiver packageChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.i(TAG, "Received " + intent);
+ Util.logExtras(intent);
+ updateApplicationList(null);
+ }
+ };
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ if (Build.VERSION.SDK_INT < MIN_SDK)
+ return false;
+
+ PackageManager pm = getPackageManager();
+
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.main, menu);
+
+ // Search
+ menuSearch = menu.findItem(R.id.menu_search);
+ menuSearch.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
+ @Override
+ public boolean onMenuItemActionExpand(MenuItem item) {
+ return true;
+ }
+
+ @Override
+ public boolean onMenuItemActionCollapse(MenuItem item) {
+ if (getIntent().hasExtra(EXTRA_SEARCH) && !getIntent().getBooleanExtra(EXTRA_RELATED, false))
+ finish();
+ return true;
+ }
+ });
+
+ final SearchView searchView = (SearchView) menuSearch.getActionView();
+ searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ if (adapter != null)
+ adapter.getFilter().filter(query);
+ searchView.clearFocus();
+ return true;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String newText) {
+ if (adapter != null)
+ adapter.getFilter().filter(newText);
+ return true;
+ }
+ });
+ searchView.setOnCloseListener(new SearchView.OnCloseListener() {
+ @Override
+ public boolean onClose() {
+ Intent intent = getIntent();
+ intent.removeExtra(EXTRA_SEARCH);
+
+ if (adapter != null)
+ adapter.getFilter().filter(null);
+ return true;
+ }
+ });
+ String search = getIntent().getStringExtra(EXTRA_SEARCH);
+ if (search != null) {
+ menuSearch.expandActionView();
+ searchView.setQuery(search, true);
+ }
+
+ markPro(menu.findItem(R.id.menu_log), ActivityPro.SKU_LOG);
+ if (!IAB.isPurchasedAny(this))
+ markPro(menu.findItem(R.id.menu_pro), null);
+
+ if (!Util.hasValidFingerprint(this) || getIntentInvite(this).resolveActivity(pm) == null)
+ menu.removeItem(R.id.menu_invite);
+
+ if (getIntentSupport().resolveActivity(getPackageManager()) == null)
+ menu.removeItem(R.id.menu_support);
+
+ menu.findItem(R.id.menu_apps).setEnabled(getIntentApps(this).resolveActivity(pm) != null);
+
+ return true;
+ }
+
+ private void markPro(MenuItem menu, String sku) {
+ if (sku == null || !IAB.isPurchased(sku, this)) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean dark = prefs.getBoolean("dark_theme", false);
+ SpannableStringBuilder ssb = new SpannableStringBuilder(" " + menu.getTitle());
+ ssb.setSpan(new ImageSpan(this, dark ? R.drawable.ic_shopping_cart_white_24dp : R.drawable.ic_shopping_cart_black_24dp), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ menu.setTitle(ssb);
+ }
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+
+ if (prefs.getBoolean("manage_system", false)) {
+ menu.findItem(R.id.menu_app_user).setChecked(prefs.getBoolean("show_user", true));
+ menu.findItem(R.id.menu_app_system).setChecked(prefs.getBoolean("show_system", false));
+ } else {
+ Menu submenu = menu.findItem(R.id.menu_filter).getSubMenu();
+ submenu.removeItem(R.id.menu_app_user);
+ submenu.removeItem(R.id.menu_app_system);
+ }
+
+ menu.findItem(R.id.menu_app_nointernet).setChecked(prefs.getBoolean("show_nointernet", true));
+ menu.findItem(R.id.menu_app_disabled).setChecked(prefs.getBoolean("show_disabled", true));
+
+ String sort = prefs.getString("sort", "name");
+ if ("uid".equals(sort))
+ menu.findItem(R.id.menu_sort_uid).setChecked(true);
+ else
+ menu.findItem(R.id.menu_sort_name).setChecked(true);
+
+ menu.findItem(R.id.menu_lockdown).setChecked(prefs.getBoolean("lockdown", false));
+
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ Log.i(TAG, "Menu=" + item.getTitle());
+
+ // Handle item selection
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ switch (item.getItemId()) {
+ case R.id.menu_app_user:
+ item.setChecked(!item.isChecked());
+ prefs.edit().putBoolean("show_user", item.isChecked()).apply();
+ return true;
+
+ case R.id.menu_app_system:
+ item.setChecked(!item.isChecked());
+ prefs.edit().putBoolean("show_system", item.isChecked()).apply();
+ return true;
+
+ case R.id.menu_app_nointernet:
+ item.setChecked(!item.isChecked());
+ prefs.edit().putBoolean("show_nointernet", item.isChecked()).apply();
+ return true;
+
+ case R.id.menu_app_disabled:
+ item.setChecked(!item.isChecked());
+ prefs.edit().putBoolean("show_disabled", item.isChecked()).apply();
+ return true;
+
+ case R.id.menu_sort_name:
+ item.setChecked(true);
+ prefs.edit().putString("sort", "name").apply();
+ return true;
+
+ case R.id.menu_sort_uid:
+ item.setChecked(true);
+ prefs.edit().putString("sort", "uid").apply();
+ return true;
+
+ case R.id.menu_lockdown:
+ menu_lockdown(item);
+ return true;
+
+ case R.id.menu_log:
+ if (Util.canFilter(this))
+ if (IAB.isPurchased(ActivityPro.SKU_LOG, this))
+ startActivity(new Intent(this, ActivityLog.class));
+ else
+ startActivity(new Intent(this, ActivityPro.class));
+ else
+ Toast.makeText(this, R.string.msg_unavailable, Toast.LENGTH_SHORT).show();
+ return true;
+
+ case R.id.menu_settings:
+ startActivity(new Intent(this, ActivitySettings.class));
+ return true;
+
+ case R.id.menu_pro:
+ startActivity(new Intent(ActivityMain.this, ActivityPro.class));
+ return true;
+
+ case R.id.menu_invite:
+ startActivityForResult(getIntentInvite(this), REQUEST_INVITE);
+ return true;
+
+ case R.id.menu_legend:
+ menu_legend();
+ return true;
+
+ case R.id.menu_support:
+ startActivity(getIntentSupport());
+ return true;
+
+ case R.id.menu_about:
+ menu_about();
+ return true;
+
+ case R.id.menu_apps:
+ menu_apps();
+ return true;
+
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ private void showHints() {
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean hintUsage = prefs.getBoolean("hint_usage", true);
+
+ // Hint white listing
+ final LinearLayout llWhitelist = findViewById(R.id.llWhitelist);
+ Button btnWhitelist = findViewById(R.id.btnWhitelist);
+ boolean whitelist_wifi = prefs.getBoolean("whitelist_wifi", false);
+ boolean whitelist_other = prefs.getBoolean("whitelist_other", false);
+ boolean hintWhitelist = prefs.getBoolean("hint_whitelist", true);
+ llWhitelist.setVisibility(!(whitelist_wifi || whitelist_other) && hintWhitelist && !hintUsage ? View.VISIBLE : View.GONE);
+ btnWhitelist.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ prefs.edit().putBoolean("hint_whitelist", false).apply();
+ llWhitelist.setVisibility(View.GONE);
+ }
+ });
+
+ // Hint push messages
+ final LinearLayout llPush = findViewById(R.id.llPush);
+ Button btnPush = findViewById(R.id.btnPush);
+ boolean hintPush = prefs.getBoolean("hint_push", true);
+ llPush.setVisibility(hintPush && !hintUsage ? View.VISIBLE : View.GONE);
+ btnPush.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ prefs.edit().putBoolean("hint_push", false).apply();
+ llPush.setVisibility(View.GONE);
+ }
+ });
+
+ // Hint system applications
+ final LinearLayout llSystem = findViewById(R.id.llSystem);
+ Button btnSystem = findViewById(R.id.btnSystem);
+ boolean system = prefs.getBoolean("manage_system", false);
+ boolean hintSystem = prefs.getBoolean("hint_system", true);
+ llSystem.setVisibility(!system && hintSystem ? View.VISIBLE : View.GONE);
+ btnSystem.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ prefs.edit().putBoolean("hint_system", false).apply();
+ llSystem.setVisibility(View.GONE);
+ }
+ });
+ }
+
+ private void checkExtras(Intent intent) {
+ // Approve request
+ if (intent.hasExtra(EXTRA_APPROVE)) {
+ Log.i(TAG, "Requesting VPN approval");
+ swEnabled.toggle();
+ }
+
+ if (intent.hasExtra(EXTRA_LOGCAT)) {
+ Log.i(TAG, "Requesting logcat");
+ Intent logcat = getIntentLogcat();
+ if (logcat.resolveActivity(getPackageManager()) != null)
+ startActivityForResult(logcat, REQUEST_LOGCAT);
+ }
+ }
+
+ private void updateApplicationList(final String search) {
+ Log.i(TAG, "Update search=" + search);
+
+ new AsyncTask>() {
+ private boolean refreshing = true;
+
+ @Override
+ protected void onPreExecute() {
+ swipeRefresh.post(new Runnable() {
+ @Override
+ public void run() {
+ if (refreshing)
+ swipeRefresh.setRefreshing(true);
+ }
+ });
+ }
+
+ @Override
+ protected List doInBackground(Object... arg) {
+ return Rule.getRules(false, ActivityMain.this);
+ }
+
+ @Override
+ protected void onPostExecute(List result) {
+ if (running) {
+ if (adapter != null) {
+ adapter.set(result);
+ updateSearch(search);
+ }
+
+ if (swipeRefresh != null) {
+ refreshing = false;
+ swipeRefresh.setRefreshing(false);
+ }
+ }
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ private void updateSearch(String search) {
+ if (menuSearch != null) {
+ SearchView searchView = (SearchView) menuSearch.getActionView();
+ if (search == null) {
+ if (menuSearch.isActionViewExpanded())
+ adapter.getFilter().filter(searchView.getQuery().toString());
+ } else {
+ menuSearch.expandActionView();
+ searchView.setQuery(search, true);
+ }
+ }
+ }
+
+ private void checkDoze() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ final Intent doze = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
+ if (Util.batteryOptimizing(this) && getPackageManager().resolveActivity(doze, 0) != null) {
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ if (!prefs.getBoolean("nodoze", false)) {
+ LayoutInflater inflater = LayoutInflater.from(this);
+ View view = inflater.inflate(R.layout.doze, null, false);
+ final CheckBox cbDontAsk = view.findViewById(R.id.cbDontAsk);
+ dialogDoze = new AlertDialog.Builder(this)
+ .setView(view)
+ .setCancelable(true)
+ .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ prefs.edit().putBoolean("nodoze", cbDontAsk.isChecked()).apply();
+ startActivity(doze);
+ }
+ })
+ .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ prefs.edit().putBoolean("nodoze", cbDontAsk.isChecked()).apply();
+ }
+ })
+ .setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialogInterface) {
+ dialogDoze = null;
+ checkDataSaving();
+ }
+ })
+ .create();
+ dialogDoze.show();
+ } else
+ checkDataSaving();
+ } else
+ checkDataSaving();
+ }
+ }
+
+ private void checkDataSaving() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ final Intent settings = new Intent(
+ Settings.ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS,
+ Uri.parse("package:" + getPackageName()));
+ if (Util.dataSaving(this) && getPackageManager().resolveActivity(settings, 0) != null)
+ try {
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ if (!prefs.getBoolean("nodata", false)) {
+ LayoutInflater inflater = LayoutInflater.from(this);
+ View view = inflater.inflate(R.layout.datasaving, null, false);
+ final CheckBox cbDontAsk = view.findViewById(R.id.cbDontAsk);
+ dialogDoze = new AlertDialog.Builder(this)
+ .setView(view)
+ .setCancelable(true)
+ .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ prefs.edit().putBoolean("nodata", cbDontAsk.isChecked()).apply();
+ startActivity(settings);
+ }
+ })
+ .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ prefs.edit().putBoolean("nodata", cbDontAsk.isChecked()).apply();
+ }
+ })
+ .setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialogInterface) {
+ dialogDoze = null;
+ }
+ })
+ .create();
+ dialogDoze.show();
+ }
+ } catch (Throwable ex) {
+ Log.e(TAG, ex + "\n" + ex.getStackTrace());
+ }
+ }
+ }
+
+ private void menu_legend() {
+ TypedValue tv = new TypedValue();
+ getTheme().resolveAttribute(R.attr.colorOn, tv, true);
+ int colorOn = tv.data;
+ getTheme().resolveAttribute(R.attr.colorOff, tv, true);
+ int colorOff = tv.data;
+
+ // Create view
+ LayoutInflater inflater = LayoutInflater.from(this);
+ View view = inflater.inflate(R.layout.legend, null, false);
+ ImageView ivLockdownOn = view.findViewById(R.id.ivLockdownOn);
+ ImageView ivWifiOn = view.findViewById(R.id.ivWifiOn);
+ ImageView ivWifiOff = view.findViewById(R.id.ivWifiOff);
+ ImageView ivOtherOn = view.findViewById(R.id.ivOtherOn);
+ ImageView ivOtherOff = view.findViewById(R.id.ivOtherOff);
+ ImageView ivScreenOn = view.findViewById(R.id.ivScreenOn);
+ ImageView ivHostAllowed = view.findViewById(R.id.ivHostAllowed);
+ ImageView ivHostBlocked = view.findViewById(R.id.ivHostBlocked);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ Drawable wrapLockdownOn = DrawableCompat.wrap(ivLockdownOn.getDrawable());
+ Drawable wrapWifiOn = DrawableCompat.wrap(ivWifiOn.getDrawable());
+ Drawable wrapWifiOff = DrawableCompat.wrap(ivWifiOff.getDrawable());
+ Drawable wrapOtherOn = DrawableCompat.wrap(ivOtherOn.getDrawable());
+ Drawable wrapOtherOff = DrawableCompat.wrap(ivOtherOff.getDrawable());
+ Drawable wrapScreenOn = DrawableCompat.wrap(ivScreenOn.getDrawable());
+ Drawable wrapHostAllowed = DrawableCompat.wrap(ivHostAllowed.getDrawable());
+ Drawable wrapHostBlocked = DrawableCompat.wrap(ivHostBlocked.getDrawable());
+
+ DrawableCompat.setTint(wrapLockdownOn, colorOff);
+ DrawableCompat.setTint(wrapWifiOn, colorOn);
+ DrawableCompat.setTint(wrapWifiOff, colorOff);
+ DrawableCompat.setTint(wrapOtherOn, colorOn);
+ DrawableCompat.setTint(wrapOtherOff, colorOff);
+ DrawableCompat.setTint(wrapScreenOn, colorOn);
+ DrawableCompat.setTint(wrapHostAllowed, colorOn);
+ DrawableCompat.setTint(wrapHostBlocked, colorOff);
+ }
+
+
+ // Show dialog
+ dialogLegend = new AlertDialog.Builder(this)
+ .setView(view)
+ .setCancelable(true)
+ .setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialogInterface) {
+ dialogLegend = null;
+ }
+ })
+ .create();
+ dialogLegend.show();
+ }
+
+ private void menu_lockdown(MenuItem item) {
+ item.setChecked(!item.isChecked());
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.edit().putBoolean("lockdown", item.isChecked()).apply();
+ ServiceSinkhole.reload("lockdown", this, false);
+ WidgetLockdown.updateWidgets(this);
+ }
+
+ private void menu_about() {
+ // Create view
+ LayoutInflater inflater = LayoutInflater.from(this);
+ View view = inflater.inflate(R.layout.about, null, false);
+ TextView tvVersionName = view.findViewById(R.id.tvVersionName);
+ TextView tvVersionCode = view.findViewById(R.id.tvVersionCode);
+ Button btnRate = view.findViewById(R.id.btnRate);
+ TextView tvEula = view.findViewById(R.id.tvEula);
+ TextView tvPrivacy = view.findViewById(R.id.tvPrivacy);
+
+ // Show version
+ tvVersionName.setText(Util.getSelfVersionName(this));
+ if (!Util.hasValidFingerprint(this))
+ tvVersionName.setTextColor(Color.GRAY);
+ tvVersionCode.setText(Integer.toString(Util.getSelfVersionCode(this)));
+
+ // Handle license
+ tvEula.setMovementMethod(LinkMovementMethod.getInstance());
+ tvPrivacy.setMovementMethod(LinkMovementMethod.getInstance());
+
+ // Handle logcat
+ view.setOnClickListener(new View.OnClickListener() {
+ private short tap = 0;
+ private Toast toast = Toast.makeText(ActivityMain.this, "", Toast.LENGTH_SHORT);
+
+ @Override
+ public void onClick(View view) {
+ tap++;
+ if (tap == 7) {
+ tap = 0;
+ toast.cancel();
+
+ Intent intent = getIntentLogcat();
+ if (intent.resolveActivity(getPackageManager()) != null)
+ startActivityForResult(intent, REQUEST_LOGCAT);
+
+ } else if (tap > 3) {
+ toast.setText(Integer.toString(7 - tap));
+ toast.show();
+ }
+ }
+ });
+
+ // Handle rate
+ btnRate.setVisibility(getIntentRate(this).resolveActivity(getPackageManager()) == null ? View.GONE : View.VISIBLE);
+ btnRate.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(getIntentRate(ActivityMain.this));
+ }
+ });
+
+ // Show dialog
+ dialogAbout = new AlertDialog.Builder(this)
+ .setView(view)
+ .setCancelable(true)
+ .setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialogInterface) {
+ dialogAbout = null;
+ }
+ })
+ .create();
+ dialogAbout.show();
+ }
+
+ private void menu_apps() {
+ startActivity(getIntentApps(this));
+ }
+
+ private static Intent getIntentPro(Context context) {
+ if (Util.isPlayStoreInstall(context))
+ return new Intent(context, ActivityPro.class);
+ else {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse("https://contact.faircode.eu/?product=netguardstandalone"));
+ return intent;
+ }
+ }
+
+ private static Intent getIntentInvite(Context context) {
+ Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.setType("text/plain");
+ intent.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.app_name));
+ intent.putExtra(Intent.EXTRA_TEXT, context.getString(R.string.msg_try) + "\n\nhttps://www.netguard.me/\n\n");
+ return intent;
+ }
+
+ private static Intent getIntentApps(Context context) {
+ return new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/dev?id=8420080860664580239"));
+ }
+
+ private static Intent getIntentRate(Context context) {
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + context.getPackageName()));
+ if (intent.resolveActivity(context.getPackageManager()) == null)
+ intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + context.getPackageName()));
+ return intent;
+ }
+
+ private static Intent getIntentSupport() {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse("https://github.com/M66B/NetGuard/blob/master/FAQ.md"));
+ return intent;
+ }
+
+ private Intent getIntentLogcat() {
+ Intent intent;
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ if (Util.isPackageInstalled("org.openintents.filemanager", this)) {
+ intent = new Intent("org.openintents.action.PICK_DIRECTORY");
+ } else {
+ intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse("https://play.google.com/store/apps/details?id=org.openintents.filemanager"));
+ }
+ } else {
+ intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("text/plain");
+ intent.putExtra(Intent.EXTRA_TITLE, "logcat.txt");
+ }
+ return intent;
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityPro.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityPro.java
new file mode 100644
index 0000000..063d360
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ActivityPro.java
@@ -0,0 +1,447 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.app.PendingIntent;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Paint;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageButton;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.NavUtils;
+
+import static android.content.ClipDescription.MIMETYPE_TEXT_PLAIN;
+
+public class ActivityPro extends AppCompatActivity {
+ private static final String TAG = "NetGuard.Pro";
+
+ private IAB iab;
+
+ // adb shell pm clear com.android.vending
+ // android.test.purchased
+
+ private static final int SKU_LOG_ID = 1;
+ private static final int SKU_FILTER_ID = 2;
+ private static final int SKU_NOTIFY_ID = 3;
+ private static final int SKU_SPEED_ID = 4;
+ private static final int SKU_THEME_ID = 5;
+ private static final int SKU_PRO1_ID = 6;
+ private static final int SKU_SUPPORT1_ID = 7;
+ private static final int SKU_SUPPORT2_ID = 8;
+
+ public static final String SKU_LOG = "log";
+ public static final String SKU_FILTER = "filter";
+ public static final String SKU_NOTIFY = "notify";
+ public static final String SKU_SPEED = "speed";
+ public static final String SKU_THEME = "theme";
+ public static final String SKU_PRO1 = "pro1";
+ public static final String SKU_SUPPORT1 = "support1";
+ public static final String SKU_SUPPORT2 = "support2";
+ public static final String SKU_DONATION = "donation";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ Log.i(TAG, "Create");
+ Util.setTheme(this);
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.pro);
+
+ getSupportActionBar().setTitle(R.string.title_pro);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
+
+ // Initial state
+ updateState();
+
+ TextView tvLogTitle = findViewById(R.id.tvLogTitle);
+ TextView tvFilterTitle = findViewById(R.id.tvFilterTitle);
+ TextView tvNotifyTitle = findViewById(R.id.tvNotifyTitle);
+ TextView tvSpeedTitle = findViewById(R.id.tvSpeedTitle);
+ TextView tvThemeTitle = findViewById(R.id.tvThemeTitle);
+ TextView tvAllTitle = findViewById(R.id.tvAllTitle);
+ TextView tvDev1Title = findViewById(R.id.tvDev1Title);
+ TextView tvDev2Title = findViewById(R.id.tvDev2Title);
+
+ tvLogTitle.setPaintFlags(tvLogTitle.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
+ tvFilterTitle.setPaintFlags(tvLogTitle.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
+ tvNotifyTitle.setPaintFlags(tvLogTitle.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
+ tvSpeedTitle.setPaintFlags(tvLogTitle.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
+ tvThemeTitle.setPaintFlags(tvLogTitle.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
+ tvAllTitle.setPaintFlags(tvLogTitle.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
+ tvDev1Title.setPaintFlags(tvLogTitle.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
+ tvDev2Title.setPaintFlags(tvLogTitle.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
+
+ View.OnClickListener listener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ String sku;
+ switch (view.getId()) {
+ case R.id.tvLogTitle:
+ sku = SKU_LOG;
+ break;
+ case R.id.tvFilterTitle:
+ sku = SKU_FILTER;
+ break;
+ case R.id.tvNotifyTitle:
+ sku = SKU_NOTIFY;
+ break;
+ case R.id.tvSpeedTitle:
+ sku = SKU_SPEED;
+ break;
+ case R.id.tvThemeTitle:
+ sku = SKU_THEME;
+ break;
+ case R.id.tvAllTitle:
+ sku = SKU_PRO1;
+ break;
+ case R.id.tvDev1Title:
+ sku = SKU_SUPPORT1;
+ break;
+ case R.id.tvDev2Title:
+ sku = SKU_SUPPORT2;
+ break;
+ default:
+ sku = SKU_PRO1;
+ break;
+ }
+
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse("http://www.netguard.me/#" + sku));
+ if (intent.resolveActivity(getPackageManager()) != null)
+ startActivity(intent);
+ }
+ };
+
+ tvLogTitle.setOnClickListener(listener);
+ tvFilterTitle.setOnClickListener(listener);
+ tvNotifyTitle.setOnClickListener(listener);
+ tvSpeedTitle.setOnClickListener(listener);
+ tvThemeTitle.setOnClickListener(listener);
+ tvAllTitle.setOnClickListener(listener);
+ tvDev1Title.setOnClickListener(listener);
+ tvDev2Title.setOnClickListener(listener);
+
+ try {
+ iab = new IAB(new IAB.Delegate() {
+ @Override
+ public void onReady(final IAB iab) {
+ Log.i(TAG, "IAB ready");
+ try {
+ iab.updatePurchases();
+ updateState();
+
+ final Button btnLog = findViewById(R.id.btnLog);
+ final Button btnFilter = findViewById(R.id.btnFilter);
+ final Button btnNotify = findViewById(R.id.btnNotify);
+ final Button btnSpeed = findViewById(R.id.btnSpeed);
+ final Button btnTheme = findViewById(R.id.btnTheme);
+ final Button btnAll = findViewById(R.id.btnAll);
+ final Button btnDev1 = findViewById(R.id.btnDev1);
+ final Button btnDev2 = findViewById(R.id.btnDev2);
+
+ View.OnClickListener listener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ try {
+ int id = 0;
+ PendingIntent pi = null;
+ if (view == btnLog) {
+ id = SKU_LOG_ID;
+ pi = iab.getBuyIntent(SKU_LOG, false);
+ } else if (view == btnFilter) {
+ id = SKU_FILTER_ID;
+ pi = iab.getBuyIntent(SKU_FILTER, false);
+ } else if (view == btnNotify) {
+ id = SKU_NOTIFY_ID;
+ pi = iab.getBuyIntent(SKU_NOTIFY, false);
+ } else if (view == btnSpeed) {
+ id = SKU_SPEED_ID;
+ pi = iab.getBuyIntent(SKU_SPEED, false);
+ } else if (view == btnTheme) {
+ id = SKU_THEME_ID;
+ pi = iab.getBuyIntent(SKU_THEME, false);
+ } else if (view == btnAll) {
+ id = SKU_PRO1_ID;
+ pi = iab.getBuyIntent(SKU_PRO1, false);
+ } else if (view == btnDev1) {
+ id = SKU_SUPPORT1_ID;
+ pi = iab.getBuyIntent(SKU_SUPPORT1, true);
+ } else if (view == btnDev2) {
+ id = SKU_SUPPORT2_ID;
+ pi = iab.getBuyIntent(SKU_SUPPORT2, true);
+ }
+
+ if (id > 0 && pi != null)
+ startIntentSenderForResult(pi.getIntentSender(), id, new Intent(), 0, 0, 0);
+ } catch (Throwable ex) {
+ Log.i(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+ };
+
+ btnLog.setOnClickListener(listener);
+ btnFilter.setOnClickListener(listener);
+ btnNotify.setOnClickListener(listener);
+ btnSpeed.setOnClickListener(listener);
+ btnTheme.setOnClickListener(listener);
+ btnAll.setOnClickListener(listener);
+ btnDev1.setOnClickListener(listener);
+ btnDev2.setOnClickListener(listener);
+
+ btnLog.setEnabled(true);
+ btnFilter.setEnabled(true);
+ btnNotify.setEnabled(true);
+ btnSpeed.setEnabled(true);
+ btnTheme.setEnabled(true);
+ btnAll.setEnabled(true);
+ btnDev1.setEnabled(true);
+ btnDev2.setEnabled(true);
+
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+ }, this);
+ iab.bind();
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ Log.i(TAG, "Destroy");
+ iab.unbind();
+ iab = null;
+ super.onDestroy();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.pro, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ Log.i(TAG, "Up");
+ NavUtils.navigateUpFromSameTask(this);
+ return true;
+ case R.id.menu_challenge:
+ menu_challenge();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ if (IAB.isPurchased(SKU_DONATION, this) || Util.isPlayStoreInstall(this))
+ menu.removeItem(R.id.menu_challenge);
+
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ private void menu_challenge() {
+ LayoutInflater inflater = LayoutInflater.from(this);
+ View view = inflater.inflate(R.layout.challenge, null, false);
+
+ final AlertDialog dialog = new AlertDialog.Builder(this)
+ .setView(view)
+ .setCancelable(true)
+ .create();
+
+ String android_id = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
+ final String challenge = (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? Build.SERIAL : "O3" + android_id);
+ String seed = (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? "NetGuard2" : "NetGuard3");
+
+ // Challenge
+ TextView tvChallenge = view.findViewById(R.id.tvChallenge);
+ tvChallenge.setText(challenge);
+
+ ImageButton ibCopy = view.findViewById(R.id.ibCopy);
+ ibCopy.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
+ ClipData clip = ClipData.newPlainText(getString(R.string.title_pro_challenge), challenge);
+ clipboard.setPrimaryClip(clip);
+ Toast.makeText(ActivityPro.this, android.R.string.copy, Toast.LENGTH_LONG).show();
+ }
+ });
+
+ // Response
+ final EditText etResponse = view.findViewById(R.id.etResponse);
+ try {
+ final String response = Util.md5(challenge, seed);
+ etResponse.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ // Do nothing
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ // Do nothing
+ }
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ if (response.equals(editable.toString().toUpperCase())) {
+ IAB.setBought(SKU_DONATION, ActivityPro.this);
+ dialog.dismiss();
+ invalidateOptionsMenu();
+ updateState();
+ }
+ }
+ });
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ ImageButton ibPaste = view.findViewById(R.id.ibPaste);
+ ibPaste.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
+ if (clipboard != null &&
+ clipboard.hasPrimaryClip() &&
+ clipboard.getPrimaryClipDescription().hasMimeType(MIMETYPE_TEXT_PLAIN)) {
+ ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);
+ etResponse.setText(item.getText().toString());
+ }
+ }
+ });
+
+ dialog.show();
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (resultCode == RESULT_OK) {
+ switch (requestCode) {
+ case SKU_LOG_ID:
+ IAB.setBought(SKU_LOG, this);
+ updateState();
+ break;
+ case SKU_FILTER_ID:
+ IAB.setBought(SKU_FILTER, this);
+ updateState();
+ break;
+ case SKU_NOTIFY_ID:
+ IAB.setBought(SKU_NOTIFY, this);
+ updateState();
+ break;
+ case SKU_SPEED_ID:
+ IAB.setBought(SKU_SPEED, this);
+ updateState();
+ break;
+ case SKU_THEME_ID:
+ IAB.setBought(SKU_THEME, this);
+ updateState();
+ break;
+ case SKU_PRO1_ID:
+ IAB.setBought(SKU_PRO1, this);
+ updateState();
+ break;
+ case SKU_SUPPORT1_ID:
+ IAB.setBought(SKU_SUPPORT1, this);
+ updateState();
+ break;
+ case SKU_SUPPORT2_ID:
+ IAB.setBought(SKU_SUPPORT2, this);
+ updateState();
+ break;
+ }
+ }
+ }
+
+ private void updateState() {
+ Button btnLog = findViewById(R.id.btnLog);
+ Button btnFilter = findViewById(R.id.btnFilter);
+ Button btnNotify = findViewById(R.id.btnNotify);
+ Button btnSpeed = findViewById(R.id.btnSpeed);
+ Button btnTheme = findViewById(R.id.btnTheme);
+ Button btnAll = findViewById(R.id.btnAll);
+ Button btnDev1 = findViewById(R.id.btnDev1);
+ Button btnDev2 = findViewById(R.id.btnDev2);
+ TextView tvLog = findViewById(R.id.tvLog);
+ TextView tvFilter = findViewById(R.id.tvFilter);
+ TextView tvNotify = findViewById(R.id.tvNotify);
+ TextView tvSpeed = findViewById(R.id.tvSpeed);
+ TextView tvTheme = findViewById(R.id.tvTheme);
+ TextView tvAll = findViewById(R.id.tvAll);
+ TextView tvDev1 = findViewById(R.id.tvDev1);
+ TextView tvDev2 = findViewById(R.id.tvDev2);
+
+ TextView tvLogUnavailable = findViewById(R.id.tvLogUnavailable);
+ TextView tvFilterUnavailable = findViewById(R.id.tvFilterUnavailable);
+
+ boolean can = Util.canFilter(this);
+
+ btnLog.setVisibility(IAB.isPurchased(SKU_LOG, this) || !can ? View.GONE : View.VISIBLE);
+ btnFilter.setVisibility(IAB.isPurchased(SKU_FILTER, this) || !can ? View.GONE : View.VISIBLE);
+ btnNotify.setVisibility(IAB.isPurchased(SKU_NOTIFY, this) ? View.GONE : View.VISIBLE);
+ btnSpeed.setVisibility(IAB.isPurchased(SKU_SPEED, this) ? View.GONE : View.VISIBLE);
+ btnTheme.setVisibility(IAB.isPurchased(SKU_THEME, this) ? View.GONE : View.VISIBLE);
+ btnAll.setVisibility(IAB.isPurchased(SKU_PRO1, this) ? View.GONE : View.VISIBLE);
+ btnDev1.setVisibility(IAB.isPurchased(SKU_SUPPORT1, this) ? View.GONE : View.VISIBLE);
+ btnDev2.setVisibility(IAB.isPurchased(SKU_SUPPORT2, this) ? View.GONE : View.VISIBLE);
+
+ tvLog.setVisibility(IAB.isPurchased(SKU_LOG, this) && can ? View.VISIBLE : View.GONE);
+ tvFilter.setVisibility(IAB.isPurchased(SKU_FILTER, this) && can ? View.VISIBLE : View.GONE);
+ tvNotify.setVisibility(IAB.isPurchased(SKU_NOTIFY, this) ? View.VISIBLE : View.GONE);
+ tvSpeed.setVisibility(IAB.isPurchased(SKU_SPEED, this) ? View.VISIBLE : View.GONE);
+ tvTheme.setVisibility(IAB.isPurchased(SKU_THEME, this) ? View.VISIBLE : View.GONE);
+ tvAll.setVisibility(IAB.isPurchased(SKU_PRO1, this) ? View.VISIBLE : View.GONE);
+ tvDev1.setVisibility(IAB.isPurchased(SKU_SUPPORT1, this) ? View.VISIBLE : View.GONE);
+ tvDev2.setVisibility(IAB.isPurchased(SKU_SUPPORT2, this) ? View.VISIBLE : View.GONE);
+
+ tvLogUnavailable.setVisibility(can ? View.GONE : View.VISIBLE);
+ tvFilterUnavailable.setVisibility(can ? View.GONE : View.VISIBLE);
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ActivitySettings.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ActivitySettings.java
new file mode 100644
index 0000000..5c38150
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ActivitySettings.java
@@ -0,0 +1,1466 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.Manifest;
+import android.annotation.TargetApi;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
+import android.net.ConnectivityManager;
+import android.net.Uri;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
+import android.preference.EditTextPreference;
+import android.preference.ListPreference;
+import android.preference.MultiSelectListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceGroup;
+import android.preference.PreferenceScreen;
+import android.preference.TwoStatePreference;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.TextUtils;
+import android.text.style.ImageSpan;
+import android.util.Log;
+import android.util.Xml;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.NavUtils;
+import androidx.core.util.PatternsCompat;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+import androidx.preference.PreferenceManager;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+
+public class ActivitySettings extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
+ private static final String TAG = "NetGuard.Settings";
+
+ private boolean running = false;
+
+ private static final int REQUEST_EXPORT = 1;
+ private static final int REQUEST_IMPORT = 2;
+ private static final int REQUEST_HOSTS = 3;
+ private static final int REQUEST_HOSTS_APPEND = 4;
+ private static final int REQUEST_CALL = 5;
+
+ private AlertDialog dialogFilter = null;
+
+ private static final Intent INTENT_VPN_SETTINGS = new Intent("android.net.vpn.SETTINGS");
+
+ protected void onCreate(Bundle savedInstanceState) {
+ Util.setTheme(this);
+ super.onCreate(savedInstanceState);
+ getFragmentManager().beginTransaction().replace(android.R.id.content, new FragmentSettings()).commit();
+ getSupportActionBar().setTitle(R.string.menu_settings);
+ running = true;
+ }
+
+ private PreferenceScreen getPreferenceScreen() {
+ return ((PreferenceFragment) getFragmentManager().findFragmentById(android.R.id.content)).getPreferenceScreen();
+ }
+
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+ final PreferenceScreen screen = getPreferenceScreen();
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+
+ PreferenceGroup cat_options = (PreferenceGroup) ((PreferenceGroup) screen.findPreference("screen_options")).findPreference("category_options");
+ PreferenceGroup cat_network = (PreferenceGroup) ((PreferenceGroup) screen.findPreference("screen_network_options")).findPreference("category_network_options");
+ PreferenceGroup cat_advanced = (PreferenceGroup) ((PreferenceGroup) screen.findPreference("screen_advanced_options")).findPreference("category_advanced_options");
+ PreferenceGroup cat_stats = (PreferenceGroup) ((PreferenceGroup) screen.findPreference("screen_stats")).findPreference("category_stats");
+ PreferenceGroup cat_backup = (PreferenceGroup) ((PreferenceGroup) screen.findPreference("screen_backup")).findPreference("category_backup");
+
+ // Handle auto enable
+ Preference pref_auto_enable = screen.findPreference("auto_enable");
+ pref_auto_enable.setTitle(getString(R.string.setting_auto, prefs.getString("auto_enable", "0")));
+
+ // Handle screen delay
+ Preference pref_screen_delay = screen.findPreference("screen_delay");
+ pref_screen_delay.setTitle(getString(R.string.setting_delay, prefs.getString("screen_delay", "0")));
+
+ // Handle theme
+ Preference pref_screen_theme = screen.findPreference("theme");
+ String theme = prefs.getString("theme", "teal");
+ String[] themeNames = getResources().getStringArray(R.array.themeNames);
+ String[] themeValues = getResources().getStringArray(R.array.themeValues);
+ for (int i = 0; i < themeNames.length; i++)
+ if (theme.equals(themeValues[i])) {
+ pref_screen_theme.setTitle(getString(R.string.setting_theme, themeNames[i]));
+ break;
+ }
+
+ // Wi-Fi home
+ MultiSelectListPreference pref_wifi_homes = (MultiSelectListPreference) screen.findPreference("wifi_homes");
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1)
+ cat_network.removePreference(pref_wifi_homes);
+ else {
+ Set ssids = prefs.getStringSet("wifi_homes", new HashSet());
+ if (ssids.size() > 0)
+ pref_wifi_homes.setTitle(getString(R.string.setting_wifi_home, TextUtils.join(", ", ssids)));
+ else
+ pref_wifi_homes.setTitle(getString(R.string.setting_wifi_home, "-"));
+
+ WifiManager wm = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+ List listSSID = new ArrayList<>();
+ List configs = wm.getConfiguredNetworks();
+ if (configs != null)
+ for (WifiConfiguration config : configs)
+ listSSID.add(config.SSID == null ? "NULL" : config.SSID);
+ for (String ssid : ssids)
+ if (!listSSID.contains(ssid))
+ listSSID.add(ssid);
+ pref_wifi_homes.setEntries(listSSID.toArray(new CharSequence[0]));
+ pref_wifi_homes.setEntryValues(listSSID.toArray(new CharSequence[0]));
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ TwoStatePreference pref_handover =
+ (TwoStatePreference) screen.findPreference("handover");
+ cat_advanced.removePreference(pref_handover);
+ }
+
+ Preference pref_reset_usage = screen.findPreference("reset_usage");
+ pref_reset_usage.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ Util.areYouSure(ActivitySettings.this, R.string.setting_reset_usage, new Util.DoubtListener() {
+ @Override
+ public void onSure() {
+ new AsyncTask() {
+ @Override
+ protected Throwable doInBackground(Object... objects) {
+ try {
+ DatabaseHelper.getInstance(ActivitySettings.this).resetUsage(-1);
+ return null;
+ } catch (Throwable ex) {
+ return ex;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Throwable ex) {
+ if (ex == null)
+ Toast.makeText(ActivitySettings.this, R.string.msg_completed, Toast.LENGTH_LONG).show();
+ else
+ Toast.makeText(ActivitySettings.this, ex.toString(), Toast.LENGTH_LONG).show();
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ });
+ return false;
+ }
+ });
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ TwoStatePreference pref_reload_onconnectivity =
+ (TwoStatePreference) screen.findPreference("reload_onconnectivity");
+ pref_reload_onconnectivity.setChecked(true);
+ pref_reload_onconnectivity.setEnabled(false);
+ }
+
+ // Handle port forwarding
+ Preference pref_forwarding = screen.findPreference("forwarding");
+ pref_forwarding.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ startActivity(new Intent(ActivitySettings.this, ActivityForwarding.class));
+ return true;
+ }
+ });
+
+ boolean can = Util.canFilter(this);
+ TwoStatePreference pref_log_app = (TwoStatePreference) screen.findPreference("log_app");
+ TwoStatePreference pref_filter = (TwoStatePreference) screen.findPreference("filter");
+ pref_log_app.setEnabled(can);
+ pref_filter.setEnabled(can);
+ if (!can) {
+ pref_log_app.setSummary(R.string.msg_unavailable);
+ pref_filter.setSummary(R.string.msg_unavailable);
+ }
+
+ // VPN parameters
+ screen.findPreference("vpn4").setTitle(getString(R.string.setting_vpn4, prefs.getString("vpn4", "10.1.10.1")));
+ screen.findPreference("vpn6").setTitle(getString(R.string.setting_vpn6, prefs.getString("vpn6", "fd00:1:fd00:1:fd00:1:fd00:1")));
+ EditTextPreference pref_dns1 = (EditTextPreference) screen.findPreference("dns");
+ EditTextPreference pref_dns2 = (EditTextPreference) screen.findPreference("dns2");
+ EditTextPreference pref_validate = (EditTextPreference) screen.findPreference("validate");
+ EditTextPreference pref_ttl = (EditTextPreference) screen.findPreference("ttl");
+ pref_dns1.setTitle(getString(R.string.setting_dns, prefs.getString("dns", "-")));
+ pref_dns2.setTitle(getString(R.string.setting_dns, prefs.getString("dns2", "-")));
+ pref_validate.setTitle(getString(R.string.setting_validate, prefs.getString("validate", "www.google.com")));
+ pref_ttl.setTitle(getString(R.string.setting_ttl, prefs.getString("ttl", "259200")));
+
+ // SOCKS5 parameters
+ screen.findPreference("socks5_addr").setTitle(getString(R.string.setting_socks5_addr, prefs.getString("socks5_addr", "-")));
+ screen.findPreference("socks5_port").setTitle(getString(R.string.setting_socks5_port, prefs.getString("socks5_port", "-")));
+ screen.findPreference("socks5_username").setTitle(getString(R.string.setting_socks5_username, prefs.getString("socks5_username", "-")));
+ screen.findPreference("socks5_password").setTitle(getString(R.string.setting_socks5_password, TextUtils.isEmpty(prefs.getString("socks5_username", "")) ? "-" : "*****"));
+
+ // PCAP parameters
+ screen.findPreference("pcap_record_size").setTitle(getString(R.string.setting_pcap_record_size, prefs.getString("pcap_record_size", "64")));
+ screen.findPreference("pcap_file_size").setTitle(getString(R.string.setting_pcap_file_size, prefs.getString("pcap_file_size", "2")));
+
+ // Watchdog
+ screen.findPreference("watchdog").setTitle(getString(R.string.setting_watchdog, prefs.getString("watchdog", "0")));
+
+ // Show resolved
+ Preference pref_show_resolved = screen.findPreference("show_resolved");
+ if (Util.isPlayStoreInstall(this))
+ cat_advanced.removePreference(pref_show_resolved);
+ else
+ pref_show_resolved.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ startActivity(new Intent(ActivitySettings.this, ActivityDns.class));
+ return true;
+ }
+ });
+
+ // Handle stats
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+ cat_stats.removePreference(screen.findPreference("show_top"));
+ EditTextPreference pref_stats_frequency = (EditTextPreference) screen.findPreference("stats_frequency");
+ EditTextPreference pref_stats_samples = (EditTextPreference) screen.findPreference("stats_samples");
+ pref_stats_frequency.setTitle(getString(R.string.setting_stats_frequency, prefs.getString("stats_frequency", "1000")));
+ pref_stats_samples.setTitle(getString(R.string.setting_stats_samples, prefs.getString("stats_samples", "90")));
+
+ // Handle export
+ Preference pref_export = screen.findPreference("export");
+ pref_export.setEnabled(getIntentCreateExport().resolveActivity(getPackageManager()) != null);
+ pref_export.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ startActivityForResult(getIntentCreateExport(), ActivitySettings.REQUEST_EXPORT);
+ return true;
+ }
+ });
+
+ // Handle import
+ Preference pref_import = screen.findPreference("import");
+ pref_import.setEnabled(getIntentOpenExport().resolveActivity(getPackageManager()) != null);
+ pref_import.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ startActivityForResult(getIntentOpenExport(), ActivitySettings.REQUEST_IMPORT);
+ return true;
+ }
+ });
+
+ // Hosts file settings
+ Preference pref_block_domains = screen.findPreference("use_hosts");
+ EditTextPreference pref_rcode = (EditTextPreference) screen.findPreference("rcode");
+ Preference pref_hosts_import = screen.findPreference("hosts_import");
+ Preference pref_hosts_import_append = screen.findPreference("hosts_import_append");
+ EditTextPreference pref_hosts_url = (EditTextPreference) screen.findPreference("hosts_url");
+ final Preference pref_hosts_download = screen.findPreference("hosts_download");
+
+ pref_rcode.setTitle(getString(R.string.setting_rcode, prefs.getString("rcode", "3")));
+
+ if (Util.isPlayStoreInstall(this) || !Util.hasValidFingerprint(this))
+ cat_options.removePreference(screen.findPreference("update_check"));
+
+ if (Util.isPlayStoreInstall(this)) {
+ Log.i(TAG, "Play store install");
+ cat_advanced.removePreference(pref_block_domains);
+ cat_advanced.removePreference(pref_rcode);
+ cat_advanced.removePreference(pref_forwarding);
+ cat_backup.removePreference(pref_hosts_import);
+ cat_backup.removePreference(pref_hosts_import_append);
+ cat_backup.removePreference(pref_hosts_url);
+ cat_backup.removePreference(pref_hosts_download);
+
+ } else {
+ String last_import = prefs.getString("hosts_last_import", null);
+ String last_download = prefs.getString("hosts_last_download", null);
+ if (last_import != null)
+ pref_hosts_import.setSummary(getString(R.string.msg_import_last, last_import));
+ if (last_download != null)
+ pref_hosts_download.setSummary(getString(R.string.msg_download_last, last_download));
+
+ // Handle hosts import
+ // https://github.com/Free-Software-for-Android/AdAway/wiki/HostsSources
+ pref_hosts_import.setEnabled(getIntentOpenHosts().resolveActivity(getPackageManager()) != null);
+ pref_hosts_import.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ startActivityForResult(getIntentOpenHosts(), ActivitySettings.REQUEST_HOSTS);
+ return true;
+ }
+ });
+ pref_hosts_import_append.setEnabled(pref_hosts_import.isEnabled());
+ pref_hosts_import_append.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ startActivityForResult(getIntentOpenHosts(), ActivitySettings.REQUEST_HOSTS_APPEND);
+ return true;
+ }
+ });
+
+ // Handle hosts file download
+ pref_hosts_url.setSummary(pref_hosts_url.getText());
+ pref_hosts_download.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ final File tmp = new File(getFilesDir(), "hosts.tmp");
+ final File hosts = new File(getFilesDir(), "hosts.txt");
+
+ EditTextPreference pref_hosts_url = (EditTextPreference) screen.findPreference("hosts_url");
+ String hosts_url = pref_hosts_url.getText();
+ if ("https://www.netguard.me/hosts".equals(hosts_url))
+ hosts_url = BuildConfig.HOSTS_FILE_URI;
+
+ try {
+ new DownloadTask(ActivitySettings.this, new URL(hosts_url), tmp, new DownloadTask.Listener() {
+ @Override
+ public void onCompleted() {
+ if (hosts.exists())
+ hosts.delete();
+ tmp.renameTo(hosts);
+
+ String last = SimpleDateFormat.getDateTimeInstance().format(new Date().getTime());
+ prefs.edit().putString("hosts_last_download", last).apply();
+
+ if (running) {
+ pref_hosts_download.setSummary(getString(R.string.msg_download_last, last));
+ Toast.makeText(ActivitySettings.this, R.string.msg_downloaded, Toast.LENGTH_LONG).show();
+ }
+
+ ServiceSinkhole.reload("hosts file download", ActivitySettings.this, false);
+ }
+
+ @Override
+ public void onCancelled() {
+ if (tmp.exists())
+ tmp.delete();
+ }
+
+ @Override
+ public void onException(Throwable ex) {
+ if (tmp.exists())
+ tmp.delete();
+
+ if (running)
+ Toast.makeText(ActivitySettings.this, ex.getMessage(), Toast.LENGTH_LONG).show();
+ }
+ }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ } catch (MalformedURLException ex) {
+ Toast.makeText(ActivitySettings.this, ex.toString(), Toast.LENGTH_LONG).show();
+ }
+ return true;
+ }
+ });
+ }
+
+ // Development
+ if (!Util.isDebuggable(this))
+ screen.removePreference(screen.findPreference("screen_development"));
+
+ // Handle technical info
+ Preference.OnPreferenceClickListener listener = new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ updateTechnicalInfo();
+ return true;
+ }
+ };
+
+ // Technical info
+ Preference pref_technical_info = screen.findPreference("technical_info");
+ Preference pref_technical_network = screen.findPreference("technical_network");
+ pref_technical_info.setEnabled(INTENT_VPN_SETTINGS.resolveActivity(this.getPackageManager()) != null);
+ pref_technical_info.setIntent(INTENT_VPN_SETTINGS);
+ pref_technical_info.setOnPreferenceClickListener(listener);
+ pref_technical_network.setOnPreferenceClickListener(listener);
+ updateTechnicalInfo();
+
+ markPro(screen.findPreference("theme"), ActivityPro.SKU_THEME);
+ markPro(screen.findPreference("install"), ActivityPro.SKU_NOTIFY);
+ markPro(screen.findPreference("show_stats"), ActivityPro.SKU_SPEED);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ checkPermissions(null);
+
+ // Listen for preference changes
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.registerOnSharedPreferenceChangeListener(this);
+
+ // Listen for interactive state changes
+ IntentFilter ifInteractive = new IntentFilter();
+ ifInteractive.addAction(Intent.ACTION_SCREEN_ON);
+ ifInteractive.addAction(Intent.ACTION_SCREEN_OFF);
+ registerReceiver(interactiveStateReceiver, ifInteractive);
+
+ // Listen for connectivity updates
+ IntentFilter ifConnectivity = new IntentFilter();
+ ifConnectivity.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ registerReceiver(connectivityChangedReceiver, ifConnectivity);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.unregisterOnSharedPreferenceChangeListener(this);
+
+ unregisterReceiver(interactiveStateReceiver);
+ unregisterReceiver(connectivityChangedReceiver);
+ }
+
+ @Override
+ protected void onDestroy() {
+ running = false;
+ if (dialogFilter != null) {
+ dialogFilter.dismiss();
+ dialogFilter = null;
+ }
+ super.onDestroy();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ Log.i(TAG, "Up");
+ NavUtils.navigateUpFromSameTask(this);
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @Override
+ @TargetApi(Build.VERSION_CODES.M)
+ public void onSharedPreferenceChanged(SharedPreferences prefs, String name) {
+ // Pro features
+ if ("theme".equals(name)) {
+ if (!"teal".equals(prefs.getString(name, "teal")) && !IAB.isPurchased(ActivityPro.SKU_THEME, this)) {
+ prefs.edit().putString(name, "teal").apply();
+ ((ListPreference) getPreferenceScreen().findPreference(name)).setValue("teal");
+ startActivity(new Intent(this, ActivityPro.class));
+ return;
+ }
+ } else if ("install".equals(name)) {
+ if (prefs.getBoolean(name, false) && !IAB.isPurchased(ActivityPro.SKU_NOTIFY, this)) {
+ prefs.edit().putBoolean(name, false).apply();
+ ((TwoStatePreference) getPreferenceScreen().findPreference(name)).setChecked(false);
+ startActivity(new Intent(this, ActivityPro.class));
+ return;
+ }
+ } else if ("show_stats".equals(name)) {
+ if (prefs.getBoolean(name, false) && !IAB.isPurchased(ActivityPro.SKU_SPEED, this)) {
+ prefs.edit().putBoolean(name, false).apply();
+ startActivity(new Intent(this, ActivityPro.class));
+ return;
+ }
+ ((TwoStatePreference) getPreferenceScreen().findPreference(name)).setChecked(prefs.getBoolean(name, false));
+ }
+
+ Object value = prefs.getAll().get(name);
+ if (value instanceof String && "".equals(value))
+ prefs.edit().remove(name).apply();
+
+ // Dependencies
+ if ("screen_on".equals(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ else if ("whitelist_wifi".equals(name) ||
+ "screen_wifi".equals(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ else if ("whitelist_other".equals(name) ||
+ "screen_other".equals(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ else if ("whitelist_roaming".equals(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ else if ("auto_enable".equals(name))
+ getPreferenceScreen().findPreference(name).setTitle(getString(R.string.setting_auto, prefs.getString(name, "0")));
+
+ else if ("screen_delay".equals(name))
+ getPreferenceScreen().findPreference(name).setTitle(getString(R.string.setting_delay, prefs.getString(name, "0")));
+
+ else if ("theme".equals(name) || "dark_theme".equals(name))
+ recreate();
+
+ else if ("subnet".equals(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ else if ("tethering".equals(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ else if ("lan".equals(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ else if ("ip6".equals(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ else if ("wifi_homes".equals(name)) {
+ MultiSelectListPreference pref_wifi_homes = (MultiSelectListPreference) getPreferenceScreen().findPreference(name);
+ Set ssid = prefs.getStringSet(name, new HashSet());
+ if (ssid.size() > 0)
+ pref_wifi_homes.setTitle(getString(R.string.setting_wifi_home, TextUtils.join(", ", ssid)));
+ else
+ pref_wifi_homes.setTitle(getString(R.string.setting_wifi_home, "-"));
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ } else if ("use_metered".equals(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ else if ("unmetered_2g".equals(name) ||
+ "unmetered_3g".equals(name) ||
+ "unmetered_4g".equals(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ else if ("national_roaming".equals(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ else if ("eu_roaming".equals(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ else if ("disable_on_call".equals(name)) {
+ if (prefs.getBoolean(name, false)) {
+ if (checkPermissions(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+ } else
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ } else if ("lockdown_wifi".equals(name) || "lockdown_other".equals(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ else if ("manage_system".equals(name)) {
+ boolean manage = prefs.getBoolean(name, false);
+ if (!manage)
+ prefs.edit().putBoolean("show_user", true).apply();
+ prefs.edit().putBoolean("show_system", manage).apply();
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ } else if ("log_app".equals(name)) {
+ Intent ruleset = new Intent(ActivityMain.ACTION_RULES_CHANGED);
+ LocalBroadcastManager.getInstance(this).sendBroadcast(ruleset);
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ } else if ("notify_access".equals(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ else if ("filter".equals(name)) {
+ // Show dialog
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && prefs.getBoolean(name, false)) {
+ LayoutInflater inflater = LayoutInflater.from(ActivitySettings.this);
+ View view = inflater.inflate(R.layout.filter, null, false);
+ dialogFilter = new AlertDialog.Builder(ActivitySettings.this)
+ .setView(view)
+ .setCancelable(false)
+ .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // Do nothing
+ }
+ })
+ .setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialogInterface) {
+ dialogFilter = null;
+ }
+ })
+ .create();
+ dialogFilter.show();
+ } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && !prefs.getBoolean(name, false)) {
+ prefs.edit().putBoolean(name, true).apply();
+ Toast.makeText(ActivitySettings.this, R.string.msg_filter4, Toast.LENGTH_SHORT).show();
+ }
+
+ ((TwoStatePreference) getPreferenceScreen().findPreference(name)).setChecked(prefs.getBoolean(name, false));
+
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ } else if ("use_hosts".equals(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ else if ("vpn4".equals(name)) {
+ String vpn4 = prefs.getString(name, null);
+ try {
+ checkAddress(vpn4, false);
+ prefs.edit().putString(name, vpn4.trim()).apply();
+ } catch (Throwable ex) {
+ prefs.edit().remove(name).apply();
+ ((EditTextPreference) getPreferenceScreen().findPreference(name)).setText(null);
+ if (!TextUtils.isEmpty(vpn4))
+ Toast.makeText(ActivitySettings.this, ex.toString(), Toast.LENGTH_LONG).show();
+ }
+ getPreferenceScreen().findPreference(name).setTitle(
+ getString(R.string.setting_vpn4, prefs.getString(name, "10.1.10.1")));
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ } else if ("vpn6".equals(name)) {
+ String vpn6 = prefs.getString(name, null);
+ try {
+ checkAddress(vpn6, false);
+ prefs.edit().putString(name, vpn6.trim()).apply();
+ } catch (Throwable ex) {
+ prefs.edit().remove(name).apply();
+ ((EditTextPreference) getPreferenceScreen().findPreference(name)).setText(null);
+ if (!TextUtils.isEmpty(vpn6))
+ Toast.makeText(ActivitySettings.this, ex.toString(), Toast.LENGTH_LONG).show();
+ }
+ getPreferenceScreen().findPreference(name).setTitle(
+ getString(R.string.setting_vpn6, prefs.getString(name, "fd00:1:fd00:1:fd00:1:fd00:1")));
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ } else if ("dns".equals(name) || "dns2".equals(name)) {
+ String dns = prefs.getString(name, null);
+ try {
+ checkAddress(dns, true);
+ prefs.edit().putString(name, dns.trim()).apply();
+ } catch (Throwable ex) {
+ prefs.edit().remove(name).apply();
+ ((EditTextPreference) getPreferenceScreen().findPreference(name)).setText(null);
+ if (!TextUtils.isEmpty(dns))
+ Toast.makeText(ActivitySettings.this, ex.toString(), Toast.LENGTH_LONG).show();
+ }
+ getPreferenceScreen().findPreference(name).setTitle(
+ getString(R.string.setting_dns, prefs.getString(name, "-")));
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ } else if ("validate".equals(name)) {
+ String host = prefs.getString(name, "www.google.com");
+ try {
+ checkDomain(host);
+ prefs.edit().putString(name, host.trim()).apply();
+ } catch (Throwable ex) {
+ prefs.edit().remove(name).apply();
+ ((EditTextPreference) getPreferenceScreen().findPreference(name)).setText(null);
+ if (!TextUtils.isEmpty(host))
+ Toast.makeText(ActivitySettings.this, ex.toString(), Toast.LENGTH_LONG).show();
+ }
+ getPreferenceScreen().findPreference(name).setTitle(
+ getString(R.string.setting_validate, prefs.getString(name, "www.google.com")));
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ } else if ("ttl".equals(name))
+ getPreferenceScreen().findPreference(name).setTitle(
+ getString(R.string.setting_ttl, prefs.getString(name, "259200")));
+
+ else if ("rcode".equals(name)) {
+ getPreferenceScreen().findPreference(name).setTitle(
+ getString(R.string.setting_rcode, prefs.getString(name, "3")));
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ } else if ("socks5_enabled".equals(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ else if ("socks5_addr".equals(name)) {
+ String socks5_addr = prefs.getString(name, null);
+ try {
+ if (!TextUtils.isEmpty(socks5_addr) && !Util.isNumericAddress(socks5_addr))
+ throw new IllegalArgumentException("Bad address");
+ } catch (Throwable ex) {
+ prefs.edit().remove(name).apply();
+ ((EditTextPreference) getPreferenceScreen().findPreference(name)).setText(null);
+ if (!TextUtils.isEmpty(socks5_addr))
+ Toast.makeText(ActivitySettings.this, ex.toString(), Toast.LENGTH_LONG).show();
+ }
+ getPreferenceScreen().findPreference(name).setTitle(
+ getString(R.string.setting_socks5_addr, prefs.getString(name, "-")));
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ } else if ("socks5_port".equals(name)) {
+ getPreferenceScreen().findPreference(name).setTitle(getString(R.string.setting_socks5_port, prefs.getString(name, "-")));
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ } else if ("socks5_username".equals(name)) {
+ getPreferenceScreen().findPreference(name).setTitle(getString(R.string.setting_socks5_username, prefs.getString(name, "-")));
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ } else if ("socks5_password".equals(name)) {
+ getPreferenceScreen().findPreference(name).setTitle(getString(R.string.setting_socks5_password, TextUtils.isEmpty(prefs.getString(name, "")) ? "-" : "*****"));
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ } else if ("pcap_record_size".equals(name) || "pcap_file_size".equals(name)) {
+ if ("pcap_record_size".equals(name))
+ getPreferenceScreen().findPreference(name).setTitle(getString(R.string.setting_pcap_record_size, prefs.getString(name, "64")));
+ else
+ getPreferenceScreen().findPreference(name).setTitle(getString(R.string.setting_pcap_file_size, prefs.getString(name, "2")));
+
+ ServiceSinkhole.setPcap(false, this);
+
+ File pcap_file = new File(getDir("data", MODE_PRIVATE), "netguard.pcap");
+ if (pcap_file.exists() && !pcap_file.delete())
+ Log.w(TAG, "Delete PCAP failed");
+
+ if (prefs.getBoolean("pcap", false))
+ ServiceSinkhole.setPcap(true, this);
+
+ } else if ("watchdog".equals(name)) {
+ getPreferenceScreen().findPreference(name).setTitle(getString(R.string.setting_watchdog, prefs.getString(name, "0")));
+ ServiceSinkhole.reload("changed " + name, this, false);
+
+ } else if ("show_stats".equals(name))
+ ServiceSinkhole.reloadStats("changed " + name, this);
+
+ else if ("stats_frequency".equals(name))
+ getPreferenceScreen().findPreference(name).setTitle(getString(R.string.setting_stats_frequency, prefs.getString(name, "1000")));
+
+ else if ("stats_samples".equals(name))
+ getPreferenceScreen().findPreference(name).setTitle(getString(R.string.setting_stats_samples, prefs.getString(name, "90")));
+
+ else if ("hosts_url".equals(name))
+ getPreferenceScreen().findPreference(name).setSummary(prefs.getString(name, BuildConfig.HOSTS_FILE_URI));
+
+ else if ("loglevel".equals(name))
+ ServiceSinkhole.reload("changed " + name, this, false);
+ }
+
+ @TargetApi(Build.VERSION_CODES.M)
+ private boolean checkPermissions(String name) {
+ PreferenceScreen screen = getPreferenceScreen();
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+
+ // Check if permission was revoked
+ if ((name == null || "disable_on_call".equals(name)) && prefs.getBoolean("disable_on_call", false))
+ if (!Util.hasPhoneStatePermission(this)) {
+ prefs.edit().putBoolean("disable_on_call", false).apply();
+ ((TwoStatePreference) screen.findPreference("disable_on_call")).setChecked(false);
+
+ requestPermissions(new String[]{Manifest.permission.READ_PHONE_STATE}, REQUEST_CALL);
+
+ if (name != null)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ PreferenceScreen screen = getPreferenceScreen();
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+
+ boolean granted = (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED);
+
+ if (requestCode == REQUEST_CALL) {
+ prefs.edit().putBoolean("disable_on_call", granted).apply();
+ ((TwoStatePreference) screen.findPreference("disable_on_call")).setChecked(granted);
+ }
+
+ if (granted)
+ ServiceSinkhole.reload("permission granted", this, false);
+ }
+
+ private void checkAddress(String address, boolean allow_local) throws IllegalArgumentException, UnknownHostException {
+ if (address != null)
+ address = address.trim();
+ if (TextUtils.isEmpty(address))
+ throw new IllegalArgumentException("Bad address");
+ if (!Util.isNumericAddress(address))
+ throw new IllegalArgumentException("Bad address");
+ if (!allow_local) {
+ InetAddress iaddr = InetAddress.getByName(address);
+ if (iaddr.isLoopbackAddress() || iaddr.isAnyLocalAddress())
+ throw new IllegalArgumentException("Bad address");
+ }
+ }
+
+ private void checkDomain(String address) throws IllegalArgumentException, UnknownHostException {
+ if (address != null)
+ address = address.trim();
+ if (TextUtils.isEmpty(address))
+ throw new IllegalArgumentException("Bad address");
+ if (Util.isNumericAddress(address))
+ throw new IllegalArgumentException("Bad address");
+ if (!PatternsCompat.DOMAIN_NAME.matcher(address).matches())
+ throw new IllegalArgumentException("Bad address");
+ }
+
+ private BroadcastReceiver interactiveStateReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Util.logExtras(intent);
+ updateTechnicalInfo();
+ }
+ };
+
+ private BroadcastReceiver connectivityChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Util.logExtras(intent);
+ updateTechnicalInfo();
+ }
+ };
+
+ private void markPro(Preference pref, String sku) {
+ if (sku == null || !IAB.isPurchased(sku, this)) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean dark = prefs.getBoolean("dark_theme", false);
+ SpannableStringBuilder ssb = new SpannableStringBuilder(" " + pref.getTitle());
+ ssb.setSpan(new ImageSpan(this, dark ? R.drawable.ic_shopping_cart_white_24dp : R.drawable.ic_shopping_cart_black_24dp), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ pref.setTitle(ssb);
+ }
+ }
+
+ private void updateTechnicalInfo() {
+ PreferenceScreen screen = getPreferenceScreen();
+ Preference pref_technical_info = screen.findPreference("technical_info");
+ Preference pref_technical_network = screen.findPreference("technical_network");
+
+ pref_technical_info.setSummary(Util.getGeneralInfo(this));
+ pref_technical_network.setSummary(Util.getNetworkInfo(this));
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
+ Log.i(TAG, "onActivityResult request=" + requestCode + " result=" + requestCode + " ok=" + (resultCode == RESULT_OK));
+ if (requestCode == REQUEST_EXPORT) {
+ if (resultCode == RESULT_OK && data != null)
+ handleExport(data);
+
+ } else if (requestCode == REQUEST_IMPORT) {
+ if (resultCode == RESULT_OK && data != null)
+ handleImport(data);
+
+ } else if (requestCode == REQUEST_HOSTS) {
+ if (resultCode == RESULT_OK && data != null)
+ handleHosts(data, false);
+
+ } else if (requestCode == REQUEST_HOSTS_APPEND) {
+ if (resultCode == RESULT_OK && data != null)
+ handleHosts(data, true);
+
+ } else {
+ Log.w(TAG, "Unknown activity result request=" + requestCode);
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+
+ private Intent getIntentCreateExport() {
+ Intent intent;
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ if (Util.isPackageInstalled("org.openintents.filemanager", this)) {
+ intent = new Intent("org.openintents.action.PICK_DIRECTORY");
+ } else {
+ intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse("https://play.google.com/store/apps/details?id=org.openintents.filemanager"));
+ }
+ } else {
+ intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("*/*"); // text/xml
+ intent.putExtra(Intent.EXTRA_TITLE, "netguard_" + new SimpleDateFormat("yyyyMMdd").format(new Date().getTime()) + ".xml");
+ }
+ return intent;
+ }
+
+ private Intent getIntentOpenExport() {
+ Intent intent;
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
+ intent = new Intent(Intent.ACTION_GET_CONTENT);
+ else
+ intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("*/*"); // text/xml
+ return intent;
+ }
+
+ private Intent getIntentOpenHosts() {
+ Intent intent;
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
+ intent = new Intent(Intent.ACTION_GET_CONTENT);
+ else
+ intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("*/*"); // text/plain
+ return intent;
+ }
+
+ private void handleExport(final Intent data) {
+ new AsyncTask() {
+ @Override
+ protected Throwable doInBackground(Object... objects) {
+ OutputStream out = null;
+ try {
+ Uri target = data.getData();
+ if (data.hasExtra("org.openintents.extra.DIR_PATH"))
+ target = Uri.parse(target + "/netguard_" + new SimpleDateFormat("yyyyMMdd").format(new Date().getTime()) + ".xml");
+ Log.i(TAG, "Writing URI=" + target);
+ out = getContentResolver().openOutputStream(target);
+ xmlExport(out);
+ return null;
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ return ex;
+ } finally {
+ if (out != null)
+ try {
+ out.close();
+ } catch (IOException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Throwable ex) {
+ if (running) {
+ if (ex == null)
+ Toast.makeText(ActivitySettings.this, R.string.msg_completed, Toast.LENGTH_LONG).show();
+ else
+ Toast.makeText(ActivitySettings.this, ex.toString(), Toast.LENGTH_LONG).show();
+ }
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ private void handleHosts(final Intent data, final boolean append) {
+ new AsyncTask() {
+ @Override
+ protected Throwable doInBackground(Object... objects) {
+ File hosts = new File(getFilesDir(), "hosts.txt");
+
+ FileOutputStream out = null;
+ InputStream in = null;
+ try {
+ Log.i(TAG, "Reading URI=" + data.getData());
+ ContentResolver resolver = getContentResolver();
+ String[] streamTypes = resolver.getStreamTypes(data.getData(), "*/*");
+ String streamType = (streamTypes == null || streamTypes.length == 0 ? "*/*" : streamTypes[0]);
+ AssetFileDescriptor descriptor = resolver.openTypedAssetFileDescriptor(data.getData(), streamType, null);
+ in = descriptor.createInputStream();
+ out = new FileOutputStream(hosts, append);
+
+ int len;
+ long total = 0;
+ byte[] buf = new byte[4096];
+ while ((len = in.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ total += len;
+ }
+ Log.i(TAG, "Copied bytes=" + total);
+
+ return null;
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ return ex;
+ } finally {
+ if (out != null)
+ try {
+ out.close();
+ } catch (IOException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ if (in != null)
+ try {
+ in.close();
+ } catch (IOException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Throwable ex) {
+ if (running) {
+ if (ex == null) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ActivitySettings.this);
+ String last = SimpleDateFormat.getDateTimeInstance().format(new Date().getTime());
+ prefs.edit().putString("hosts_last_import", last).apply();
+
+ if (running) {
+ getPreferenceScreen().findPreference("hosts_import").setSummary(getString(R.string.msg_import_last, last));
+ Toast.makeText(ActivitySettings.this, R.string.msg_completed, Toast.LENGTH_LONG).show();
+ }
+
+ ServiceSinkhole.reload("hosts import", ActivitySettings.this, false);
+ } else
+ Toast.makeText(ActivitySettings.this, ex.toString(), Toast.LENGTH_LONG).show();
+ }
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ private void handleImport(final Intent data) {
+ new AsyncTask() {
+ @Override
+ protected Throwable doInBackground(Object... objects) {
+ InputStream in = null;
+ try {
+ Log.i(TAG, "Reading URI=" + data.getData());
+ ContentResolver resolver = getContentResolver();
+ String[] streamTypes = resolver.getStreamTypes(data.getData(), "*/*");
+ String streamType = (streamTypes == null || streamTypes.length == 0 ? "*/*" : streamTypes[0]);
+ AssetFileDescriptor descriptor = resolver.openTypedAssetFileDescriptor(data.getData(), streamType, null);
+ in = descriptor.createInputStream();
+ xmlImport(in);
+ return null;
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ return ex;
+ } finally {
+ if (in != null)
+ try {
+ in.close();
+ } catch (IOException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Throwable ex) {
+ if (running) {
+ if (ex == null) {
+ Toast.makeText(ActivitySettings.this, R.string.msg_completed, Toast.LENGTH_LONG).show();
+ ServiceSinkhole.reloadStats("import", ActivitySettings.this);
+ // Update theme, request permissions
+ recreate();
+ } else
+ Toast.makeText(ActivitySettings.this, ex.toString(), Toast.LENGTH_LONG).show();
+ }
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ private void xmlExport(OutputStream out) throws IOException {
+ XmlSerializer serializer = Xml.newSerializer();
+ serializer.setOutput(out, "UTF-8");
+ serializer.startDocument(null, true);
+ serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+ serializer.startTag(null, "netguard");
+
+ serializer.startTag(null, "application");
+ xmlExport(PreferenceManager.getDefaultSharedPreferences(this), serializer);
+ serializer.endTag(null, "application");
+
+ serializer.startTag(null, "wifi");
+ xmlExport(getSharedPreferences("wifi", Context.MODE_PRIVATE), serializer);
+ serializer.endTag(null, "wifi");
+
+ serializer.startTag(null, "mobile");
+ xmlExport(getSharedPreferences("other", Context.MODE_PRIVATE), serializer);
+ serializer.endTag(null, "mobile");
+
+ serializer.startTag(null, "screen_wifi");
+ xmlExport(getSharedPreferences("screen_wifi", Context.MODE_PRIVATE), serializer);
+ serializer.endTag(null, "screen_wifi");
+
+ serializer.startTag(null, "screen_other");
+ xmlExport(getSharedPreferences("screen_other", Context.MODE_PRIVATE), serializer);
+ serializer.endTag(null, "screen_other");
+
+ serializer.startTag(null, "roaming");
+ xmlExport(getSharedPreferences("roaming", Context.MODE_PRIVATE), serializer);
+ serializer.endTag(null, "roaming");
+
+ serializer.startTag(null, "lockdown");
+ xmlExport(getSharedPreferences("lockdown", Context.MODE_PRIVATE), serializer);
+ serializer.endTag(null, "lockdown");
+
+ serializer.startTag(null, "apply");
+ xmlExport(getSharedPreferences("apply", Context.MODE_PRIVATE), serializer);
+ serializer.endTag(null, "apply");
+
+ serializer.startTag(null, "notify");
+ xmlExport(getSharedPreferences("notify", Context.MODE_PRIVATE), serializer);
+ serializer.endTag(null, "notify");
+
+ serializer.startTag(null, "filter");
+ filterExport(serializer);
+ serializer.endTag(null, "filter");
+
+ serializer.startTag(null, "forward");
+ forwardExport(serializer);
+ serializer.endTag(null, "forward");
+
+ serializer.endTag(null, "netguard");
+ serializer.endDocument();
+ serializer.flush();
+ }
+
+ private void xmlExport(SharedPreferences prefs, XmlSerializer serializer) throws IOException {
+ Map settings = prefs.getAll();
+ for (String key : settings.keySet()) {
+ Object value = settings.get(key);
+
+ if ("imported".equals(key))
+ continue;
+
+ if (value instanceof Boolean) {
+ serializer.startTag(null, "setting");
+ serializer.attribute(null, "key", key);
+ serializer.attribute(null, "type", "boolean");
+ serializer.attribute(null, "value", value.toString());
+ serializer.endTag(null, "setting");
+
+ } else if (value instanceof Integer) {
+ serializer.startTag(null, "setting");
+ serializer.attribute(null, "key", key);
+ serializer.attribute(null, "type", "integer");
+ serializer.attribute(null, "value", value.toString());
+ serializer.endTag(null, "setting");
+
+ } else if (value instanceof String) {
+ serializer.startTag(null, "setting");
+ serializer.attribute(null, "key", key);
+ serializer.attribute(null, "type", "string");
+ serializer.attribute(null, "value", value.toString());
+ serializer.endTag(null, "setting");
+
+ } else if (value instanceof Set) {
+ Set set = (Set) value;
+ serializer.startTag(null, "setting");
+ serializer.attribute(null, "key", key);
+ serializer.attribute(null, "type", "set");
+ serializer.attribute(null, "value", TextUtils.join("\n", set));
+ serializer.endTag(null, "setting");
+
+ } else
+ Log.e(TAG, "Unknown key=" + key);
+ }
+ }
+
+ private void filterExport(XmlSerializer serializer) throws IOException {
+ try (Cursor cursor = DatabaseHelper.getInstance(this).getAccess()) {
+ int colUid = cursor.getColumnIndex("uid");
+ int colVersion = cursor.getColumnIndex("version");
+ int colProtocol = cursor.getColumnIndex("protocol");
+ int colDAddr = cursor.getColumnIndex("daddr");
+ int colDPort = cursor.getColumnIndex("dport");
+ int colTime = cursor.getColumnIndex("time");
+ int colBlock = cursor.getColumnIndex("block");
+ while (cursor.moveToNext())
+ for (String pkg : getPackages(cursor.getInt(colUid))) {
+ serializer.startTag(null, "rule");
+ serializer.attribute(null, "pkg", pkg);
+ serializer.attribute(null, "version", Integer.toString(cursor.getInt(colVersion)));
+ serializer.attribute(null, "protocol", Integer.toString(cursor.getInt(colProtocol)));
+ serializer.attribute(null, "daddr", cursor.getString(colDAddr));
+ serializer.attribute(null, "dport", Integer.toString(cursor.getInt(colDPort)));
+ serializer.attribute(null, "time", Long.toString(cursor.getLong(colTime)));
+ serializer.attribute(null, "block", Integer.toString(cursor.getInt(colBlock)));
+ serializer.endTag(null, "rule");
+ }
+ }
+ }
+
+ private void forwardExport(XmlSerializer serializer) throws IOException {
+ try (Cursor cursor = DatabaseHelper.getInstance(this).getForwarding()) {
+ int colProtocol = cursor.getColumnIndex("protocol");
+ int colDPort = cursor.getColumnIndex("dport");
+ int colRAddr = cursor.getColumnIndex("raddr");
+ int colRPort = cursor.getColumnIndex("rport");
+ int colRUid = cursor.getColumnIndex("ruid");
+ while (cursor.moveToNext())
+ for (String pkg : getPackages(cursor.getInt(colRUid))) {
+ serializer.startTag(null, "port");
+ serializer.attribute(null, "pkg", pkg);
+ serializer.attribute(null, "protocol", Integer.toString(cursor.getInt(colProtocol)));
+ serializer.attribute(null, "dport", Integer.toString(cursor.getInt(colDPort)));
+ serializer.attribute(null, "raddr", cursor.getString(colRAddr));
+ serializer.attribute(null, "rport", Integer.toString(cursor.getInt(colRPort)));
+ serializer.endTag(null, "port");
+ }
+ }
+ }
+
+ private String[] getPackages(int uid) {
+ if (uid == 0)
+ return new String[]{"root"};
+ else if (uid == 1013)
+ return new String[]{"mediaserver"};
+ else if (uid == 9999)
+ return new String[]{"nobody"};
+ else {
+ String pkgs[] = getPackageManager().getPackagesForUid(uid);
+ if (pkgs == null)
+ return new String[0];
+ else
+ return pkgs;
+ }
+ }
+
+ private void xmlImport(InputStream in) throws IOException, SAXException, ParserConfigurationException {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.unregisterOnSharedPreferenceChangeListener(this);
+ prefs.edit().putBoolean("enabled", false).apply();
+ ServiceSinkhole.stop("import", this, false);
+
+ XMLReader reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
+ XmlImportHandler handler = new XmlImportHandler(this);
+ reader.setContentHandler(handler);
+ reader.parse(new InputSource(in));
+
+ xmlImport(handler.application, prefs);
+ xmlImport(handler.wifi, getSharedPreferences("wifi", Context.MODE_PRIVATE));
+ xmlImport(handler.mobile, getSharedPreferences("other", Context.MODE_PRIVATE));
+ xmlImport(handler.screen_wifi, getSharedPreferences("screen_wifi", Context.MODE_PRIVATE));
+ xmlImport(handler.screen_other, getSharedPreferences("screen_other", Context.MODE_PRIVATE));
+ xmlImport(handler.roaming, getSharedPreferences("roaming", Context.MODE_PRIVATE));
+ xmlImport(handler.lockdown, getSharedPreferences("lockdown", Context.MODE_PRIVATE));
+ xmlImport(handler.apply, getSharedPreferences("apply", Context.MODE_PRIVATE));
+ xmlImport(handler.notify, getSharedPreferences("notify", Context.MODE_PRIVATE));
+
+ // Upgrade imported settings
+ ReceiverAutostart.upgrade(true, this);
+
+ DatabaseHelper.clearCache();
+
+ // Refresh UI
+ prefs.edit().putBoolean("imported", true).apply();
+ prefs.registerOnSharedPreferenceChangeListener(this);
+ }
+
+ private void xmlImport(Map settings, SharedPreferences prefs) {
+ SharedPreferences.Editor editor = prefs.edit();
+
+ // Clear existing setting
+ for (String key : prefs.getAll().keySet())
+ if (!"enabled".equals(key))
+ editor.remove(key);
+
+ // Apply new settings
+ for (String key : settings.keySet()) {
+ Object value = settings.get(key);
+ if (value instanceof Boolean)
+ editor.putBoolean(key, (Boolean) value);
+ else if (value instanceof Integer)
+ editor.putInt(key, (Integer) value);
+ else if (value instanceof String)
+ editor.putString(key, (String) value);
+ else if (value instanceof Set)
+ editor.putStringSet(key, (Set) value);
+ else
+ Log.e(TAG, "Unknown type=" + value.getClass());
+ }
+
+ editor.apply();
+ }
+
+ private class XmlImportHandler extends DefaultHandler {
+ private Context context;
+ public boolean enabled = false;
+ public Map application = new HashMap<>();
+ public Map wifi = new HashMap<>();
+ public Map mobile = new HashMap<>();
+ public Map screen_wifi = new HashMap<>();
+ public Map screen_other = new HashMap<>();
+ public Map roaming = new HashMap<>();
+ public Map lockdown = new HashMap<>();
+ public Map apply = new HashMap<>();
+ public Map notify = new HashMap<>();
+ private Map current = null;
+
+ public XmlImportHandler(Context context) {
+ this.context = context;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) {
+ if (qName.equals("netguard"))
+ ; // Ignore
+
+ else if (qName.equals("application"))
+ current = application;
+
+ else if (qName.equals("wifi"))
+ current = wifi;
+
+ else if (qName.equals("mobile"))
+ current = mobile;
+
+ else if (qName.equals("screen_wifi"))
+ current = screen_wifi;
+
+ else if (qName.equals("screen_other"))
+ current = screen_other;
+
+ else if (qName.equals("roaming"))
+ current = roaming;
+
+ else if (qName.equals("lockdown"))
+ current = lockdown;
+
+ else if (qName.equals("apply"))
+ current = apply;
+
+ else if (qName.equals("notify"))
+ current = notify;
+
+ else if (qName.equals("filter")) {
+ current = null;
+ Log.i(TAG, "Clearing filters");
+ DatabaseHelper.getInstance(context).clearAccess();
+
+ } else if (qName.equals("forward")) {
+ current = null;
+ Log.i(TAG, "Clearing forwards");
+ DatabaseHelper.getInstance(context).deleteForward();
+
+ } else if (qName.equals("setting")) {
+ String key = attributes.getValue("key");
+ String type = attributes.getValue("type");
+ String value = attributes.getValue("value");
+
+ if (current == null)
+ Log.e(TAG, "No current key=" + key);
+ else {
+ if ("enabled".equals(key))
+ enabled = Boolean.parseBoolean(value);
+ else {
+ if (current == application) {
+ // Pro features
+ if ("log".equals(key)) {
+ if (!IAB.isPurchased(ActivityPro.SKU_LOG, context))
+ return;
+ } else if ("theme".equals(key)) {
+ if (!IAB.isPurchased(ActivityPro.SKU_THEME, context))
+ return;
+ } else if ("show_stats".equals(key)) {
+ if (!IAB.isPurchased(ActivityPro.SKU_SPEED, context))
+ return;
+ }
+
+ if ("hosts_last_import".equals(key) || "hosts_last_download".equals(key))
+ return;
+ }
+
+ if ("boolean".equals(type))
+ current.put(key, Boolean.parseBoolean(value));
+ else if ("integer".equals(type))
+ current.put(key, Integer.parseInt(value));
+ else if ("string".equals(type))
+ current.put(key, value);
+ else if ("set".equals(type)) {
+ Set set = new HashSet<>();
+ if (!TextUtils.isEmpty(value))
+ for (String s : value.split("\n"))
+ set.add(s);
+ current.put(key, set);
+ } else
+ Log.e(TAG, "Unknown type key=" + key);
+ }
+ }
+
+ } else if (qName.equals("rule")) {
+ String pkg = attributes.getValue("pkg");
+
+ String version = attributes.getValue("version");
+ String protocol = attributes.getValue("protocol");
+
+ Packet packet = new Packet();
+ packet.version = (version == null ? 4 : Integer.parseInt(version));
+ packet.protocol = (protocol == null ? 6 /* TCP */ : Integer.parseInt(protocol));
+ packet.daddr = attributes.getValue("daddr");
+ packet.dport = Integer.parseInt(attributes.getValue("dport"));
+ packet.time = Long.parseLong(attributes.getValue("time"));
+
+ int block = Integer.parseInt(attributes.getValue("block"));
+
+ try {
+ packet.uid = getUid(pkg);
+ DatabaseHelper.getInstance(context).updateAccess(packet, null, block);
+ } catch (PackageManager.NameNotFoundException ex) {
+ Log.w(TAG, "Package not found pkg=" + pkg);
+ }
+
+ } else if (qName.equals("port")) {
+ String pkg = attributes.getValue("pkg");
+ int protocol = Integer.parseInt(attributes.getValue("protocol"));
+ int dport = Integer.parseInt(attributes.getValue("dport"));
+ String raddr = attributes.getValue("raddr");
+ int rport = Integer.parseInt(attributes.getValue("rport"));
+
+ try {
+ int uid = getUid(pkg);
+ DatabaseHelper.getInstance(context).addForward(protocol, dport, raddr, rport, uid);
+ } catch (PackageManager.NameNotFoundException ex) {
+ Log.w(TAG, "Package not found pkg=" + pkg);
+ }
+
+ } else
+ Log.e(TAG, "Unknown element qname=" + qName);
+ }
+
+ private int getUid(String pkg) throws PackageManager.NameNotFoundException {
+ if ("root".equals(pkg))
+ return 0;
+ else if ("android.media".equals(pkg))
+ return 1013;
+ else if ("android.multicast".equals(pkg))
+ return 1020;
+ else if ("android.gps".equals(pkg))
+ return 1021;
+ else if ("android.dns".equals(pkg))
+ return 1051;
+ else if ("nobody".equals(pkg))
+ return 9999;
+ else
+ return getPackageManager().getApplicationInfo(pkg, 0).uid;
+ }
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/AdapterAccess.java b/NetGuard/app/src/main/java/eu/faircode/netguard/AdapterAccess.java
new file mode 100644
index 0000000..1ddbc11
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/AdapterAccess.java
@@ -0,0 +1,186 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.database.Cursor;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.text.SpannableString;
+import android.text.style.UnderlineSpan;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CursorAdapter;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.core.graphics.drawable.DrawableCompat;
+import androidx.core.view.ViewCompat;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.text.SimpleDateFormat;
+
+public class AdapterAccess extends CursorAdapter {
+ private int colVersion;
+ private int colProtocol;
+ private int colDaddr;
+ private int colDPort;
+ private int colTime;
+ private int colAllowed;
+ private int colBlock;
+ private int colCount;
+ private int colSent;
+ private int colReceived;
+ private int colConnections;
+
+ private int colorText;
+ private int colorOn;
+ private int colorOff;
+
+ public AdapterAccess(Context context, Cursor cursor) {
+ super(context, cursor, 0);
+ colVersion = cursor.getColumnIndex("version");
+ colProtocol = cursor.getColumnIndex("protocol");
+ colDaddr = cursor.getColumnIndex("daddr");
+ colDPort = cursor.getColumnIndex("dport");
+ colTime = cursor.getColumnIndex("time");
+ colAllowed = cursor.getColumnIndex("allowed");
+ colBlock = cursor.getColumnIndex("block");
+ colCount = cursor.getColumnIndex("count");
+ colSent = cursor.getColumnIndex("sent");
+ colReceived = cursor.getColumnIndex("received");
+ colConnections = cursor.getColumnIndex("connections");
+
+ TypedArray ta = context.getTheme().obtainStyledAttributes(new int[]{android.R.attr.textColorSecondary});
+ try {
+ colorText = ta.getColor(0, 0);
+ } finally {
+ ta.recycle();
+ }
+
+ TypedValue tv = new TypedValue();
+ context.getTheme().resolveAttribute(R.attr.colorOn, tv, true);
+ colorOn = tv.data;
+ context.getTheme().resolveAttribute(R.attr.colorOff, tv, true);
+ colorOff = tv.data;
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return LayoutInflater.from(context).inflate(R.layout.access, parent, false);
+ }
+
+ @Override
+ public void bindView(final View view, final Context context, final Cursor cursor) {
+ // Get values
+ final int version = cursor.getInt(colVersion);
+ final int protocol = cursor.getInt(colProtocol);
+ final String daddr = cursor.getString(colDaddr);
+ final int dport = cursor.getInt(colDPort);
+ long time = cursor.getLong(colTime);
+ int allowed = cursor.getInt(colAllowed);
+ int block = cursor.getInt(colBlock);
+ int count = cursor.getInt(colCount);
+ long sent = cursor.isNull(colSent) ? -1 : cursor.getLong(colSent);
+ long received = cursor.isNull(colReceived) ? -1 : cursor.getLong(colReceived);
+ int connections = cursor.isNull(colConnections) ? -1 : cursor.getInt(colConnections);
+
+ // Get views
+ TextView tvTime = view.findViewById(R.id.tvTime);
+ ImageView ivBlock = view.findViewById(R.id.ivBlock);
+ final TextView tvDest = view.findViewById(R.id.tvDest);
+ LinearLayout llTraffic = view.findViewById(R.id.llTraffic);
+ TextView tvConnections = view.findViewById(R.id.tvConnections);
+ TextView tvTraffic = view.findViewById(R.id.tvTraffic);
+
+ // Set values
+ tvTime.setText(new SimpleDateFormat("dd HH:mm").format(time));
+ if (block < 0)
+ ivBlock.setImageDrawable(null);
+ else {
+ ivBlock.setImageResource(block > 0 ? R.drawable.host_blocked : R.drawable.host_allowed);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ Drawable wrap = DrawableCompat.wrap(ivBlock.getDrawable());
+ DrawableCompat.setTint(wrap, block > 0 ? colorOff : colorOn);
+ }
+ }
+
+ String dest = Util.getProtocolName(protocol, version, true) +
+ " " + daddr + (dport > 0 ? "/" + dport : "") + (count > 1 ? " ?" + count : "");
+ SpannableString span = new SpannableString(dest);
+ span.setSpan(new UnderlineSpan(), 0, dest.length(), 0);
+ tvDest.setText(span);
+
+ if (Util.isNumericAddress(daddr))
+ new AsyncTask() {
+ @Override
+ protected void onPreExecute() {
+ ViewCompat.setHasTransientState(tvDest, true);
+ }
+
+ @Override
+ protected String doInBackground(String... args) {
+ try {
+ return InetAddress.getByName(args[0]).getHostName();
+ } catch (UnknownHostException ignored) {
+ return args[0];
+ }
+ }
+
+ @Override
+ protected void onPostExecute(String addr) {
+ tvDest.setText(
+ Util.getProtocolName(protocol, version, true) +
+ " >" + addr + (dport > 0 ? "/" + dport : ""));
+ ViewCompat.setHasTransientState(tvDest, false);
+ }
+ }.execute(daddr);
+
+ if (allowed < 0)
+ tvDest.setTextColor(colorText);
+ else if (allowed > 0)
+ tvDest.setTextColor(colorOn);
+ else
+ tvDest.setTextColor(colorOff);
+
+ llTraffic.setVisibility(connections > 0 || sent > 0 || received > 0 ? View.VISIBLE : View.GONE);
+ if (connections > 0)
+ tvConnections.setText(context.getString(R.string.msg_count, connections));
+
+ if (sent > 1024 * 1204 * 1024L || received > 1024 * 1024 * 1024L)
+ tvTraffic.setText(context.getString(R.string.msg_gb,
+ (sent > 0 ? sent / (1024 * 1024 * 1024f) : 0),
+ (received > 0 ? received / (1024 * 1024 * 1024f) : 0)));
+ else if (sent > 1204 * 1024L || received > 1024 * 1024L)
+ tvTraffic.setText(context.getString(R.string.msg_mb,
+ (sent > 0 ? sent / (1024 * 1024f) : 0),
+ (received > 0 ? received / (1024 * 1024f) : 0)));
+ else
+ tvTraffic.setText(context.getString(R.string.msg_kb,
+ (sent > 0 ? sent / 1024f : 0),
+ (received > 0 ? received / 1024f : 0)));
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/AdapterDns.java b/NetGuard/app/src/main/java/eu/faircode/netguard/AdapterDns.java
new file mode 100644
index 0000000..6ddd7e6
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/AdapterDns.java
@@ -0,0 +1,95 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.graphics.Color;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CursorAdapter;
+import android.widget.TextView;
+
+import androidx.preference.PreferenceManager;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class AdapterDns extends CursorAdapter {
+ private int colorExpired;
+
+ private int colTime;
+ private int colQName;
+ private int colAName;
+ private int colResource;
+ private int colTTL;
+
+ public AdapterDns(Context context, Cursor cursor) {
+ super(context, cursor, 0);
+
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+
+ if (prefs.getBoolean("dark_theme", false))
+ colorExpired = Color.argb(128, Color.red(Color.DKGRAY), Color.green(Color.DKGRAY), Color.blue(Color.DKGRAY));
+ else
+ colorExpired = Color.argb(128, Color.red(Color.LTGRAY), Color.green(Color.LTGRAY), Color.blue(Color.LTGRAY));
+
+ colTime = cursor.getColumnIndex("time");
+ colQName = cursor.getColumnIndex("qname");
+ colAName = cursor.getColumnIndex("aname");
+ colResource = cursor.getColumnIndex("resource");
+ colTTL = cursor.getColumnIndex("ttl");
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return LayoutInflater.from(context).inflate(R.layout.dns, parent, false);
+ }
+
+ @Override
+ public void bindView(final View view, final Context context, final Cursor cursor) {
+ // Get values
+ long time = cursor.getLong(colTime);
+ String qname = cursor.getString(colQName);
+ String aname = cursor.getString(colAName);
+ String resource = cursor.getString(colResource);
+ int ttl = cursor.getInt(colTTL);
+
+ long now = new Date().getTime();
+ boolean expired = (time + ttl < now);
+ view.setBackgroundColor(expired ? colorExpired : Color.TRANSPARENT);
+
+ // Get views
+ TextView tvTime = view.findViewById(R.id.tvTime);
+ TextView tvQName = view.findViewById(R.id.tvQName);
+ TextView tvAName = view.findViewById(R.id.tvAName);
+ TextView tvResource = view.findViewById(R.id.tvResource);
+ TextView tvTTL = view.findViewById(R.id.tvTTL);
+
+ // Set values
+ tvTime.setText(new SimpleDateFormat("dd HH:mm").format(time));
+ tvQName.setText(qname);
+ tvAName.setText(aname);
+ tvResource.setText(resource);
+ tvTTL.setText("+" + Integer.toString(ttl / 1000));
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/AdapterForwarding.java b/NetGuard/app/src/main/java/eu/faircode/netguard/AdapterForwarding.java
new file mode 100644
index 0000000..44ceaa0
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/AdapterForwarding.java
@@ -0,0 +1,74 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.content.Context;
+import android.database.Cursor;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CursorAdapter;
+import android.widget.TextView;
+
+public class AdapterForwarding extends CursorAdapter {
+ private int colProtocol;
+ private int colDPort;
+ private int colRAddr;
+ private int colRPort;
+ private int colRUid;
+
+ public AdapterForwarding(Context context, Cursor cursor) {
+ super(context, cursor, 0);
+ colProtocol = cursor.getColumnIndex("protocol");
+ colDPort = cursor.getColumnIndex("dport");
+ colRAddr = cursor.getColumnIndex("raddr");
+ colRPort = cursor.getColumnIndex("rport");
+ colRUid = cursor.getColumnIndex("ruid");
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return LayoutInflater.from(context).inflate(R.layout.forward, parent, false);
+ }
+
+ @Override
+ public void bindView(final View view, final Context context, final Cursor cursor) {
+ // Get values
+ int protocol = cursor.getInt(colProtocol);
+ int dport = cursor.getInt(colDPort);
+ String raddr = cursor.getString(colRAddr);
+ int rport = cursor.getInt(colRPort);
+ int ruid = cursor.getInt(colRUid);
+
+ // Get views
+ TextView tvProtocol = view.findViewById(R.id.tvProtocol);
+ TextView tvDPort = view.findViewById(R.id.tvDPort);
+ TextView tvRAddr = view.findViewById(R.id.tvRAddr);
+ TextView tvRPort = view.findViewById(R.id.tvRPort);
+ TextView tvRUid = view.findViewById(R.id.tvRUid);
+
+ tvProtocol.setText(Util.getProtocolName(protocol, 0, false));
+ tvDPort.setText(Integer.toString(dport));
+ tvRAddr.setText(raddr);
+ tvRPort.setText(Integer.toString(rport));
+ tvRUid.setText(TextUtils.join(", ", Util.getApplicationNames(ruid, context)));
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/AdapterLog.java b/NetGuard/app/src/main/java/eu/faircode/netguard/AdapterLog.java
new file mode 100644
index 0000000..892bf79
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/AdapterLog.java
@@ -0,0 +1,370 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CursorAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.core.graphics.drawable.DrawableCompat;
+import androidx.core.view.ViewCompat;
+import androidx.preference.PreferenceManager;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.text.SimpleDateFormat;
+import java.util.List;
+
+public class AdapterLog extends CursorAdapter {
+ private static String TAG = "NetGuard.Log";
+
+ private boolean resolve;
+ private boolean organization;
+ private int colTime;
+ private int colVersion;
+ private int colProtocol;
+ private int colFlags;
+ private int colSAddr;
+ private int colSPort;
+ private int colDAddr;
+ private int colDPort;
+ private int colDName;
+ private int colUid;
+ private int colData;
+ private int colAllowed;
+ private int colConnection;
+ private int colInteractive;
+ private int colorOn;
+ private int colorOff;
+ private int iconSize;
+ private InetAddress dns1 = null;
+ private InetAddress dns2 = null;
+ private InetAddress vpn4 = null;
+ private InetAddress vpn6 = null;
+
+ public AdapterLog(Context context, Cursor cursor, boolean resolve, boolean organization) {
+ super(context, cursor, 0);
+ this.resolve = resolve;
+ this.organization = organization;
+ colTime = cursor.getColumnIndex("time");
+ colVersion = cursor.getColumnIndex("version");
+ colProtocol = cursor.getColumnIndex("protocol");
+ colFlags = cursor.getColumnIndex("flags");
+ colSAddr = cursor.getColumnIndex("saddr");
+ colSPort = cursor.getColumnIndex("sport");
+ colDAddr = cursor.getColumnIndex("daddr");
+ colDPort = cursor.getColumnIndex("dport");
+ colDName = cursor.getColumnIndex("dname");
+ colUid = cursor.getColumnIndex("uid");
+ colData = cursor.getColumnIndex("data");
+ colAllowed = cursor.getColumnIndex("allowed");
+ colConnection = cursor.getColumnIndex("connection");
+ colInteractive = cursor.getColumnIndex("interactive");
+
+ TypedValue tv = new TypedValue();
+ context.getTheme().resolveAttribute(R.attr.colorOn, tv, true);
+ colorOn = tv.data;
+ context.getTheme().resolveAttribute(R.attr.colorOff, tv, true);
+ colorOff = tv.data;
+
+ iconSize = Util.dips2pixels(24, context);
+
+ try {
+ List lstDns = ServiceSinkhole.getDns(context);
+ dns1 = (lstDns.size() > 0 ? lstDns.get(0) : null);
+ dns2 = (lstDns.size() > 1 ? lstDns.get(1) : null);
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ vpn4 = InetAddress.getByName(prefs.getString("vpn4", "10.1.10.1"));
+ vpn6 = InetAddress.getByName(prefs.getString("vpn6", "fd00:1:fd00:1:fd00:1:fd00:1"));
+ } catch (UnknownHostException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+
+ public void setResolve(boolean resolve) {
+ this.resolve = resolve;
+ }
+
+ public void setOrganization(boolean organization) {
+ this.organization = organization;
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return LayoutInflater.from(context).inflate(R.layout.log, parent, false);
+ }
+
+ @Override
+ public void bindView(final View view, final Context context, final Cursor cursor) {
+ // Get values
+ long time = cursor.getLong(colTime);
+ int version = (cursor.isNull(colVersion) ? -1 : cursor.getInt(colVersion));
+ int protocol = (cursor.isNull(colProtocol) ? -1 : cursor.getInt(colProtocol));
+ String flags = cursor.getString(colFlags);
+ String saddr = cursor.getString(colSAddr);
+ int sport = (cursor.isNull(colSPort) ? -1 : cursor.getInt(colSPort));
+ String daddr = cursor.getString(colDAddr);
+ int dport = (cursor.isNull(colDPort) ? -1 : cursor.getInt(colDPort));
+ String dname = (cursor.isNull(colDName) ? null : cursor.getString(colDName));
+ int uid = (cursor.isNull(colUid) ? -1 : cursor.getInt(colUid));
+ String data = cursor.getString(colData);
+ int allowed = (cursor.isNull(colAllowed) ? -1 : cursor.getInt(colAllowed));
+ int connection = (cursor.isNull(colConnection) ? -1 : cursor.getInt(colConnection));
+ int interactive = (cursor.isNull(colInteractive) ? -1 : cursor.getInt(colInteractive));
+
+ // Get views
+ TextView tvTime = view.findViewById(R.id.tvTime);
+ TextView tvProtocol = view.findViewById(R.id.tvProtocol);
+ TextView tvFlags = view.findViewById(R.id.tvFlags);
+ TextView tvSAddr = view.findViewById(R.id.tvSAddr);
+ TextView tvSPort = view.findViewById(R.id.tvSPort);
+ final TextView tvDaddr = view.findViewById(R.id.tvDAddr);
+ TextView tvDPort = view.findViewById(R.id.tvDPort);
+ final TextView tvOrganization = view.findViewById(R.id.tvOrganization);
+ final ImageView ivIcon = view.findViewById(R.id.ivIcon);
+ TextView tvUid = view.findViewById(R.id.tvUid);
+ TextView tvData = view.findViewById(R.id.tvData);
+ ImageView ivConnection = view.findViewById(R.id.ivConnection);
+ ImageView ivInteractive = view.findViewById(R.id.ivInteractive);
+
+ // Show time
+ tvTime.setText(new SimpleDateFormat("HH:mm:ss").format(time));
+
+ // Show connection type
+ if (connection <= 0)
+ ivConnection.setImageResource(allowed > 0 ? R.drawable.host_allowed : R.drawable.host_blocked);
+ else {
+ if (allowed > 0)
+ ivConnection.setImageResource(connection == 1 ? R.drawable.wifi_on : R.drawable.other_on);
+ else
+ ivConnection.setImageResource(connection == 1 ? R.drawable.wifi_off : R.drawable.other_off);
+ }
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ Drawable wrap = DrawableCompat.wrap(ivConnection.getDrawable());
+ DrawableCompat.setTint(wrap, allowed > 0 ? colorOn : colorOff);
+ }
+
+ // Show if screen on
+ if (interactive <= 0)
+ ivInteractive.setImageDrawable(null);
+ else {
+ ivInteractive.setImageResource(R.drawable.screen_on);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ Drawable wrap = DrawableCompat.wrap(ivInteractive.getDrawable());
+ DrawableCompat.setTint(wrap, colorOn);
+ }
+ }
+
+ // Show protocol name
+ tvProtocol.setText(Util.getProtocolName(protocol, version, false));
+
+ // SHow TCP flags
+ tvFlags.setText(flags);
+ tvFlags.setVisibility(TextUtils.isEmpty(flags) ? View.GONE : View.VISIBLE);
+
+ // Show source and destination port
+ if (protocol == 6 || protocol == 17) {
+ tvSPort.setText(sport < 0 ? "" : getKnownPort(sport));
+ tvDPort.setText(dport < 0 ? "" : getKnownPort(dport));
+ } else {
+ tvSPort.setText(sport < 0 ? "" : Integer.toString(sport));
+ tvDPort.setText(dport < 0 ? "" : Integer.toString(dport));
+ }
+
+ // Application icon
+ ApplicationInfo info = null;
+ PackageManager pm = context.getPackageManager();
+ String[] pkg = pm.getPackagesForUid(uid);
+ if (pkg != null && pkg.length > 0)
+ try {
+ info = pm.getApplicationInfo(pkg[0], 0);
+ } catch (PackageManager.NameNotFoundException ignored) {
+ }
+
+ if (info == null)
+ ivIcon.setImageDrawable(null);
+ else {
+ if (info.icon <= 0)
+ ivIcon.setImageResource(android.R.drawable.sym_def_app_icon);
+ else {
+ Uri uri = Uri.parse("android.resource://" + info.packageName + "/" + info.icon);
+ GlideApp.with(context)
+ .load(uri)
+ //.diskCacheStrategy(DiskCacheStrategy.NONE)
+ //.skipMemoryCache(true)
+ .override(iconSize, iconSize)
+ .into(ivIcon);
+ }
+ }
+
+ boolean we = (android.os.Process.myUid() == uid);
+
+ // https://android.googlesource.com/platform/system/core/+/master/include/private/android_filesystem_config.h
+ uid = uid % 100000; // strip off user ID
+ if (uid == -1)
+ tvUid.setText("");
+ else if (uid == 0)
+ tvUid.setText(context.getString(R.string.title_root));
+ else if (uid == 9999)
+ tvUid.setText("-"); // nobody
+ else
+ tvUid.setText(Integer.toString(uid));
+
+ // Show source address
+ tvSAddr.setText(getKnownAddress(saddr));
+
+ // Show destination address
+ if (!we && resolve && !isKnownAddress(daddr))
+ if (dname == null) {
+ tvDaddr.setText(daddr);
+ new AsyncTask() {
+ @Override
+ protected void onPreExecute() {
+ ViewCompat.setHasTransientState(tvDaddr, true);
+ }
+
+ @Override
+ protected String doInBackground(String... args) {
+ try {
+ return InetAddress.getByName(args[0]).getHostName();
+ } catch (UnknownHostException ignored) {
+ return args[0];
+ }
+ }
+
+ @Override
+ protected void onPostExecute(String name) {
+ tvDaddr.setText(">" + name);
+ ViewCompat.setHasTransientState(tvDaddr, false);
+ }
+ }.execute(daddr);
+ } else
+ tvDaddr.setText(dname);
+ else
+ tvDaddr.setText(getKnownAddress(daddr));
+
+ // Show organization
+ tvOrganization.setVisibility(View.GONE);
+ if (!we && organization) {
+ if (!isKnownAddress(daddr))
+ new AsyncTask() {
+ @Override
+ protected void onPreExecute() {
+ ViewCompat.setHasTransientState(tvOrganization, true);
+ }
+
+ @Override
+ protected String doInBackground(String... args) {
+ try {
+ return Util.getOrganization(args[0]);
+ } catch (Throwable ex) {
+ Log.w(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ return null;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(String organization) {
+ if (organization != null) {
+ tvOrganization.setText(organization);
+ tvOrganization.setVisibility(View.VISIBLE);
+ }
+ ViewCompat.setHasTransientState(tvOrganization, false);
+ }
+ }.execute(daddr);
+ }
+
+ // Show extra data
+ if (TextUtils.isEmpty(data)) {
+ tvData.setText("");
+ tvData.setVisibility(View.GONE);
+ } else {
+ tvData.setText(data);
+ tvData.setVisibility(View.VISIBLE);
+ }
+ }
+
+ public boolean isKnownAddress(String addr) {
+ try {
+ InetAddress a = InetAddress.getByName(addr);
+ if (a.equals(dns1) || a.equals(dns2) || a.equals(vpn4) || a.equals(vpn6))
+ return true;
+ } catch (UnknownHostException ignored) {
+ }
+ return false;
+ }
+
+ private String getKnownAddress(String addr) {
+ try {
+ InetAddress a = InetAddress.getByName(addr);
+ if (a.equals(dns1))
+ return "dns1";
+ if (a.equals(dns2))
+ return "dns2";
+ if (a.equals(vpn4) || a.equals(vpn6))
+ return "vpn";
+ } catch (UnknownHostException ignored) {
+ }
+ return addr;
+ }
+
+ private String getKnownPort(int port) {
+ // https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports
+ switch (port) {
+ case 7:
+ return "echo";
+ case 25:
+ return "smtp";
+ case 53:
+ return "dns";
+ case 80:
+ return "http";
+ case 110:
+ return "pop3";
+ case 143:
+ return "imap";
+ case 443:
+ return "https";
+ case 465:
+ return "smtps";
+ case 993:
+ return "imaps";
+ case 995:
+ return "pop3s";
+ default:
+ return Integer.toString(port);
+ }
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/AdapterRule.java b/NetGuard/app/src/main/java/eu/faircode/netguard/AdapterRule.java
new file mode 100644
index 0000000..81b1dd3
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/AdapterRule.java
@@ -0,0 +1,1033 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.annotation.TargetApi;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.content.res.TypedArray;
+import android.database.Cursor;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.style.ImageSpan;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.SubMenu;
+import android.view.TouchDelegate;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.CursorAdapter;
+import android.widget.Filter;
+import android.widget.Filterable;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.PopupMenu;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.core.app.NotificationManagerCompat;
+import androidx.core.content.ContextCompat;
+import androidx.core.graphics.drawable.DrawableCompat;
+import androidx.core.widget.CompoundButtonCompat;
+import androidx.preference.PreferenceManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.bumptech.glide.load.DecodeFormat;
+import com.bumptech.glide.request.RequestOptions;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class AdapterRule extends RecyclerView.Adapter implements Filterable {
+ private static final String TAG = "NetGuard.Adapter";
+
+ private View anchor;
+ private LayoutInflater inflater;
+ private RecyclerView rv;
+ private int colorText;
+ private int colorChanged;
+ private int colorOn;
+ private int colorOff;
+ private int colorGrayed;
+ private int iconSize;
+ private boolean wifiActive = true;
+ private boolean otherActive = true;
+ private boolean live = true;
+ private List listAll = new ArrayList<>();
+ private List listFiltered = new ArrayList<>();
+
+ private List messaging = Arrays.asList(
+ "com.discord",
+ "com.facebook.mlite",
+ "com.facebook.orca",
+ "com.instagram.android",
+ "com.Slack",
+ "com.skype.raider",
+ "com.snapchat.android",
+ "com.whatsapp",
+ "com.whatsapp.w4b"
+ );
+
+ private List download = Arrays.asList(
+ "com.google.android.youtube"
+ );
+
+ public static class ViewHolder extends RecyclerView.ViewHolder {
+ public View view;
+
+ public LinearLayout llApplication;
+ public ImageView ivIcon;
+ public ImageView ivExpander;
+ public TextView tvName;
+
+ public TextView tvHosts;
+
+ public RelativeLayout rlLockdown;
+ public ImageView ivLockdown;
+
+ public CheckBox cbWifi;
+ public ImageView ivScreenWifi;
+
+ public CheckBox cbOther;
+ public ImageView ivScreenOther;
+ public TextView tvRoaming;
+
+ public TextView tvRemarkMessaging;
+ public TextView tvRemarkDownload;
+
+ public LinearLayout llConfiguration;
+ public TextView tvUid;
+ public TextView tvPackage;
+ public TextView tvVersion;
+ public TextView tvInternet;
+ public TextView tvDisabled;
+
+ public Button btnRelated;
+ public ImageButton ibSettings;
+ public ImageButton ibLaunch;
+
+ public CheckBox cbApply;
+
+ public LinearLayout llScreenWifi;
+ public ImageView ivWifiLegend;
+ public CheckBox cbScreenWifi;
+
+ public LinearLayout llScreenOther;
+ public ImageView ivOtherLegend;
+ public CheckBox cbScreenOther;
+
+ public CheckBox cbRoaming;
+
+ public CheckBox cbLockdown;
+ public ImageView ivLockdownLegend;
+
+ public ImageButton btnClear;
+
+ public LinearLayout llFilter;
+ public ImageView ivLive;
+ public TextView tvLogging;
+ public Button btnLogging;
+ public ListView lvAccess;
+ public ImageButton btnClearAccess;
+ public CheckBox cbNotify;
+
+ public ViewHolder(View itemView) {
+ super(itemView);
+ view = itemView;
+
+ llApplication = itemView.findViewById(R.id.llApplication);
+ ivIcon = itemView.findViewById(R.id.ivIcon);
+ ivExpander = itemView.findViewById(R.id.ivExpander);
+ tvName = itemView.findViewById(R.id.tvName);
+
+ tvHosts = itemView.findViewById(R.id.tvHosts);
+
+ rlLockdown = itemView.findViewById(R.id.rlLockdown);
+ ivLockdown = itemView.findViewById(R.id.ivLockdown);
+
+ cbWifi = itemView.findViewById(R.id.cbWifi);
+ ivScreenWifi = itemView.findViewById(R.id.ivScreenWifi);
+
+ cbOther = itemView.findViewById(R.id.cbOther);
+ ivScreenOther = itemView.findViewById(R.id.ivScreenOther);
+ tvRoaming = itemView.findViewById(R.id.tvRoaming);
+
+ tvRemarkMessaging = itemView.findViewById(R.id.tvRemarkMessaging);
+ tvRemarkDownload = itemView.findViewById(R.id.tvRemarkDownload);
+
+ llConfiguration = itemView.findViewById(R.id.llConfiguration);
+ tvUid = itemView.findViewById(R.id.tvUid);
+ tvPackage = itemView.findViewById(R.id.tvPackage);
+ tvVersion = itemView.findViewById(R.id.tvVersion);
+ tvInternet = itemView.findViewById(R.id.tvInternet);
+ tvDisabled = itemView.findViewById(R.id.tvDisabled);
+
+ btnRelated = itemView.findViewById(R.id.btnRelated);
+ ibSettings = itemView.findViewById(R.id.ibSettings);
+ ibLaunch = itemView.findViewById(R.id.ibLaunch);
+
+ cbApply = itemView.findViewById(R.id.cbApply);
+
+ llScreenWifi = itemView.findViewById(R.id.llScreenWifi);
+ ivWifiLegend = itemView.findViewById(R.id.ivWifiLegend);
+ cbScreenWifi = itemView.findViewById(R.id.cbScreenWifi);
+
+ llScreenOther = itemView.findViewById(R.id.llScreenOther);
+ ivOtherLegend = itemView.findViewById(R.id.ivOtherLegend);
+ cbScreenOther = itemView.findViewById(R.id.cbScreenOther);
+
+ cbRoaming = itemView.findViewById(R.id.cbRoaming);
+
+ cbLockdown = itemView.findViewById(R.id.cbLockdown);
+ ivLockdownLegend = itemView.findViewById(R.id.ivLockdownLegend);
+
+ btnClear = itemView.findViewById(R.id.btnClear);
+
+ llFilter = itemView.findViewById(R.id.llFilter);
+ ivLive = itemView.findViewById(R.id.ivLive);
+ tvLogging = itemView.findViewById(R.id.tvLogging);
+ btnLogging = itemView.findViewById(R.id.btnLogging);
+ lvAccess = itemView.findViewById(R.id.lvAccess);
+ btnClearAccess = itemView.findViewById(R.id.btnClearAccess);
+ cbNotify = itemView.findViewById(R.id.cbNotify);
+
+ final View wifiParent = (View) cbWifi.getParent();
+ wifiParent.post(new Runnable() {
+ public void run() {
+ Rect rect = new Rect();
+ cbWifi.getHitRect(rect);
+ rect.bottom += rect.top;
+ rect.right += rect.left;
+ rect.top = 0;
+ rect.left = 0;
+ wifiParent.setTouchDelegate(new TouchDelegate(rect, cbWifi));
+ }
+ });
+
+ final View otherParent = (View) cbOther.getParent();
+ otherParent.post(new Runnable() {
+ public void run() {
+ Rect rect = new Rect();
+ cbOther.getHitRect(rect);
+ rect.bottom += rect.top;
+ rect.right += rect.left;
+ rect.top = 0;
+ rect.left = 0;
+ otherParent.setTouchDelegate(new TouchDelegate(rect, cbOther));
+ }
+ });
+ }
+ }
+
+ public AdapterRule(Context context, View anchor) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+
+ this.anchor = anchor;
+ this.inflater = LayoutInflater.from(context);
+
+ if (prefs.getBoolean("dark_theme", false))
+ colorChanged = Color.argb(128, Color.red(Color.DKGRAY), Color.green(Color.DKGRAY), Color.blue(Color.DKGRAY));
+ else
+ colorChanged = Color.argb(128, Color.red(Color.LTGRAY), Color.green(Color.LTGRAY), Color.blue(Color.LTGRAY));
+
+ TypedArray ta = context.getTheme().obtainStyledAttributes(new int[]{android.R.attr.textColorPrimary});
+ try {
+ colorText = ta.getColor(0, 0);
+ } finally {
+ ta.recycle();
+ }
+
+ TypedValue tv = new TypedValue();
+ context.getTheme().resolveAttribute(R.attr.colorOn, tv, true);
+ colorOn = tv.data;
+ context.getTheme().resolveAttribute(R.attr.colorOff, tv, true);
+ colorOff = tv.data;
+
+ colorGrayed = ContextCompat.getColor(context, R.color.colorGrayed);
+
+ TypedValue typedValue = new TypedValue();
+ context.getTheme().resolveAttribute(android.R.attr.listPreferredItemHeight, typedValue, true);
+ int height = TypedValue.complexToDimensionPixelSize(typedValue.data, context.getResources().getDisplayMetrics());
+ this.iconSize = Math.round(height * context.getResources().getDisplayMetrics().density + 0.5f);
+
+ setHasStableIds(true);
+ }
+
+ public void set(List listRule) {
+ listAll = listRule;
+ listFiltered = new ArrayList<>();
+ listFiltered.addAll(listRule);
+ notifyDataSetChanged();
+ }
+
+ public void setWifiActive() {
+ wifiActive = true;
+ otherActive = false;
+ notifyDataSetChanged();
+ }
+
+ public void setMobileActive() {
+ wifiActive = false;
+ otherActive = true;
+ notifyDataSetChanged();
+ }
+
+ public void setDisconnected() {
+ wifiActive = false;
+ otherActive = false;
+ notifyDataSetChanged();
+ }
+
+ public boolean isLive() {
+ return this.live;
+ }
+
+ @Override
+ public void onAttachedToRecyclerView(RecyclerView recyclerView) {
+ super.onAttachedToRecyclerView(recyclerView);
+ rv = recyclerView;
+ }
+
+ @Override
+ public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
+ super.onDetachedFromRecyclerView(recyclerView);
+ rv = null;
+ }
+
+ @Override
+ public void onBindViewHolder(final ViewHolder holder, int position) {
+ final Context context = holder.itemView.getContext();
+
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ final boolean log_app = prefs.getBoolean("log_app", false);
+ final boolean filter = prefs.getBoolean("filter", false);
+ final boolean notify_access = prefs.getBoolean("notify_access", false);
+
+ // Get rule
+ final Rule rule = listFiltered.get(position);
+
+ // Handle expanding/collapsing
+ holder.llApplication.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ rule.expanded = !rule.expanded;
+ notifyItemChanged(holder.getAdapterPosition());
+ }
+ });
+
+ // Show if non default rules
+ holder.itemView.setBackgroundColor(rule.changed ? colorChanged : Color.TRANSPARENT);
+
+ // Show expand/collapse indicator
+ holder.ivExpander.setImageLevel(rule.expanded ? 1 : 0);
+
+ // Show application icon
+ if (rule.icon <= 0)
+ holder.ivIcon.setImageResource(android.R.drawable.sym_def_app_icon);
+ else {
+ Uri uri = Uri.parse("android.resource://" + rule.packageName + "/" + rule.icon);
+ GlideApp.with(holder.itemView.getContext())
+ .applyDefaultRequestOptions(new RequestOptions().format(DecodeFormat.PREFER_RGB_565))
+ .load(uri)
+ //.diskCacheStrategy(DiskCacheStrategy.NONE)
+ //.skipMemoryCache(true)
+ .override(iconSize, iconSize)
+ .into(holder.ivIcon);
+ }
+
+ // Show application label
+ holder.tvName.setText(rule.name);
+
+ // Show application state
+ int color = rule.system ? colorOff : colorText;
+ if (!rule.internet || !rule.enabled)
+ color = Color.argb(128, Color.red(color), Color.green(color), Color.blue(color));
+ holder.tvName.setTextColor(color);
+
+ holder.tvHosts.setVisibility(rule.hosts > 0 ? View.VISIBLE : View.GONE);
+ holder.tvHosts.setText(Long.toString(rule.hosts));
+
+ // Lockdown settings
+ boolean lockdown = prefs.getBoolean("lockdown", false);
+ boolean lockdown_wifi = prefs.getBoolean("lockdown_wifi", true);
+ boolean lockdown_other = prefs.getBoolean("lockdown_other", true);
+ if ((otherActive && !lockdown_other) || (wifiActive && !lockdown_wifi))
+ lockdown = false;
+
+ holder.rlLockdown.setVisibility(lockdown && !rule.lockdown ? View.VISIBLE : View.GONE);
+ holder.ivLockdown.setEnabled(rule.apply);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ Drawable wrap = DrawableCompat.wrap(holder.ivLockdown.getDrawable());
+ DrawableCompat.setTint(wrap, rule.apply ? colorOff : colorGrayed);
+ }
+
+ boolean screen_on = prefs.getBoolean("screen_on", true);
+
+ // Wi-Fi settings
+ holder.cbWifi.setEnabled(rule.apply);
+ holder.cbWifi.setAlpha(wifiActive ? 1 : 0.5f);
+ holder.cbWifi.setOnCheckedChangeListener(null);
+ holder.cbWifi.setChecked(rule.wifi_blocked);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ Drawable wrap = DrawableCompat.wrap(CompoundButtonCompat.getButtonDrawable(holder.cbWifi));
+ DrawableCompat.setTint(wrap, rule.apply ? (rule.wifi_blocked ? colorOff : colorOn) : colorGrayed);
+ }
+ holder.cbWifi.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
+ rule.wifi_blocked = isChecked;
+ updateRule(context, rule, true, listAll);
+ }
+ });
+
+ holder.ivScreenWifi.setEnabled(rule.apply);
+ holder.ivScreenWifi.setAlpha(wifiActive ? 1 : 0.5f);
+ holder.ivScreenWifi.setVisibility(rule.screen_wifi && rule.wifi_blocked ? View.VISIBLE : View.INVISIBLE);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ Drawable wrap = DrawableCompat.wrap(holder.ivScreenWifi.getDrawable());
+ DrawableCompat.setTint(wrap, rule.apply ? colorOn : colorGrayed);
+ }
+
+ // Mobile settings
+ holder.cbOther.setEnabled(rule.apply);
+ holder.cbOther.setAlpha(otherActive ? 1 : 0.5f);
+ holder.cbOther.setOnCheckedChangeListener(null);
+ holder.cbOther.setChecked(rule.other_blocked);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ Drawable wrap = DrawableCompat.wrap(CompoundButtonCompat.getButtonDrawable(holder.cbOther));
+ DrawableCompat.setTint(wrap, rule.apply ? (rule.other_blocked ? colorOff : colorOn) : colorGrayed);
+ }
+ holder.cbOther.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
+ rule.other_blocked = isChecked;
+ updateRule(context, rule, true, listAll);
+ }
+ });
+
+ holder.ivScreenOther.setEnabled(rule.apply);
+ holder.ivScreenOther.setAlpha(otherActive ? 1 : 0.5f);
+ holder.ivScreenOther.setVisibility(rule.screen_other && rule.other_blocked ? View.VISIBLE : View.INVISIBLE);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ Drawable wrap = DrawableCompat.wrap(holder.ivScreenOther.getDrawable());
+ DrawableCompat.setTint(wrap, rule.apply ? colorOn : colorGrayed);
+ }
+
+ holder.tvRoaming.setTextColor(rule.apply ? colorOff : colorGrayed);
+ holder.tvRoaming.setAlpha(otherActive ? 1 : 0.5f);
+ holder.tvRoaming.setVisibility(rule.roaming && (!rule.other_blocked || rule.screen_other) ? View.VISIBLE : View.INVISIBLE);
+
+ holder.tvRemarkMessaging.setVisibility(messaging.contains(rule.packageName) ? View.VISIBLE : View.GONE);
+ holder.tvRemarkDownload.setVisibility(download.contains(rule.packageName) ? View.VISIBLE : View.GONE);
+
+ // Expanded configuration section
+ holder.llConfiguration.setVisibility(rule.expanded ? View.VISIBLE : View.GONE);
+
+ // Show application details
+ holder.tvUid.setText(Integer.toString(rule.uid));
+ holder.tvPackage.setText(rule.packageName);
+ holder.tvVersion.setText(rule.version);
+
+ // Show application state
+ holder.tvInternet.setVisibility(rule.internet ? View.GONE : View.VISIBLE);
+ holder.tvDisabled.setVisibility(rule.enabled ? View.GONE : View.VISIBLE);
+
+ // Show related
+ holder.btnRelated.setVisibility(rule.relateduids ? View.VISIBLE : View.GONE);
+ holder.btnRelated.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent main = new Intent(context, ActivityMain.class);
+ main.putExtra(ActivityMain.EXTRA_SEARCH, Integer.toString(rule.uid));
+ main.putExtra(ActivityMain.EXTRA_RELATED, true);
+ context.startActivity(main);
+ }
+ });
+
+ // Launch application settings
+ if (rule.expanded) {
+ Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ intent.setData(Uri.parse("package:" + rule.packageName));
+ final Intent settings = (intent.resolveActivity(context.getPackageManager()) == null ? null : intent);
+
+ holder.ibSettings.setVisibility(settings == null ? View.GONE : View.VISIBLE);
+ holder.ibSettings.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ context.startActivity(settings);
+ }
+ });
+ } else
+ holder.ibSettings.setVisibility(View.GONE);
+
+ // Launch application
+ if (rule.expanded) {
+ Intent intent = context.getPackageManager().getLaunchIntentForPackage(rule.packageName);
+ final Intent launch = (intent == null ||
+ intent.resolveActivity(context.getPackageManager()) == null ? null : intent);
+
+ holder.ibLaunch.setVisibility(launch == null ? View.GONE : View.VISIBLE);
+ holder.ibLaunch.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ context.startActivity(launch);
+ }
+ });
+ } else
+ holder.ibLaunch.setVisibility(View.GONE);
+
+ // Apply
+ holder.cbApply.setEnabled(rule.pkg && filter);
+ holder.cbApply.setOnCheckedChangeListener(null);
+ holder.cbApply.setChecked(rule.apply);
+ holder.cbApply.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
+ rule.apply = isChecked;
+ updateRule(context, rule, true, listAll);
+ }
+ });
+
+ // Show Wi-Fi screen on condition
+ holder.llScreenWifi.setVisibility(screen_on ? View.VISIBLE : View.GONE);
+ holder.cbScreenWifi.setEnabled(rule.wifi_blocked && rule.apply);
+ holder.cbScreenWifi.setOnCheckedChangeListener(null);
+ holder.cbScreenWifi.setChecked(rule.screen_wifi);
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ Drawable wrap = DrawableCompat.wrap(holder.ivWifiLegend.getDrawable());
+ DrawableCompat.setTint(wrap, colorOn);
+ }
+
+ holder.cbScreenWifi.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ rule.screen_wifi = isChecked;
+ updateRule(context, rule, true, listAll);
+ }
+ });
+
+ // Show mobile screen on condition
+ holder.llScreenOther.setVisibility(screen_on ? View.VISIBLE : View.GONE);
+ holder.cbScreenOther.setEnabled(rule.other_blocked && rule.apply);
+ holder.cbScreenOther.setOnCheckedChangeListener(null);
+ holder.cbScreenOther.setChecked(rule.screen_other);
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ Drawable wrap = DrawableCompat.wrap(holder.ivOtherLegend.getDrawable());
+ DrawableCompat.setTint(wrap, colorOn);
+ }
+
+ holder.cbScreenOther.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ rule.screen_other = isChecked;
+ updateRule(context, rule, true, listAll);
+ }
+ });
+
+ // Show roaming condition
+ holder.cbRoaming.setEnabled((!rule.other_blocked || rule.screen_other) && rule.apply);
+ holder.cbRoaming.setOnCheckedChangeListener(null);
+ holder.cbRoaming.setChecked(rule.roaming);
+ holder.cbRoaming.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ @TargetApi(Build.VERSION_CODES.M)
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ rule.roaming = isChecked;
+ updateRule(context, rule, true, listAll);
+ }
+ });
+
+ // Show lockdown
+ holder.cbLockdown.setEnabled(rule.apply);
+ holder.cbLockdown.setOnCheckedChangeListener(null);
+ holder.cbLockdown.setChecked(rule.lockdown);
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ Drawable wrap = DrawableCompat.wrap(holder.ivLockdownLegend.getDrawable());
+ DrawableCompat.setTint(wrap, colorOn);
+ }
+
+ holder.cbLockdown.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ @TargetApi(Build.VERSION_CODES.M)
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ rule.lockdown = isChecked;
+ updateRule(context, rule, true, listAll);
+ }
+ });
+
+ // Reset rule
+ holder.btnClear.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Util.areYouSure(view.getContext(), R.string.msg_clear_rules, new Util.DoubtListener() {
+ @Override
+ public void onSure() {
+ holder.cbApply.setChecked(true);
+ holder.cbWifi.setChecked(rule.wifi_default);
+ holder.cbOther.setChecked(rule.other_default);
+ holder.cbScreenWifi.setChecked(rule.screen_wifi_default);
+ holder.cbScreenOther.setChecked(rule.screen_other_default);
+ holder.cbRoaming.setChecked(rule.roaming_default);
+ holder.cbLockdown.setChecked(false);
+ }
+ });
+ }
+ });
+
+ holder.llFilter.setVisibility(Util.canFilter(context) ? View.VISIBLE : View.GONE);
+
+ // Live
+ holder.ivLive.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ live = !live;
+ TypedValue tv = new TypedValue();
+ view.getContext().getTheme().resolveAttribute(live ? R.attr.iconPause : R.attr.iconPlay, tv, true);
+ holder.ivLive.setImageResource(tv.resourceId);
+ if (live)
+ AdapterRule.this.notifyDataSetChanged();
+ }
+ });
+
+ // Show logging/filtering is disabled
+ holder.tvLogging.setText(log_app && filter ? R.string.title_logging_enabled : R.string.title_logging_disabled);
+ holder.btnLogging.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ LayoutInflater inflater = LayoutInflater.from(context);
+ View view = inflater.inflate(R.layout.enable, null, false);
+
+ final CheckBox cbLogging = view.findViewById(R.id.cbLogging);
+ final CheckBox cbFiltering = view.findViewById(R.id.cbFiltering);
+ final CheckBox cbNotify = view.findViewById(R.id.cbNotify);
+ TextView tvFilter4 = view.findViewById(R.id.tvFilter4);
+
+ cbLogging.setChecked(log_app);
+ cbFiltering.setChecked(filter);
+ cbFiltering.setEnabled(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP);
+ tvFilter4.setVisibility(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? View.GONE : View.VISIBLE);
+ cbNotify.setChecked(notify_access);
+ cbNotify.setEnabled(log_app);
+
+ cbLogging.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
+ prefs.edit().putBoolean("log_app", checked).apply();
+ cbNotify.setEnabled(checked);
+ if (!checked) {
+ cbNotify.setChecked(false);
+ prefs.edit().putBoolean("notify_access", false).apply();
+ }
+ ServiceSinkhole.reload("changed notify", context, false);
+ AdapterRule.this.notifyDataSetChanged();
+ }
+ });
+
+ cbFiltering.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
+ if (checked)
+ cbLogging.setChecked(true);
+ prefs.edit().putBoolean("filter", checked).apply();
+ ServiceSinkhole.reload("changed filter", context, false);
+ AdapterRule.this.notifyDataSetChanged();
+ }
+ });
+
+ cbNotify.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
+ prefs.edit().putBoolean("notify_access", checked).apply();
+ ServiceSinkhole.reload("changed notify", context, false);
+ AdapterRule.this.notifyDataSetChanged();
+ }
+ });
+
+ AlertDialog dialog = new AlertDialog.Builder(context)
+ .setView(view)
+ .setCancelable(true)
+ .create();
+ dialog.show();
+ }
+ });
+
+ // Show access rules
+ if (rule.expanded) {
+ // Access the database when expanded only
+ final AdapterAccess badapter = new AdapterAccess(context,
+ DatabaseHelper.getInstance(context).getAccess(rule.uid));
+ holder.lvAccess.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, final int bposition, long bid) {
+ PackageManager pm = context.getPackageManager();
+ Cursor cursor = (Cursor) badapter.getItem(bposition);
+ final long id = cursor.getLong(cursor.getColumnIndex("ID"));
+ final int version = cursor.getInt(cursor.getColumnIndex("version"));
+ final int protocol = cursor.getInt(cursor.getColumnIndex("protocol"));
+ final String daddr = cursor.getString(cursor.getColumnIndex("daddr"));
+ final int dport = cursor.getInt(cursor.getColumnIndex("dport"));
+ long time = cursor.getLong(cursor.getColumnIndex("time"));
+ int block = cursor.getInt(cursor.getColumnIndex("block"));
+
+ PopupMenu popup = new PopupMenu(context, anchor);
+ popup.inflate(R.menu.access);
+
+ popup.getMenu().findItem(R.id.menu_host).setTitle(
+ Util.getProtocolName(protocol, version, false) + " " +
+ daddr + (dport > 0 ? "/" + dport : ""));
+
+ SubMenu sub = popup.getMenu().findItem(R.id.menu_host).getSubMenu();
+ boolean multiple = false;
+ Cursor alt = null;
+ try {
+ alt = DatabaseHelper.getInstance(context).getAlternateQNames(daddr);
+ while (alt.moveToNext()) {
+ multiple = true;
+ sub.add(Menu.NONE, Menu.NONE, 0, alt.getString(0)).setEnabled(false);
+ }
+ } finally {
+ if (alt != null)
+ alt.close();
+ }
+ popup.getMenu().findItem(R.id.menu_host).setEnabled(multiple);
+
+ markPro(context, popup.getMenu().findItem(R.id.menu_allow), ActivityPro.SKU_FILTER);
+ markPro(context, popup.getMenu().findItem(R.id.menu_block), ActivityPro.SKU_FILTER);
+
+ // Whois
+ final Intent lookupIP = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.dnslytics.com/whois-lookup/" + daddr));
+ if (pm.resolveActivity(lookupIP, 0) == null)
+ popup.getMenu().removeItem(R.id.menu_whois);
+ else
+ popup.getMenu().findItem(R.id.menu_whois).setTitle(context.getString(R.string.title_log_whois, daddr));
+
+ // Lookup port
+ final Intent lookupPort = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.speedguide.net/port.php?port=" + dport));
+ if (dport <= 0 || pm.resolveActivity(lookupPort, 0) == null)
+ popup.getMenu().removeItem(R.id.menu_port);
+ else
+ popup.getMenu().findItem(R.id.menu_port).setTitle(context.getString(R.string.title_log_port, dport));
+
+ popup.getMenu().findItem(R.id.menu_time).setTitle(
+ SimpleDateFormat.getDateTimeInstance().format(time));
+
+ popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem menuItem) {
+ int menu = menuItem.getItemId();
+ boolean result = false;
+ switch (menu) {
+ case R.id.menu_whois:
+ context.startActivity(lookupIP);
+ result = true;
+ break;
+
+ case R.id.menu_port:
+ context.startActivity(lookupPort);
+ result = true;
+ break;
+
+ case R.id.menu_allow:
+ if (IAB.isPurchased(ActivityPro.SKU_FILTER, context)) {
+ DatabaseHelper.getInstance(context).setAccess(id, 0);
+ ServiceSinkhole.reload("allow host", context, false);
+ } else
+ context.startActivity(new Intent(context, ActivityPro.class));
+ result = true;
+ break;
+
+ case R.id.menu_block:
+ if (IAB.isPurchased(ActivityPro.SKU_FILTER, context)) {
+ DatabaseHelper.getInstance(context).setAccess(id, 1);
+ ServiceSinkhole.reload("block host", context, false);
+ } else
+ context.startActivity(new Intent(context, ActivityPro.class));
+ result = true;
+ break;
+
+ case R.id.menu_reset:
+ DatabaseHelper.getInstance(context).setAccess(id, -1);
+ ServiceSinkhole.reload("reset host", context, false);
+ result = true;
+ break;
+
+ case R.id.menu_copy:
+ ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
+ ClipData clip = ClipData.newPlainText("netguard", daddr);
+ clipboard.setPrimaryClip(clip);
+ return true;
+ }
+
+ if (menu == R.id.menu_allow || menu == R.id.menu_block || menu == R.id.menu_reset)
+ new AsyncTask() {
+ @Override
+ protected Long doInBackground(Object... objects) {
+ return DatabaseHelper.getInstance(context).getHostCount(rule.uid, false);
+ }
+
+ @Override
+ protected void onPostExecute(Long hosts) {
+ rule.hosts = hosts;
+ notifyDataSetChanged();
+ }
+ }.execute();
+
+ return result;
+ }
+ });
+
+ if (block == 0)
+ popup.getMenu().removeItem(R.id.menu_allow);
+ else if (block == 1)
+ popup.getMenu().removeItem(R.id.menu_block);
+
+ popup.show();
+ }
+ });
+
+ holder.lvAccess.setAdapter(badapter);
+ } else {
+ holder.lvAccess.setAdapter(null);
+ holder.lvAccess.setOnItemClickListener(null);
+ }
+
+ // Clear access log
+ holder.btnClearAccess.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Util.areYouSure(view.getContext(), R.string.msg_reset_access, new Util.DoubtListener() {
+ @Override
+ public void onSure() {
+ DatabaseHelper.getInstance(context).clearAccess(rule.uid, true);
+ if (!live)
+ notifyDataSetChanged();
+ if (rv != null)
+ rv.scrollToPosition(holder.getAdapterPosition());
+ }
+ });
+ }
+ });
+
+ // Notify on access
+ holder.cbNotify.setEnabled(prefs.getBoolean("notify_access", false) && rule.apply);
+ holder.cbNotify.setOnCheckedChangeListener(null);
+ holder.cbNotify.setChecked(rule.notify);
+ holder.cbNotify.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
+ rule.notify = isChecked;
+ updateRule(context, rule, true, listAll);
+ }
+ });
+ }
+
+ @Override
+ public void onViewRecycled(ViewHolder holder) {
+ super.onViewRecycled(holder);
+
+ //Context context = holder.itemView.getContext();
+ //GlideApp.with(context).clear(holder.ivIcon);
+
+ CursorAdapter adapter = (CursorAdapter) holder.lvAccess.getAdapter();
+ if (adapter != null) {
+ Log.i(TAG, "Closing access cursor");
+ adapter.changeCursor(null);
+ holder.lvAccess.setAdapter(null);
+ }
+ }
+
+ private void markPro(Context context, MenuItem menu, String sku) {
+ if (sku == null || !IAB.isPurchased(sku, context)) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ boolean dark = prefs.getBoolean("dark_theme", false);
+ SpannableStringBuilder ssb = new SpannableStringBuilder(" " + menu.getTitle());
+ ssb.setSpan(new ImageSpan(context, dark ? R.drawable.ic_shopping_cart_white_24dp : R.drawable.ic_shopping_cart_black_24dp), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ menu.setTitle(ssb);
+ }
+ }
+
+ private void updateRule(Context context, Rule rule, boolean root, List listAll) {
+ SharedPreferences wifi = context.getSharedPreferences("wifi", Context.MODE_PRIVATE);
+ SharedPreferences other = context.getSharedPreferences("other", Context.MODE_PRIVATE);
+ SharedPreferences apply = context.getSharedPreferences("apply", Context.MODE_PRIVATE);
+ SharedPreferences screen_wifi = context.getSharedPreferences("screen_wifi", Context.MODE_PRIVATE);
+ SharedPreferences screen_other = context.getSharedPreferences("screen_other", Context.MODE_PRIVATE);
+ SharedPreferences roaming = context.getSharedPreferences("roaming", Context.MODE_PRIVATE);
+ SharedPreferences lockdown = context.getSharedPreferences("lockdown", Context.MODE_PRIVATE);
+ SharedPreferences notify = context.getSharedPreferences("notify", Context.MODE_PRIVATE);
+
+ if (rule.wifi_blocked == rule.wifi_default)
+ wifi.edit().remove(rule.packageName).apply();
+ else
+ wifi.edit().putBoolean(rule.packageName, rule.wifi_blocked).apply();
+
+ if (rule.other_blocked == rule.other_default)
+ other.edit().remove(rule.packageName).apply();
+ else
+ other.edit().putBoolean(rule.packageName, rule.other_blocked).apply();
+
+ if (rule.apply)
+ apply.edit().remove(rule.packageName).apply();
+ else
+ apply.edit().putBoolean(rule.packageName, rule.apply).apply();
+
+ if (rule.screen_wifi == rule.screen_wifi_default)
+ screen_wifi.edit().remove(rule.packageName).apply();
+ else
+ screen_wifi.edit().putBoolean(rule.packageName, rule.screen_wifi).apply();
+
+ if (rule.screen_other == rule.screen_other_default)
+ screen_other.edit().remove(rule.packageName).apply();
+ else
+ screen_other.edit().putBoolean(rule.packageName, rule.screen_other).apply();
+
+ if (rule.roaming == rule.roaming_default)
+ roaming.edit().remove(rule.packageName).apply();
+ else
+ roaming.edit().putBoolean(rule.packageName, rule.roaming).apply();
+
+ if (rule.lockdown)
+ lockdown.edit().putBoolean(rule.packageName, rule.lockdown).apply();
+ else
+ lockdown.edit().remove(rule.packageName).apply();
+
+ if (rule.notify)
+ notify.edit().remove(rule.packageName).apply();
+ else
+ notify.edit().putBoolean(rule.packageName, rule.notify).apply();
+
+ rule.updateChanged(context);
+ Log.i(TAG, "Updated " + rule);
+
+ List listModified = new ArrayList<>();
+ for (String pkg : rule.related) {
+ for (Rule related : listAll)
+ if (related.packageName.equals(pkg)) {
+ related.wifi_blocked = rule.wifi_blocked;
+ related.other_blocked = rule.other_blocked;
+ related.apply = rule.apply;
+ related.screen_wifi = rule.screen_wifi;
+ related.screen_other = rule.screen_other;
+ related.roaming = rule.roaming;
+ related.lockdown = rule.lockdown;
+ related.notify = rule.notify;
+ listModified.add(related);
+ }
+ }
+
+ List listSearch = (root ? new ArrayList<>(listAll) : listAll);
+ listSearch.remove(rule);
+ for (Rule modified : listModified)
+ listSearch.remove(modified);
+ for (Rule modified : listModified)
+ updateRule(context, modified, false, listSearch);
+
+ if (root) {
+ notifyDataSetChanged();
+ NotificationManagerCompat.from(context).cancel(rule.uid);
+ ServiceSinkhole.reload("rule changed", context, false);
+ }
+ }
+
+ @Override
+ public Filter getFilter() {
+ return new Filter() {
+ @Override
+ protected FilterResults performFiltering(CharSequence query) {
+ List listResult = new ArrayList<>();
+ if (query == null)
+ listResult.addAll(listAll);
+ else {
+ query = query.toString().toLowerCase().trim();
+ int uid;
+ try {
+ uid = Integer.parseInt(query.toString());
+ } catch (NumberFormatException ignore) {
+ uid = -1;
+ }
+ for (Rule rule : listAll)
+ if (rule.uid == uid ||
+ rule.packageName.toLowerCase().contains(query) ||
+ (rule.name != null && rule.name.toLowerCase().contains(query)))
+ listResult.add(rule);
+ }
+
+ FilterResults result = new FilterResults();
+ result.values = listResult;
+ result.count = listResult.size();
+ return result;
+ }
+
+ @Override
+ protected void publishResults(CharSequence query, FilterResults result) {
+ listFiltered.clear();
+ if (result == null)
+ listFiltered.addAll(listAll);
+ else {
+ listFiltered.addAll((List) result.values);
+ if (listFiltered.size() == 1)
+ listFiltered.get(0).expanded = true;
+ }
+ notifyDataSetChanged();
+ }
+ };
+ }
+
+ @Override
+ public AdapterRule.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ return new ViewHolder(inflater.inflate(R.layout.rule, parent, false));
+ }
+
+ @Override
+ public long getItemId(int position) {
+ Rule rule = listFiltered.get(position);
+ return rule.packageName.hashCode() * 100000L + rule.uid;
+ }
+
+ @Override
+ public int getItemCount() {
+ return listFiltered.size();
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/Allowed.java b/NetGuard/app/src/main/java/eu/faircode/netguard/Allowed.java
new file mode 100644
index 0000000..c854d38
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/Allowed.java
@@ -0,0 +1,35 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+public class Allowed {
+ public String raddr;
+ public int rport;
+
+ public Allowed() {
+ this.raddr = null;
+ this.rport = 0;
+ }
+
+ public Allowed(String raddr, int rport) {
+ this.raddr = raddr;
+ this.rport = rport;
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ApplicationEx.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ApplicationEx.java
new file mode 100644
index 0000000..3b7e0da
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ApplicationEx.java
@@ -0,0 +1,78 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.annotation.TargetApi;
+import android.app.Application;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.Build;
+import android.util.Log;
+
+public class ApplicationEx extends Application {
+ private static final String TAG = "NetGuard.App";
+
+ private Thread.UncaughtExceptionHandler mPrevHandler;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ Log.i(TAG, "Create version=" + Util.getSelfVersionName(this) + "/" + Util.getSelfVersionCode(this));
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ createNotificationChannels();
+
+ mPrevHandler = Thread.getDefaultUncaughtExceptionHandler();
+ Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+ @Override
+ public void uncaughtException(Thread thread, Throwable ex) {
+ if (Util.ownFault(ApplicationEx.this, ex)
+ && Util.isPlayStoreInstall(ApplicationEx.this)) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ mPrevHandler.uncaughtException(thread, ex);
+ } else {
+ Log.w(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ System.exit(1);
+ }
+ }
+ });
+ }
+
+ @TargetApi(Build.VERSION_CODES.O)
+ private void createNotificationChannels() {
+ NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+
+ NotificationChannel foreground = new NotificationChannel("foreground", getString(R.string.channel_foreground), NotificationManager.IMPORTANCE_MIN);
+ foreground.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
+ nm.createNotificationChannel(foreground);
+
+ NotificationChannel notify = new NotificationChannel("notify", getString(R.string.channel_notify), NotificationManager.IMPORTANCE_DEFAULT);
+ notify.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
+ notify.setBypassDnd(true);
+ nm.createNotificationChannel(notify);
+
+ NotificationChannel access = new NotificationChannel("access", getString(R.string.channel_access), NotificationManager.IMPORTANCE_DEFAULT);
+ access.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
+ access.setBypassDnd(true);
+ nm.createNotificationChannel(access);
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/DatabaseHelper.java b/NetGuard/app/src/main/java/eu/faircode/netguard/DatabaseHelper.java
new file mode 100644
index 0000000..47c0b9a
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/DatabaseHelper.java
@@ -0,0 +1,1164 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDoneException;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.util.Log;
+
+import androidx.preference.PreferenceManager;
+
+import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+public class DatabaseHelper extends SQLiteOpenHelper {
+ private static final String TAG = "NetGuard.Database";
+
+ private static final String DB_NAME = "Netguard";
+ private static final int DB_VERSION = 21;
+
+ private static boolean once = true;
+ private static List logChangedListeners = new ArrayList<>();
+ private static List accessChangedListeners = new ArrayList<>();
+ private static List forwardChangedListeners = new ArrayList<>();
+
+ private static HandlerThread hthread = null;
+ private static Handler handler = null;
+
+ private static final Map mapUidHosts = new HashMap<>();
+
+ private final static int MSG_LOG = 1;
+ private final static int MSG_ACCESS = 2;
+ private final static int MSG_FORWARD = 3;
+
+ private SharedPreferences prefs;
+ private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+
+ static {
+ hthread = new HandlerThread("DatabaseHelper");
+ hthread.start();
+ handler = new Handler(hthread.getLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ handleChangedNotification(msg);
+ }
+ };
+ }
+
+ private static DatabaseHelper dh = null;
+
+ public static DatabaseHelper getInstance(Context context) {
+ if (dh == null)
+ dh = new DatabaseHelper(context.getApplicationContext());
+ return dh;
+ }
+
+ public static void clearCache() {
+ synchronized (mapUidHosts) {
+ mapUidHosts.clear();
+ }
+ }
+
+ @Override
+ public void close() {
+ Log.w(TAG, "Database is being closed");
+ }
+
+ private DatabaseHelper(Context context) {
+ super(context, DB_NAME, null, DB_VERSION);
+ prefs = PreferenceManager.getDefaultSharedPreferences(context);
+
+ if (!once) {
+ once = true;
+
+ File dbfile = context.getDatabasePath(DB_NAME);
+ if (dbfile.exists()) {
+ Log.w(TAG, "Deleting " + dbfile);
+ dbfile.delete();
+ }
+
+ File dbjournal = context.getDatabasePath(DB_NAME + "-journal");
+ if (dbjournal.exists()) {
+ Log.w(TAG, "Deleting " + dbjournal);
+ dbjournal.delete();
+ }
+ }
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ Log.i(TAG, "Creating database " + DB_NAME + " version " + DB_VERSION);
+ createTableLog(db);
+ createTableAccess(db);
+ createTableDns(db);
+ createTableForward(db);
+ createTableApp(db);
+ }
+
+ @Override
+ public void onConfigure(SQLiteDatabase db) {
+ db.enableWriteAheadLogging();
+ super.onConfigure(db);
+ }
+
+ private void createTableLog(SQLiteDatabase db) {
+ Log.i(TAG, "Creating log table");
+ db.execSQL("CREATE TABLE log (" +
+ " ID INTEGER PRIMARY KEY AUTOINCREMENT" +
+ ", time INTEGER NOT NULL" +
+ ", version INTEGER" +
+ ", protocol INTEGER" +
+ ", flags TEXT" +
+ ", saddr TEXT" +
+ ", sport INTEGER" +
+ ", daddr TEXT" +
+ ", dport INTEGER" +
+ ", dname TEXT" +
+ ", uid INTEGER" +
+ ", data TEXT" +
+ ", allowed INTEGER" +
+ ", connection INTEGER" +
+ ", interactive INTEGER" +
+ ");");
+ db.execSQL("CREATE INDEX idx_log_time ON log(time)");
+ db.execSQL("CREATE INDEX idx_log_dest ON log(daddr)");
+ db.execSQL("CREATE INDEX idx_log_dname ON log(dname)");
+ db.execSQL("CREATE INDEX idx_log_dport ON log(dport)");
+ db.execSQL("CREATE INDEX idx_log_uid ON log(uid)");
+ }
+
+ private void createTableAccess(SQLiteDatabase db) {
+ Log.i(TAG, "Creating access table");
+ db.execSQL("CREATE TABLE access (" +
+ " ID INTEGER PRIMARY KEY AUTOINCREMENT" +
+ ", uid INTEGER NOT NULL" +
+ ", version INTEGER NOT NULL" +
+ ", protocol INTEGER NOT NULL" +
+ ", daddr TEXT NOT NULL" +
+ ", dport INTEGER NOT NULL" +
+ ", time INTEGER NOT NULL" +
+ ", allowed INTEGER" +
+ ", block INTEGER NOT NULL" +
+ ", sent INTEGER" +
+ ", received INTEGER" +
+ ", connections INTEGER" +
+ ");");
+ db.execSQL("CREATE UNIQUE INDEX idx_access ON access(uid, version, protocol, daddr, dport)");
+ db.execSQL("CREATE INDEX idx_access_daddr ON access(daddr)");
+ db.execSQL("CREATE INDEX idx_access_block ON access(block)");
+ }
+
+ private void createTableDns(SQLiteDatabase db) {
+ Log.i(TAG, "Creating dns table");
+ db.execSQL("CREATE TABLE dns (" +
+ " ID INTEGER PRIMARY KEY AUTOINCREMENT" +
+ ", time INTEGER NOT NULL" +
+ ", qname TEXT NOT NULL" +
+ ", aname TEXT NOT NULL" +
+ ", resource TEXT NOT NULL" +
+ ", ttl INTEGER" +
+ ");");
+ db.execSQL("CREATE UNIQUE INDEX idx_dns ON dns(qname, aname, resource)");
+ db.execSQL("CREATE INDEX idx_dns_resource ON dns(resource)");
+ }
+
+ private void createTableForward(SQLiteDatabase db) {
+ Log.i(TAG, "Creating forward table");
+ db.execSQL("CREATE TABLE forward (" +
+ " ID INTEGER PRIMARY KEY AUTOINCREMENT" +
+ ", protocol INTEGER NOT NULL" +
+ ", dport INTEGER NOT NULL" +
+ ", raddr TEXT NOT NULL" +
+ ", rport INTEGER NOT NULL" +
+ ", ruid INTEGER NOT NULL" +
+ ");");
+ db.execSQL("CREATE UNIQUE INDEX idx_forward ON forward(protocol, dport)");
+ }
+
+ private void createTableApp(SQLiteDatabase db) {
+ Log.i(TAG, "Creating app table");
+ db.execSQL("CREATE TABLE app (" +
+ " ID INTEGER PRIMARY KEY AUTOINCREMENT" +
+ ", package TEXT" +
+ ", label TEXT" +
+ ", system INTEGER NOT NULL" +
+ ", internet INTEGER NOT NULL" +
+ ", enabled INTEGER NOT NULL" +
+ ");");
+ db.execSQL("CREATE UNIQUE INDEX idx_package ON app(package)");
+ }
+
+ private boolean columnExists(SQLiteDatabase db, String table, String column) {
+ Cursor cursor = null;
+ try {
+ cursor = db.rawQuery("SELECT * FROM " + table + " LIMIT 0", null);
+ return (cursor.getColumnIndex(column) >= 0);
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ return false;
+ } finally {
+ if (cursor != null)
+ cursor.close();
+ }
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ Log.i(TAG, DB_NAME + " upgrading from version " + oldVersion + " to " + newVersion);
+
+ db.beginTransaction();
+ try {
+ if (oldVersion < 2) {
+ if (!columnExists(db, "log", "version"))
+ db.execSQL("ALTER TABLE log ADD COLUMN version INTEGER");
+ if (!columnExists(db, "log", "protocol"))
+ db.execSQL("ALTER TABLE log ADD COLUMN protocol INTEGER");
+ if (!columnExists(db, "log", "uid"))
+ db.execSQL("ALTER TABLE log ADD COLUMN uid INTEGER");
+ oldVersion = 2;
+ }
+ if (oldVersion < 3) {
+ if (!columnExists(db, "log", "port"))
+ db.execSQL("ALTER TABLE log ADD COLUMN port INTEGER");
+ if (!columnExists(db, "log", "flags"))
+ db.execSQL("ALTER TABLE log ADD COLUMN flags TEXT");
+ oldVersion = 3;
+ }
+ if (oldVersion < 4) {
+ if (!columnExists(db, "log", "connection"))
+ db.execSQL("ALTER TABLE log ADD COLUMN connection INTEGER");
+ oldVersion = 4;
+ }
+ if (oldVersion < 5) {
+ if (!columnExists(db, "log", "interactive"))
+ db.execSQL("ALTER TABLE log ADD COLUMN interactive INTEGER");
+ oldVersion = 5;
+ }
+ if (oldVersion < 6) {
+ if (!columnExists(db, "log", "allowed"))
+ db.execSQL("ALTER TABLE log ADD COLUMN allowed INTEGER");
+ oldVersion = 6;
+ }
+ if (oldVersion < 7) {
+ db.execSQL("DROP TABLE log");
+ createTableLog(db);
+ oldVersion = 8;
+ }
+ if (oldVersion < 8) {
+ if (!columnExists(db, "log", "data"))
+ db.execSQL("ALTER TABLE log ADD COLUMN data TEXT");
+ db.execSQL("DROP INDEX idx_log_source");
+ db.execSQL("DROP INDEX idx_log_dest");
+ db.execSQL("CREATE INDEX idx_log_source ON log(saddr)");
+ db.execSQL("CREATE INDEX idx_log_dest ON log(daddr)");
+ db.execSQL("CREATE INDEX IF NOT EXISTS idx_log_uid ON log(uid)");
+ oldVersion = 8;
+ }
+ if (oldVersion < 9) {
+ createTableAccess(db);
+ oldVersion = 9;
+ }
+ if (oldVersion < 10) {
+ db.execSQL("DROP TABLE log");
+ db.execSQL("DROP TABLE access");
+ createTableLog(db);
+ createTableAccess(db);
+ oldVersion = 10;
+ }
+ if (oldVersion < 12) {
+ db.execSQL("DROP TABLE access");
+ createTableAccess(db);
+ oldVersion = 12;
+ }
+ if (oldVersion < 13) {
+ db.execSQL("CREATE INDEX IF NOT EXISTS idx_log_dport ON log(dport)");
+ db.execSQL("CREATE INDEX IF NOT EXISTS idx_log_dname ON log(dname)");
+ oldVersion = 13;
+ }
+ if (oldVersion < 14) {
+ createTableDns(db);
+ oldVersion = 14;
+ }
+ if (oldVersion < 15) {
+ db.execSQL("DROP TABLE access");
+ createTableAccess(db);
+ oldVersion = 15;
+ }
+ if (oldVersion < 16) {
+ createTableForward(db);
+ oldVersion = 16;
+ }
+ if (oldVersion < 17) {
+ if (!columnExists(db, "access", "sent"))
+ db.execSQL("ALTER TABLE access ADD COLUMN sent INTEGER");
+ if (!columnExists(db, "access", "received"))
+ db.execSQL("ALTER TABLE access ADD COLUMN received INTEGER");
+ oldVersion = 17;
+ }
+ if (oldVersion < 18) {
+ db.execSQL("CREATE INDEX IF NOT EXISTS idx_access_block ON access(block)");
+ db.execSQL("DROP INDEX idx_dns");
+ db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS idx_dns ON dns(qname, aname, resource)");
+ db.execSQL("CREATE INDEX IF NOT EXISTS idx_dns_resource ON dns(resource)");
+ oldVersion = 18;
+ }
+ if (oldVersion < 19) {
+ if (!columnExists(db, "access", "connections"))
+ db.execSQL("ALTER TABLE access ADD COLUMN connections INTEGER");
+ oldVersion = 19;
+ }
+ if (oldVersion < 20) {
+ db.execSQL("CREATE INDEX IF NOT EXISTS idx_access_daddr ON access(daddr)");
+ oldVersion = 20;
+ }
+ if (oldVersion < 21) {
+ createTableApp(db);
+ oldVersion = 21;
+ }
+
+ if (oldVersion == DB_VERSION) {
+ db.setVersion(oldVersion);
+ db.setTransactionSuccessful();
+ Log.i(TAG, DB_NAME + " upgraded to " + DB_VERSION);
+ } else
+ throw new IllegalArgumentException(DB_NAME + " upgraded to " + oldVersion + " but required " + DB_VERSION);
+
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ } finally {
+ db.endTransaction();
+ }
+ }
+
+ // Log
+
+ public void insertLog(Packet packet, String dname, int connection, boolean interactive) {
+ lock.writeLock().lock();
+ try {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransactionNonExclusive();
+ try {
+ ContentValues cv = new ContentValues();
+ cv.put("time", packet.time);
+ cv.put("version", packet.version);
+
+ if (packet.protocol < 0)
+ cv.putNull("protocol");
+ else
+ cv.put("protocol", packet.protocol);
+
+ cv.put("flags", packet.flags);
+
+ cv.put("saddr", packet.saddr);
+ if (packet.sport < 0)
+ cv.putNull("sport");
+ else
+ cv.put("sport", packet.sport);
+
+ cv.put("daddr", packet.daddr);
+ if (packet.dport < 0)
+ cv.putNull("dport");
+ else
+ cv.put("dport", packet.dport);
+
+ if (dname == null)
+ cv.putNull("dname");
+ else
+ cv.put("dname", dname);
+
+ cv.put("data", packet.data);
+
+ if (packet.uid < 0)
+ cv.putNull("uid");
+ else
+ cv.put("uid", packet.uid);
+
+ cv.put("allowed", packet.allowed ? 1 : 0);
+
+ cv.put("connection", connection);
+ cv.put("interactive", interactive ? 1 : 0);
+
+ if (db.insert("log", null, cv) == -1)
+ Log.e(TAG, "Insert log failed");
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+
+ notifyLogChanged();
+ }
+
+ public void clearLog(int uid) {
+ lock.writeLock().lock();
+ try {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransactionNonExclusive();
+ try {
+ if (uid < 0)
+ db.delete("log", null, new String[]{});
+ else
+ db.delete("log", "uid = ?", new String[]{Integer.toString(uid)});
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+
+ db.execSQL("VACUUM");
+ } finally {
+ lock.writeLock().unlock();
+ }
+
+ notifyLogChanged();
+ }
+
+ public void cleanupLog(long time) {
+ lock.writeLock().lock();
+ try {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransactionNonExclusive();
+ try {
+ // There an index on time
+ int rows = db.delete("log", "time < ?", new String[]{Long.toString(time)});
+ Log.i(TAG, "Cleanup log" +
+ " before=" + SimpleDateFormat.getDateTimeInstance().format(new Date(time)) +
+ " rows=" + rows);
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ public Cursor getLog(boolean udp, boolean tcp, boolean other, boolean allowed, boolean blocked) {
+ lock.readLock().lock();
+ try {
+ SQLiteDatabase db = this.getReadableDatabase();
+ // There is an index on time
+ // There is no index on protocol/allowed for write performance
+ String query = "SELECT ID AS _id, *";
+ query += " FROM log";
+ query += " WHERE (0 = 1";
+ if (udp)
+ query += " OR protocol = 17";
+ if (tcp)
+ query += " OR protocol = 6";
+ if (other)
+ query += " OR (protocol <> 6 AND protocol <> 17)";
+ query += ") AND (0 = 1";
+ if (allowed)
+ query += " OR allowed = 1";
+ if (blocked)
+ query += " OR allowed = 0";
+ query += ")";
+ query += " ORDER BY time DESC";
+ return db.rawQuery(query, new String[]{});
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ public Cursor searchLog(String find) {
+ lock.readLock().lock();
+ try {
+ SQLiteDatabase db = this.getReadableDatabase();
+ // There is an index on daddr, dname, dport and uid
+ String query = "SELECT ID AS _id, *";
+ query += " FROM log";
+ query += " WHERE daddr LIKE ? OR dname LIKE ? OR dport = ? OR uid = ?";
+ query += " ORDER BY time DESC";
+ return db.rawQuery(query, new String[]{"%" + find + "%", "%" + find + "%", find, find});
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ // Access
+
+ public boolean updateAccess(Packet packet, String dname, int block) {
+ int rows;
+
+ lock.writeLock().lock();
+ try {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransactionNonExclusive();
+ try {
+ ContentValues cv = new ContentValues();
+ cv.put("time", packet.time);
+ cv.put("allowed", packet.allowed ? 1 : 0);
+ if (block >= 0)
+ cv.put("block", block);
+
+ // There is a segmented index on uid, version, protocol, daddr and dport
+ rows = db.update("access", cv, "uid = ? AND version = ? AND protocol = ? AND daddr = ? AND dport = ?",
+ new String[]{
+ Integer.toString(packet.uid),
+ Integer.toString(packet.version),
+ Integer.toString(packet.protocol),
+ dname == null ? packet.daddr : dname,
+ Integer.toString(packet.dport)});
+
+ if (rows == 0) {
+ cv.put("uid", packet.uid);
+ cv.put("version", packet.version);
+ cv.put("protocol", packet.protocol);
+ cv.put("daddr", dname == null ? packet.daddr : dname);
+ cv.put("dport", packet.dport);
+ if (block < 0)
+ cv.put("block", block);
+
+ if (db.insert("access", null, cv) == -1)
+ Log.e(TAG, "Insert access failed");
+ } else if (rows != 1)
+ Log.e(TAG, "Update access failed rows=" + rows);
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+
+ notifyAccessChanged();
+ return (rows == 0);
+ }
+
+ public void updateUsage(Usage usage, String dname) {
+ lock.writeLock().lock();
+ try {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransactionNonExclusive();
+ try {
+ // There is a segmented index on uid, version, protocol, daddr and dport
+ String selection = "uid = ? AND version = ? AND protocol = ? AND daddr = ? AND dport = ?";
+ String[] selectionArgs = new String[]{
+ Integer.toString(usage.Uid),
+ Integer.toString(usage.Version),
+ Integer.toString(usage.Protocol),
+ dname == null ? usage.DAddr : dname,
+ Integer.toString(usage.DPort)
+ };
+
+ try (Cursor cursor = db.query("access", new String[]{"sent", "received", "connections"}, selection, selectionArgs, null, null, null)) {
+ long sent = 0;
+ long received = 0;
+ int connections = 0;
+ int colSent = cursor.getColumnIndex("sent");
+ int colReceived = cursor.getColumnIndex("received");
+ int colConnections = cursor.getColumnIndex("connections");
+ if (cursor.moveToNext()) {
+ sent = cursor.isNull(colSent) ? 0 : cursor.getLong(colSent);
+ received = cursor.isNull(colReceived) ? 0 : cursor.getLong(colReceived);
+ connections = cursor.isNull(colConnections) ? 0 : cursor.getInt(colConnections);
+ }
+
+ ContentValues cv = new ContentValues();
+ cv.put("sent", sent + usage.Sent);
+ cv.put("received", received + usage.Received);
+ cv.put("connections", connections + 1);
+
+ int rows = db.update("access", cv, selection, selectionArgs);
+ if (rows != 1)
+ Log.e(TAG, "Update usage failed rows=" + rows);
+ }
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+
+ notifyAccessChanged();
+ }
+
+ public void setAccess(long id, int block) {
+ lock.writeLock().lock();
+ try {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransactionNonExclusive();
+ try {
+ ContentValues cv = new ContentValues();
+ cv.put("block", block);
+ cv.put("allowed", -1);
+
+ if (db.update("access", cv, "ID = ?", new String[]{Long.toString(id)}) != 1)
+ Log.e(TAG, "Set access failed");
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+
+ notifyAccessChanged();
+ }
+
+ public void clearAccess() {
+ lock.writeLock().lock();
+ try {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransactionNonExclusive();
+ try {
+ db.delete("access", null, null);
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+
+ notifyAccessChanged();
+ }
+
+ public void clearAccess(int uid, boolean keeprules) {
+ lock.writeLock().lock();
+ try {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransactionNonExclusive();
+ try {
+ // There is a segmented index on uid
+ // There is an index on block
+ if (keeprules)
+ db.delete("access", "uid = ? AND block < 0", new String[]{Integer.toString(uid)});
+ else
+ db.delete("access", "uid = ?", new String[]{Integer.toString(uid)});
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+
+ notifyAccessChanged();
+ }
+
+ public void resetUsage(int uid) {
+ lock.writeLock().lock();
+ try {
+ // There is a segmented index on uid
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransactionNonExclusive();
+ try {
+ ContentValues cv = new ContentValues();
+ cv.putNull("sent");
+ cv.putNull("received");
+ cv.putNull("connections");
+ db.update("access", cv,
+ (uid < 0 ? null : "uid = ?"),
+ (uid < 0 ? null : new String[]{Integer.toString(uid)}));
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+
+ notifyAccessChanged();
+ }
+
+ public Cursor getAccess(int uid) {
+ lock.readLock().lock();
+ try {
+ SQLiteDatabase db = this.getReadableDatabase();
+ // There is a segmented index on uid
+ // There is no index on time for write performance
+ String query = "SELECT a.ID AS _id, a.*";
+ query += ", (SELECT COUNT(DISTINCT d.qname) FROM dns d WHERE d.resource IN (SELECT d1.resource FROM dns d1 WHERE d1.qname = a.daddr)) count";
+ query += " FROM access a";
+ query += " WHERE a.uid = ?";
+ query += " ORDER BY a.time DESC";
+ query += " LIMIT 250";
+ return db.rawQuery(query, new String[]{Integer.toString(uid)});
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ public Cursor getAccess() {
+ lock.readLock().lock();
+ try {
+ SQLiteDatabase db = this.getReadableDatabase();
+ // There is a segmented index on uid
+ // There is an index on block
+ return db.query("access", null, "block >= 0", null, null, null, "uid");
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ public Cursor getAccessUnset(int uid, int limit, long since) {
+ lock.readLock().lock();
+ try {
+ SQLiteDatabase db = this.getReadableDatabase();
+ // There is a segmented index on uid, block and daddr
+ // There is no index on allowed and time for write performance
+ String query = "SELECT MAX(time) AS time, daddr, allowed";
+ query += " FROM access";
+ query += " WHERE uid = ?";
+ query += " AND block < 0";
+ query += " AND time >= ?";
+ query += " GROUP BY daddr, allowed";
+ query += " ORDER BY time DESC";
+ if (limit > 0)
+ query += " LIMIT " + limit;
+ return db.rawQuery(query, new String[]{Integer.toString(uid), Long.toString(since)});
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ public long getHostCount(int uid, boolean usecache) {
+ if (usecache)
+ synchronized (mapUidHosts) {
+ if (mapUidHosts.containsKey(uid))
+ return mapUidHosts.get(uid);
+ }
+
+ lock.readLock().lock();
+ try {
+ SQLiteDatabase db = this.getReadableDatabase();
+ // There is a segmented index on uid
+ // There is an index on block
+ long hosts = db.compileStatement("SELECT COUNT(*) FROM access WHERE block >= 0 AND uid =" + uid).simpleQueryForLong();
+ synchronized (mapUidHosts) {
+ mapUidHosts.put(uid, hosts);
+ }
+ return hosts;
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ // DNS
+
+ public boolean insertDns(ResourceRecord rr) {
+ lock.writeLock().lock();
+ try {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransactionNonExclusive();
+ try {
+ int ttl = rr.TTL;
+
+ int min = Integer.parseInt(prefs.getString("ttl", "259200"));
+ if (ttl < min)
+ ttl = min;
+
+ ContentValues cv = new ContentValues();
+ cv.put("time", rr.Time);
+ cv.put("ttl", ttl * 1000L);
+
+ int rows = db.update("dns", cv, "qname = ? AND aname = ? AND resource = ?",
+ new String[]{rr.QName, rr.AName, rr.Resource});
+
+ if (rows == 0) {
+ cv.put("qname", rr.QName);
+ cv.put("aname", rr.AName);
+ cv.put("resource", rr.Resource);
+
+ if (db.insert("dns", null, cv) == -1)
+ Log.e(TAG, "Insert dns failed");
+ else
+ rows = 1;
+ } else if (rows != 1)
+ Log.e(TAG, "Update dns failed rows=" + rows);
+
+ db.setTransactionSuccessful();
+
+ return (rows > 0);
+ } finally {
+ db.endTransaction();
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ public void cleanupDns() {
+ lock.writeLock().lock();
+ try {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransactionNonExclusive();
+ try {
+ // There is no index on time for write performance
+ long now = new Date().getTime();
+ db.execSQL("DELETE FROM dns WHERE time + ttl < " + now);
+ Log.i(TAG, "Cleanup DNS");
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ public void clearDns() {
+ lock.writeLock().lock();
+ try {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransactionNonExclusive();
+ try {
+ db.delete("dns", null, new String[]{});
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ public String getQName(int uid, String ip) {
+ lock.readLock().lock();
+ try {
+ SQLiteDatabase db = this.getReadableDatabase();
+ // There is a segmented index on resource
+ String query = "SELECT d.qname";
+ query += " FROM dns AS d";
+ query += " WHERE d.resource = '" + ip.replace("'", "''") + "'";
+ query += " ORDER BY d.qname";
+ query += " LIMIT 1";
+ // There is no way to known for sure which domain name an app used, so just pick the first one
+ return db.compileStatement(query).simpleQueryForString();
+ } catch (SQLiteDoneException ignored) {
+ // Not found
+ return null;
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ public Cursor getAlternateQNames(String qname) {
+ lock.readLock().lock();
+ try {
+ SQLiteDatabase db = this.getReadableDatabase();
+ String query = "SELECT DISTINCT d2.qname";
+ query += " FROM dns d1";
+ query += " JOIN dns d2";
+ query += " ON d2.resource = d1.resource AND d2.id <> d1.id";
+ query += " WHERE d1.qname = ?";
+ query += " ORDER BY d2.qname";
+ return db.rawQuery(query, new String[]{qname});
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ public Cursor getDns() {
+ lock.readLock().lock();
+ try {
+ SQLiteDatabase db = this.getReadableDatabase();
+ // There is an index on resource
+ // There is a segmented index on qname
+ String query = "SELECT ID AS _id, *";
+ query += " FROM dns";
+ query += " ORDER BY resource, qname";
+ return db.rawQuery(query, new String[]{});
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ public Cursor getAccessDns(String dname) {
+ long now = new Date().getTime();
+ lock.readLock().lock();
+ try {
+ SQLiteDatabase db = this.getReadableDatabase();
+
+ // There is a segmented index on dns.qname
+ // There is an index on access.daddr and access.block
+ String query = "SELECT a.uid, a.version, a.protocol, a.daddr, d.resource, a.dport, a.block, d.time, d.ttl";
+ query += " FROM access AS a";
+ query += " LEFT JOIN dns AS d";
+ query += " ON d.qname = a.daddr";
+ query += " WHERE a.block >= 0";
+ query += " AND (d.time IS NULL OR d.time + d.ttl >= " + now + ")";
+ if (dname != null)
+ query += " AND a.daddr = ?";
+
+ return db.rawQuery(query, dname == null ? new String[]{} : new String[]{dname});
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ // Forward
+
+ public void addForward(int protocol, int dport, String raddr, int rport, int ruid) {
+ lock.writeLock().lock();
+ try {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransactionNonExclusive();
+ try {
+ ContentValues cv = new ContentValues();
+ cv.put("protocol", protocol);
+ cv.put("dport", dport);
+ cv.put("raddr", raddr);
+ cv.put("rport", rport);
+ cv.put("ruid", ruid);
+
+ if (db.insert("forward", null, cv) < 0)
+ Log.e(TAG, "Insert forward failed");
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+
+ notifyForwardChanged();
+ }
+
+ public void deleteForward() {
+ lock.writeLock().lock();
+ try {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransactionNonExclusive();
+ try {
+ db.delete("forward", null, null);
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+
+ notifyForwardChanged();
+ }
+
+ public void deleteForward(int protocol, int dport) {
+ lock.writeLock().lock();
+ try {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransactionNonExclusive();
+ try {
+ db.delete("forward", "protocol = ? AND dport = ?",
+ new String[]{Integer.toString(protocol), Integer.toString(dport)});
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+
+ notifyForwardChanged();
+ }
+
+ public Cursor getForwarding() {
+ lock.readLock().lock();
+ try {
+ SQLiteDatabase db = this.getReadableDatabase();
+ String query = "SELECT ID AS _id, *";
+ query += " FROM forward";
+ query += " ORDER BY dport";
+ return db.rawQuery(query, new String[]{});
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ public void addApp(String packageName, String label, boolean system, boolean internet, boolean enabled) {
+ lock.writeLock().lock();
+ try {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransactionNonExclusive();
+ try {
+ ContentValues cv = new ContentValues();
+ cv.put("package", packageName);
+ if (label == null)
+ cv.putNull("label");
+ else
+ cv.put("label", label);
+ cv.put("system", system ? 1 : 0);
+ cv.put("internet", internet ? 1 : 0);
+ cv.put("enabled", enabled ? 1 : 0);
+
+ if (db.insert("app", null, cv) < 0)
+ Log.e(TAG, "Insert app failed");
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ public Cursor getApp(String packageName) {
+ lock.readLock().lock();
+ try {
+ SQLiteDatabase db = this.getReadableDatabase();
+
+ // There is an index on package
+ String query = "SELECT * FROM app WHERE package = ?";
+
+ return db.rawQuery(query, new String[]{packageName});
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ public void clearApps() {
+ lock.writeLock().lock();
+ try {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.beginTransactionNonExclusive();
+ try {
+ db.delete("app", null, null);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ public void addLogChangedListener(LogChangedListener listener) {
+ logChangedListeners.add(listener);
+ }
+
+ public void removeLogChangedListener(LogChangedListener listener) {
+ logChangedListeners.remove(listener);
+ }
+
+ public void addAccessChangedListener(AccessChangedListener listener) {
+ accessChangedListeners.add(listener);
+ }
+
+ public void removeAccessChangedListener(AccessChangedListener listener) {
+ accessChangedListeners.remove(listener);
+ }
+
+ public void addForwardChangedListener(ForwardChangedListener listener) {
+ forwardChangedListeners.add(listener);
+ }
+
+ public void removeForwardChangedListener(ForwardChangedListener listener) {
+ forwardChangedListeners.remove(listener);
+ }
+
+ private void notifyLogChanged() {
+ Message msg = handler.obtainMessage();
+ msg.what = MSG_LOG;
+ handler.sendMessage(msg);
+ }
+
+ private void notifyAccessChanged() {
+ Message msg = handler.obtainMessage();
+ msg.what = MSG_ACCESS;
+ handler.sendMessage(msg);
+ }
+
+ private void notifyForwardChanged() {
+ Message msg = handler.obtainMessage();
+ msg.what = MSG_FORWARD;
+ handler.sendMessage(msg);
+ }
+
+ private static void handleChangedNotification(Message msg) {
+ // Batch notifications
+ try {
+ Thread.sleep(1000);
+ if (handler.hasMessages(msg.what))
+ handler.removeMessages(msg.what);
+ } catch (InterruptedException ignored) {
+ }
+
+ // Notify listeners
+ if (msg.what == MSG_LOG) {
+ for (LogChangedListener listener : logChangedListeners)
+ try {
+ listener.onChanged();
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ } else if (msg.what == MSG_ACCESS) {
+ for (AccessChangedListener listener : accessChangedListeners)
+ try {
+ listener.onChanged();
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ } else if (msg.what == MSG_FORWARD) {
+ for (ForwardChangedListener listener : forwardChangedListeners)
+ try {
+ listener.onChanged();
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+ }
+
+ public interface LogChangedListener {
+ void onChanged();
+ }
+
+ public interface AccessChangedListener {
+ void onChanged();
+ }
+
+ public interface ForwardChangedListener {
+ void onChanged();
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/DownloadTask.java b/NetGuard/app/src/main/java/eu/faircode/netguard/DownloadTask.java
new file mode 100644
index 0000000..ca74ade
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/DownloadTask.java
@@ -0,0 +1,181 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.PowerManager;
+import android.util.Log;
+import android.util.TypedValue;
+import android.widget.Toast;
+
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationManagerCompat;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+
+public class DownloadTask extends AsyncTask {
+ private static final String TAG = "NetGuard.Download";
+
+ private Context context;
+ private URL url;
+ private File file;
+ private Listener listener;
+ private PowerManager.WakeLock wakeLock;
+
+ public interface Listener {
+ void onCompleted();
+
+ void onCancelled();
+
+ void onException(Throwable ex);
+ }
+
+ public DownloadTask(Activity context, URL url, File file, Listener listener) {
+ this.context = context;
+ this.url = url;
+ this.file = file;
+ this.listener = listener;
+ }
+
+ @Override
+ protected void onPreExecute() {
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
+ wakeLock.acquire();
+ showNotification(0);
+ Toast.makeText(context, context.getString(R.string.msg_downloading, url.toString()), Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ protected Object doInBackground(Object... args) {
+ Log.i(TAG, "Downloading " + url + " into " + file);
+
+ InputStream in = null;
+ OutputStream out = null;
+ URLConnection connection = null;
+ try {
+ connection = url.openConnection();
+ connection.connect();
+
+ if (connection instanceof HttpURLConnection) {
+ HttpURLConnection httpConnection = (HttpURLConnection) connection;
+ if (httpConnection.getResponseCode() != HttpURLConnection.HTTP_OK)
+ throw new IOException(httpConnection.getResponseCode() + " " + httpConnection.getResponseMessage());
+ }
+
+ int contentLength = connection.getContentLength();
+ Log.i(TAG, "Content length=" + contentLength);
+ in = connection.getInputStream();
+ out = new FileOutputStream(file);
+
+ long size = 0;
+ byte buffer[] = new byte[4096];
+ int bytes;
+ while (!isCancelled() && (bytes = in.read(buffer)) != -1) {
+ out.write(buffer, 0, bytes);
+
+ size += bytes;
+ if (contentLength > 0)
+ publishProgress((int) (size * 100 / contentLength));
+ }
+
+ Log.i(TAG, "Downloaded size=" + size);
+ return null;
+ } catch (Throwable ex) {
+ return ex;
+ } finally {
+ try {
+ if (out != null)
+ out.close();
+ } catch (IOException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ try {
+ if (in != null)
+ in.close();
+ } catch (IOException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ if (connection instanceof HttpURLConnection)
+ ((HttpURLConnection) connection).disconnect();
+ }
+ }
+
+ @Override
+ protected void onProgressUpdate(Integer... progress) {
+ super.onProgressUpdate(progress);
+ showNotification(progress[0]);
+ }
+
+ @Override
+ protected void onCancelled() {
+ super.onCancelled();
+ Log.i(TAG, "Cancelled");
+ listener.onCancelled();
+ }
+
+ @Override
+ protected void onPostExecute(Object result) {
+ wakeLock.release();
+ NotificationManagerCompat.from(context).cancel(ServiceSinkhole.NOTIFY_DOWNLOAD);
+ if (result instanceof Throwable) {
+ Log.e(TAG, result.toString() + "\n" + Log.getStackTraceString((Throwable) result));
+ listener.onException((Throwable) result);
+ } else
+ listener.onCompleted();
+ }
+
+ private void showNotification(int progress) {
+ Intent main = new Intent(context, ActivitySettings.class);
+ PendingIntent pi = PendingIntent.getActivity(context, ServiceSinkhole.NOTIFY_DOWNLOAD, main, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+
+ TypedValue tv = new TypedValue();
+ context.getTheme().resolveAttribute(R.attr.colorOff, tv, true);
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "notify");
+ builder.setSmallIcon(R.drawable.ic_file_download_white_24dp)
+ .setContentTitle(context.getString(R.string.app_name))
+ .setContentText(context.getString(R.string.msg_downloading, url.toString()))
+ .setContentIntent(pi)
+ .setProgress(100, progress, false)
+ .setColor(tv.data)
+ .setOngoing(true)
+ .setAutoCancel(false);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
+ builder.setCategory(NotificationCompat.CATEGORY_STATUS)
+ .setVisibility(NotificationCompat.VISIBILITY_SECRET);
+
+ NotificationManagerCompat.from(context).notify(ServiceSinkhole.NOTIFY_DOWNLOAD, builder.build());
+ }
+
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ExpandedListView.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ExpandedListView.java
new file mode 100644
index 0000000..ba3a684
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ExpandedListView.java
@@ -0,0 +1,45 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.ListView;
+
+// This requires list view items with equal heights
+
+public class ExpandedListView extends ListView {
+ public ExpandedListView(Context context) {
+ super(context);
+ }
+
+ public ExpandedListView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ExpandedListView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 4, MeasureSpec.AT_MOST));
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/Forward.java b/NetGuard/app/src/main/java/eu/faircode/netguard/Forward.java
new file mode 100644
index 0000000..675d782
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/Forward.java
@@ -0,0 +1,33 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+public class Forward {
+ public int protocol;
+ public int dport;
+ public String raddr;
+ public int rport;
+ public int ruid;
+
+ @Override
+ public String toString() {
+ return "protocol=" + protocol + " port " + dport + " to " + raddr + "/" + rport + " uid " + ruid;
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/FragmentSettings.java b/NetGuard/app/src/main/java/eu/faircode/netguard/FragmentSettings.java
new file mode 100644
index 0000000..df8b3d3
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/FragmentSettings.java
@@ -0,0 +1,32 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+
+public class FragmentSettings extends PreferenceFragment {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.preferences);
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/GlideHelper.java b/NetGuard/app/src/main/java/eu/faircode/netguard/GlideHelper.java
new file mode 100644
index 0000000..a10561e
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/GlideHelper.java
@@ -0,0 +1,8 @@
+package eu.faircode.netguard;
+
+import com.bumptech.glide.annotation.GlideModule;
+import com.bumptech.glide.module.AppGlideModule;
+
+@GlideModule
+public final class GlideHelper extends AppGlideModule {
+}
\ No newline at end of file
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/IAB.java b/NetGuard/app/src/main/java/eu/faircode/netguard/IAB.java
new file mode 100644
index 0000000..86b0dd1
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/IAB.java
@@ -0,0 +1,240 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import androidx.preference.PreferenceManager;
+
+import com.android.vending.billing.IInAppBillingService;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class IAB implements ServiceConnection {
+ private static final String TAG = "NetGuard.IAB";
+
+ private Context context;
+ private Delegate delegate;
+ private IInAppBillingService service = null;
+
+ private static final int IAB_VERSION = 3;
+
+ public interface Delegate {
+ void onReady(IAB iab);
+ }
+
+ public IAB(Delegate delegate, Context context) {
+ this.context = context.getApplicationContext();
+ this.delegate = delegate;
+ }
+
+ public void bind() {
+ Log.i(TAG, "Bind");
+ Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
+ serviceIntent.setPackage("com.android.vending");
+ context.bindService(serviceIntent, this, Context.BIND_AUTO_CREATE);
+ }
+
+ public void unbind() {
+ if (service != null) {
+ Log.i(TAG, "Unbind");
+ context.unbindService(this);
+ service = null;
+ }
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder binder) {
+ Log.i(TAG, "Connected");
+ service = IInAppBillingService.Stub.asInterface(binder);
+ delegate.onReady(this);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ Log.i(TAG, "Disconnected");
+ service = null;
+ }
+
+ public boolean isAvailable(String sku) throws RemoteException, JSONException {
+ // Get available SKUs
+ ArrayList skuList = new ArrayList<>();
+ skuList.add(sku);
+ Bundle query = new Bundle();
+ query.putStringArrayList("ITEM_ID_LIST", skuList);
+ Bundle bundle = service.getSkuDetails(IAB_VERSION, context.getPackageName(), "inapp", query);
+ Log.i(TAG, "getSkuDetails");
+ Util.logBundle(bundle);
+ int response = (bundle == null ? -1 : bundle.getInt("RESPONSE_CODE", -1));
+ Log.i(TAG, "Response=" + getResult(response));
+ if (response != 0)
+ throw new IllegalArgumentException(getResult(response));
+
+ // Check available SKUs
+ boolean found = false;
+ ArrayList details = bundle.getStringArrayList("DETAILS_LIST");
+ if (details != null)
+ for (String item : details) {
+ JSONObject object = new JSONObject(item);
+ if (sku.equals(object.getString("productId"))) {
+ found = true;
+ break;
+ }
+ }
+ Log.i(TAG, sku + "=" + found);
+
+ return found;
+ }
+
+ public void updatePurchases() throws RemoteException {
+ // Get purchases
+ List skus = new ArrayList<>();
+ skus.addAll(getPurchases("inapp"));
+ skus.addAll(getPurchases("subs"));
+
+ SharedPreferences prefs = context.getSharedPreferences("IAB", Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = prefs.edit();
+ for (String product : prefs.getAll().keySet())
+ if (!ActivityPro.SKU_DONATION.equals(product)) {
+ Log.i(TAG, "removing SKU=" + product);
+ editor.remove(product);
+ }
+ for (String sku : skus) {
+ Log.i(TAG, "adding SKU=" + sku);
+ editor.putBoolean(sku, true);
+ }
+ editor.apply();
+ }
+
+ public boolean isPurchased(String sku, String type) throws RemoteException {
+ return getPurchases(type).contains(sku);
+ }
+
+ public List getPurchases(String type) throws RemoteException {
+ // Get purchases
+ Bundle bundle = service.getPurchases(IAB_VERSION, context.getPackageName(), type, null);
+ Log.i(TAG, "getPurchases");
+ Util.logBundle(bundle);
+ int response = (bundle == null ? -1 : bundle.getInt("RESPONSE_CODE", -1));
+ Log.i(TAG, "Response=" + getResult(response));
+ if (response != 0)
+ throw new IllegalArgumentException(getResult(response));
+
+ ArrayList details = bundle.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
+ return (details == null ? new ArrayList() : details);
+ }
+
+ public PendingIntent getBuyIntent(String sku, boolean subscription) throws RemoteException {
+ if (service == null)
+ return null;
+ Bundle bundle = service.getBuyIntent(IAB_VERSION, context.getPackageName(), sku, subscription ? "subs" : "inapp", "netguard");
+ Log.i(TAG, "getBuyIntent sku=" + sku + " subscription=" + subscription);
+ Util.logBundle(bundle);
+ int response = (bundle == null ? -1 : bundle.getInt("RESPONSE_CODE", -1));
+ Log.i(TAG, "Response=" + getResult(response));
+ if (response != 0)
+ throw new IllegalArgumentException(getResult(response));
+ if (!bundle.containsKey("BUY_INTENT"))
+ throw new IllegalArgumentException("BUY_INTENT missing");
+ return bundle.getParcelable("BUY_INTENT");
+ }
+
+ public static void setBought(String sku, Context context) {
+ Log.i(TAG, "Bought " + sku);
+ SharedPreferences prefs = context.getSharedPreferences("IAB", Context.MODE_PRIVATE);
+ prefs.edit().putBoolean(sku, true).apply();
+ }
+
+ public static boolean isPurchased(String sku, Context context) {
+ try {
+ if (Util.isDebuggable(context)) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ return !prefs.getBoolean("debug_iab", false);
+ }
+
+ SharedPreferences prefs = context.getSharedPreferences("IAB", Context.MODE_PRIVATE);
+ if (ActivityPro.SKU_SUPPORT1.equals(sku) || ActivityPro.SKU_SUPPORT2.equals(sku))
+ return prefs.getBoolean(sku, false);
+
+ return (prefs.getBoolean(sku, false) ||
+ prefs.getBoolean(ActivityPro.SKU_PRO1, false) ||
+ prefs.getBoolean(ActivityPro.SKU_SUPPORT1, false) ||
+ prefs.getBoolean(ActivityPro.SKU_SUPPORT2, false) ||
+ prefs.getBoolean(ActivityPro.SKU_DONATION, false));
+ } catch (SecurityException ignored) {
+ return false;
+ }
+ }
+
+ public static boolean isPurchasedAny(Context context) {
+ try {
+ if (Util.isDebuggable(context)) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ return !(prefs.getBoolean("debug_iab", false));
+ }
+
+ SharedPreferences prefs = context.getSharedPreferences("IAB", Context.MODE_PRIVATE);
+ for (String key : prefs.getAll().keySet())
+ if (prefs.getBoolean(key, false))
+ return true;
+ return false;
+ } catch (SecurityException ignored) {
+ return false;
+ }
+ }
+
+ public static String getResult(int responseCode) {
+ switch (responseCode) {
+ case 0:
+ return "OK";
+ case 1:
+ return "USER_CANCELED";
+ case 2:
+ return "SERVICE_UNAVAILABLE";
+ case 3:
+ return "BILLING_UNAVAILABLE";
+ case 4:
+ return "ITEM_UNAVAILABLE";
+ case 5:
+ return "DEVELOPER_ERROR";
+ case 6:
+ return "ERROR";
+ case 7:
+ return "ITEM_ALREADY_OWNED";
+ case 8:
+ return "ITEM_NOT_OWNED";
+ default:
+ return Integer.toString(responseCode);
+ }
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/IPUtil.java b/NetGuard/app/src/main/java/eu/faircode/netguard/IPUtil.java
new file mode 100644
index 0000000..e18170d
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/IPUtil.java
@@ -0,0 +1,140 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class IPUtil {
+ private static final String TAG = "NetGuard.IPUtil";
+
+ public static List toCIDR(String start, String end) throws UnknownHostException {
+ return toCIDR(InetAddress.getByName(start), InetAddress.getByName(end));
+ }
+
+ public static List toCIDR(InetAddress start, InetAddress end) throws UnknownHostException {
+ List listResult = new ArrayList<>();
+
+ Log.i(TAG, "toCIDR(" + start.getHostAddress() + "," + end.getHostAddress() + ")");
+
+ long from = inet2long(start);
+ long to = inet2long(end);
+ while (to >= from) {
+ byte prefix = 32;
+ while (prefix > 0) {
+ long mask = prefix2mask(prefix - 1);
+ if ((from & mask) != from)
+ break;
+ prefix--;
+ }
+
+ byte max = (byte) (32 - Math.floor(Math.log(to - from + 1) / Math.log(2)));
+ if (prefix < max)
+ prefix = max;
+
+ listResult.add(new CIDR(long2inet(from), prefix));
+
+ from += Math.pow(2, (32 - prefix));
+ }
+
+ for (CIDR cidr : listResult)
+ Log.i(TAG, cidr.toString());
+
+ return listResult;
+ }
+
+ private static long prefix2mask(int bits) {
+ return (0xFFFFFFFF00000000L >> bits) & 0xFFFFFFFFL;
+ }
+
+ private static long inet2long(InetAddress addr) {
+ long result = 0;
+ if (addr != null)
+ for (byte b : addr.getAddress())
+ result = result << 8 | (b & 0xFF);
+ return result;
+ }
+
+ private static InetAddress long2inet(long addr) {
+ try {
+ byte[] b = new byte[4];
+ for (int i = b.length - 1; i >= 0; i--) {
+ b[i] = (byte) (addr & 0xFF);
+ addr = addr >> 8;
+ }
+ return InetAddress.getByAddress(b);
+ } catch (UnknownHostException ignore) {
+ return null;
+ }
+ }
+
+ public static InetAddress minus1(InetAddress addr) {
+ return long2inet(inet2long(addr) - 1);
+ }
+
+ public static InetAddress plus1(InetAddress addr) {
+ return long2inet(inet2long(addr) + 1);
+ }
+
+ public static class CIDR implements Comparable {
+ public InetAddress address;
+ public int prefix;
+
+ public CIDR(InetAddress address, int prefix) {
+ this.address = address;
+ this.prefix = prefix;
+ }
+
+ public CIDR(String ip, int prefix) {
+ try {
+ this.address = InetAddress.getByName(ip);
+ this.prefix = prefix;
+ } catch (UnknownHostException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+
+ public InetAddress getStart() {
+ return long2inet(inet2long(this.address) & prefix2mask(this.prefix));
+ }
+
+ public InetAddress getEnd() {
+ return long2inet((inet2long(this.address) & prefix2mask(this.prefix)) + (1L << (32 - this.prefix)) - 1);
+ }
+
+ @Override
+ public String toString() {
+ return address.getHostAddress() + "/" + prefix + "=" + getStart().getHostAddress() + "..." + getEnd().getHostAddress();
+ }
+
+ @Override
+ public int compareTo(@NonNull CIDR other) {
+ Long lcidr = IPUtil.inet2long(this.address);
+ Long lother = IPUtil.inet2long(other.address);
+ return lcidr.compareTo(lother);
+ }
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/Packet.java b/NetGuard/app/src/main/java/eu/faircode/netguard/Packet.java
new file mode 100644
index 0000000..5460add
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/Packet.java
@@ -0,0 +1,42 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+public class Packet {
+ public long time;
+ public int version;
+ public int protocol;
+ public String flags;
+ public String saddr;
+ public int sport;
+ public String daddr;
+ public int dport;
+ public String data;
+ public int uid;
+ public boolean allowed;
+
+ public Packet() {
+ }
+
+ @Override
+ public String toString() {
+ return "uid=" + uid + " v" + version + " p" + protocol + " " + daddr + "/" + dport;
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ReceiverAutostart.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ReceiverAutostart.java
new file mode 100644
index 0000000..75aad2a
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ReceiverAutostart.java
@@ -0,0 +1,132 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Build;
+import android.util.Log;
+
+import androidx.preference.PreferenceManager;
+
+import java.util.Map;
+
+public class ReceiverAutostart extends BroadcastReceiver {
+ private static final String TAG = "NetGuard.Receiver";
+
+ @Override
+ public void onReceive(final Context context, Intent intent) {
+ Log.i(TAG, "Received " + intent);
+ Util.logExtras(intent);
+
+ String action = (intent == null ? null : intent.getAction());
+ if (Intent.ACTION_BOOT_COMPLETED.equals(action) || Intent.ACTION_MY_PACKAGE_REPLACED.equals(action))
+ try {
+ // Upgrade settings
+ upgrade(true, context);
+
+ // Start service
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ if (prefs.getBoolean("enabled", false))
+ ServiceSinkhole.start("receiver", context);
+ else if (prefs.getBoolean("show_stats", false))
+ ServiceSinkhole.run("receiver", context);
+
+ if (Util.isInteractive(context))
+ ServiceSinkhole.reloadStats("receiver", context);
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+
+ public static void upgrade(boolean initialized, Context context) {
+ synchronized (context.getApplicationContext()) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ int oldVersion = prefs.getInt("version", -1);
+ int newVersion = Util.getSelfVersionCode(context);
+ if (oldVersion == newVersion)
+ return;
+ Log.i(TAG, "Upgrading from version " + oldVersion + " to " + newVersion);
+
+ SharedPreferences.Editor editor = prefs.edit();
+
+ if (initialized) {
+ if (oldVersion < 38) {
+ Log.i(TAG, "Converting screen wifi/mobile");
+ editor.putBoolean("screen_wifi", prefs.getBoolean("unused", false));
+ editor.putBoolean("screen_other", prefs.getBoolean("unused", false));
+ editor.remove("unused");
+
+ SharedPreferences unused = context.getSharedPreferences("unused", Context.MODE_PRIVATE);
+ SharedPreferences screen_wifi = context.getSharedPreferences("screen_wifi", Context.MODE_PRIVATE);
+ SharedPreferences screen_other = context.getSharedPreferences("screen_other", Context.MODE_PRIVATE);
+
+ Map punused = unused.getAll();
+ SharedPreferences.Editor edit_screen_wifi = screen_wifi.edit();
+ SharedPreferences.Editor edit_screen_other = screen_other.edit();
+ for (String key : punused.keySet()) {
+ edit_screen_wifi.putBoolean(key, (Boolean) punused.get(key));
+ edit_screen_other.putBoolean(key, (Boolean) punused.get(key));
+ }
+ edit_screen_wifi.apply();
+ edit_screen_other.apply();
+
+ } else if (oldVersion <= 2017032112)
+ editor.remove("ip6");
+
+ } else {
+ Log.i(TAG, "Initializing sdk=" + Build.VERSION.SDK_INT);
+ editor.putBoolean("filter_udp", true);
+ editor.putBoolean("whitelist_wifi", false);
+ editor.putBoolean("whitelist_other", false);
+ if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP)
+ editor.putBoolean("filter", true); // Optional
+ }
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
+ editor.putBoolean("filter", true); // Mandatory
+
+ if (!Util.canFilter(context)) {
+ editor.putBoolean("log_app", false);
+ editor.putBoolean("filter", false);
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ editor.remove("show_top");
+ if ("data".equals(prefs.getString("sort", "name")))
+ editor.remove("sort");
+ }
+
+ if (Util.isPlayStoreInstall(context)) {
+ editor.remove("update_check");
+ editor.remove("use_hosts");
+ editor.remove("hosts_url");
+ }
+
+ if (!Util.isDebuggable(context))
+ editor.remove("loglevel");
+
+ editor.putInt("version", newVersion);
+ editor.apply();
+ }
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ReceiverPackageRemoved.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ReceiverPackageRemoved.java
new file mode 100644
index 0000000..d8ebf9a
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ReceiverPackageRemoved.java
@@ -0,0 +1,50 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import androidx.core.app.NotificationManagerCompat;
+
+public class ReceiverPackageRemoved extends BroadcastReceiver {
+ private static final String TAG = "NetGuard.Receiver";
+
+ @Override
+ public void onReceive(final Context context, Intent intent) {
+ Log.i(TAG, "Received " + intent);
+ Util.logExtras(intent);
+
+ String action = (intent == null ? null : intent.getAction());
+ if (Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) {
+ int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
+ if (uid > 0) {
+ DatabaseHelper dh = DatabaseHelper.getInstance(context);
+ dh.clearLog(uid);
+ dh.clearAccess(uid, false);
+
+ NotificationManagerCompat.from(context).cancel(uid); // installed notification
+ NotificationManagerCompat.from(context).cancel(uid + 10000); // access notification
+ }
+ }
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ResourceRecord.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ResourceRecord.java
new file mode 100644
index 0000000..0d689d1
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ResourceRecord.java
@@ -0,0 +1,47 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class ResourceRecord {
+ public long Time;
+ public String QName;
+ public String AName;
+ public String Resource;
+ public int TTL;
+
+ private static DateFormat formatter = SimpleDateFormat.getDateTimeInstance();
+
+ public ResourceRecord() {
+ }
+
+ @Override
+ public String toString() {
+ return formatter.format(new Date(Time).getTime()) +
+ " Q " + QName +
+ " A " + AName +
+ " R " + Resource +
+ " TTL " + TTL +
+ " " + formatter.format(new Date(Time + TTL * 1000L).getTime());
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/Rule.java b/NetGuard/app/src/main/java/eu/faircode/netguard/Rule.java
new file mode 100644
index 0000000..e2e2b6e
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/Rule.java
@@ -0,0 +1,453 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.res.XmlResourceParser;
+import android.database.Cursor;
+import android.os.Build;
+import android.os.Process;
+import android.util.Log;
+
+import androidx.preference.PreferenceManager;
+
+import org.xmlpull.v1.XmlPullParser;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+public class Rule {
+ private static final String TAG = "NetGuard.Rule";
+
+ public int uid;
+ public String packageName;
+ public int icon;
+ public String name;
+ public String version;
+ public boolean system;
+ public boolean internet;
+ public boolean enabled;
+ public boolean pkg = true;
+
+ public boolean wifi_default = false;
+ public boolean other_default = false;
+ public boolean screen_wifi_default = false;
+ public boolean screen_other_default = false;
+ public boolean roaming_default = false;
+
+ public boolean wifi_blocked = false;
+ public boolean other_blocked = false;
+ public boolean screen_wifi = false;
+ public boolean screen_other = false;
+ public boolean roaming = false;
+ public boolean lockdown = false;
+
+ public boolean apply = true;
+ public boolean notify = true;
+
+ public boolean relateduids = false;
+ public String[] related = null;
+
+ public long hosts;
+ public boolean changed;
+
+ public boolean expanded = false;
+
+ private static List cachePackageInfo = null;
+ private static Map cacheLabel = new HashMap<>();
+ private static Map cacheSystem = new HashMap<>();
+ private static Map cacheInternet = new HashMap<>();
+ private static Map cacheEnabled = new HashMap<>();
+
+ private static List getPackages(Context context) {
+ if (cachePackageInfo == null) {
+ PackageManager pm = context.getPackageManager();
+ cachePackageInfo = pm.getInstalledPackages(0);
+ }
+ return new ArrayList<>(cachePackageInfo);
+ }
+
+ private static String getLabel(PackageInfo info, Context context) {
+ if (!cacheLabel.containsKey(info)) {
+ PackageManager pm = context.getPackageManager();
+ cacheLabel.put(info, info.applicationInfo.loadLabel(pm).toString());
+ }
+ return cacheLabel.get(info);
+ }
+
+ private static boolean isSystem(String packageName, Context context) {
+ if (!cacheSystem.containsKey(packageName))
+ cacheSystem.put(packageName, Util.isSystem(packageName, context));
+ return cacheSystem.get(packageName);
+ }
+
+ private static boolean hasInternet(String packageName, Context context) {
+ if (!cacheInternet.containsKey(packageName))
+ cacheInternet.put(packageName, Util.hasInternet(packageName, context));
+ return cacheInternet.get(packageName);
+ }
+
+ private static boolean isEnabled(PackageInfo info, Context context) {
+ if (!cacheEnabled.containsKey(info))
+ cacheEnabled.put(info, Util.isEnabled(info, context));
+ return cacheEnabled.get(info);
+ }
+
+ public static void clearCache(Context context) {
+ Log.i(TAG, "Clearing cache");
+ synchronized (context.getApplicationContext()) {
+ cachePackageInfo = null;
+ cacheLabel.clear();
+ cacheSystem.clear();
+ cacheInternet.clear();
+ cacheEnabled.clear();
+ }
+
+ DatabaseHelper dh = DatabaseHelper.getInstance(context);
+ dh.clearApps();
+ }
+
+ private Rule(DatabaseHelper dh, PackageInfo info, Context context) {
+ this.uid = info.applicationInfo.uid;
+ this.packageName = info.packageName;
+ this.icon = info.applicationInfo.icon;
+ this.version = info.versionName;
+ if (info.applicationInfo.uid == 0) {
+ this.name = context.getString(R.string.title_root);
+ this.system = true;
+ this.internet = true;
+ this.enabled = true;
+ this.pkg = false;
+ } else if (info.applicationInfo.uid == 1013) {
+ this.name = context.getString(R.string.title_mediaserver);
+ this.system = true;
+ this.internet = true;
+ this.enabled = true;
+ this.pkg = false;
+ } else if (info.applicationInfo.uid == 1020) {
+ this.name = "MulticastDNSResponder";
+ this.system = true;
+ this.internet = true;
+ this.enabled = true;
+ this.pkg = false;
+ } else if (info.applicationInfo.uid == 1021) {
+ this.name = context.getString(R.string.title_gpsdaemon);
+ this.system = true;
+ this.internet = true;
+ this.enabled = true;
+ this.pkg = false;
+ } else if (info.applicationInfo.uid == 1051) {
+ this.name = context.getString(R.string.title_dnsdaemon);
+ this.system = true;
+ this.internet = true;
+ this.enabled = true;
+ this.pkg = false;
+ } else if (info.applicationInfo.uid == 9999) {
+ this.name = context.getString(R.string.title_nobody);
+ this.system = true;
+ this.internet = true;
+ this.enabled = true;
+ this.pkg = false;
+ } else {
+ Cursor cursor = null;
+ try {
+ cursor = dh.getApp(this.packageName);
+ if (cursor.moveToNext()) {
+ this.name = cursor.getString(cursor.getColumnIndex("label"));
+ this.system = cursor.getInt(cursor.getColumnIndex("system")) > 0;
+ this.internet = cursor.getInt(cursor.getColumnIndex("internet")) > 0;
+ this.enabled = cursor.getInt(cursor.getColumnIndex("enabled")) > 0;
+ } else {
+ this.name = getLabel(info, context);
+ this.system = isSystem(info.packageName, context);
+ this.internet = hasInternet(info.packageName, context);
+ this.enabled = isEnabled(info, context);
+
+ dh.addApp(this.packageName, this.name, this.system, this.internet, this.enabled);
+ }
+ } finally {
+ if (cursor != null)
+ cursor.close();
+ }
+ }
+ }
+
+ public static List getRules(final boolean all, Context context) {
+ synchronized (context.getApplicationContext()) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ SharedPreferences wifi = context.getSharedPreferences("wifi", Context.MODE_PRIVATE);
+ SharedPreferences other = context.getSharedPreferences("other", Context.MODE_PRIVATE);
+ SharedPreferences screen_wifi = context.getSharedPreferences("screen_wifi", Context.MODE_PRIVATE);
+ SharedPreferences screen_other = context.getSharedPreferences("screen_other", Context.MODE_PRIVATE);
+ SharedPreferences roaming = context.getSharedPreferences("roaming", Context.MODE_PRIVATE);
+ SharedPreferences lockdown = context.getSharedPreferences("lockdown", Context.MODE_PRIVATE);
+ SharedPreferences apply = context.getSharedPreferences("apply", Context.MODE_PRIVATE);
+ SharedPreferences notify = context.getSharedPreferences("notify", Context.MODE_PRIVATE);
+
+ // Get settings
+ boolean default_wifi = prefs.getBoolean("whitelist_wifi", true);
+ boolean default_other = prefs.getBoolean("whitelist_other", true);
+ boolean default_screen_wifi = prefs.getBoolean("screen_wifi", false);
+ boolean default_screen_other = prefs.getBoolean("screen_other", false);
+ boolean default_roaming = prefs.getBoolean("whitelist_roaming", true);
+
+ boolean manage_system = prefs.getBoolean("manage_system", false);
+ boolean screen_on = prefs.getBoolean("screen_on", true);
+ boolean show_user = prefs.getBoolean("show_user", true);
+ boolean show_system = prefs.getBoolean("show_system", false);
+ boolean show_nointernet = prefs.getBoolean("show_nointernet", true);
+ boolean show_disabled = prefs.getBoolean("show_disabled", true);
+
+ default_screen_wifi = default_screen_wifi && screen_on;
+ default_screen_other = default_screen_other && screen_on;
+
+ // Get predefined rules
+ Map pre_wifi_blocked = new HashMap<>();
+ Map pre_other_blocked = new HashMap<>();
+ Map pre_roaming = new HashMap<>();
+ Map pre_related = new HashMap<>();
+ Map pre_system = new HashMap<>();
+ try {
+ XmlResourceParser xml = context.getResources().getXml(R.xml.predefined);
+ int eventType = xml.getEventType();
+ while (eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG)
+ if ("wifi".equals(xml.getName())) {
+ String pkg = xml.getAttributeValue(null, "package");
+ boolean pblocked = xml.getAttributeBooleanValue(null, "blocked", false);
+ pre_wifi_blocked.put(pkg, pblocked);
+
+ } else if ("other".equals(xml.getName())) {
+ String pkg = xml.getAttributeValue(null, "package");
+ boolean pblocked = xml.getAttributeBooleanValue(null, "blocked", false);
+ boolean proaming = xml.getAttributeBooleanValue(null, "roaming", default_roaming);
+ pre_other_blocked.put(pkg, pblocked);
+ pre_roaming.put(pkg, proaming);
+
+ } else if ("relation".equals(xml.getName())) {
+ String pkg = xml.getAttributeValue(null, "package");
+ String[] rel = xml.getAttributeValue(null, "related").split(",");
+ pre_related.put(pkg, rel);
+
+ } else if ("type".equals(xml.getName())) {
+ String pkg = xml.getAttributeValue(null, "package");
+ boolean system = xml.getAttributeBooleanValue(null, "system", true);
+ pre_system.put(pkg, system);
+ }
+
+
+ eventType = xml.next();
+ }
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ // Build rule list
+ List listRules = new ArrayList<>();
+ List listPI = getPackages(context);
+
+ int userId = Process.myUid() / 100000;
+
+ // Add root
+ PackageInfo root = new PackageInfo();
+ root.packageName = "root";
+ root.versionCode = Build.VERSION.SDK_INT;
+ root.versionName = Build.VERSION.RELEASE;
+ root.applicationInfo = new ApplicationInfo();
+ root.applicationInfo.uid = 0;
+ root.applicationInfo.icon = 0;
+ listPI.add(root);
+
+ // Add mediaserver
+ PackageInfo media = new PackageInfo();
+ media.packageName = "android.media";
+ media.versionCode = Build.VERSION.SDK_INT;
+ media.versionName = Build.VERSION.RELEASE;
+ media.applicationInfo = new ApplicationInfo();
+ media.applicationInfo.uid = 1013 + userId * 100000;
+ media.applicationInfo.icon = 0;
+ listPI.add(media);
+
+ // MulticastDNSResponder
+ PackageInfo mdr = new PackageInfo();
+ mdr.packageName = "android.multicast";
+ mdr.versionCode = Build.VERSION.SDK_INT;
+ mdr.versionName = Build.VERSION.RELEASE;
+ mdr.applicationInfo = new ApplicationInfo();
+ mdr.applicationInfo.uid = 1020 + userId * 100000;
+ mdr.applicationInfo.icon = 0;
+ listPI.add(mdr);
+
+ // Add GPS daemon
+ PackageInfo gps = new PackageInfo();
+ gps.packageName = "android.gps";
+ gps.versionCode = Build.VERSION.SDK_INT;
+ gps.versionName = Build.VERSION.RELEASE;
+ gps.applicationInfo = new ApplicationInfo();
+ gps.applicationInfo.uid = 1021 + userId * 100000;
+ gps.applicationInfo.icon = 0;
+ listPI.add(gps);
+
+ // Add DNS daemon
+ PackageInfo dns = new PackageInfo();
+ dns.packageName = "android.dns";
+ dns.versionCode = Build.VERSION.SDK_INT;
+ dns.versionName = Build.VERSION.RELEASE;
+ dns.applicationInfo = new ApplicationInfo();
+ dns.applicationInfo.uid = 1051 + userId * 100000;
+ dns.applicationInfo.icon = 0;
+ listPI.add(dns);
+
+ // Add nobody
+ PackageInfo nobody = new PackageInfo();
+ nobody.packageName = "nobody";
+ nobody.versionCode = Build.VERSION.SDK_INT;
+ nobody.versionName = Build.VERSION.RELEASE;
+ nobody.applicationInfo = new ApplicationInfo();
+ nobody.applicationInfo.uid = 9999;
+ nobody.applicationInfo.icon = 0;
+ listPI.add(nobody);
+
+ DatabaseHelper dh = DatabaseHelper.getInstance(context);
+ for (PackageInfo info : listPI)
+ try {
+ // Skip self
+ if (info.applicationInfo.uid == Process.myUid())
+ continue;
+
+ Rule rule = new Rule(dh, info, context);
+
+ if (pre_system.containsKey(info.packageName))
+ rule.system = pre_system.get(info.packageName);
+ if (info.applicationInfo.uid == Process.myUid())
+ rule.system = true;
+
+ if (all ||
+ ((rule.system ? show_system : show_user) &&
+ (show_nointernet || rule.internet) &&
+ (show_disabled || rule.enabled))) {
+
+ rule.wifi_default = (pre_wifi_blocked.containsKey(info.packageName) ? pre_wifi_blocked.get(info.packageName) : default_wifi);
+ rule.other_default = (pre_other_blocked.containsKey(info.packageName) ? pre_other_blocked.get(info.packageName) : default_other);
+ rule.screen_wifi_default = default_screen_wifi;
+ rule.screen_other_default = default_screen_other;
+ rule.roaming_default = (pre_roaming.containsKey(info.packageName) ? pre_roaming.get(info.packageName) : default_roaming);
+
+ rule.wifi_blocked = (!(rule.system && !manage_system) && wifi.getBoolean(info.packageName, rule.wifi_default));
+ rule.other_blocked = (!(rule.system && !manage_system) && other.getBoolean(info.packageName, rule.other_default));
+ rule.screen_wifi = screen_wifi.getBoolean(info.packageName, rule.screen_wifi_default) && screen_on;
+ rule.screen_other = screen_other.getBoolean(info.packageName, rule.screen_other_default) && screen_on;
+ rule.roaming = roaming.getBoolean(info.packageName, rule.roaming_default);
+ rule.lockdown = lockdown.getBoolean(info.packageName, false);
+
+ rule.apply = apply.getBoolean(info.packageName, true);
+ rule.notify = notify.getBoolean(info.packageName, true);
+
+ // Related packages
+ List listPkg = new ArrayList<>();
+ if (pre_related.containsKey(info.packageName))
+ listPkg.addAll(Arrays.asList(pre_related.get(info.packageName)));
+ for (PackageInfo pi : listPI)
+ if (pi.applicationInfo.uid == rule.uid && !pi.packageName.equals(rule.packageName)) {
+ rule.relateduids = true;
+ listPkg.add(pi.packageName);
+ }
+ rule.related = listPkg.toArray(new String[0]);
+
+ rule.hosts = dh.getHostCount(rule.uid, true);
+
+ rule.updateChanged(default_wifi, default_other, default_roaming);
+
+ listRules.add(rule);
+ }
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ // Sort rule list
+ final Collator collator = Collator.getInstance(Locale.getDefault());
+ collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc
+
+ String sort = prefs.getString("sort", "name");
+ if ("uid".equals(sort))
+ Collections.sort(listRules, new Comparator() {
+ @Override
+ public int compare(Rule rule, Rule other) {
+ if (rule.uid < other.uid)
+ return -1;
+ else if (rule.uid > other.uid)
+ return 1;
+ else {
+ int i = collator.compare(rule.name, other.name);
+ return (i == 0 ? rule.packageName.compareTo(other.packageName) : i);
+ }
+ }
+ });
+ else
+ Collections.sort(listRules, new Comparator() {
+ @Override
+ public int compare(Rule rule, Rule other) {
+ if (all || rule.changed == other.changed) {
+ int i = collator.compare(rule.name, other.name);
+ return (i == 0 ? rule.packageName.compareTo(other.packageName) : i);
+ }
+ return (rule.changed ? -1 : 1);
+ }
+ });
+
+ return listRules;
+ }
+ }
+
+ private void updateChanged(boolean default_wifi, boolean default_other, boolean default_roaming) {
+ changed = (wifi_blocked != default_wifi ||
+ (other_blocked != default_other) ||
+ (wifi_blocked && screen_wifi != screen_wifi_default) ||
+ (other_blocked && screen_other != screen_other_default) ||
+ ((!other_blocked || screen_other) && roaming != default_roaming) ||
+ hosts > 0 || lockdown || !apply);
+ }
+
+ public void updateChanged(Context context) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ boolean screen_on = prefs.getBoolean("screen_on", false);
+ boolean default_wifi = prefs.getBoolean("whitelist_wifi", true) && screen_on;
+ boolean default_other = prefs.getBoolean("whitelist_other", true) && screen_on;
+ boolean default_roaming = prefs.getBoolean("whitelist_roaming", true);
+ updateChanged(default_wifi, default_other, default_roaming);
+ }
+
+ @Override
+ public String toString() {
+ // This is used in the port forwarding dialog application selector
+ return this.name;
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceExternal.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceExternal.java
new file mode 100644
index 0000000..3330548
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceExternal.java
@@ -0,0 +1,146 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.app.IntentService;
+import android.app.Notification;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.util.Log;
+
+import androidx.core.app.NotificationCompat;
+import androidx.preference.PreferenceManager;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class ServiceExternal extends IntentService {
+ private static final String TAG = "NetGuard.External";
+ private static final String ACTION_DOWNLOAD_HOSTS_FILE = "eu.faircode.netguard.DOWNLOAD_HOSTS_FILE";
+
+ // am startservice -a eu.faircode.netguard.DOWNLOAD_HOSTS_FILE
+
+ public ServiceExternal() {
+ super(TAG);
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ try {
+ startForeground(ServiceSinkhole.NOTIFY_EXTERNAL, getForegroundNotification(this));
+
+ Log.i(TAG, "Received " + intent);
+ Util.logExtras(intent);
+
+ if (ACTION_DOWNLOAD_HOSTS_FILE.equals(intent.getAction())) {
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+
+ String hosts_url = prefs.getString("hosts_url", null);
+ if ("https://www.netguard.me/hosts".equals(hosts_url))
+ hosts_url = BuildConfig.HOSTS_FILE_URI;
+
+ File tmp = new File(getFilesDir(), "hosts.tmp");
+ File hosts = new File(getFilesDir(), "hosts.txt");
+
+ InputStream in = null;
+ OutputStream out = null;
+ URLConnection connection = null;
+ try {
+ URL url = new URL(hosts_url);
+ connection = url.openConnection();
+ connection.connect();
+
+ if (connection instanceof HttpURLConnection) {
+ HttpURLConnection httpConnection = (HttpURLConnection) connection;
+ if (httpConnection.getResponseCode() != HttpURLConnection.HTTP_OK)
+ throw new IOException(httpConnection.getResponseCode() + " " + httpConnection.getResponseMessage());
+ }
+
+ int contentLength = connection.getContentLength();
+ Log.i(TAG, "Content length=" + contentLength);
+ in = connection.getInputStream();
+ out = new FileOutputStream(tmp);
+
+ long size = 0;
+ byte buffer[] = new byte[4096];
+ int bytes;
+ while ((bytes = in.read(buffer)) != -1) {
+ out.write(buffer, 0, bytes);
+ size += bytes;
+ }
+
+ Log.i(TAG, "Downloaded size=" + size);
+
+ if (hosts.exists())
+ hosts.delete();
+ tmp.renameTo(hosts);
+
+ String last = SimpleDateFormat.getDateTimeInstance().format(new Date().getTime());
+ prefs.edit().putString("hosts_last_download", last).apply();
+
+ ServiceSinkhole.reload("hosts file download", this, false);
+
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+
+ if (tmp.exists())
+ tmp.delete();
+ } finally {
+ try {
+ if (out != null)
+ out.close();
+ } catch (IOException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ try {
+ if (in != null)
+ in.close();
+ } catch (IOException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ if (connection instanceof HttpURLConnection)
+ ((HttpURLConnection) connection).disconnect();
+ }
+ }
+ } finally {
+ stopForeground(true);
+ }
+ }
+
+ private static Notification getForegroundNotification(Context context) {
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "foreground");
+ builder.setSmallIcon(R.drawable.ic_hourglass_empty_white_24dp);
+ builder.setPriority(NotificationCompat.PRIORITY_MIN);
+ builder.setCategory(NotificationCompat.CATEGORY_STATUS);
+ builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
+ builder.setContentTitle(context.getString(R.string.app_name));
+ return builder.build();
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceSinkhole.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceSinkhole.java
new file mode 100644
index 0000000..ccaf7b1
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceSinkhole.java
@@ -0,0 +1,3331 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.annotation.TargetApi;
+import android.app.AlarmManager;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Typeface;
+import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkRequest;
+import android.net.TrafficStats;
+import android.net.Uri;
+import android.net.VpnService;
+import android.os.Build;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.os.PowerManager;
+import android.os.Process;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.telephony.PhoneStateListener;
+import android.telephony.TelephonyManager;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.TextUtils;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.StyleSpan;
+import android.util.Log;
+import android.util.Pair;
+import android.util.TypedValue;
+import android.widget.RemoteViews;
+
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationManagerCompat;
+import androidx.core.content.ContextCompat;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+import androidx.preference.PreferenceManager;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.math.BigInteger;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import javax.net.ssl.HttpsURLConnection;
+
+public class ServiceSinkhole extends VpnService implements SharedPreferences.OnSharedPreferenceChangeListener {
+ private static final String TAG = "NetGuard.Service";
+
+ private boolean registeredUser = false;
+ private boolean registeredIdleState = false;
+ private boolean registeredConnectivityChanged = false;
+ private boolean registeredPackageChanged = false;
+
+ private boolean phone_state = false;
+ private Object networkCallback = null;
+
+ private boolean registeredInteractiveState = false;
+ private PhoneStateListener callStateListener = null;
+
+ private State state = State.none;
+ private boolean user_foreground = true;
+ private boolean last_connected = false;
+ private boolean last_metered = true;
+ private boolean last_interactive = false;
+
+ private int last_allowed = -1;
+ private int last_blocked = -1;
+ private int last_hosts = -1;
+
+ private static Object jni_lock = new Object();
+ private static long jni_context = 0;
+ private Thread tunnelThread = null;
+ private ServiceSinkhole.Builder last_builder = null;
+ private ParcelFileDescriptor vpn = null;
+ private boolean temporarilyStopped = false;
+
+ private long last_hosts_modified = 0;
+ private Map mapHostsBlocked = new HashMap<>();
+ private Map mapUidAllowed = new HashMap<>();
+ private Map mapUidKnown = new HashMap<>();
+ private final Map> mapUidIPFilters = new HashMap<>();
+ private Map mapForward = new HashMap<>();
+ private Map mapNotify = new HashMap<>();
+ private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+
+ private volatile Looper commandLooper;
+ private volatile Looper logLooper;
+ private volatile Looper statsLooper;
+ private volatile CommandHandler commandHandler;
+ private volatile LogHandler logHandler;
+ private volatile StatsHandler statsHandler;
+
+ private static final int NOTIFY_ENFORCING = 1;
+ private static final int NOTIFY_WAITING = 2;
+ private static final int NOTIFY_DISABLED = 3;
+ private static final int NOTIFY_LOCKDOWN = 4;
+ private static final int NOTIFY_AUTOSTART = 5;
+ private static final int NOTIFY_ERROR = 6;
+ private static final int NOTIFY_TRAFFIC = 7;
+ private static final int NOTIFY_UPDATE = 8;
+ public static final int NOTIFY_EXTERNAL = 9;
+ public static final int NOTIFY_DOWNLOAD = 10;
+
+ public static final String EXTRA_COMMAND = "Command";
+ private static final String EXTRA_REASON = "Reason";
+ public static final String EXTRA_NETWORK = "Network";
+ public static final String EXTRA_UID = "UID";
+ public static final String EXTRA_PACKAGE = "Package";
+ public static final String EXTRA_BLOCKED = "Blocked";
+ public static final String EXTRA_INTERACTIVE = "Interactive";
+ public static final String EXTRA_TEMPORARY = "Temporary";
+
+ private static final int MSG_STATS_START = 1;
+ private static final int MSG_STATS_STOP = 2;
+ private static final int MSG_STATS_UPDATE = 3;
+ private static final int MSG_PACKET = 4;
+ private static final int MSG_USAGE = 5;
+
+ private enum State {none, waiting, enforcing, stats}
+
+ public enum Command {run, start, reload, stop, stats, set, householding, watchdog}
+
+ private static volatile PowerManager.WakeLock wlInstance = null;
+
+ private ExecutorService executor = Executors.newCachedThreadPool();
+
+ private static final String ACTION_HOUSE_HOLDING = "eu.faircode.netguard.HOUSE_HOLDING";
+ private static final String ACTION_SCREEN_OFF_DELAYED = "eu.faircode.netguard.SCREEN_OFF_DELAYED";
+ private static final String ACTION_WATCHDOG = "eu.faircode.netguard.WATCHDOG";
+
+ private native long jni_init(int sdk);
+
+ private native void jni_start(long context, int loglevel);
+
+ private native void jni_run(long context, int tun, boolean fwd53, int rcode);
+
+ private native void jni_stop(long context);
+
+ private native void jni_clear(long context);
+
+ private native int jni_get_mtu();
+
+ private native int[] jni_get_stats(long context);
+
+ private static native void jni_pcap(String name, int record_size, int file_size);
+
+ private native void jni_socks5(String addr, int port, String username, String password);
+
+ private native void jni_done(long context);
+
+ public static void setPcap(boolean enabled, Context context) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+
+ int record_size = 64;
+ try {
+ String r = prefs.getString("pcap_record_size", null);
+ if (TextUtils.isEmpty(r))
+ r = "64";
+ record_size = Integer.parseInt(r);
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ int file_size = 2 * 1024 * 1024;
+ try {
+ String f = prefs.getString("pcap_file_size", null);
+ if (TextUtils.isEmpty(f))
+ f = "2";
+ file_size = Integer.parseInt(f) * 1024 * 1024;
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ File pcap = (enabled ? new File(context.getDir("data", MODE_PRIVATE), "netguard.pcap") : null);
+ jni_pcap(pcap == null ? null : pcap.getAbsolutePath(), record_size, file_size);
+ }
+
+ synchronized private static PowerManager.WakeLock getLock(Context context) {
+ if (wlInstance == null) {
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ wlInstance = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, context.getString(R.string.app_name) + " wakelock");
+ wlInstance.setReferenceCounted(true);
+ }
+ return wlInstance;
+ }
+
+ synchronized private static void releaseLock(Context context) {
+ if (wlInstance != null) {
+ while (wlInstance.isHeld())
+ wlInstance.release();
+ wlInstance = null;
+ }
+ }
+
+ private final class CommandHandler extends Handler {
+ public int queue = 0;
+
+ public CommandHandler(Looper looper) {
+ super(looper);
+ }
+
+ private void reportQueueSize() {
+ Intent ruleset = new Intent(ActivityMain.ACTION_QUEUE_CHANGED);
+ ruleset.putExtra(ActivityMain.EXTRA_SIZE, queue);
+ LocalBroadcastManager.getInstance(ServiceSinkhole.this).sendBroadcast(ruleset);
+ }
+
+ public void queue(Intent intent) {
+ synchronized (this) {
+ queue++;
+ reportQueueSize();
+ }
+ Command cmd = (Command) intent.getSerializableExtra(EXTRA_COMMAND);
+ Message msg = commandHandler.obtainMessage();
+ msg.obj = intent;
+ msg.what = cmd.ordinal();
+ commandHandler.sendMessage(msg);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ try {
+ synchronized (ServiceSinkhole.this) {
+ handleIntent((Intent) msg.obj);
+ }
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ } finally {
+ synchronized (this) {
+ queue--;
+ reportQueueSize();
+ }
+ try {
+ PowerManager.WakeLock wl = getLock(ServiceSinkhole.this);
+ if (wl.isHeld())
+ wl.release();
+ else
+ Log.w(TAG, "Wakelock under-locked");
+ Log.i(TAG, "Messages=" + hasMessages(0) + " wakelock=" + wlInstance.isHeld());
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+ }
+
+ private void handleIntent(Intent intent) {
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+
+ Command cmd = (Command) intent.getSerializableExtra(EXTRA_COMMAND);
+ String reason = intent.getStringExtra(EXTRA_REASON);
+ Log.i(TAG, "Executing intent=" + intent + " command=" + cmd + " reason=" + reason +
+ " vpn=" + (vpn != null) + " user=" + (Process.myUid() / 100000));
+
+ // Check if foreground
+ if (cmd != Command.stop)
+ if (!user_foreground) {
+ Log.i(TAG, "Command " + cmd + " ignored for background user");
+ return;
+ }
+
+ // Handle temporary stop
+ if (cmd == Command.stop)
+ temporarilyStopped = intent.getBooleanExtra(EXTRA_TEMPORARY, false);
+ else if (cmd == Command.start)
+ temporarilyStopped = false;
+ else if (cmd == Command.reload && temporarilyStopped) {
+ // Prevent network/interactive changes from restarting the VPN
+ Log.i(TAG, "Command " + cmd + " ignored because of temporary stop");
+ return;
+ }
+
+ // Optionally listen for interactive state changes
+ if (prefs.getBoolean("screen_on", true)) {
+ if (!registeredInteractiveState) {
+ Log.i(TAG, "Starting listening for interactive state changes");
+ last_interactive = Util.isInteractive(ServiceSinkhole.this);
+ IntentFilter ifInteractive = new IntentFilter();
+ ifInteractive.addAction(Intent.ACTION_SCREEN_ON);
+ ifInteractive.addAction(Intent.ACTION_SCREEN_OFF);
+ ifInteractive.addAction(ACTION_SCREEN_OFF_DELAYED);
+ registerReceiver(interactiveStateReceiver, ifInteractive);
+ registeredInteractiveState = true;
+ }
+ } else {
+ if (registeredInteractiveState) {
+ Log.i(TAG, "Stopping listening for interactive state changes");
+ unregisterReceiver(interactiveStateReceiver);
+ registeredInteractiveState = false;
+ last_interactive = false;
+ }
+ }
+
+ // Optionally listen for call state changes
+ TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
+ if (prefs.getBoolean("disable_on_call", false)) {
+ if (tm != null && callStateListener == null && Util.hasPhoneStatePermission(ServiceSinkhole.this)) {
+ Log.i(TAG, "Starting listening for call states");
+ PhoneStateListener listener = new PhoneStateListener() {
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ Log.i(TAG, "New call state=" + state);
+ if (prefs.getBoolean("enabled", false))
+ if (state == TelephonyManager.CALL_STATE_IDLE)
+ ServiceSinkhole.start("call state", ServiceSinkhole.this);
+ else
+ ServiceSinkhole.stop("call state", ServiceSinkhole.this, true);
+ }
+ };
+ tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
+ callStateListener = listener;
+ }
+ } else {
+ if (tm != null && callStateListener != null) {
+ Log.i(TAG, "Stopping listening for call states");
+ tm.listen(callStateListener, PhoneStateListener.LISTEN_NONE);
+ callStateListener = null;
+ }
+ }
+
+ // Watchdog
+ if (cmd == Command.start || cmd == Command.reload || cmd == Command.stop) {
+ Intent watchdogIntent = new Intent(ServiceSinkhole.this, ServiceSinkhole.class);
+ watchdogIntent.setAction(ACTION_WATCHDOG);
+ PendingIntent pi;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ pi = PendingIntent.getForegroundService(ServiceSinkhole.this, 1, watchdogIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+ else
+ pi = PendingIntent.getService(ServiceSinkhole.this, 1, watchdogIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+
+ AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
+ am.cancel(pi);
+
+ if (cmd != Command.stop) {
+ int watchdog = Integer.parseInt(prefs.getString("watchdog", "0"));
+ if (watchdog > 0) {
+ Log.i(TAG, "Watchdog " + watchdog + " minutes");
+ am.setInexactRepeating(AlarmManager.RTC, SystemClock.elapsedRealtime() + watchdog * 60 * 1000, watchdog * 60 * 1000, pi);
+ }
+ }
+ }
+
+ try {
+ switch (cmd) {
+ case run:
+ break;
+
+ case start:
+ start();
+ break;
+
+ case reload:
+ reload(intent.getBooleanExtra(EXTRA_INTERACTIVE, false));
+ break;
+
+ case stop:
+ stop(temporarilyStopped);
+ break;
+
+ case stats:
+ statsHandler.sendEmptyMessage(MSG_STATS_STOP);
+ statsHandler.sendEmptyMessage(MSG_STATS_START);
+ break;
+
+ case householding:
+ householding(intent);
+ break;
+
+ case watchdog:
+ watchdog(intent);
+ break;
+
+ default:
+ Log.e(TAG, "Unknown command=" + cmd);
+ }
+
+ if (cmd == Command.start || cmd == Command.reload) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ boolean filter = prefs.getBoolean("filter", false);
+ if (filter && isLockdownEnabled())
+ showLockdownNotification();
+ else
+ removeLockdownNotification();
+ }
+ }
+
+ if (cmd == Command.start || cmd == Command.reload || cmd == Command.stop) {
+ // Update main view
+ Intent ruleset = new Intent(ActivityMain.ACTION_RULES_CHANGED);
+ ruleset.putExtra(ActivityMain.EXTRA_CONNECTED, cmd == Command.stop ? false : last_connected);
+ ruleset.putExtra(ActivityMain.EXTRA_METERED, cmd == Command.stop ? false : last_metered);
+ LocalBroadcastManager.getInstance(ServiceSinkhole.this).sendBroadcast(ruleset);
+
+ // Update widgets
+ WidgetMain.updateWidgets(ServiceSinkhole.this);
+ }
+
+ // Stop service if needed
+ if (!commandHandler.hasMessages(Command.start.ordinal()) &&
+ !commandHandler.hasMessages(Command.reload.ordinal()) &&
+ !prefs.getBoolean("enabled", false) &&
+ !prefs.getBoolean("show_stats", false))
+ stopForeground(true);
+
+ // Request garbage collection
+ System.gc();
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+
+ if (cmd == Command.start || cmd == Command.reload) {
+ if (VpnService.prepare(ServiceSinkhole.this) == null) {
+ Log.w(TAG, "VPN prepared connected=" + last_connected);
+ if (last_connected && !(ex instanceof StartFailedException)) {
+ //showAutoStartNotification();
+ if (!Util.isPlayStoreInstall(ServiceSinkhole.this))
+ showErrorNotification(ex.toString());
+ }
+ // Retried on connectivity change
+ } else {
+ showErrorNotification(ex.toString());
+
+ // Disable firewall
+ if (!(ex instanceof StartFailedException)) {
+ prefs.edit().putBoolean("enabled", false).apply();
+ WidgetMain.updateWidgets(ServiceSinkhole.this);
+ }
+ }
+ } else
+ showErrorNotification(ex.toString());
+ }
+ }
+
+ private void start() {
+ if (vpn == null) {
+ if (state != State.none) {
+ Log.d(TAG, "Stop foreground state=" + state.toString());
+ stopForeground(true);
+ }
+ startForeground(NOTIFY_ENFORCING, getEnforcingNotification(-1, -1, -1));
+ state = State.enforcing;
+ Log.d(TAG, "Start foreground state=" + state.toString());
+
+ List listRule = Rule.getRules(true, ServiceSinkhole.this);
+ List listAllowed = getAllowedRules(listRule);
+
+ last_builder = getBuilder(listAllowed, listRule);
+ vpn = startVPN(last_builder);
+ if (vpn == null)
+ throw new StartFailedException(getString((R.string.msg_start_failed)));
+
+ startNative(vpn, listAllowed, listRule);
+
+ removeWarningNotifications();
+ updateEnforcingNotification(listAllowed.size(), listRule.size());
+ }
+ }
+
+ private void reload(boolean interactive) {
+ List listRule = Rule.getRules(true, ServiceSinkhole.this);
+
+ // Check if rules needs to be reloaded
+ if (interactive) {
+ boolean process = false;
+ for (Rule rule : listRule) {
+ boolean blocked = (last_metered ? rule.other_blocked : rule.wifi_blocked);
+ boolean screen = (last_metered ? rule.screen_other : rule.screen_wifi);
+ if (blocked && screen) {
+ process = true;
+ break;
+ }
+ }
+ if (!process) {
+ Log.i(TAG, "No changed rules on interactive state change");
+ return;
+ }
+ }
+
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+
+ if (state != State.enforcing) {
+ if (state != State.none) {
+ Log.d(TAG, "Stop foreground state=" + state.toString());
+ stopForeground(true);
+ }
+ startForeground(NOTIFY_ENFORCING, getEnforcingNotification(-1, -1, -1));
+ state = State.enforcing;
+ Log.d(TAG, "Start foreground state=" + state.toString());
+ }
+
+ List listAllowed = getAllowedRules(listRule);
+ ServiceSinkhole.Builder builder = getBuilder(listAllowed, listRule);
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
+ last_builder = builder;
+ Log.i(TAG, "Legacy restart");
+
+ if (vpn != null) {
+ stopNative(vpn);
+ stopVPN(vpn);
+ vpn = null;
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException ignored) {
+ }
+ }
+ vpn = startVPN(last_builder);
+
+ } else {
+ if (vpn != null && prefs.getBoolean("filter", false) && builder.equals(last_builder)) {
+ Log.i(TAG, "Native restart");
+ stopNative(vpn);
+
+ } else {
+ last_builder = builder;
+
+ boolean handover = prefs.getBoolean("handover", false);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
+ handover = false;
+ Log.i(TAG, "VPN restart handover=" + handover);
+
+ if (handover) {
+ // Attempt seamless handover
+ ParcelFileDescriptor prev = vpn;
+ vpn = startVPN(builder);
+
+ if (prev != null && vpn == null) {
+ Log.w(TAG, "Handover failed");
+ stopNative(prev);
+ stopVPN(prev);
+ prev = null;
+ try {
+ Thread.sleep(3000);
+ } catch (InterruptedException ignored) {
+ }
+ vpn = startVPN(last_builder);
+ if (vpn == null)
+ throw new IllegalStateException("Handover failed");
+ }
+
+ if (prev != null) {
+ stopNative(prev);
+ stopVPN(prev);
+ }
+ } else {
+ if (vpn != null) {
+ stopNative(vpn);
+ stopVPN(vpn);
+ }
+
+ vpn = startVPN(builder);
+ }
+ }
+ }
+
+ if (vpn == null)
+ throw new StartFailedException(getString((R.string.msg_start_failed)));
+
+ startNative(vpn, listAllowed, listRule);
+
+ removeWarningNotifications();
+ updateEnforcingNotification(listAllowed.size(), listRule.size());
+ }
+
+ private void stop(boolean temporary) {
+ if (vpn != null) {
+ stopNative(vpn);
+ stopVPN(vpn);
+ vpn = null;
+ unprepare();
+ }
+ if (state == State.enforcing && !temporary) {
+ Log.d(TAG, "Stop foreground state=" + state.toString());
+ last_allowed = -1;
+ last_blocked = -1;
+ last_hosts = -1;
+
+ stopForeground(true);
+
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+ if (prefs.getBoolean("show_stats", false)) {
+ startForeground(NOTIFY_WAITING, getWaitingNotification());
+ state = State.waiting;
+ Log.d(TAG, "Start foreground state=" + state.toString());
+ } else {
+ state = State.none;
+ stopSelf();
+ }
+ }
+ }
+
+ private void householding(Intent intent) {
+ // Keep log records for three days
+ DatabaseHelper.getInstance(ServiceSinkhole.this).cleanupLog(new Date().getTime() - 3 * 24 * 3600 * 1000L);
+
+ // Clear expired DNS records
+ DatabaseHelper.getInstance(ServiceSinkhole.this).cleanupDns();
+
+ // Check for update
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+ if (!Util.isPlayStoreInstall(ServiceSinkhole.this) &&
+ Util.hasValidFingerprint(ServiceSinkhole.this) &&
+ prefs.getBoolean("update_check", true))
+ checkUpdate();
+ }
+
+ private void watchdog(Intent intent) {
+ if (vpn == null) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+ if (prefs.getBoolean("enabled", false)) {
+ Log.e(TAG, "Service was killed");
+ start();
+ }
+ }
+ }
+
+ private void checkUpdate() {
+ StringBuilder json = new StringBuilder();
+ HttpsURLConnection urlConnection = null;
+ try {
+ URL url = new URL(BuildConfig.GITHUB_LATEST_API);
+ urlConnection = (HttpsURLConnection) url.openConnection();
+ BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
+
+ String line;
+ while ((line = br.readLine()) != null)
+ json.append(line);
+
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ } finally {
+ if (urlConnection != null)
+ urlConnection.disconnect();
+ }
+
+ try {
+ JSONObject jroot = new JSONObject(json.toString());
+ if (jroot.has("tag_name") && jroot.has("html_url") && jroot.has("assets")) {
+ String url = jroot.getString("html_url");
+ JSONArray jassets = jroot.getJSONArray("assets");
+ if (jassets.length() > 0) {
+ JSONObject jasset = jassets.getJSONObject(0);
+ if (jasset.has("name")) {
+ String version = jroot.getString("tag_name");
+ String name = jasset.getString("name");
+ Log.i(TAG, "Tag " + version + " name " + name + " url " + url);
+
+ Version current = new Version(Util.getSelfVersionName(ServiceSinkhole.this));
+ Version available = new Version(version);
+ if (current.compareTo(available) < 0) {
+ Log.i(TAG, "Update available from " + current + " to " + available);
+ showUpdateNotification(name, url);
+ } else
+ Log.i(TAG, "Up-to-date current version " + current);
+ }
+ }
+ }
+ } catch (JSONException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+
+ private class StartFailedException extends IllegalStateException {
+ public StartFailedException(String msg) {
+ super(msg);
+ }
+ }
+ }
+
+ private final class LogHandler extends Handler {
+ public int queue = 0;
+
+ private static final int MAX_QUEUE = 250;
+
+ public LogHandler(Looper looper) {
+ super(looper);
+ }
+
+ public void queue(Packet packet) {
+ Message msg = obtainMessage();
+ msg.obj = packet;
+ msg.what = MSG_PACKET;
+ msg.arg1 = (last_connected ? (last_metered ? 2 : 1) : 0);
+ msg.arg2 = (last_interactive ? 1 : 0);
+
+ synchronized (this) {
+ if (queue > MAX_QUEUE) {
+ Log.w(TAG, "Log queue full");
+ return;
+ }
+
+ sendMessage(msg);
+
+ queue++;
+ }
+ }
+
+ public void account(Usage usage) {
+ Message msg = obtainMessage();
+ msg.obj = usage;
+ msg.what = MSG_USAGE;
+
+ synchronized (this) {
+ if (queue > MAX_QUEUE) {
+ Log.w(TAG, "Log queue full");
+ return;
+ }
+
+ sendMessage(msg);
+
+ queue++;
+ }
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ try {
+ switch (msg.what) {
+ case MSG_PACKET:
+ log((Packet) msg.obj, msg.arg1, msg.arg2 > 0);
+ break;
+
+ case MSG_USAGE:
+ usage((Usage) msg.obj);
+ break;
+
+ default:
+ Log.e(TAG, "Unknown log message=" + msg.what);
+ }
+
+ synchronized (this) {
+ queue--;
+ }
+
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+
+ private void log(Packet packet, int connection, boolean interactive) {
+ // Get settings
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+ boolean log = prefs.getBoolean("log", false);
+ boolean log_app = prefs.getBoolean("log_app", false);
+
+ DatabaseHelper dh = DatabaseHelper.getInstance(ServiceSinkhole.this);
+
+ // Get real name
+ String dname = dh.getQName(packet.uid, packet.daddr);
+
+ // Traffic log
+ if (log)
+ dh.insertLog(packet, dname, connection, interactive);
+
+ // Application log
+ if (log_app && packet.uid >= 0 &&
+ !(packet.uid == 0 && (packet.protocol == 6 || packet.protocol == 17) && packet.dport == 53)) {
+ if (!(packet.protocol == 6 /* TCP */ || packet.protocol == 17 /* UDP */))
+ packet.dport = 0;
+ if (dh.updateAccess(packet, dname, -1)) {
+ lock.readLock().lock();
+ if (!mapNotify.containsKey(packet.uid) || mapNotify.get(packet.uid))
+ showAccessNotification(packet.uid);
+ lock.readLock().unlock();
+ }
+ }
+ }
+
+ private void usage(Usage usage) {
+ if (usage.Uid >= 0 && !(usage.Uid == 0 && usage.Protocol == 17 && usage.DPort == 53)) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+ boolean filter = prefs.getBoolean("filter", false);
+ boolean log_app = prefs.getBoolean("log_app", false);
+ boolean track_usage = prefs.getBoolean("track_usage", false);
+ if (filter && log_app && track_usage) {
+ DatabaseHelper dh = DatabaseHelper.getInstance(ServiceSinkhole.this);
+ String dname = dh.getQName(usage.Uid, usage.DAddr);
+ Log.i(TAG, "Usage account " + usage + " dname=" + dname);
+ dh.updateUsage(usage, dname);
+ }
+ }
+ }
+ }
+
+ private final class StatsHandler extends Handler {
+ private boolean stats = false;
+ private long when;
+
+ private long t = -1;
+ private long tx = -1;
+ private long rx = -1;
+
+ private List gt = new ArrayList<>();
+ private List gtx = new ArrayList<>();
+ private List grx = new ArrayList<>();
+
+ private HashMap mapUidBytes = new HashMap<>();
+
+ public StatsHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ try {
+ switch (msg.what) {
+ case MSG_STATS_START:
+ startStats();
+ break;
+
+ case MSG_STATS_STOP:
+ stopStats();
+ break;
+
+ case MSG_STATS_UPDATE:
+ updateStats();
+ break;
+
+ default:
+ Log.e(TAG, "Unknown stats message=" + msg.what);
+ }
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+
+ private void startStats() {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+ boolean enabled = (!stats && prefs.getBoolean("show_stats", false));
+ Log.i(TAG, "Stats start enabled=" + enabled);
+ if (enabled) {
+ when = new Date().getTime();
+ t = -1;
+ tx = -1;
+ rx = -1;
+ gt.clear();
+ gtx.clear();
+ grx.clear();
+ mapUidBytes.clear();
+ stats = true;
+ updateStats();
+ }
+ }
+
+ private void stopStats() {
+ Log.i(TAG, "Stats stop");
+ stats = false;
+ this.removeMessages(MSG_STATS_UPDATE);
+ if (state == State.stats) {
+ Log.d(TAG, "Stop foreground state=" + state.toString());
+ stopForeground(true);
+ state = State.none;
+ } else
+ NotificationManagerCompat.from(ServiceSinkhole.this).cancel(NOTIFY_TRAFFIC);
+ }
+
+ private void updateStats() {
+ RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.traffic);
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+ long frequency = Long.parseLong(prefs.getString("stats_frequency", "1000"));
+ long samples = Long.parseLong(prefs.getString("stats_samples", "90"));
+ boolean filter = prefs.getBoolean("filter", false);
+ boolean show_top = prefs.getBoolean("show_top", false);
+ int loglevel = Integer.parseInt(prefs.getString("loglevel", Integer.toString(Log.WARN)));
+
+ // Schedule next update
+ this.sendEmptyMessageDelayed(MSG_STATS_UPDATE, frequency);
+
+ long ct = SystemClock.elapsedRealtime();
+
+ // Cleanup
+ while (gt.size() > 0 && ct - gt.get(0) > samples * 1000) {
+ gt.remove(0);
+ gtx.remove(0);
+ grx.remove(0);
+ }
+
+ // Calculate network speed
+ float txsec = 0;
+ float rxsec = 0;
+ long ttx = TrafficStats.getTotalTxBytes();
+ long trx = TrafficStats.getTotalRxBytes();
+ if (filter) {
+ ttx -= TrafficStats.getUidTxBytes(Process.myUid());
+ trx -= TrafficStats.getUidRxBytes(Process.myUid());
+ if (ttx < 0)
+ ttx = 0;
+ if (trx < 0)
+ trx = 0;
+ }
+ if (t > 0 && tx > 0 && rx > 0) {
+ float dt = (ct - t) / 1000f;
+ txsec = (ttx - tx) / dt;
+ rxsec = (trx - rx) / dt;
+ gt.add(ct);
+ gtx.add(txsec);
+ grx.add(rxsec);
+ }
+
+ // Calculate application speeds
+ if (show_top) {
+ if (mapUidBytes.size() == 0) {
+ for (ApplicationInfo ainfo : getPackageManager().getInstalledApplications(0))
+ if (ainfo.uid != Process.myUid())
+ mapUidBytes.put(ainfo.uid, TrafficStats.getUidTxBytes(ainfo.uid) + TrafficStats.getUidRxBytes(ainfo.uid));
+
+ } else if (t > 0) {
+ TreeMap mapSpeedUid = new TreeMap<>(new Comparator() {
+ @Override
+ public int compare(Float value, Float other) {
+ return -value.compareTo(other);
+ }
+ });
+ float dt = (ct - t) / 1000f;
+ for (int uid : mapUidBytes.keySet()) {
+ long bytes = TrafficStats.getUidTxBytes(uid) + TrafficStats.getUidRxBytes(uid);
+ float speed = (bytes - mapUidBytes.get(uid)) / dt;
+ if (speed > 0) {
+ mapSpeedUid.put(speed, uid);
+ mapUidBytes.put(uid, bytes);
+ }
+ }
+
+ StringBuilder sb = new StringBuilder();
+ int i = 0;
+ for (float speed : mapSpeedUid.keySet()) {
+ if (i++ >= 3)
+ break;
+ if (speed < 1000 * 1000)
+ sb.append(getString(R.string.msg_kbsec, speed / 1000));
+ else
+ sb.append(getString(R.string.msg_mbsec, speed / 1000 / 1000));
+ sb.append(' ');
+ List apps = Util.getApplicationNames(mapSpeedUid.get(speed), ServiceSinkhole.this);
+ sb.append(apps.size() > 0 ? apps.get(0) : "?");
+ sb.append("\r\n");
+ }
+ if (sb.length() > 0)
+ sb.setLength(sb.length() - 2);
+ remoteViews.setTextViewText(R.id.tvTop, sb.toString());
+ }
+ }
+
+ t = ct;
+ tx = ttx;
+ rx = trx;
+
+ // Create bitmap
+ int height = Util.dips2pixels(96, ServiceSinkhole.this);
+ int width = Util.dips2pixels(96 * 5, ServiceSinkhole.this);
+ Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+
+ // Create canvas
+ Canvas canvas = new Canvas(bitmap);
+ canvas.drawColor(Color.TRANSPARENT);
+
+ // Determine max
+ float max = 0;
+ long xmax = 0;
+ float ymax = 0;
+ for (int i = 0; i < gt.size(); i++) {
+ long t = gt.get(i);
+ float tx = gtx.get(i);
+ float rx = grx.get(i);
+ if (t > xmax)
+ xmax = t;
+ if (tx > max)
+ max = tx;
+ if (rx > max)
+ max = rx;
+ if (tx > ymax)
+ ymax = tx;
+ if (rx > ymax)
+ ymax = rx;
+ }
+
+ // Build paths
+ Path ptx = new Path();
+ Path prx = new Path();
+ for (int i = 0; i < gtx.size(); i++) {
+ float x = width - width * (xmax - gt.get(i)) / 1000f / samples;
+ float ytx = height - height * gtx.get(i) / ymax;
+ float yrx = height - height * grx.get(i) / ymax;
+ if (i == 0) {
+ ptx.moveTo(x, ytx);
+ prx.moveTo(x, yrx);
+ } else {
+ ptx.lineTo(x, ytx);
+ prx.lineTo(x, yrx);
+ }
+ }
+
+ // Build paint
+ Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ paint.setStyle(Paint.Style.STROKE);
+
+ // Draw scale line
+ paint.setStrokeWidth(Util.dips2pixels(1, ServiceSinkhole.this));
+ paint.setColor(ContextCompat.getColor(ServiceSinkhole.this, R.color.colorGrayed));
+ float y = height / 2;
+ canvas.drawLine(0, y, width, y, paint);
+
+ // Draw paths
+ paint.setStrokeWidth(Util.dips2pixels(2, ServiceSinkhole.this));
+ paint.setColor(ContextCompat.getColor(ServiceSinkhole.this, R.color.colorSend));
+ canvas.drawPath(ptx, paint);
+ paint.setColor(ContextCompat.getColor(ServiceSinkhole.this, R.color.colorReceive));
+ canvas.drawPath(prx, paint);
+
+ // Update remote view
+ remoteViews.setImageViewBitmap(R.id.ivTraffic, bitmap);
+ if (txsec < 1000 * 1000)
+ remoteViews.setTextViewText(R.id.tvTx, getString(R.string.msg_kbsec, txsec / 1000));
+ else
+ remoteViews.setTextViewText(R.id.tvTx, getString(R.string.msg_mbsec, txsec / 1000 / 1000));
+
+ if (rxsec < 1000 * 1000)
+ remoteViews.setTextViewText(R.id.tvRx, getString(R.string.msg_kbsec, rxsec / 1000));
+ else
+ remoteViews.setTextViewText(R.id.tvRx, getString(R.string.msg_mbsec, rxsec / 1000 / 1000));
+
+ if (max < 1000 * 1000)
+ remoteViews.setTextViewText(R.id.tvMax, getString(R.string.msg_kbsec, max / 2 / 1000));
+ else
+ remoteViews.setTextViewText(R.id.tvMax, getString(R.string.msg_mbsec, max / 2 / 1000 / 1000));
+
+ // Show session/file count
+ if (filter && loglevel <= Log.WARN) {
+ int[] count = jni_get_stats(jni_context);
+ remoteViews.setTextViewText(R.id.tvSessions, count[0] + "/" + count[1] + "/" + count[2]);
+ remoteViews.setTextViewText(R.id.tvFiles, count[3] + "/" + count[4]);
+ } else {
+ remoteViews.setTextViewText(R.id.tvSessions, "");
+ remoteViews.setTextViewText(R.id.tvFiles, "");
+ }
+
+ // Show notification
+ Intent main = new Intent(ServiceSinkhole.this, ActivityMain.class);
+ PendingIntent pi = PendingIntent.getActivity(ServiceSinkhole.this, 0, main, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+
+ TypedValue tv = new TypedValue();
+ getTheme().resolveAttribute(R.attr.colorPrimary, tv, true);
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(ServiceSinkhole.this, "notify");
+ builder.setWhen(when)
+ .setSmallIcon(R.drawable.ic_equalizer_white_24dp)
+ .setContent(remoteViews)
+ .setContentIntent(pi)
+ .setColor(tv.data)
+ .setOngoing(true)
+ .setAutoCancel(false);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
+ builder.setCategory(NotificationCompat.CATEGORY_STATUS)
+ .setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
+
+ if (state == State.none || state == State.waiting) {
+ if (state != State.none) {
+ Log.d(TAG, "Stop foreground state=" + state.toString());
+ stopForeground(true);
+ }
+ startForeground(NOTIFY_TRAFFIC, builder.build());
+ state = State.stats;
+ Log.d(TAG, "Start foreground state=" + state.toString());
+ } else
+ NotificationManagerCompat.from(ServiceSinkhole.this).notify(NOTIFY_TRAFFIC, builder.build());
+ }
+ }
+
+ public static List getDns(Context context) {
+ List listDns = new ArrayList<>();
+ List sysDns = Util.getDefaultDNS(context);
+
+ // Get custom DNS servers
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ boolean ip6 = prefs.getBoolean("ip6", true);
+ boolean filter = prefs.getBoolean("filter", false);
+ String vpnDns1 = prefs.getString("dns", null);
+ String vpnDns2 = prefs.getString("dns2", null);
+ Log.i(TAG, "DNS system=" + TextUtils.join(",", sysDns) + " config=" + vpnDns1 + "," + vpnDns2);
+
+ if (vpnDns1 != null)
+ try {
+ InetAddress dns = InetAddress.getByName(vpnDns1);
+ if (!(dns.isLoopbackAddress() || dns.isAnyLocalAddress()) &&
+ (ip6 || dns instanceof Inet4Address))
+ listDns.add(dns);
+ } catch (Throwable ignored) {
+ }
+
+ if (vpnDns2 != null)
+ try {
+ InetAddress dns = InetAddress.getByName(vpnDns2);
+ if (!(dns.isLoopbackAddress() || dns.isAnyLocalAddress()) &&
+ (ip6 || dns instanceof Inet4Address))
+ listDns.add(dns);
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ if (listDns.size() == 2)
+ return listDns;
+
+ for (String def_dns : sysDns)
+ try {
+ InetAddress ddns = InetAddress.getByName(def_dns);
+ if (!listDns.contains(ddns) &&
+ !(ddns.isLoopbackAddress() || ddns.isAnyLocalAddress()) &&
+ (ip6 || ddns instanceof Inet4Address))
+ listDns.add(ddns);
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ // Remove local DNS servers when not routing LAN
+ int count = listDns.size();
+ boolean lan = prefs.getBoolean("lan", false);
+ boolean use_hosts = prefs.getBoolean("use_hosts", false);
+ if (lan && use_hosts && filter)
+ try {
+ List> subnets = new ArrayList<>();
+ subnets.add(new Pair<>(InetAddress.getByName("10.0.0.0"), 8));
+ subnets.add(new Pair<>(InetAddress.getByName("172.16.0.0"), 12));
+ subnets.add(new Pair<>(InetAddress.getByName("192.168.0.0"), 16));
+
+ for (Pair subnet : subnets) {
+ InetAddress hostAddress = subnet.first;
+ BigInteger host = new BigInteger(1, hostAddress.getAddress());
+
+ int prefix = subnet.second;
+ BigInteger mask = BigInteger.valueOf(-1).shiftLeft(hostAddress.getAddress().length * 8 - prefix);
+
+ for (InetAddress dns : new ArrayList<>(listDns))
+ if (hostAddress.getAddress().length == dns.getAddress().length) {
+ BigInteger ip = new BigInteger(1, dns.getAddress());
+
+ if (host.and(mask).equals(ip.and(mask))) {
+ Log.i(TAG, "Local DNS server host=" + hostAddress + "/" + prefix + " dns=" + dns);
+ listDns.remove(dns);
+ }
+ }
+ }
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ // Always set DNS servers
+ if (listDns.size() == 0 || listDns.size() < count)
+ try {
+ listDns.add(InetAddress.getByName("8.8.8.8"));
+ listDns.add(InetAddress.getByName("8.8.4.4"));
+ if (ip6) {
+ listDns.add(InetAddress.getByName("2001:4860:4860::8888"));
+ listDns.add(InetAddress.getByName("2001:4860:4860::8844"));
+ }
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ Log.i(TAG, "Get DNS=" + TextUtils.join(",", listDns));
+
+ return listDns;
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ private ParcelFileDescriptor startVPN(Builder builder) throws SecurityException {
+ try {
+ ParcelFileDescriptor pfd = builder.establish();
+
+ // Set underlying network
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
+ Network active = (cm == null ? null : cm.getActiveNetwork());
+ if (active != null) {
+ Log.i(TAG, "Setting underlying network=" + cm.getNetworkInfo(active));
+ setUnderlyingNetworks(new Network[]{active});
+ }
+ }
+
+ return pfd;
+ } catch (SecurityException ex) {
+ throw ex;
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ return null;
+ }
+ }
+
+ private Builder getBuilder(List listAllowed, List listRule) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean subnet = prefs.getBoolean("subnet", false);
+ boolean tethering = prefs.getBoolean("tethering", false);
+ boolean lan = prefs.getBoolean("lan", false);
+ boolean ip6 = prefs.getBoolean("ip6", true);
+ boolean filter = prefs.getBoolean("filter", false);
+ boolean system = prefs.getBoolean("manage_system", false);
+
+ // Build VPN service
+ Builder builder = new Builder();
+ builder.setSession(getString(R.string.app_name));
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
+ builder.setMetered(Util.isMeteredNetwork(this));
+
+ // VPN address
+ String vpn4 = prefs.getString("vpn4", "10.1.10.1");
+ Log.i(TAG, "Using VPN4=" + vpn4);
+ builder.addAddress(vpn4, 32);
+ if (ip6) {
+ String vpn6 = prefs.getString("vpn6", "fd00:1:fd00:1:fd00:1:fd00:1");
+ Log.i(TAG, "Using VPN6=" + vpn6);
+ builder.addAddress(vpn6, 128);
+ }
+
+ // DNS address
+ if (filter)
+ for (InetAddress dns : getDns(ServiceSinkhole.this)) {
+ if (ip6 || dns instanceof Inet4Address) {
+ Log.i(TAG, "Using DNS=" + dns);
+ builder.addDnsServer(dns);
+ }
+ }
+
+ // Subnet routing
+ if (subnet) {
+ // Exclude IP ranges
+ List listExclude = new ArrayList<>();
+ listExclude.add(new IPUtil.CIDR("127.0.0.0", 8)); // localhost
+
+ if (tethering && !lan) {
+ // USB tethering 192.168.42.x
+ // Wi-Fi tethering 192.168.43.x
+ listExclude.add(new IPUtil.CIDR("192.168.42.0", 23));
+ // Bluetooth tethering 192.168.44.x
+ listExclude.add(new IPUtil.CIDR("192.168.44.0", 24));
+ // Wi-Fi direct 192.168.49.x
+ listExclude.add(new IPUtil.CIDR("192.168.49.0", 24));
+ }
+
+ if (lan) {
+ // https://tools.ietf.org/html/rfc1918
+ listExclude.add(new IPUtil.CIDR("10.0.0.0", 8));
+ listExclude.add(new IPUtil.CIDR("172.16.0.0", 12));
+ listExclude.add(new IPUtil.CIDR("192.168.0.0", 16));
+ }
+
+ if (!filter) {
+ for (InetAddress dns : getDns(ServiceSinkhole.this))
+ if (dns instanceof Inet4Address)
+ listExclude.add(new IPUtil.CIDR(dns.getHostAddress(), 32));
+
+ String dns_specifier = Util.getPrivateDnsSpecifier(ServiceSinkhole.this);
+ if (!TextUtils.isEmpty(dns_specifier))
+ try {
+ Log.i(TAG, "Resolving private dns=" + dns_specifier);
+ for (InetAddress pdns : InetAddress.getAllByName(dns_specifier))
+ if (pdns instanceof Inet4Address)
+ listExclude.add(new IPUtil.CIDR(pdns.getHostAddress(), 32));
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString());
+ }
+ }
+
+ // https://en.wikipedia.org/wiki/Mobile_country_code
+ Configuration config = getResources().getConfiguration();
+
+ // T-Mobile Wi-Fi calling
+ if (config.mcc == 310 && (config.mnc == 160 ||
+ config.mnc == 200 ||
+ config.mnc == 210 ||
+ config.mnc == 220 ||
+ config.mnc == 230 ||
+ config.mnc == 240 ||
+ config.mnc == 250 ||
+ config.mnc == 260 ||
+ config.mnc == 270 ||
+ config.mnc == 310 ||
+ config.mnc == 490 ||
+ config.mnc == 660 ||
+ config.mnc == 800)) {
+ listExclude.add(new IPUtil.CIDR("66.94.2.0", 24));
+ listExclude.add(new IPUtil.CIDR("66.94.6.0", 23));
+ listExclude.add(new IPUtil.CIDR("66.94.8.0", 22));
+ listExclude.add(new IPUtil.CIDR("208.54.0.0", 16));
+ }
+
+ // Verizon wireless calling
+ if ((config.mcc == 310 &&
+ (config.mnc == 4 ||
+ config.mnc == 5 ||
+ config.mnc == 6 ||
+ config.mnc == 10 ||
+ config.mnc == 12 ||
+ config.mnc == 13 ||
+ config.mnc == 350 ||
+ config.mnc == 590 ||
+ config.mnc == 820 ||
+ config.mnc == 890 ||
+ config.mnc == 910)) ||
+ (config.mcc == 311 && (config.mnc == 12 ||
+ config.mnc == 110 ||
+ (config.mnc >= 270 && config.mnc <= 289) ||
+ config.mnc == 390 ||
+ (config.mnc >= 480 && config.mnc <= 489) ||
+ config.mnc == 590)) ||
+ (config.mcc == 312 && (config.mnc == 770))) {
+ listExclude.add(new IPUtil.CIDR("66.174.0.0", 16)); // 66.174.0.0 - 66.174.255.255
+ listExclude.add(new IPUtil.CIDR("66.82.0.0", 15)); // 69.82.0.0 - 69.83.255.255
+ listExclude.add(new IPUtil.CIDR("69.96.0.0", 13)); // 69.96.0.0 - 69.103.255.255
+ listExclude.add(new IPUtil.CIDR("70.192.0.0", 11)); // 70.192.0.0 - 70.223.255.255
+ listExclude.add(new IPUtil.CIDR("97.128.0.0", 9)); // 97.128.0.0 - 97.255.255.255
+ listExclude.add(new IPUtil.CIDR("174.192.0.0", 9)); // 174.192.0.0 - 174.255.255.255
+ listExclude.add(new IPUtil.CIDR("72.96.0.0", 9)); // 72.96.0.0 - 72.127.255.255
+ listExclude.add(new IPUtil.CIDR("75.192.0.0", 9)); // 75.192.0.0 - 75.255.255.255
+ listExclude.add(new IPUtil.CIDR("97.0.0.0", 10)); // 97.0.0.0 - 97.63.255.255
+ }
+
+ // SFR MMS
+ if (config.mnc == 10 && config.mcc == 208)
+ listExclude.add(new IPUtil.CIDR("10.151.0.0", 24));
+
+ // Broadcast
+ listExclude.add(new IPUtil.CIDR("224.0.0.0", 3));
+
+ Collections.sort(listExclude);
+
+ try {
+ InetAddress start = InetAddress.getByName("0.0.0.0");
+ for (IPUtil.CIDR exclude : listExclude) {
+ Log.i(TAG, "Exclude " + exclude.getStart().getHostAddress() + "..." + exclude.getEnd().getHostAddress());
+ for (IPUtil.CIDR include : IPUtil.toCIDR(start, IPUtil.minus1(exclude.getStart())))
+ try {
+ builder.addRoute(include.address, include.prefix);
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ start = IPUtil.plus1(exclude.getEnd());
+ }
+ String end = (lan ? "255.255.255.254" : "255.255.255.255");
+ for (IPUtil.CIDR include : IPUtil.toCIDR("224.0.0.0", end))
+ try {
+ builder.addRoute(include.address, include.prefix);
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ } catch (UnknownHostException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ } else
+ builder.addRoute("0.0.0.0", 0);
+
+ Log.i(TAG, "IPv6=" + ip6);
+ if (ip6)
+ builder.addRoute("2000::", 3); // unicast
+
+ // MTU
+ int mtu = jni_get_mtu();
+ Log.i(TAG, "MTU=" + mtu);
+ builder.setMtu(mtu);
+
+ // Add list of allowed applications
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ try {
+ builder.addDisallowedApplication(getPackageName());
+ } catch (PackageManager.NameNotFoundException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ if (last_connected && !filter)
+ for (Rule rule : listAllowed)
+ try {
+ builder.addDisallowedApplication(rule.packageName);
+ } catch (PackageManager.NameNotFoundException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ else if (filter)
+ for (Rule rule : listRule)
+ if (!rule.apply || (!system && rule.system))
+ try {
+ Log.i(TAG, "Not routing " + rule.packageName);
+ builder.addDisallowedApplication(rule.packageName);
+ } catch (PackageManager.NameNotFoundException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+
+ // Build configure intent
+ Intent configure = new Intent(this, ActivityMain.class);
+ PendingIntent pi = PendingIntent.getActivity(this, 0, configure, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+ builder.setConfigureIntent(pi);
+
+ return builder;
+ }
+
+ private void startNative(final ParcelFileDescriptor vpn, List listAllowed, List listRule) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+ boolean log = prefs.getBoolean("log", false);
+ boolean log_app = prefs.getBoolean("log_app", false);
+ boolean filter = prefs.getBoolean("filter", false);
+
+ Log.i(TAG, "Start native log=" + log + "/" + log_app + " filter=" + filter);
+
+ // Prepare rules
+ if (filter) {
+ prepareUidAllowed(listAllowed, listRule);
+ prepareHostsBlocked();
+ prepareUidIPFilters(null);
+ prepareForwarding();
+ } else {
+ lock.writeLock().lock();
+ mapUidAllowed.clear();
+ mapUidKnown.clear();
+ mapHostsBlocked.clear();
+ mapUidIPFilters.clear();
+ mapForward.clear();
+ lock.writeLock().unlock();
+ }
+
+ if (log_app)
+ prepareNotify(listRule);
+ else {
+ lock.writeLock().lock();
+ mapNotify.clear();
+ lock.writeLock().unlock();
+ }
+
+ if (log || log_app || filter) {
+ int prio = Integer.parseInt(prefs.getString("loglevel", Integer.toString(Log.WARN)));
+ final int rcode = Integer.parseInt(prefs.getString("rcode", "3"));
+ if (prefs.getBoolean("socks5_enabled", false))
+ jni_socks5(
+ prefs.getString("socks5_addr", ""),
+ Integer.parseInt(prefs.getString("socks5_port", "0")),
+ prefs.getString("socks5_username", ""),
+ prefs.getString("socks5_password", ""));
+ else
+ jni_socks5("", 0, "", "");
+
+ if (tunnelThread == null) {
+ Log.i(TAG, "Starting tunnel thread context=" + jni_context);
+ jni_start(jni_context, prio);
+
+ tunnelThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ Log.i(TAG, "Running tunnel context=" + jni_context);
+ jni_run(jni_context, vpn.getFd(), mapForward.containsKey(53), rcode);
+ Log.i(TAG, "Tunnel exited");
+ tunnelThread = null;
+ }
+ });
+ //tunnelThread.setPriority(Thread.MAX_PRIORITY);
+ tunnelThread.start();
+
+ Log.i(TAG, "Started tunnel thread");
+ }
+ }
+ }
+
+ private void stopNative(ParcelFileDescriptor vpn) {
+ Log.i(TAG, "Stop native");
+
+ if (tunnelThread != null) {
+ Log.i(TAG, "Stopping tunnel thread");
+
+ jni_stop(jni_context);
+
+ Thread thread = tunnelThread;
+ while (thread != null && thread.isAlive()) {
+ try {
+ Log.i(TAG, "Joining tunnel thread context=" + jni_context);
+ thread.join();
+ } catch (InterruptedException ignored) {
+ Log.i(TAG, "Joined tunnel interrupted");
+ }
+ thread = tunnelThread;
+ }
+ tunnelThread = null;
+
+ jni_clear(jni_context);
+
+ Log.i(TAG, "Stopped tunnel thread");
+ }
+ }
+
+ private void unprepare() {
+ lock.writeLock().lock();
+ mapUidAllowed.clear();
+ mapUidKnown.clear();
+ mapHostsBlocked.clear();
+ mapUidIPFilters.clear();
+ mapForward.clear();
+ mapNotify.clear();
+ lock.writeLock().unlock();
+ }
+
+ private void prepareUidAllowed(List listAllowed, List listRule) {
+ lock.writeLock().lock();
+
+ mapUidAllowed.clear();
+ for (Rule rule : listAllowed)
+ mapUidAllowed.put(rule.uid, true);
+
+ mapUidKnown.clear();
+ for (Rule rule : listRule)
+ mapUidKnown.put(rule.uid, rule.uid);
+
+ lock.writeLock().unlock();
+ }
+
+ private void prepareHostsBlocked() {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+ boolean use_hosts = prefs.getBoolean("filter", false) && prefs.getBoolean("use_hosts", false);
+ File hosts = new File(getFilesDir(), "hosts.txt");
+ if (!use_hosts || !hosts.exists() || !hosts.canRead()) {
+ Log.i(TAG, "Hosts file use=" + use_hosts + " exists=" + hosts.exists());
+ lock.writeLock().lock();
+ mapHostsBlocked.clear();
+ lock.writeLock().unlock();
+ return;
+ }
+
+ boolean changed = (hosts.lastModified() != last_hosts_modified);
+ if (!changed && mapHostsBlocked.size() > 0) {
+ Log.i(TAG, "Hosts file unchanged");
+ return;
+ }
+ last_hosts_modified = hosts.lastModified();
+
+ lock.writeLock().lock();
+
+ mapHostsBlocked.clear();
+
+ int count = 0;
+ BufferedReader br = null;
+ try {
+ br = new BufferedReader(new FileReader(hosts));
+ String line;
+ while ((line = br.readLine()) != null) {
+ int hash = line.indexOf('#');
+ if (hash >= 0)
+ line = line.substring(0, hash);
+ line = line.trim();
+ if (line.length() > 0) {
+ String[] words = line.split("\\s+");
+ if (words.length == 2) {
+ count++;
+ mapHostsBlocked.put(words[1], true);
+ } else
+ Log.i(TAG, "Invalid hosts file line: " + line);
+ }
+ }
+ mapHostsBlocked.put("test.netguard.me", true);
+ Log.i(TAG, count + " hosts read");
+ } catch (IOException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ } finally {
+ if (br != null)
+ try {
+ br.close();
+ } catch (IOException exex) {
+ Log.e(TAG, exex.toString() + "\n" + Log.getStackTraceString(exex));
+ }
+ }
+
+ lock.writeLock().unlock();
+ }
+
+ private void prepareUidIPFilters(String dname) {
+ SharedPreferences lockdown = getSharedPreferences("lockdown", Context.MODE_PRIVATE);
+
+ lock.writeLock().lock();
+
+ if (dname == null) {
+ mapUidIPFilters.clear();
+ if (!IAB.isPurchased(ActivityPro.SKU_FILTER, ServiceSinkhole.this)) {
+ lock.writeLock().unlock();
+ return;
+ }
+ }
+
+ try (Cursor cursor = DatabaseHelper.getInstance(ServiceSinkhole.this).getAccessDns(dname)) {
+ int colUid = cursor.getColumnIndex("uid");
+ int colVersion = cursor.getColumnIndex("version");
+ int colProtocol = cursor.getColumnIndex("protocol");
+ int colDAddr = cursor.getColumnIndex("daddr");
+ int colResource = cursor.getColumnIndex("resource");
+ int colDPort = cursor.getColumnIndex("dport");
+ int colBlock = cursor.getColumnIndex("block");
+ int colTime = cursor.getColumnIndex("time");
+ int colTTL = cursor.getColumnIndex("ttl");
+ while (cursor.moveToNext()) {
+ int uid = cursor.getInt(colUid);
+ int version = cursor.getInt(colVersion);
+ int protocol = cursor.getInt(colProtocol);
+ String daddr = cursor.getString(colDAddr);
+ String dresource = (cursor.isNull(colResource) ? null : cursor.getString(colResource));
+ int dport = cursor.getInt(colDPort);
+ boolean block = (cursor.getInt(colBlock) > 0);
+ long time = (cursor.isNull(colTime) ? new Date().getTime() : cursor.getLong(colTime));
+ long ttl = (cursor.isNull(colTTL) ? 7 * 24 * 3600 * 1000L : cursor.getLong(colTTL));
+
+ if (isLockedDown(last_metered)) {
+ String[] pkg = getPackageManager().getPackagesForUid(uid);
+ if (pkg != null && pkg.length > 0) {
+ if (!lockdown.getBoolean(pkg[0], false))
+ continue;
+ }
+ }
+
+ IPKey key = new IPKey(version, protocol, dport, uid);
+ synchronized (mapUidIPFilters) {
+ if (!mapUidIPFilters.containsKey(key))
+ mapUidIPFilters.put(key, new HashMap());
+
+ try {
+ String name = (dresource == null ? daddr : dresource);
+ if (Util.isNumericAddress(name)) {
+ InetAddress iname = InetAddress.getByName(name);
+ if (version == 4 && !(iname instanceof Inet4Address))
+ continue;
+ if (version == 6 && !(iname instanceof Inet6Address))
+ continue;
+
+ boolean exists = mapUidIPFilters.get(key).containsKey(iname);
+ if (!exists || !mapUidIPFilters.get(key).get(iname).isBlocked()) {
+ IPRule rule = new IPRule(key, name + "/" + iname, block, time, ttl);
+ mapUidIPFilters.get(key).put(iname, rule);
+ if (exists)
+ Log.w(TAG, "Address conflict " + key + " " + daddr + "/" + dresource);
+ } else if (exists) {
+ mapUidIPFilters.get(key).get(iname).updateExpires(time, ttl);
+ if (dname != null && ttl > 60 * 1000L)
+ Log.w(TAG, "Address updated " + key + " " + daddr + "/" + dresource);
+ } else {
+ if (dname != null)
+ Log.i(TAG, "Ignored " + key + " " + daddr + "/" + dresource + "=" + block);
+ }
+ } else
+ Log.w(TAG, "Address not numeric " + name);
+ } catch (UnknownHostException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+ }
+ }
+
+ lock.writeLock().unlock();
+ }
+
+ private void prepareForwarding() {
+ lock.writeLock().lock();
+ mapForward.clear();
+
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ if (prefs.getBoolean("filter", false)) {
+ try (Cursor cursor = DatabaseHelper.getInstance(ServiceSinkhole.this).getForwarding()) {
+ int colProtocol = cursor.getColumnIndex("protocol");
+ int colDPort = cursor.getColumnIndex("dport");
+ int colRAddr = cursor.getColumnIndex("raddr");
+ int colRPort = cursor.getColumnIndex("rport");
+ int colRUid = cursor.getColumnIndex("ruid");
+ while (cursor.moveToNext()) {
+ Forward fwd = new Forward();
+ fwd.protocol = cursor.getInt(colProtocol);
+ fwd.dport = cursor.getInt(colDPort);
+ fwd.raddr = cursor.getString(colRAddr);
+ fwd.rport = cursor.getInt(colRPort);
+ fwd.ruid = cursor.getInt(colRUid);
+ mapForward.put(fwd.dport, fwd);
+ Log.i(TAG, "Forward " + fwd);
+ }
+ }
+ }
+ lock.writeLock().unlock();
+ }
+
+ private void prepareNotify(List listRule) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean notify = prefs.getBoolean("notify_access", false);
+ boolean system = prefs.getBoolean("manage_system", false);
+
+ lock.writeLock().lock();
+ mapNotify.clear();
+ for (Rule rule : listRule)
+ mapNotify.put(rule.uid, notify && rule.notify && (system || !rule.system));
+ lock.writeLock().unlock();
+ }
+
+ private boolean isLockedDown(boolean metered) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+ boolean lockdown = prefs.getBoolean("lockdown", false);
+ boolean lockdown_wifi = prefs.getBoolean("lockdown_wifi", true);
+ boolean lockdown_other = prefs.getBoolean("lockdown_other", true);
+ if (metered ? !lockdown_other : !lockdown_wifi)
+ lockdown = false;
+
+ return lockdown;
+ }
+
+ private List getAllowedRules(List listRule) {
+ List listAllowed = new ArrayList<>();
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+
+ // Check state
+ boolean wifi = Util.isWifiActive(this);
+ boolean metered = Util.isMeteredNetwork(this);
+ boolean useMetered = prefs.getBoolean("use_metered", false);
+ Set ssidHomes = prefs.getStringSet("wifi_homes", new HashSet());
+ String ssidNetwork = Util.getWifiSSID(this);
+ String generation = Util.getNetworkGeneration(this);
+ boolean unmetered_2g = prefs.getBoolean("unmetered_2g", false);
+ boolean unmetered_3g = prefs.getBoolean("unmetered_3g", false);
+ boolean unmetered_4g = prefs.getBoolean("unmetered_4g", false);
+ boolean roaming = Util.isRoaming(ServiceSinkhole.this);
+ boolean national = prefs.getBoolean("national_roaming", false);
+ boolean eu = prefs.getBoolean("eu_roaming", false);
+ boolean tethering = prefs.getBoolean("tethering", false);
+ boolean filter = prefs.getBoolean("filter", false);
+
+ // Update connected state
+ last_connected = Util.isConnected(ServiceSinkhole.this);
+
+ boolean org_metered = metered;
+ boolean org_roaming = roaming;
+
+ // https://issuetracker.google.com/issues/70633700
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1)
+ ssidHomes.clear();
+
+ // Update metered state
+ if (wifi && !useMetered)
+ metered = false;
+ if (wifi && ssidHomes.size() > 0 &&
+ !(ssidHomes.contains(ssidNetwork) || ssidHomes.contains('"' + ssidNetwork + '"'))) {
+ metered = true;
+ Log.i(TAG, "!@home=" + ssidNetwork + " homes=" + TextUtils.join(",", ssidHomes));
+ }
+ if (unmetered_2g && "2G".equals(generation))
+ metered = false;
+ if (unmetered_3g && "3G".equals(generation))
+ metered = false;
+ if (unmetered_4g && "4G".equals(generation))
+ metered = false;
+ last_metered = metered;
+
+ boolean lockdown = isLockedDown(last_metered);
+
+ // Update roaming state
+ if (roaming && eu)
+ roaming = !Util.isEU(this);
+ if (roaming && national)
+ roaming = !Util.isNational(this);
+
+ Log.i(TAG, "Get allowed" +
+ " connected=" + last_connected +
+ " wifi=" + wifi +
+ " home=" + TextUtils.join(",", ssidHomes) +
+ " network=" + ssidNetwork +
+ " metered=" + metered + "/" + org_metered +
+ " generation=" + generation +
+ " roaming=" + roaming + "/" + org_roaming +
+ " interactive=" + last_interactive +
+ " tethering=" + tethering +
+ " filter=" + filter +
+ " lockdown=" + lockdown);
+
+ if (last_connected)
+ for (Rule rule : listRule) {
+ boolean blocked = (metered ? rule.other_blocked : rule.wifi_blocked);
+ boolean screen = (metered ? rule.screen_other : rule.screen_wifi);
+ if ((!blocked || (screen && last_interactive)) &&
+ (!metered || !(rule.roaming && roaming)) &&
+ (!lockdown || rule.lockdown))
+ listAllowed.add(rule);
+ }
+
+ Log.i(TAG, "Allowed " + listAllowed.size() + " of " + listRule.size());
+ return listAllowed;
+ }
+
+ private void stopVPN(ParcelFileDescriptor pfd) {
+ Log.i(TAG, "Stopping");
+ try {
+ pfd.close();
+ } catch (IOException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+
+ // Called from native code
+ private void nativeExit(String reason) {
+ Log.w(TAG, "Native exit reason=" + reason);
+ if (reason != null) {
+ showErrorNotification(reason);
+
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.edit().putBoolean("enabled", false).apply();
+ WidgetMain.updateWidgets(this);
+ }
+ }
+
+ // Called from native code
+ private void nativeError(int error, String message) {
+ Log.w(TAG, "Native error " + error + ": " + message);
+ showErrorNotification(message);
+ }
+
+ // Called from native code
+ private void logPacket(Packet packet) {
+ logHandler.queue(packet);
+ }
+
+ // Called from native code
+ private void dnsResolved(ResourceRecord rr) {
+ if (DatabaseHelper.getInstance(ServiceSinkhole.this).insertDns(rr)) {
+ Log.i(TAG, "New IP " + rr);
+ prepareUidIPFilters(rr.QName);
+ }
+ }
+
+ // Called from native code
+ private boolean isDomainBlocked(String name) {
+ lock.readLock().lock();
+ boolean blocked = (mapHostsBlocked.containsKey(name) && mapHostsBlocked.get(name));
+ lock.readLock().unlock();
+ return blocked;
+ }
+
+ // Called from native code
+ @TargetApi(Build.VERSION_CODES.Q)
+ private int getUidQ(int version, int protocol, String saddr, int sport, String daddr, int dport) {
+ if (protocol != 6 /* TCP */ && protocol != 17 /* UDP */)
+ return Process.INVALID_UID;
+
+ ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
+ if (cm == null)
+ return Process.INVALID_UID;
+
+ InetSocketAddress local = new InetSocketAddress(saddr, sport);
+ InetSocketAddress remote = new InetSocketAddress(daddr, dport);
+
+ Log.i(TAG, "Get uid local=" + local + " remote=" + remote);
+ int uid = cm.getConnectionOwnerUid(protocol, local, remote);
+ Log.i(TAG, "Get uid=" + uid);
+ return uid;
+ }
+
+ private boolean isSupported(int protocol) {
+ return (protocol == 1 /* ICMPv4 */ ||
+ protocol == 58 /* ICMPv6 */ ||
+ protocol == 6 /* TCP */ ||
+ protocol == 17 /* UDP */);
+ }
+
+ // Called from native code
+ private Allowed isAddressAllowed(Packet packet) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+
+ lock.readLock().lock();
+
+ packet.allowed = false;
+ if (prefs.getBoolean("filter", false)) {
+ // https://android.googlesource.com/platform/system/core/+/master/include/private/android_filesystem_config.h
+ if (packet.protocol == 17 /* UDP */ && !prefs.getBoolean("filter_udp", false)) {
+ // Allow unfiltered UDP
+ packet.allowed = true;
+ Log.i(TAG, "Allowing UDP " + packet);
+ } else if (packet.uid < 2000 &&
+ !last_connected && isSupported(packet.protocol) && false) {
+ // Allow system applications in disconnected state
+ packet.allowed = true;
+ Log.w(TAG, "Allowing disconnected system " + packet);
+ } else if (packet.uid < 2000 &&
+ !mapUidKnown.containsKey(packet.uid) && isSupported(packet.protocol)) {
+ // Allow unknown system traffic
+ packet.allowed = true;
+ Log.w(TAG, "Allowing unknown system " + packet);
+ } else if (packet.uid == Process.myUid()) {
+ // Allow self
+ packet.allowed = true;
+ Log.w(TAG, "Allowing self " + packet);
+ } else {
+ boolean filtered = false;
+ IPKey key = new IPKey(packet.version, packet.protocol, packet.dport, packet.uid);
+ if (mapUidIPFilters.containsKey(key))
+ try {
+ InetAddress iaddr = InetAddress.getByName(packet.daddr);
+ Map map = mapUidIPFilters.get(key);
+ if (map != null && map.containsKey(iaddr)) {
+ IPRule rule = map.get(iaddr);
+ if (rule.isExpired())
+ Log.i(TAG, "DNS expired " + packet + " rule " + rule);
+ else {
+ filtered = true;
+ packet.allowed = !rule.isBlocked();
+ Log.i(TAG, "Filtering " + packet +
+ " allowed=" + packet.allowed + " rule " + rule);
+ }
+ }
+ } catch (UnknownHostException ex) {
+ Log.w(TAG, "Allowed " + ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ if (!filtered)
+ if (mapUidAllowed.containsKey(packet.uid))
+ packet.allowed = mapUidAllowed.get(packet.uid);
+ else
+ Log.w(TAG, "No rules for " + packet);
+ }
+ }
+
+ Allowed allowed = null;
+ if (packet.allowed) {
+ if (mapForward.containsKey(packet.dport)) {
+ Forward fwd = mapForward.get(packet.dport);
+ if (fwd.ruid == packet.uid) {
+ allowed = new Allowed();
+ } else {
+ allowed = new Allowed(fwd.raddr, fwd.rport);
+ packet.data = "> " + fwd.raddr + "/" + fwd.rport;
+ }
+ } else
+ allowed = new Allowed();
+ }
+
+ lock.readLock().unlock();
+
+ if (prefs.getBoolean("log", false) || prefs.getBoolean("log_app", false))
+ if (packet.protocol != 6 /* TCP */ || !"".equals(packet.flags))
+ if (packet.uid != Process.myUid())
+ logPacket(packet);
+
+ return allowed;
+ }
+
+ // Called from native code
+ private void accountUsage(Usage usage) {
+ logHandler.account(usage);
+ }
+
+ private BroadcastReceiver interactiveStateReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(final Context context, final Intent intent) {
+ Log.i(TAG, "Received " + intent);
+ Util.logExtras(intent);
+
+ executor.submit(new Runnable() {
+ @Override
+ public void run() {
+ AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ Intent i = new Intent(ACTION_SCREEN_OFF_DELAYED);
+ i.setPackage(context.getPackageName());
+ PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+ am.cancel(pi);
+
+ try {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+ int delay;
+ try {
+ delay = Integer.parseInt(prefs.getString("screen_delay", "0"));
+ } catch (NumberFormatException ignored) {
+ delay = 0;
+ }
+ boolean interactive = Intent.ACTION_SCREEN_ON.equals(intent.getAction());
+
+ if (interactive || delay == 0) {
+ last_interactive = interactive;
+ reload("interactive state changed", ServiceSinkhole.this, true);
+ } else {
+ if (ACTION_SCREEN_OFF_DELAYED.equals(intent.getAction())) {
+ last_interactive = interactive;
+ reload("interactive state changed", ServiceSinkhole.this, true);
+ } else {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
+ am.set(AlarmManager.RTC_WAKEUP, new Date().getTime() + delay * 60 * 1000L, pi);
+ else
+ am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, new Date().getTime() + delay * 60 * 1000L, pi);
+ }
+ }
+
+ // Start/stop stats
+ statsHandler.sendEmptyMessage(
+ Util.isInteractive(ServiceSinkhole.this) ? MSG_STATS_START : MSG_STATS_STOP);
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
+ am.set(AlarmManager.RTC_WAKEUP, new Date().getTime() + 15 * 1000L, pi);
+ else
+ am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, new Date().getTime() + 15 * 1000L, pi);
+ }
+ }
+ });
+ }
+ };
+
+ private BroadcastReceiver userReceiver = new BroadcastReceiver() {
+ @Override
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
+ public void onReceive(Context context, Intent intent) {
+ Log.i(TAG, "Received " + intent);
+ Util.logExtras(intent);
+
+ user_foreground = Intent.ACTION_USER_FOREGROUND.equals(intent.getAction());
+ Log.i(TAG, "User foreground=" + user_foreground + " user=" + (Process.myUid() / 100000));
+
+ if (user_foreground) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+ if (prefs.getBoolean("enabled", false)) {
+ // Allow service of background user to stop
+ try {
+ Thread.sleep(3000);
+ } catch (InterruptedException ignored) {
+ }
+
+ start("foreground", ServiceSinkhole.this);
+ }
+ } else
+ stop("background", ServiceSinkhole.this, true);
+ }
+ };
+
+ private BroadcastReceiver idleStateReceiver = new BroadcastReceiver() {
+ @Override
+ @TargetApi(Build.VERSION_CODES.M)
+ public void onReceive(Context context, Intent intent) {
+ Log.i(TAG, "Received " + intent);
+ Util.logExtras(intent);
+
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ Log.i(TAG, "device idle=" + pm.isDeviceIdleMode());
+
+ // Reload rules when coming from idle mode
+ if (!pm.isDeviceIdleMode())
+ reload("idle state changed", ServiceSinkhole.this, false);
+ }
+ };
+
+ private BroadcastReceiver connectivityChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // Filter VPN connectivity changes
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ int networkType = intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_DUMMY);
+ if (networkType == ConnectivityManager.TYPE_VPN)
+ return;
+ }
+
+ // Reload rules
+ Log.i(TAG, "Received " + intent);
+ Util.logExtras(intent);
+ reload("connectivity changed", ServiceSinkhole.this, false);
+ }
+ };
+
+ ConnectivityManager.NetworkCallback networkMonitorCallback = new ConnectivityManager.NetworkCallback() {
+ private String TAG = "NetGuard.Monitor";
+
+ private Map validated = new HashMap<>();
+
+ // https://android.googlesource.com/platform/frameworks/base/+/master/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+
+ @Override
+ public void onAvailable(Network network) {
+ ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo ni = cm.getNetworkInfo(network);
+ NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
+ Log.i(TAG, "Available network " + network + " " + ni);
+ Log.i(TAG, "Capabilities=" + capabilities);
+ checkConnectivity(network, ni, capabilities);
+ }
+
+ @Override
+ public void onCapabilitiesChanged(Network network, NetworkCapabilities capabilities) {
+ ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo ni = cm.getNetworkInfo(network);
+ Log.i(TAG, "New capabilities network " + network + " " + ni);
+ Log.i(TAG, "Capabilities=" + capabilities);
+ checkConnectivity(network, ni, capabilities);
+ }
+
+ @Override
+ public void onLosing(Network network, int maxMsToLive) {
+ ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo ni = cm.getNetworkInfo(network);
+ Log.i(TAG, "Losing network " + network + " within " + maxMsToLive + " ms " + ni);
+ }
+
+ @Override
+ public void onLost(Network network) {
+ ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo ni = cm.getNetworkInfo(network);
+ Log.i(TAG, "Lost network " + network + " " + ni);
+
+ synchronized (validated) {
+ validated.remove(network);
+ }
+ }
+
+ @Override
+ public void onUnavailable() {
+ Log.i(TAG, "No networks available");
+ }
+
+ private void checkConnectivity(Network network, NetworkInfo ni, NetworkCapabilities capabilities) {
+ if (ni != null && capabilities != null &&
+ ni.getDetailedState() != NetworkInfo.DetailedState.SUSPENDED &&
+ ni.getDetailedState() != NetworkInfo.DetailedState.BLOCKED &&
+ ni.getDetailedState() != NetworkInfo.DetailedState.DISCONNECTED &&
+ capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) &&
+ !capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
+
+ synchronized (validated) {
+ if (validated.containsKey(network) &&
+ validated.get(network) + 20 * 1000 > new Date().getTime()) {
+ Log.i(TAG, "Already validated " + network + " " + ni);
+ return;
+ }
+ }
+
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+ String host = prefs.getString("validate", "www.google.com");
+ Log.i(TAG, "Validating " + network + " " + ni + " host=" + host);
+
+ Socket socket = null;
+ try {
+ socket = network.getSocketFactory().createSocket();
+ socket.connect(new InetSocketAddress(host, 443), 10000);
+ Log.i(TAG, "Validated " + network + " " + ni + " host=" + host);
+ synchronized (validated) {
+ validated.put(network, new Date().getTime());
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+ cm.reportNetworkConnectivity(network, true);
+ Log.i(TAG, "Reported " + network + " " + ni);
+ }
+ } catch (IOException ex) {
+ Log.e(TAG, ex.toString());
+ Log.i(TAG, "No connectivity " + network + " " + ni);
+ } finally {
+ if (socket != null)
+ try {
+ socket.close();
+ } catch (IOException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+ }
+ }
+ };
+
+ private PhoneStateListener phoneStateListener = new PhoneStateListener() {
+ private String last_generation = null;
+
+ @Override
+ public void onDataConnectionStateChanged(int state, int networkType) {
+ if (state == TelephonyManager.DATA_CONNECTED) {
+ String current_generation = Util.getNetworkGeneration(ServiceSinkhole.this);
+ Log.i(TAG, "Data connected generation=" + current_generation);
+
+ if (last_generation == null || !last_generation.equals(current_generation)) {
+ Log.i(TAG, "New network generation=" + current_generation);
+ last_generation = current_generation;
+
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+ if (prefs.getBoolean("unmetered_2g", false) ||
+ prefs.getBoolean("unmetered_3g", false) ||
+ prefs.getBoolean("unmetered_4g", false))
+ reload("data connection state changed", ServiceSinkhole.this, false);
+ }
+ }
+ }
+ };
+
+ private BroadcastReceiver packageChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.i(TAG, "Received " + intent);
+ Util.logExtras(intent);
+
+ try {
+ if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
+ // Application added
+ Rule.clearCache(context);
+
+ if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+ // Show notification
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ if (IAB.isPurchased(ActivityPro.SKU_NOTIFY, context) && prefs.getBoolean("install", true)) {
+ int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+ notifyNewApplication(uid);
+ }
+ }
+
+ reload("package added", context, false);
+
+ } else if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
+ // Application removed
+ Rule.clearCache(context);
+
+ if (intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false)) {
+ // Remove settings
+ String packageName = intent.getData().getSchemeSpecificPart();
+ Log.i(TAG, "Deleting settings package=" + packageName);
+ context.getSharedPreferences("wifi", Context.MODE_PRIVATE).edit().remove(packageName).apply();
+ context.getSharedPreferences("other", Context.MODE_PRIVATE).edit().remove(packageName).apply();
+ context.getSharedPreferences("screen_wifi", Context.MODE_PRIVATE).edit().remove(packageName).apply();
+ context.getSharedPreferences("screen_other", Context.MODE_PRIVATE).edit().remove(packageName).apply();
+ context.getSharedPreferences("roaming", Context.MODE_PRIVATE).edit().remove(packageName).apply();
+ context.getSharedPreferences("lockdown", Context.MODE_PRIVATE).edit().remove(packageName).apply();
+ context.getSharedPreferences("apply", Context.MODE_PRIVATE).edit().remove(packageName).apply();
+ context.getSharedPreferences("notify", Context.MODE_PRIVATE).edit().remove(packageName).apply();
+
+ int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
+ if (uid > 0) {
+ DatabaseHelper dh = DatabaseHelper.getInstance(context);
+ dh.clearLog(uid);
+ dh.clearAccess(uid, false);
+
+ NotificationManagerCompat.from(context).cancel(uid); // installed notification
+ NotificationManagerCompat.from(context).cancel(uid + 10000); // access notification
+ }
+ }
+
+ reload("package deleted", context, false);
+ }
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+ };
+
+ public void notifyNewApplication(int uid) {
+ if (uid < 0)
+ return;
+
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ try {
+ // Get application name
+ String name = TextUtils.join(", ", Util.getApplicationNames(uid, this));
+
+ // Get application info
+ PackageManager pm = getPackageManager();
+ String[] packages = pm.getPackagesForUid(uid);
+ if (packages == null || packages.length < 1)
+ throw new PackageManager.NameNotFoundException(Integer.toString(uid));
+ boolean internet = Util.hasInternet(uid, this);
+
+ // Build notification
+ Intent main = new Intent(this, ActivityMain.class);
+ main.putExtra(ActivityMain.EXTRA_REFRESH, true);
+ main.putExtra(ActivityMain.EXTRA_SEARCH, Integer.toString(uid));
+ PendingIntent pi = PendingIntent.getActivity(this, uid, main, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+
+ TypedValue tv = new TypedValue();
+ getTheme().resolveAttribute(R.attr.colorPrimary, tv, true);
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "notify");
+ builder.setSmallIcon(R.drawable.ic_security_white_24dp)
+ .setContentIntent(pi)
+ .setColor(tv.data)
+ .setAutoCancel(true);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+ builder.setContentTitle(name)
+ .setContentText(getString(R.string.msg_installed_n));
+ else
+ builder.setContentTitle(getString(R.string.app_name))
+ .setContentText(getString(R.string.msg_installed, name));
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
+ builder.setCategory(NotificationCompat.CATEGORY_STATUS)
+ .setVisibility(NotificationCompat.VISIBILITY_SECRET);
+
+ // Get defaults
+ SharedPreferences prefs_wifi = getSharedPreferences("wifi", Context.MODE_PRIVATE);
+ SharedPreferences prefs_other = getSharedPreferences("other", Context.MODE_PRIVATE);
+ boolean wifi = prefs_wifi.getBoolean(packages[0], prefs.getBoolean("whitelist_wifi", true));
+ boolean other = prefs_other.getBoolean(packages[0], prefs.getBoolean("whitelist_other", true));
+
+ // Build Wi-Fi action
+ Intent riWifi = new Intent(this, ServiceSinkhole.class);
+ riWifi.putExtra(ServiceSinkhole.EXTRA_COMMAND, ServiceSinkhole.Command.set);
+ riWifi.putExtra(ServiceSinkhole.EXTRA_NETWORK, "wifi");
+ riWifi.putExtra(ServiceSinkhole.EXTRA_UID, uid);
+ riWifi.putExtra(ServiceSinkhole.EXTRA_PACKAGE, packages[0]);
+ riWifi.putExtra(ServiceSinkhole.EXTRA_BLOCKED, !wifi);
+
+ PendingIntent piWifi = PendingIntent.getService(this, uid, riWifi, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+ NotificationCompat.Action wAction = new NotificationCompat.Action.Builder(
+ wifi ? R.drawable.wifi_on : R.drawable.wifi_off,
+ getString(wifi ? R.string.title_allow_wifi : R.string.title_block_wifi),
+ piWifi
+ ).build();
+ builder.addAction(wAction);
+
+ // Build mobile action
+ Intent riOther = new Intent(this, ServiceSinkhole.class);
+ riOther.putExtra(ServiceSinkhole.EXTRA_COMMAND, ServiceSinkhole.Command.set);
+ riOther.putExtra(ServiceSinkhole.EXTRA_NETWORK, "other");
+ riOther.putExtra(ServiceSinkhole.EXTRA_UID, uid);
+ riOther.putExtra(ServiceSinkhole.EXTRA_PACKAGE, packages[0]);
+ riOther.putExtra(ServiceSinkhole.EXTRA_BLOCKED, !other);
+ PendingIntent piOther = PendingIntent.getService(this, uid + 10000, riOther, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+ NotificationCompat.Action oAction = new NotificationCompat.Action.Builder(
+ other ? R.drawable.other_on : R.drawable.other_off,
+ getString(other ? R.string.title_allow_other : R.string.title_block_other),
+ piOther
+ ).build();
+ builder.addAction(oAction);
+
+ // Show notification
+ if (internet)
+ NotificationManagerCompat.from(this).notify(uid, builder.build());
+ else {
+ NotificationCompat.BigTextStyle expanded = new NotificationCompat.BigTextStyle(builder);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+ expanded.bigText(getString(R.string.msg_installed_n));
+ else
+ expanded.bigText(getString(R.string.msg_installed, name));
+ expanded.setSummaryText(getString(R.string.title_internet));
+ NotificationManagerCompat.from(this).notify(uid, expanded.build());
+ }
+
+ } catch (PackageManager.NameNotFoundException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+
+ @Override
+ public void onCreate() {
+ Log.i(TAG, "Create version=" + Util.getSelfVersionName(this) + "/" + Util.getSelfVersionCode(this));
+ startForeground(NOTIFY_WAITING, getWaitingNotification());
+
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+
+ if (jni_context != 0) {
+ Log.w(TAG, "Create with context=" + jni_context);
+ jni_stop(jni_context);
+ synchronized (jni_lock) {
+ jni_done(jni_context);
+ jni_context = 0;
+ }
+ }
+
+ // Native init
+ jni_context = jni_init(Build.VERSION.SDK_INT);
+ Log.i(TAG, "Created context=" + jni_context);
+ boolean pcap = prefs.getBoolean("pcap", false);
+ setPcap(pcap, this);
+
+ prefs.registerOnSharedPreferenceChangeListener(this);
+
+ Util.setTheme(this);
+ super.onCreate();
+
+ HandlerThread commandThread = new HandlerThread(getString(R.string.app_name) + " command", Process.THREAD_PRIORITY_FOREGROUND);
+ HandlerThread logThread = new HandlerThread(getString(R.string.app_name) + " log", Process.THREAD_PRIORITY_BACKGROUND);
+ HandlerThread statsThread = new HandlerThread(getString(R.string.app_name) + " stats", Process.THREAD_PRIORITY_BACKGROUND);
+ commandThread.start();
+ logThread.start();
+ statsThread.start();
+
+ commandLooper = commandThread.getLooper();
+ logLooper = logThread.getLooper();
+ statsLooper = statsThread.getLooper();
+
+ commandHandler = new CommandHandler(commandLooper);
+ logHandler = new LogHandler(logLooper);
+ statsHandler = new StatsHandler(statsLooper);
+
+ // Listen for user switches
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ IntentFilter ifUser = new IntentFilter();
+ ifUser.addAction(Intent.ACTION_USER_BACKGROUND);
+ ifUser.addAction(Intent.ACTION_USER_FOREGROUND);
+ registerReceiver(userReceiver, ifUser);
+ registeredUser = true;
+ }
+
+ // Listen for idle mode state changes
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ IntentFilter ifIdle = new IntentFilter();
+ ifIdle.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
+ registerReceiver(idleStateReceiver, ifIdle);
+ registeredIdleState = true;
+ }
+
+ // Listen for added/removed applications
+ IntentFilter ifPackage = new IntentFilter();
+ ifPackage.addAction(Intent.ACTION_PACKAGE_ADDED);
+ ifPackage.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ ifPackage.addDataScheme("package");
+ registerReceiver(packageChangedReceiver, ifPackage);
+ registeredPackageChanged = true;
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
+ try {
+ listenNetworkChanges();
+ } catch (Throwable ex) {
+ Log.w(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ listenConnectivityChanges();
+ }
+ else
+ listenConnectivityChanges();
+
+ // Monitor networks
+ ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+ cm.registerNetworkCallback(
+ new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build(),
+ networkMonitorCallback);
+
+ // Setup house holding
+ Intent alarmIntent = new Intent(this, ServiceSinkhole.class);
+ alarmIntent.setAction(ACTION_HOUSE_HOLDING);
+ PendingIntent pi;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ pi = PendingIntent.getForegroundService(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+ else
+ pi = PendingIntent.getService(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+
+ AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
+ am.setInexactRepeating(AlarmManager.RTC, SystemClock.elapsedRealtime() + 60 * 1000, AlarmManager.INTERVAL_HALF_DAY, pi);
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ private void listenNetworkChanges() {
+ // Listen for network changes
+ Log.i(TAG, "Starting listening to network changes");
+ ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkRequest.Builder builder = new NetworkRequest.Builder();
+ builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ builder.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
+
+ ConnectivityManager.NetworkCallback nc = new ConnectivityManager.NetworkCallback() {
+ private Boolean last_connected = null;
+ private Boolean last_unmetered = null;
+ private String last_generation = null;
+ private List last_dns = null;
+
+ @Override
+ public void onAvailable(Network network) {
+ Log.i(TAG, "Available network=" + network);
+ last_connected = Util.isConnected(ServiceSinkhole.this);
+ reload("network available", ServiceSinkhole.this, false);
+ }
+
+ @Override
+ public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
+ Log.i(TAG, "Changed properties=" + network + " props=" + linkProperties);
+
+ // Make sure the right DNS servers are being used
+ List dns = linkProperties.getDnsServers();
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
+ ? !same(last_dns, dns)
+ : prefs.getBoolean("reload_onconnectivity", false)) {
+ Log.i(TAG, "Changed link properties=" + linkProperties +
+ "DNS cur=" + TextUtils.join(",", dns) +
+ "DNS prv=" + (last_dns == null ? null : TextUtils.join(",", last_dns)));
+ last_dns = dns;
+ reload("link properties changed", ServiceSinkhole.this, false);
+ }
+ }
+
+ @Override
+ public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
+ Log.i(TAG, "Changed capabilities=" + network + " caps=" + networkCapabilities);
+
+ boolean connected = Util.isConnected(ServiceSinkhole.this);
+ boolean unmetered = networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+ String generation = Util.getNetworkGeneration(ServiceSinkhole.this);
+ Log.i(TAG, "Connected=" + connected + "/" + last_connected +
+ " unmetered=" + unmetered + "/" + last_unmetered +
+ " generation=" + generation + "/" + last_generation);
+
+ if (last_connected != null && !last_connected.equals(connected))
+ reload("Connected state changed", ServiceSinkhole.this, false);
+
+ if (last_unmetered != null && !last_unmetered.equals(unmetered))
+ reload("Unmetered state changed", ServiceSinkhole.this, false);
+
+ if (last_generation != null && !last_generation.equals(generation)) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+ if (prefs.getBoolean("unmetered_2g", false) ||
+ prefs.getBoolean("unmetered_3g", false) ||
+ prefs.getBoolean("unmetered_4g", false))
+ reload("Generation changed", ServiceSinkhole.this, false);
+ }
+
+ last_connected = connected;
+ last_unmetered = unmetered;
+ last_generation = generation;
+ }
+
+ @Override
+ public void onLost(Network network) {
+ Log.i(TAG, "Lost network=" + network);
+ last_connected = Util.isConnected(ServiceSinkhole.this);
+ reload("network lost", ServiceSinkhole.this, false);
+ }
+
+ boolean same(List last, List current) {
+ if (last == null || current == null)
+ return false;
+ if (last == null || last.size() != current.size())
+ return false;
+
+ for (int i = 0; i < current.size(); i++)
+ if (!last.get(i).equals(current.get(i)))
+ return false;
+
+ return true;
+ }
+ };
+ cm.registerNetworkCallback(builder.build(), nc);
+ networkCallback = nc;
+ }
+
+ private void listenConnectivityChanges() {
+ // Listen for connectivity updates
+ Log.i(TAG, "Starting listening to connectivity changes");
+ IntentFilter ifConnectivity = new IntentFilter();
+ ifConnectivity.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ registerReceiver(connectivityChangedReceiver, ifConnectivity);
+ registeredConnectivityChanged = true;
+
+ // Listen for phone state changes
+ Log.i(TAG, "Starting listening to service state changes");
+ TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
+ if (tm != null) {
+ tm.listen(phoneStateListener, PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
+ phone_state = true;
+ }
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences prefs, String name) {
+ if ("theme".equals(name)) {
+ Log.i(TAG, "Theme changed");
+ Util.setTheme(this);
+ if (state != State.none) {
+ Log.d(TAG, "Stop foreground state=" + state.toString());
+ stopForeground(true);
+ }
+ if (state == State.enforcing)
+ startForeground(NOTIFY_ENFORCING, getEnforcingNotification(-1, -1, -1));
+ else if (state != State.none)
+ startForeground(NOTIFY_WAITING, getWaitingNotification());
+ Log.d(TAG, "Start foreground state=" + state.toString());
+ }
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if (state == State.enforcing)
+ startForeground(NOTIFY_ENFORCING, getEnforcingNotification(-1, -1, -1));
+ else
+ startForeground(NOTIFY_WAITING, getWaitingNotification());
+
+ Log.i(TAG, "Received " + intent);
+ Util.logExtras(intent);
+
+ // Check for set command
+ if (intent != null && intent.hasExtra(EXTRA_COMMAND) &&
+ intent.getSerializableExtra(EXTRA_COMMAND) == Command.set) {
+ set(intent);
+ return START_STICKY;
+ }
+
+ // Keep awake
+ getLock(this).acquire();
+
+ // Get state
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean enabled = prefs.getBoolean("enabled", false);
+
+ // Handle service restart
+ if (intent == null) {
+ Log.i(TAG, "Restart");
+
+ // Recreate intent
+ intent = new Intent(this, ServiceSinkhole.class);
+ intent.putExtra(EXTRA_COMMAND, enabled ? Command.start : Command.stop);
+ }
+
+ if (ACTION_HOUSE_HOLDING.equals(intent.getAction()))
+ intent.putExtra(EXTRA_COMMAND, Command.householding);
+ if (ACTION_WATCHDOG.equals(intent.getAction()))
+ intent.putExtra(EXTRA_COMMAND, Command.watchdog);
+
+ Command cmd = (Command) intent.getSerializableExtra(EXTRA_COMMAND);
+ if (cmd == null)
+ intent.putExtra(EXTRA_COMMAND, enabled ? Command.start : Command.stop);
+ String reason = intent.getStringExtra(EXTRA_REASON);
+ Log.i(TAG, "Start intent=" + intent + " command=" + cmd + " reason=" + reason +
+ " vpn=" + (vpn != null) + " user=" + (Process.myUid() / 100000));
+
+ commandHandler.queue(intent);
+
+ return START_STICKY;
+ }
+
+ private void set(Intent intent) {
+ // Get arguments
+ int uid = intent.getIntExtra(EXTRA_UID, 0);
+ String network = intent.getStringExtra(EXTRA_NETWORK);
+ String pkg = intent.getStringExtra(EXTRA_PACKAGE);
+ boolean blocked = intent.getBooleanExtra(EXTRA_BLOCKED, false);
+ Log.i(TAG, "Set " + pkg + " " + network + "=" + blocked);
+
+ // Get defaults
+ SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(ServiceSinkhole.this);
+ boolean default_wifi = settings.getBoolean("whitelist_wifi", true);
+ boolean default_other = settings.getBoolean("whitelist_other", true);
+
+ // Update setting
+ SharedPreferences prefs = getSharedPreferences(network, Context.MODE_PRIVATE);
+ if (blocked == ("wifi".equals(network) ? default_wifi : default_other))
+ prefs.edit().remove(pkg).apply();
+ else
+ prefs.edit().putBoolean(pkg, blocked).apply();
+
+ // Apply rules
+ ServiceSinkhole.reload("notification", ServiceSinkhole.this, false);
+
+ // Update notification
+ notifyNewApplication(uid);
+
+ // Update UI
+ Intent ruleset = new Intent(ActivityMain.ACTION_RULES_CHANGED);
+ LocalBroadcastManager.getInstance(ServiceSinkhole.this).sendBroadcast(ruleset);
+ }
+
+ @Override
+ public void onRevoke() {
+ Log.i(TAG, "Revoke");
+
+ // Disable firewall (will result in stop command)
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.edit().putBoolean("enabled", false).apply();
+
+ // Feedback
+ showDisabledNotification();
+ WidgetMain.updateWidgets(this);
+
+ super.onRevoke();
+ }
+
+ @Override
+ public void onDestroy() {
+ synchronized (this) {
+ Log.i(TAG, "Destroy");
+ commandLooper.quit();
+ logLooper.quit();
+ statsLooper.quit();
+
+ for (Command command : Command.values())
+ commandHandler.removeMessages(command.ordinal());
+ releaseLock(this);
+
+ // Registered in command loop
+ if (registeredInteractiveState) {
+ unregisterReceiver(interactiveStateReceiver);
+ registeredInteractiveState = false;
+ }
+ if (callStateListener != null) {
+ TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
+ tm.listen(callStateListener, PhoneStateListener.LISTEN_NONE);
+ callStateListener = null;
+ }
+
+ // Register in onCreate
+ if (registeredUser) {
+ unregisterReceiver(userReceiver);
+ registeredUser = false;
+ }
+ if (registeredIdleState) {
+ unregisterReceiver(idleStateReceiver);
+ registeredIdleState = false;
+ }
+ if (registeredPackageChanged) {
+ unregisterReceiver(packageChangedReceiver);
+ registeredPackageChanged = false;
+ }
+
+ if (networkCallback != null) {
+ unlistenNetworkChanges();
+ networkCallback = null;
+ }
+ if (registeredConnectivityChanged) {
+ unregisterReceiver(connectivityChangedReceiver);
+ registeredConnectivityChanged = false;
+ }
+
+ ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+ cm.unregisterNetworkCallback(networkMonitorCallback);
+
+ if (phone_state) {
+ TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
+ tm.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
+ phone_state = false;
+ }
+
+ try {
+ if (vpn != null) {
+ stopNative(vpn);
+ stopVPN(vpn);
+ vpn = null;
+ unprepare();
+ }
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+
+ Log.i(TAG, "Destroy context=" + jni_context);
+ synchronized (jni_lock) {
+ jni_done(jni_context);
+ jni_context = 0;
+ }
+
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.unregisterOnSharedPreferenceChangeListener(this);
+ }
+
+ super.onDestroy();
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ private void unlistenNetworkChanges() {
+ ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+ cm.unregisterNetworkCallback((ConnectivityManager.NetworkCallback) networkCallback);
+ }
+
+ private Notification getEnforcingNotification(int allowed, int blocked, int hosts) {
+ Intent main = new Intent(this, ActivityMain.class);
+ PendingIntent pi = PendingIntent.getActivity(this, 0, main, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+
+ TypedValue tv = new TypedValue();
+ getTheme().resolveAttribute(R.attr.colorPrimary, tv, true);
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "foreground");
+ builder.setSmallIcon(isLockedDown(last_metered) ? R.drawable.ic_lock_outline_white_24dp : R.drawable.ic_security_white_24dp)
+ .setContentIntent(pi)
+ .setColor(tv.data)
+ .setOngoing(true)
+ .setAutoCancel(false);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+ builder.setContentTitle(getString(R.string.msg_started));
+ else
+ builder.setContentTitle(getString(R.string.app_name))
+ .setContentText(getString(R.string.msg_started));
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
+ builder.setCategory(NotificationCompat.CATEGORY_STATUS)
+ .setVisibility(NotificationCompat.VISIBILITY_SECRET)
+ .setPriority(NotificationCompat.PRIORITY_MIN);
+
+ if (allowed >= 0)
+ last_allowed = allowed;
+ else
+ allowed = last_allowed;
+ if (blocked >= 0)
+ last_blocked = blocked;
+ else
+ blocked = last_blocked;
+ if (hosts >= 0)
+ last_hosts = hosts;
+ else
+ hosts = last_hosts;
+
+ if (allowed >= 0 || blocked >= 0 || hosts >= 0) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ if (Util.isPlayStoreInstall(this))
+ builder.setContentText(getString(R.string.msg_packages, allowed, blocked));
+ else
+ builder.setContentText(getString(R.string.msg_hosts, allowed, blocked, hosts));
+ return builder.build();
+ } else {
+ NotificationCompat.BigTextStyle notification = new NotificationCompat.BigTextStyle(builder);
+ notification.bigText(getString(R.string.msg_started));
+ if (Util.isPlayStoreInstall(this))
+ notification.setSummaryText(getString(R.string.msg_packages, allowed, blocked));
+ else
+ notification.setSummaryText(getString(R.string.msg_hosts, allowed, blocked, hosts));
+ return notification.build();
+ }
+ } else
+ return builder.build();
+ }
+
+ private void updateEnforcingNotification(int allowed, int total) {
+ // Update notification
+ Notification notification = getEnforcingNotification(allowed, total - allowed, mapHostsBlocked.size());
+ NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+ nm.notify(NOTIFY_ENFORCING, notification);
+ }
+
+ private Notification getWaitingNotification() {
+ Intent main = new Intent(this, ActivityMain.class);
+ PendingIntent pi = PendingIntent.getActivity(this, 0, main, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+
+ TypedValue tv = new TypedValue();
+ getTheme().resolveAttribute(R.attr.colorPrimary, tv, true);
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "foreground");
+ builder.setSmallIcon(R.drawable.ic_security_white_24dp)
+ .setContentIntent(pi)
+ .setColor(tv.data)
+ .setOngoing(true)
+ .setAutoCancel(false);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+ builder.setContentTitle(getString(R.string.msg_waiting));
+ else
+ builder.setContentTitle(getString(R.string.app_name))
+ .setContentText(getString(R.string.msg_waiting));
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
+ builder.setCategory(NotificationCompat.CATEGORY_STATUS)
+ .setVisibility(NotificationCompat.VISIBILITY_SECRET)
+ .setPriority(NotificationCompat.PRIORITY_MIN);
+
+ return builder.build();
+ }
+
+ private void showDisabledNotification() {
+ Intent main = new Intent(this, ActivityMain.class);
+ PendingIntent pi = PendingIntent.getActivity(this, 0, main, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+
+ TypedValue tv = new TypedValue();
+ getTheme().resolveAttribute(R.attr.colorOff, tv, true);
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "notify");
+ builder.setSmallIcon(R.drawable.ic_error_white_24dp)
+ .setContentTitle(getString(R.string.app_name))
+ .setContentText(getString(R.string.msg_revoked))
+ .setContentIntent(pi)
+ .setColor(tv.data)
+ .setOngoing(false)
+ .setAutoCancel(true);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
+ builder.setCategory(NotificationCompat.CATEGORY_STATUS)
+ .setVisibility(NotificationCompat.VISIBILITY_SECRET);
+
+ NotificationCompat.BigTextStyle notification = new NotificationCompat.BigTextStyle(builder);
+ notification.bigText(getString(R.string.msg_revoked));
+
+ NotificationManagerCompat.from(this).notify(NOTIFY_DISABLED, notification.build());
+ }
+
+ private void showLockdownNotification() {
+ Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
+ PendingIntent pi = PendingIntent.getActivity(this, NOTIFY_LOCKDOWN, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+
+ TypedValue tv = new TypedValue();
+ getTheme().resolveAttribute(R.attr.colorOff, tv, true);
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "notify");
+ builder.setSmallIcon(R.drawable.ic_error_white_24dp)
+ .setContentTitle(getString(R.string.app_name))
+ .setContentText(getString(R.string.msg_always_on_lockdown))
+ .setContentIntent(pi)
+ .setPriority(NotificationCompat.PRIORITY_HIGH)
+ .setColor(tv.data)
+ .setOngoing(false)
+ .setAutoCancel(true);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
+ builder.setCategory(NotificationCompat.CATEGORY_STATUS)
+ .setVisibility(NotificationCompat.VISIBILITY_SECRET);
+
+ NotificationCompat.BigTextStyle notification = new NotificationCompat.BigTextStyle(builder);
+ notification.bigText(getString(R.string.msg_always_on_lockdown));
+
+ NotificationManagerCompat.from(this).notify(NOTIFY_LOCKDOWN, notification.build());
+ }
+
+ private void removeLockdownNotification() {
+ NotificationManagerCompat.from(this).cancel(NOTIFY_LOCKDOWN);
+ }
+
+ private void showAutoStartNotification() {
+ Intent main = new Intent(this, ActivityMain.class);
+ main.putExtra(ActivityMain.EXTRA_APPROVE, true);
+ PendingIntent pi = PendingIntent.getActivity(this, NOTIFY_AUTOSTART, main, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+
+ TypedValue tv = new TypedValue();
+ getTheme().resolveAttribute(R.attr.colorOff, tv, true);
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "notify");
+ builder.setSmallIcon(R.drawable.ic_error_white_24dp)
+ .setContentTitle(getString(R.string.app_name))
+ .setContentText(getString(R.string.msg_autostart))
+ .setContentIntent(pi)
+ .setColor(tv.data)
+ .setOngoing(false)
+ .setAutoCancel(true);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
+ builder.setCategory(NotificationCompat.CATEGORY_STATUS)
+ .setVisibility(NotificationCompat.VISIBILITY_SECRET);
+
+ NotificationCompat.BigTextStyle notification = new NotificationCompat.BigTextStyle(builder);
+ notification.bigText(getString(R.string.msg_autostart));
+
+ NotificationManagerCompat.from(this).notify(NOTIFY_AUTOSTART, notification.build());
+ }
+
+ private void showErrorNotification(String message) {
+ Intent main = new Intent(this, ActivityMain.class);
+ PendingIntent pi = PendingIntent.getActivity(this, 0, main, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+
+ TypedValue tv = new TypedValue();
+ getTheme().resolveAttribute(R.attr.colorOff, tv, true);
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "notify");
+ builder.setSmallIcon(R.drawable.ic_error_white_24dp)
+ .setContentTitle(getString(R.string.app_name))
+ .setContentText(getString(R.string.msg_error, message))
+ .setContentIntent(pi)
+ .setColor(tv.data)
+ .setOngoing(false)
+ .setAutoCancel(true);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
+ builder.setCategory(NotificationCompat.CATEGORY_STATUS)
+ .setVisibility(NotificationCompat.VISIBILITY_SECRET);
+
+ NotificationCompat.BigTextStyle notification = new NotificationCompat.BigTextStyle(builder);
+ notification.bigText(getString(R.string.msg_error, message));
+ notification.setSummaryText(message);
+
+ NotificationManagerCompat.from(this).notify(NOTIFY_ERROR, notification.build());
+ }
+
+ private void showAccessNotification(int uid) {
+ String name = TextUtils.join(", ", Util.getApplicationNames(uid, ServiceSinkhole.this));
+
+ Intent main = new Intent(ServiceSinkhole.this, ActivityMain.class);
+ main.putExtra(ActivityMain.EXTRA_SEARCH, Integer.toString(uid));
+ PendingIntent pi = PendingIntent.getActivity(ServiceSinkhole.this, uid + 10000, main, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+
+ TypedValue tv = new TypedValue();
+ getTheme().resolveAttribute(R.attr.colorOn, tv, true);
+ int colorOn = tv.data;
+ getTheme().resolveAttribute(R.attr.colorOff, tv, true);
+ int colorOff = tv.data;
+
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "access");
+ builder.setSmallIcon(R.drawable.ic_cloud_upload_white_24dp)
+ .setGroup("AccessAttempt")
+ .setContentIntent(pi)
+ .setColor(colorOff)
+ .setOngoing(false)
+ .setAutoCancel(true);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+ builder.setContentTitle(name)
+ .setContentText(getString(R.string.msg_access_n));
+ else
+ builder.setContentTitle(getString(R.string.app_name))
+ .setContentText(getString(R.string.msg_access, name));
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
+ builder.setCategory(NotificationCompat.CATEGORY_STATUS)
+ .setVisibility(NotificationCompat.VISIBILITY_SECRET);
+
+ DateFormat df = new SimpleDateFormat("dd HH:mm");
+
+ NotificationCompat.InboxStyle notification = new NotificationCompat.InboxStyle(builder);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+ notification.addLine(getString(R.string.msg_access_n));
+ else {
+ String sname = getString(R.string.msg_access, name);
+ int pos = sname.indexOf(name);
+ Spannable sp = new SpannableString(sname);
+ sp.setSpan(new StyleSpan(Typeface.BOLD), pos, pos + name.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ notification.addLine(sp);
+ }
+
+ long since = 0;
+ PackageManager pm = getPackageManager();
+ String[] packages = pm.getPackagesForUid(uid);
+ if (packages != null && packages.length > 0)
+ try {
+ since = pm.getPackageInfo(packages[0], 0).firstInstallTime;
+ } catch (PackageManager.NameNotFoundException ignored) {
+ }
+
+ try (Cursor cursor = DatabaseHelper.getInstance(ServiceSinkhole.this).getAccessUnset(uid, 7, since)) {
+ int colDAddr = cursor.getColumnIndex("daddr");
+ int colTime = cursor.getColumnIndex("time");
+ int colAllowed = cursor.getColumnIndex("allowed");
+ while (cursor.moveToNext()) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(df.format(cursor.getLong(colTime))).append(' ');
+
+ String daddr = cursor.getString(colDAddr);
+ if (Util.isNumericAddress(daddr))
+ try {
+ daddr = InetAddress.getByName(daddr).getHostName();
+ } catch (UnknownHostException ignored) {
+ }
+ sb.append(daddr);
+
+ int allowed = cursor.getInt(colAllowed);
+ if (allowed >= 0) {
+ int pos = sb.indexOf(daddr);
+ Spannable sp = new SpannableString(sb);
+ ForegroundColorSpan fgsp = new ForegroundColorSpan(allowed > 0 ? colorOn : colorOff);
+ sp.setSpan(fgsp, pos, pos + daddr.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ notification.addLine(sp);
+ } else
+ notification.addLine(sb);
+ }
+ }
+
+ NotificationManagerCompat.from(this).notify(uid + 10000, notification.build());
+ }
+
+ private void showUpdateNotification(String name, String url) {
+ Intent download = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ PendingIntent pi = PendingIntent.getActivity(this, 0, download, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+
+ TypedValue tv = new TypedValue();
+ getTheme().resolveAttribute(R.attr.colorPrimary, tv, true);
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "notify");
+ builder.setSmallIcon(R.drawable.ic_security_white_24dp)
+ .setContentTitle(name)
+ .setContentText(getString(R.string.msg_update))
+ .setContentIntent(pi)
+ .setColor(tv.data)
+ .setOngoing(false)
+ .setAutoCancel(true);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
+ builder.setCategory(NotificationCompat.CATEGORY_STATUS)
+ .setVisibility(NotificationCompat.VISIBILITY_SECRET);
+
+ NotificationManagerCompat.from(this).notify(NOTIFY_UPDATE, builder.build());
+ }
+
+ private void removeWarningNotifications() {
+ NotificationManagerCompat.from(this).cancel(NOTIFY_DISABLED);
+ NotificationManagerCompat.from(this).cancel(NOTIFY_AUTOSTART);
+ NotificationManagerCompat.from(this).cancel(NOTIFY_ERROR);
+ }
+
+ private class Builder extends VpnService.Builder {
+ private NetworkInfo networkInfo;
+ private int mtu;
+ private List listAddress = new ArrayList<>();
+ private List listRoute = new ArrayList<>();
+ private List listDns = new ArrayList<>();
+ private List listDisallowed = new ArrayList<>();
+
+ private Builder() {
+ super();
+ ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+ networkInfo = cm.getActiveNetworkInfo();
+ }
+
+ @Override
+ public VpnService.Builder setMtu(int mtu) {
+ this.mtu = mtu;
+ super.setMtu(mtu);
+ return this;
+ }
+
+ @Override
+ public Builder addAddress(String address, int prefixLength) {
+ listAddress.add(address + "/" + prefixLength);
+ super.addAddress(address, prefixLength);
+ return this;
+ }
+
+ @Override
+ public Builder addRoute(String address, int prefixLength) {
+ listRoute.add(address + "/" + prefixLength);
+ super.addRoute(address, prefixLength);
+ return this;
+ }
+
+ @Override
+ public Builder addRoute(InetAddress address, int prefixLength) {
+ listRoute.add(address.getHostAddress() + "/" + prefixLength);
+ super.addRoute(address, prefixLength);
+ return this;
+ }
+
+ @Override
+ public Builder addDnsServer(InetAddress address) {
+ listDns.add(address);
+ super.addDnsServer(address);
+ return this;
+ }
+
+ @Override
+ public Builder addDisallowedApplication(String packageName) throws PackageManager.NameNotFoundException {
+ listDisallowed.add(packageName);
+ super.addDisallowedApplication(packageName);
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ Builder other = (Builder) obj;
+
+ if (other == null)
+ return false;
+
+ if (this.networkInfo == null || other.networkInfo == null ||
+ this.networkInfo.getType() != other.networkInfo.getType())
+ return false;
+
+ if (this.mtu != other.mtu)
+ return false;
+
+ if (this.listAddress.size() != other.listAddress.size())
+ return false;
+
+ if (this.listRoute.size() != other.listRoute.size())
+ return false;
+
+ if (this.listDns.size() != other.listDns.size())
+ return false;
+
+ if (this.listDisallowed.size() != other.listDisallowed.size())
+ return false;
+
+ for (String address : this.listAddress)
+ if (!other.listAddress.contains(address))
+ return false;
+
+ for (String route : this.listRoute)
+ if (!other.listRoute.contains(route))
+ return false;
+
+ for (InetAddress dns : this.listDns)
+ if (!other.listDns.contains(dns))
+ return false;
+
+ for (String pkg : this.listDisallowed)
+ if (!other.listDisallowed.contains(pkg))
+ return false;
+
+ return true;
+ }
+ }
+
+ private class IPKey {
+ int version;
+ int protocol;
+ int dport;
+ int uid;
+
+ public IPKey(int version, int protocol, int dport, int uid) {
+ this.version = version;
+ this.protocol = protocol;
+ // Only TCP (6) and UDP (17) have port numbers
+ this.dport = (protocol == 6 || protocol == 17 ? dport : 0);
+ this.uid = uid;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof IPKey))
+ return false;
+ IPKey other = (IPKey) obj;
+ return (this.version == other.version &&
+ this.protocol == other.protocol &&
+ this.dport == other.dport &&
+ this.uid == other.uid);
+ }
+
+ @Override
+ public int hashCode() {
+ return (version << 40) | (protocol << 32) | (dport << 16) | uid;
+ }
+
+ @Override
+ public String toString() {
+ return "v" + version + " p" + protocol + " port=" + dport + " uid=" + uid;
+ }
+ }
+
+ private class IPRule {
+ private IPKey key;
+ private String name;
+ private boolean block;
+ private long time;
+ private long ttl;
+
+ public IPRule(IPKey key, String name, boolean block, long time, long ttl) {
+ this.key = key;
+ this.name = name;
+ this.block = block;
+ this.time = time;
+ this.ttl = ttl;
+ }
+
+ public boolean isBlocked() {
+ return this.block;
+ }
+
+ public boolean isExpired() {
+ return System.currentTimeMillis() > (this.time + this.ttl * 2);
+ }
+
+ public void updateExpires(long time, long ttl) {
+ this.time = time;
+ this.ttl = ttl;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ IPRule other = (IPRule) obj;
+ return (this.block == other.block &&
+ this.time == other.time &&
+ this.ttl == other.ttl);
+ }
+
+ @Override
+ public String toString() {
+ return this.key + " " + this.name;
+ }
+ }
+
+ public static void run(String reason, Context context) {
+ Intent intent = new Intent(context, ServiceSinkhole.class);
+ intent.putExtra(EXTRA_COMMAND, Command.run);
+ intent.putExtra(EXTRA_REASON, reason);
+ ContextCompat.startForegroundService(context, intent);
+ }
+
+ public static void start(String reason, Context context) {
+ Intent intent = new Intent(context, ServiceSinkhole.class);
+ intent.putExtra(EXTRA_COMMAND, Command.start);
+ intent.putExtra(EXTRA_REASON, reason);
+ ContextCompat.startForegroundService(context, intent);
+ }
+
+ public static void reload(String reason, Context context, boolean interactive) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ if (prefs.getBoolean("enabled", false)) {
+ Intent intent = new Intent(context, ServiceSinkhole.class);
+ intent.putExtra(EXTRA_COMMAND, Command.reload);
+ intent.putExtra(EXTRA_REASON, reason);
+ intent.putExtra(EXTRA_INTERACTIVE, interactive);
+ ContextCompat.startForegroundService(context, intent);
+ }
+ }
+
+ public static void stop(String reason, Context context, boolean vpnonly) {
+ Intent intent = new Intent(context, ServiceSinkhole.class);
+ intent.putExtra(EXTRA_COMMAND, Command.stop);
+ intent.putExtra(EXTRA_REASON, reason);
+ intent.putExtra(EXTRA_TEMPORARY, vpnonly);
+ ContextCompat.startForegroundService(context, intent);
+ }
+
+ public static void reloadStats(String reason, Context context) {
+ Intent intent = new Intent(context, ServiceSinkhole.class);
+ intent.putExtra(EXTRA_COMMAND, Command.stats);
+ intent.putExtra(EXTRA_REASON, reason);
+ ContextCompat.startForegroundService(context, intent);
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceTileFilter.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceTileFilter.java
new file mode 100644
index 0000000..3ffd0d4
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceTileFilter.java
@@ -0,0 +1,81 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+
+import android.annotation.TargetApi;
+import android.content.SharedPreferences;
+import android.graphics.drawable.Icon;
+import android.os.Build;
+import android.service.quicksettings.Tile;
+import android.service.quicksettings.TileService;
+import android.util.Log;
+import android.widget.Toast;
+
+import androidx.preference.PreferenceManager;
+
+@TargetApi(Build.VERSION_CODES.N)
+public class ServiceTileFilter extends TileService implements SharedPreferences.OnSharedPreferenceChangeListener {
+ private static final String TAG = "NetGuard.TileFilter";
+
+ public void onStartListening() {
+ Log.i(TAG, "Start listening");
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.registerOnSharedPreferenceChangeListener(this);
+ update();
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
+ if ("filter".equals(key))
+ update();
+ }
+
+ private void update() {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean filter = prefs.getBoolean("filter", false);
+ Tile tile = getQsTile();
+ if (tile != null) {
+ tile.setState(filter ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
+ tile.setIcon(Icon.createWithResource(this, filter ? R.drawable.ic_filter_list_white_24dp : R.drawable.ic_filter_list_white_24dp_60));
+ tile.updateTile();
+ }
+ }
+
+ public void onStopListening() {
+ Log.i(TAG, "Stop listening");
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.unregisterOnSharedPreferenceChangeListener(this);
+ }
+
+ public void onClick() {
+ Log.i(TAG, "Click");
+
+ if (Util.canFilter(this)) {
+ if (IAB.isPurchased(ActivityPro.SKU_FILTER, this)) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.edit().putBoolean("filter", !prefs.getBoolean("filter", false)).apply();
+ ServiceSinkhole.reload("tile", this, false);
+ } else
+ Toast.makeText(this, R.string.title_pro_feature, Toast.LENGTH_SHORT).show();
+ } else
+ Toast.makeText(this, R.string.msg_unavailable, Toast.LENGTH_SHORT).show();
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceTileGraph.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceTileGraph.java
new file mode 100644
index 0000000..30c38ca
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceTileGraph.java
@@ -0,0 +1,80 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+
+import android.annotation.TargetApi;
+import android.content.SharedPreferences;
+import android.graphics.drawable.Icon;
+import android.os.Build;
+import android.service.quicksettings.Tile;
+import android.service.quicksettings.TileService;
+import android.util.Log;
+import android.widget.Toast;
+
+import androidx.preference.PreferenceManager;
+
+@TargetApi(Build.VERSION_CODES.N)
+public class ServiceTileGraph extends TileService implements SharedPreferences.OnSharedPreferenceChangeListener {
+ private static final String TAG = "NetGuard.TileGraph";
+
+ public void onStartListening() {
+ Log.i(TAG, "Start listening");
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.registerOnSharedPreferenceChangeListener(this);
+ update();
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
+ if ("show_stats".equals(key))
+ update();
+ }
+
+ private void update() {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean stats = prefs.getBoolean("show_stats", false);
+ Tile tile = getQsTile();
+ if (tile != null) {
+ tile.setState(stats ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
+ tile.setIcon(Icon.createWithResource(this, stats ? R.drawable.ic_equalizer_white_24dp : R.drawable.ic_equalizer_white_24dp_60));
+ tile.updateTile();
+ }
+ }
+
+ public void onStopListening() {
+ Log.i(TAG, "Stop listening");
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.unregisterOnSharedPreferenceChangeListener(this);
+ }
+
+ public void onClick() {
+ Log.i(TAG, "Click");
+
+ // Check state
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean stats = !prefs.getBoolean("show_stats", false);
+ if (stats && !IAB.isPurchased(ActivityPro.SKU_SPEED, this))
+ Toast.makeText(this, R.string.title_pro_feature, Toast.LENGTH_SHORT).show();
+ else
+ prefs.edit().putBoolean("show_stats", stats).apply();
+ ServiceSinkhole.reloadStats("tile", this);
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceTileLockdown.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceTileLockdown.java
new file mode 100644
index 0000000..1aaffea
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceTileLockdown.java
@@ -0,0 +1,75 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+
+import android.annotation.TargetApi;
+import android.content.SharedPreferences;
+import android.graphics.drawable.Icon;
+import android.os.Build;
+import android.service.quicksettings.Tile;
+import android.service.quicksettings.TileService;
+import android.util.Log;
+
+import androidx.preference.PreferenceManager;
+
+@TargetApi(Build.VERSION_CODES.N)
+public class ServiceTileLockdown extends TileService implements SharedPreferences.OnSharedPreferenceChangeListener {
+ private static final String TAG = "NetGuard.TileLockdown";
+
+ public void onStartListening() {
+ Log.i(TAG, "Start listening");
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.registerOnSharedPreferenceChangeListener(this);
+ update();
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
+ if ("lockdown".equals(key))
+ update();
+ }
+
+ private void update() {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean lockdown = prefs.getBoolean("lockdown", false);
+ Tile tile = getQsTile();
+ if (tile != null) {
+ tile.setState(lockdown ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
+ tile.setIcon(Icon.createWithResource(this, lockdown ? R.drawable.ic_lock_outline_white_24dp : R.drawable.ic_lock_outline_white_24dp_60));
+ tile.updateTile();
+ }
+ }
+
+ public void onStopListening() {
+ Log.i(TAG, "Stop listening");
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.unregisterOnSharedPreferenceChangeListener(this);
+ }
+
+ public void onClick() {
+ Log.i(TAG, "Click");
+
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.edit().putBoolean("lockdown", !prefs.getBoolean("lockdown", false)).apply();
+ ServiceSinkhole.reload("tile", this, false);
+ WidgetLockdown.updateWidgets(this);
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceTileMain.java b/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceTileMain.java
new file mode 100644
index 0000000..655819f
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/ServiceTileMain.java
@@ -0,0 +1,103 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+
+import android.annotation.TargetApi;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.graphics.drawable.Icon;
+import android.os.Build;
+import android.service.quicksettings.Tile;
+import android.service.quicksettings.TileService;
+import android.util.Log;
+
+import androidx.preference.PreferenceManager;
+
+import java.util.Date;
+
+@TargetApi(Build.VERSION_CODES.N)
+public class ServiceTileMain extends TileService implements SharedPreferences.OnSharedPreferenceChangeListener {
+ private static final String TAG = "NetGuard.TileMain";
+
+ public void onStartListening() {
+ Log.i(TAG, "Start listening");
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.registerOnSharedPreferenceChangeListener(this);
+ update();
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
+ if ("enabled".equals(key))
+ update();
+ }
+
+ private void update() {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean enabled = prefs.getBoolean("enabled", false);
+ Tile tile = getQsTile();
+ if (tile != null) {
+ tile.setState(enabled ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
+ tile.setIcon(Icon.createWithResource(this, enabled ? R.drawable.ic_security_white_24dp : R.drawable.ic_security_white_24dp_60));
+ tile.updateTile();
+ }
+ }
+
+ public void onStopListening() {
+ Log.i(TAG, "Stop listening");
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ prefs.unregisterOnSharedPreferenceChangeListener(this);
+ }
+
+ public void onClick() {
+ Log.i(TAG, "Click");
+
+ // Cancel set alarm
+ AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
+ Intent intent = new Intent(WidgetAdmin.INTENT_ON);
+ intent.setPackage(getPackageName());
+ PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+ am.cancel(pi);
+
+ // Check state
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ boolean enabled = !prefs.getBoolean("enabled", false);
+ prefs.edit().putBoolean("enabled", enabled).apply();
+ if (enabled)
+ ServiceSinkhole.start("tile", this);
+ else {
+ ServiceSinkhole.stop("tile", this, false);
+
+ // Auto enable
+ int auto = Integer.parseInt(prefs.getString("auto_enable", "0"));
+ if (auto > 0) {
+ Log.i(TAG, "Scheduling enabled after minutes=" + auto);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
+ am.set(AlarmManager.RTC_WAKEUP, new Date().getTime() + auto * 60 * 1000L, pi);
+ else
+ am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, new Date().getTime() + auto * 60 * 1000L, pi);
+ }
+ }
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/SwitchPreference.java b/NetGuard/app/src/main/java/eu/faircode/netguard/SwitchPreference.java
new file mode 100644
index 0000000..c8192c6
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/SwitchPreference.java
@@ -0,0 +1,39 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+// https://code.google.com/p/android/issues/detail?id=26194
+
+public class SwitchPreference extends android.preference.SwitchPreference {
+ public SwitchPreference(Context context) {
+ this(context, null);
+ }
+
+ public SwitchPreference(Context context, AttributeSet attrs) {
+ this(context, attrs, android.R.attr.switchPreferenceStyle);
+ }
+
+ public SwitchPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/Usage.java b/NetGuard/app/src/main/java/eu/faircode/netguard/Usage.java
new file mode 100644
index 0000000..ccfcb7e
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/Usage.java
@@ -0,0 +1,46 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class Usage {
+ public long Time;
+ public int Version;
+ public int Protocol;
+ public String DAddr;
+ public int DPort;
+ public int Uid;
+ public long Sent;
+ public long Received;
+
+ private static DateFormat formatter = SimpleDateFormat.getDateTimeInstance();
+
+ @Override
+ public String toString() {
+ return formatter.format(new Date(Time).getTime()) +
+ " v" + Version + " p" + Protocol +
+ " " + DAddr + "/" + DPort +
+ " uid " + Uid +
+ " out " + Sent + " in " + Received;
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/Util.java b/NetGuard/app/src/main/java/eu/faircode/netguard/Util.java
new file mode 100644
index 0000000..1cae9fb
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/Util.java
@@ -0,0 +1,1075 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.Manifest;
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.ApplicationErrorReport;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkInfo;
+import android.net.Uri;
+import android.net.VpnService;
+import android.net.wifi.WifiManager;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Debug;
+import android.os.PowerManager;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.core.net.ConnectivityManagerCompat;
+import androidx.preference.PreferenceManager;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.InterfaceAddress;
+import java.net.NetworkInterface;
+import java.net.URL;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class Util {
+ private static final String TAG = "NetGuard.Util";
+
+ // Roam like at home
+ private static final List listEU = Arrays.asList(
+ "AT", // Austria
+ "BE", // Belgium
+ "BG", // Bulgaria
+ "HR", // Croatia
+ "CY", // Cyprus
+ "CZ", // Czech Republic
+ "DK", // Denmark
+ "EE", // Estonia
+ "FI", // Finland
+ "FR", // France
+ "DE", // Germany
+ "GR", // Greece
+ "HU", // Hungary
+ "IS", // Iceland
+ "IE", // Ireland
+ "IT", // Italy
+ "LV", // Latvia
+ "LI", // Liechtenstein
+ "LT", // Lithuania
+ "LU", // Luxembourg
+ "MT", // Malta
+ "NL", // Netherlands
+ "NO", // Norway
+ "PL", // Poland
+ "PT", // Portugal
+ "RE", // La Réunion
+ "RO", // Romania
+ "SK", // Slovakia
+ "SI", // Slovenia
+ "ES", // Spain
+ "SE" // Sweden
+ );
+
+ private static native String jni_getprop(String name);
+
+ private static native boolean is_numeric_address(String ip);
+
+ private static native void dump_memory_profile();
+
+ static {
+ try {
+ System.loadLibrary("netguard");
+ } catch (UnsatisfiedLinkError ignored) {
+ System.exit(1);
+ }
+ }
+
+ public static String getSelfVersionName(Context context) {
+ try {
+ PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
+ return pInfo.versionName;
+ } catch (PackageManager.NameNotFoundException ex) {
+ return ex.toString();
+ }
+ }
+
+ public static int getSelfVersionCode(Context context) {
+ try {
+ PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
+ return pInfo.versionCode;
+ } catch (PackageManager.NameNotFoundException ex) {
+ return -1;
+ }
+ }
+
+ public static boolean isNetworkActive(Context context) {
+ ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ return (cm != null && cm.getActiveNetworkInfo() != null);
+ }
+
+ public static boolean isConnected(Context context) {
+ ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (cm == null)
+ return false;
+
+ NetworkInfo ni = cm.getActiveNetworkInfo();
+ if (ni != null && ni.isConnected())
+ return true;
+
+ Network[] networks = cm.getAllNetworks();
+ if (networks == null)
+ return false;
+
+ for (Network network : networks) {
+ ni = cm.getNetworkInfo(network);
+ if (ni != null && ni.getType() != ConnectivityManager.TYPE_VPN && ni.isConnected())
+ return true;
+ }
+
+ return false;
+ }
+
+ public static boolean isWifiActive(Context context) {
+ ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo ni = (cm == null ? null : cm.getActiveNetworkInfo());
+ return (ni != null && ni.getType() == ConnectivityManager.TYPE_WIFI);
+ }
+
+ public static boolean isMeteredNetwork(Context context) {
+ ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ return (cm != null && ConnectivityManagerCompat.isActiveNetworkMetered(cm));
+ }
+
+ public static String getWifiSSID(Context context) {
+ WifiManager wm = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+ String ssid = (wm == null ? null : wm.getConnectionInfo().getSSID());
+ return (ssid == null ? "NULL" : ssid);
+ }
+
+ public static int getNetworkType(Context context) {
+ ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo ni = (cm == null ? null : cm.getActiveNetworkInfo());
+ return (ni == null ? TelephonyManager.NETWORK_TYPE_UNKNOWN : ni.getSubtype());
+ }
+
+ public static String getNetworkGeneration(Context context) {
+ ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo ni = cm.getActiveNetworkInfo();
+ return (ni != null && ni.getType() == ConnectivityManager.TYPE_MOBILE ? getNetworkGeneration(ni.getSubtype()) : null);
+ }
+
+ public static boolean isRoaming(Context context) {
+ ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo ni = (cm == null ? null : cm.getActiveNetworkInfo());
+ return (ni != null && ni.isRoaming());
+ }
+
+ public static boolean isNational(Context context) {
+ try {
+ TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ return (tm != null && tm.getSimCountryIso() != null && tm.getSimCountryIso().equals(tm.getNetworkCountryIso()));
+ } catch (Throwable ignored) {
+ return false;
+ }
+ }
+
+ public static boolean isEU(Context context) {
+ try {
+ TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ return (tm != null && isEU(tm.getSimCountryIso()) && isEU(tm.getNetworkCountryIso()));
+ } catch (Throwable ignored) {
+ return false;
+ }
+ }
+
+ public static boolean isEU(String country) {
+ return (country != null && listEU.contains(country.toUpperCase()));
+ }
+
+ public static boolean isPrivateDns(Context context) {
+ String dns_mode = Settings.Global.getString(context.getContentResolver(), "private_dns_mode");
+ Log.i(TAG, "Private DNS mode=" + dns_mode);
+ if (dns_mode == null)
+ dns_mode = "off";
+ return (!"off".equals(dns_mode));
+ }
+
+ public static String getPrivateDnsSpecifier(Context context) {
+ String dns_mode = Settings.Global.getString(context.getContentResolver(), "private_dns_mode");
+ if ("hostname".equals(dns_mode))
+ return Settings.Global.getString(context.getContentResolver(), "private_dns_specifier");
+ else
+ return null;
+ }
+
+ public static String getNetworkGeneration(int networkType) {
+ switch (networkType) {
+ case TelephonyManager.NETWORK_TYPE_1xRTT:
+ case TelephonyManager.NETWORK_TYPE_CDMA:
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ case TelephonyManager.NETWORK_TYPE_IDEN:
+ case TelephonyManager.NETWORK_TYPE_GSM:
+ return "2G";
+
+ case TelephonyManager.NETWORK_TYPE_EHRPD:
+ case TelephonyManager.NETWORK_TYPE_EVDO_0:
+ case TelephonyManager.NETWORK_TYPE_EVDO_A:
+ case TelephonyManager.NETWORK_TYPE_EVDO_B:
+ case TelephonyManager.NETWORK_TYPE_HSDPA:
+ case TelephonyManager.NETWORK_TYPE_HSPA:
+ case TelephonyManager.NETWORK_TYPE_HSPAP:
+ case TelephonyManager.NETWORK_TYPE_HSUPA:
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
+ return "3G";
+
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ case TelephonyManager.NETWORK_TYPE_IWLAN:
+ return "4G";
+
+ default:
+ return "?G";
+ }
+ }
+
+ public static boolean hasPhoneStatePermission(Context context) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
+ return (context.checkSelfPermission(Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED);
+ else
+ return true;
+ }
+
+ public static List getDefaultDNS(Context context) {
+ List listDns = new ArrayList<>();
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ Network an = cm.getActiveNetwork();
+ if (an != null) {
+ LinkProperties lp = cm.getLinkProperties(an);
+ if (lp != null) {
+ List dns = lp.getDnsServers();
+ if (dns != null)
+ for (InetAddress d : dns) {
+ Log.i(TAG, "DNS from LP: " + d.getHostAddress());
+ listDns.add(d.getHostAddress().split("%")[0]);
+ }
+ }
+ }
+ } else {
+ String dns1 = jni_getprop("net.dns1");
+ String dns2 = jni_getprop("net.dns2");
+ if (dns1 != null)
+ listDns.add(dns1.split("%")[0]);
+ if (dns2 != null)
+ listDns.add(dns2.split("%")[0]);
+ }
+
+ return listDns;
+ }
+
+ public static boolean isNumericAddress(String ip) {
+ return is_numeric_address(ip);
+ }
+
+ public static boolean isInteractive(Context context) {
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT_WATCH)
+ return (pm != null && pm.isScreenOn());
+ else
+ return (pm != null && pm.isInteractive());
+ }
+
+ public static boolean isPackageInstalled(String packageName, Context context) {
+ try {
+ context.getPackageManager().getPackageInfo(packageName, 0);
+ return true;
+ } catch (PackageManager.NameNotFoundException ignored) {
+ return false;
+ }
+ }
+
+ public static boolean isSystem(int uid, Context context) {
+ PackageManager pm = context.getPackageManager();
+ String[] pkgs = pm.getPackagesForUid(uid);
+ if (pkgs != null)
+ for (String pkg : pkgs)
+ if (isSystem(pkg, context))
+ return true;
+ return false;
+ }
+
+ public static boolean isSystem(String packageName, Context context) {
+ try {
+ PackageManager pm = context.getPackageManager();
+ PackageInfo info = pm.getPackageInfo(packageName, 0);
+ return ((info.applicationInfo.flags & (ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0);
+ /*
+ PackageInfo pkg = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
+ PackageInfo sys = pm.getPackageInfo("android", PackageManager.GET_SIGNATURES);
+ return (pkg != null && pkg.signatures != null && pkg.signatures.length > 0 &&
+ sys.signatures.length > 0 && sys.signatures[0].equals(pkg.signatures[0]));
+ */
+ } catch (PackageManager.NameNotFoundException ignore) {
+ return false;
+ }
+ }
+
+ public static boolean hasInternet(String packageName, Context context) {
+ PackageManager pm = context.getPackageManager();
+ return (pm.checkPermission("android.permission.INTERNET", packageName) == PackageManager.PERMISSION_GRANTED);
+ }
+
+ public static boolean hasInternet(int uid, Context context) {
+ PackageManager pm = context.getPackageManager();
+ String[] pkgs = pm.getPackagesForUid(uid);
+ if (pkgs != null)
+ for (String pkg : pkgs)
+ if (hasInternet(pkg, context))
+ return true;
+ return false;
+ }
+
+ public static boolean isEnabled(PackageInfo info, Context context) {
+ int setting;
+ try {
+ PackageManager pm = context.getPackageManager();
+ setting = pm.getApplicationEnabledSetting(info.packageName);
+ } catch (IllegalArgumentException ex) {
+ setting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+ Log.w(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ if (setting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)
+ return info.applicationInfo.enabled;
+ else
+ return (setting == PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+ }
+
+ public static List getApplicationNames(int uid, Context context) {
+ List listResult = new ArrayList<>();
+ if (uid == 0)
+ listResult.add(context.getString(R.string.title_root));
+ else if (uid == 1013)
+ listResult.add(context.getString(R.string.title_mediaserver));
+ else if (uid == 9999)
+ listResult.add(context.getString(R.string.title_nobody));
+ else {
+ PackageManager pm = context.getPackageManager();
+ String[] pkgs = pm.getPackagesForUid(uid);
+ if (pkgs == null)
+ listResult.add(Integer.toString(uid));
+ else
+ for (String pkg : pkgs)
+ try {
+ ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
+ listResult.add(pm.getApplicationLabel(info).toString());
+ } catch (PackageManager.NameNotFoundException ignored) {
+ }
+ Collections.sort(listResult);
+ }
+ return listResult;
+ }
+
+ public static boolean canFilter(Context context) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
+ return true;
+
+ // https://android-review.googlesource.com/#/c/206710/1/untrusted_app.te
+ File tcp = new File("/proc/net/tcp");
+ File tcp6 = new File("/proc/net/tcp6");
+ try {
+ if (tcp.exists() && tcp.canRead())
+ return true;
+ } catch (SecurityException ignored) {
+ }
+ try {
+ return (tcp6.exists() && tcp6.canRead());
+ } catch (SecurityException ignored) {
+ return false;
+ }
+ }
+
+ public static boolean isDebuggable(Context context) {
+ return ((context.getApplicationContext().getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0);
+ }
+
+ public static boolean isPlayStoreInstall(Context context) {
+ if (BuildConfig.PLAY_STORE_RELEASE)
+ return true;
+ try {
+ return "com.android.vending".equals(context.getPackageManager().getInstallerPackageName(context.getPackageName()));
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ return false;
+ }
+ }
+
+ public static boolean hasXposed(Context context) {
+ if (true || !isPlayStoreInstall(context))
+ return false;
+ for (StackTraceElement ste : Thread.currentThread().getStackTrace())
+ if (ste.getClassName().startsWith("de.robv.android.xposed"))
+ return true;
+ return false;
+ }
+
+ public static boolean ownFault(Context context, Throwable ex) {
+ if (ex instanceof OutOfMemoryError)
+ return false;
+ if (ex.getCause() != null)
+ ex = ex.getCause();
+ for (StackTraceElement ste : ex.getStackTrace())
+ if (ste.getClassName().startsWith(context.getPackageName()))
+ return true;
+ return false;
+ }
+
+ public static String getFingerprint(Context context) {
+ try {
+ PackageManager pm = context.getPackageManager();
+ String pkg = context.getPackageName();
+ PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
+ byte[] cert = info.signatures[0].toByteArray();
+ MessageDigest digest = MessageDigest.getInstance("SHA1");
+ byte[] bytes = digest.digest(cert);
+ StringBuilder sb = new StringBuilder();
+ for (byte b : bytes)
+ sb.append(Integer.toString(b & 0xff, 16).toLowerCase());
+ return sb.toString();
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ return null;
+ }
+ }
+
+ public static boolean hasValidFingerprint(Context context) {
+ String calculated = getFingerprint(context);
+ String expected = context.getString(R.string.fingerprint);
+ return (calculated != null && calculated.equals(expected));
+ }
+
+ public static void setTheme(Context context) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ boolean dark = prefs.getBoolean("dark_theme", false);
+ String theme = prefs.getString("theme", "teal");
+ if (theme.equals("teal"))
+ context.setTheme(dark ? R.style.AppThemeTealDark : R.style.AppThemeTeal);
+ else if (theme.equals("blue"))
+ context.setTheme(dark ? R.style.AppThemeBlueDark : R.style.AppThemeBlue);
+ else if (theme.equals("purple"))
+ context.setTheme(dark ? R.style.AppThemePurpleDark : R.style.AppThemePurple);
+ else if (theme.equals("amber"))
+ context.setTheme(dark ? R.style.AppThemeAmberDark : R.style.AppThemeAmber);
+ else if (theme.equals("orange"))
+ context.setTheme(dark ? R.style.AppThemeOrangeDark : R.style.AppThemeOrange);
+ else if (theme.equals("green"))
+ context.setTheme(dark ? R.style.AppThemeGreenDark : R.style.AppThemeGreen);
+
+ if (context instanceof Activity && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
+ setTaskColor(context);
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ private static void setTaskColor(Context context) {
+ TypedValue tv = new TypedValue();
+ context.getTheme().resolveAttribute(R.attr.colorPrimary, tv, true);
+ ((Activity) context).setTaskDescription(new ActivityManager.TaskDescription(null, null, tv.data));
+ }
+
+ public static int dips2pixels(int dips, Context context) {
+ return Math.round(dips * context.getResources().getDisplayMetrics().density + 0.5f);
+ }
+
+ private static int calculateInSampleSize(
+ BitmapFactory.Options options, int reqWidth, int reqHeight) {
+ int height = options.outHeight;
+ int width = options.outWidth;
+ int inSampleSize = 1;
+
+ if (height > reqHeight || width > reqWidth) {
+ int halfHeight = height / 2;
+ int halfWidth = width / 2;
+
+ while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth)
+ inSampleSize *= 2;
+ }
+
+ return inSampleSize;
+ }
+
+ public static Bitmap decodeSampledBitmapFromResource(
+ Resources resources, int resourceId, int reqWidth, int reqHeight) {
+
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeResource(resources, resourceId, options);
+ options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
+ options.inJustDecodeBounds = false;
+
+ return BitmapFactory.decodeResource(resources, resourceId, options);
+ }
+
+ public static String getProtocolName(int protocol, int version, boolean brief) {
+ // https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers
+ String p = null;
+ String b = null;
+ switch (protocol) {
+ case 0:
+ p = "HOPO";
+ b = "H";
+ break;
+ case 2:
+ p = "IGMP";
+ b = "G";
+ break;
+ case 1:
+ case 58:
+ p = "ICMP";
+ b = "I";
+ break;
+ case 6:
+ p = "TCP";
+ b = "T";
+ break;
+ case 17:
+ p = "UDP";
+ b = "U";
+ break;
+ case 50:
+ p = "ESP";
+ b = "E";
+ break;
+ }
+ if (p == null)
+ return Integer.toString(protocol) + "/" + version;
+ return ((brief ? b : p) + (version > 0 ? version : ""));
+ }
+
+ public interface DoubtListener {
+ void onSure();
+ }
+
+ public static void areYouSure(Context context, int explanation, final DoubtListener listener) {
+ LayoutInflater inflater = LayoutInflater.from(context);
+ View view = inflater.inflate(R.layout.sure, null, false);
+ TextView tvExplanation = view.findViewById(R.id.tvExplanation);
+ tvExplanation.setText(explanation);
+ new AlertDialog.Builder(context)
+ .setView(view)
+ .setCancelable(true)
+ .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ listener.onSure();
+ }
+ })
+ .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // Do nothing
+ }
+ })
+ .create().show();
+ }
+
+ private static final Map mapIPOrganization = new HashMap<>();
+
+ public static String getOrganization(String ip) throws Exception {
+ synchronized (mapIPOrganization) {
+ if (mapIPOrganization.containsKey(ip))
+ return mapIPOrganization.get(ip);
+ }
+ BufferedReader reader = null;
+ try {
+ URL url = new URL("https://ipinfo.io/" + ip + "/org");
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setReadTimeout(15 * 1000);
+ connection.connect();
+ reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+ String organization = reader.readLine();
+ if ("undefined".equals(organization))
+ organization = null;
+ synchronized (mapIPOrganization) {
+ mapIPOrganization.put(ip, organization);
+ }
+ return organization;
+ } finally {
+ if (reader != null)
+ reader.close();
+ }
+ }
+
+ public static String md5(String text, String salt) throws NoSuchAlgorithmException, UnsupportedEncodingException {
+ // MD5
+ byte[] bytes = MessageDigest.getInstance("MD5").digest((text + salt).getBytes("UTF-8"));
+ StringBuilder sb = new StringBuilder();
+ for (byte b : bytes)
+ sb.append(String.format("%02X", b));
+ return sb.toString();
+ }
+
+ public static void logExtras(Intent intent) {
+ if (intent != null)
+ logBundle(intent.getExtras());
+ }
+
+ public static void logBundle(Bundle data) {
+ if (data != null) {
+ Set keys = data.keySet();
+ StringBuilder stringBuilder = new StringBuilder();
+ for (String key : keys) {
+ Object value = data.get(key);
+ stringBuilder.append(key)
+ .append("=")
+ .append(value)
+ .append(value == null ? "" : " (" + value.getClass().getSimpleName() + ")")
+ .append("\r\n");
+ }
+ Log.d(TAG, stringBuilder.toString());
+ }
+ }
+
+ public static StringBuilder readString(InputStreamReader reader) {
+ StringBuilder sb = new StringBuilder(2048);
+ char[] read = new char[128];
+ try {
+ for (int i; (i = reader.read(read)) >= 0; sb.append(read, 0, i)) ;
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ return sb;
+ }
+
+ public static void sendCrashReport(Throwable ex, final Context context) {
+ if (!isPlayStoreInstall(context) || Util.isDebuggable(context))
+ return;
+
+ try {
+ ApplicationErrorReport report = new ApplicationErrorReport();
+ report.packageName = report.processName = context.getPackageName();
+ report.time = System.currentTimeMillis();
+ report.type = ApplicationErrorReport.TYPE_CRASH;
+ report.systemApp = false;
+
+ ApplicationErrorReport.CrashInfo crash = new ApplicationErrorReport.CrashInfo();
+ crash.exceptionClassName = ex.getClass().getSimpleName();
+ crash.exceptionMessage = ex.getMessage();
+
+ StringWriter writer = new StringWriter();
+ PrintWriter printer = new PrintWriter(writer);
+ ex.printStackTrace(printer);
+
+ crash.stackTrace = writer.toString();
+
+ StackTraceElement stack = ex.getStackTrace()[0];
+ crash.throwClassName = stack.getClassName();
+ crash.throwFileName = stack.getFileName();
+ crash.throwLineNumber = stack.getLineNumber();
+ crash.throwMethodName = stack.getMethodName();
+
+ report.crashInfo = crash;
+
+ final Intent bug = new Intent(Intent.ACTION_APP_ERROR);
+ bug.putExtra(Intent.EXTRA_BUG_REPORT, report);
+ bug.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ if (bug.resolveActivity(context.getPackageManager()) != null)
+ context.startActivity(bug);
+ } catch (Throwable exex) {
+ Log.e(TAG, exex.toString() + "\n" + Log.getStackTraceString(exex));
+ }
+ }
+
+ public static String getGeneralInfo(Context context) {
+ StringBuilder sb = new StringBuilder();
+ TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+
+ sb.append(String.format("Interactive %B\r\n", isInteractive(context)));
+ sb.append(String.format("Connected %B\r\n", isConnected(context)));
+ sb.append(String.format("WiFi %B\r\n", isWifiActive(context)));
+ sb.append(String.format("Metered %B\r\n", isMeteredNetwork(context)));
+ sb.append(String.format("Roaming %B\r\n", isRoaming(context)));
+
+ if (tm.getSimState() == TelephonyManager.SIM_STATE_READY)
+ sb.append(String.format("SIM %s/%s/%s\r\n", tm.getSimCountryIso(), tm.getSimOperatorName(), tm.getSimOperator()));
+ //if (tm.getNetworkType() != TelephonyManager.NETWORK_TYPE_UNKNOWN)
+ try {
+ sb.append(String.format("Network %s/%s/%s\r\n", tm.getNetworkCountryIso(), tm.getNetworkOperatorName(), tm.getNetworkOperator()));
+ } catch (Throwable ex) {
+ /*
+ 06-14 13:02:41.331 19703 19703 W ircode.netguar: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
+ 06-14 13:02:41.332 19703 19703 W ircode.netguar: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
+ 06-14 13:02:41.495 19703 19703 I TetheringManager: registerTetheringEventCallback:eu.faircode.netguard
+ 06-14 13:02:41.518 19703 19703 E AndroidRuntime: Process: eu.faircode.netguard, PID: 19703
+ 06-14 13:02:41.518 19703 19703 E AndroidRuntime: at eu.faircode.netguard.Util.getGeneralInfo(SourceFile:744)
+ 06-14 13:02:41.518 19703 19703 E AndroidRuntime: at eu.faircode.netguard.ActivitySettings.updateTechnicalInfo(SourceFile:858)
+ 06-14 13:02:41.518 19703 19703 E AndroidRuntime: at eu.faircode.netguard.ActivitySettings.onPostCreate(SourceFile:425)
+ 06-14 13:02:41.520 19703 19703 W NetGuard.App: java.lang.SecurityException: getDataNetworkTypeForSubscriber
+ 06-14 13:02:41.520 19703 19703 W NetGuard.App: java.lang.SecurityException: getDataNetworkTypeForSubscriber
+ 06-14 13:02:41.520 19703 19703 W NetGuard.App: at android.os.Parcel.createExceptionOrNull(Parcel.java:2373)
+ 06-14 13:02:41.520 19703 19703 W NetGuard.App: at android.os.Parcel.createException(Parcel.java:2357)
+ 06-14 13:02:41.520 19703 19703 W NetGuard.App: at android.os.Parcel.readException(Parcel.java:2340)
+ 06-14 13:02:41.520 19703 19703 W NetGuard.App: at android.os.Parcel.readException(Parcel.java:2282)
+ 06-14 13:02:41.520 19703 19703 W NetGuard.App: at com.android.internal.telephony.ITelephony$Stub$Proxy.getNetworkTypeForSubscriber(ITelephony.java:8711)
+ 06-14 13:02:41.520 19703 19703 W NetGuard.App: at android.telephony.TelephonyManager.getNetworkType(TelephonyManager.java:2945)
+ 06-14 13:02:41.520 19703 19703 W NetGuard.App: at android.telephony.TelephonyManager.getNetworkType(TelephonyManager.java:2909)
+ */
+ }
+
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
+ sb.append(String.format("Power saving %B\r\n", pm.isPowerSaveMode()));
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
+ sb.append(String.format("Battery optimizing %B\r\n", batteryOptimizing(context)));
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+ sb.append(String.format("Data saving %B\r\n", dataSaving(context)));
+
+ if (sb.length() > 2)
+ sb.setLength(sb.length() - 2);
+
+ return sb.toString();
+ }
+
+ public static String getNetworkInfo(Context context) {
+ StringBuilder sb = new StringBuilder();
+ ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+
+ NetworkInfo ani = cm.getActiveNetworkInfo();
+ List listNI = new ArrayList<>();
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
+ listNI.addAll(Arrays.asList(cm.getAllNetworkInfo()));
+ else
+ for (Network network : cm.getAllNetworks()) {
+ NetworkInfo ni = cm.getNetworkInfo(network);
+ if (ni != null)
+ listNI.add(ni);
+ }
+
+ for (NetworkInfo ni : listNI) {
+ sb.append(ni.getTypeName()).append('/').append(ni.getSubtypeName())
+ .append(' ').append(ni.getDetailedState())
+ .append(TextUtils.isEmpty(ni.getExtraInfo()) ? "" : " " + ni.getExtraInfo())
+ .append(ni.getType() == ConnectivityManager.TYPE_MOBILE ? " " + Util.getNetworkGeneration(ni.getSubtype()) : "")
+ .append(ni.isRoaming() ? " R" : "")
+ .append(ani != null && ni.getType() == ani.getType() && ni.getSubtype() == ani.getSubtype() ? " *" : "")
+ .append("\r\n");
+ }
+
+ try {
+ Enumeration nis = NetworkInterface.getNetworkInterfaces();
+ if (nis != null)
+ while (nis.hasMoreElements()) {
+ NetworkInterface ni = nis.nextElement();
+ if (ni != null && !ni.isLoopback()) {
+ List ias = ni.getInterfaceAddresses();
+ if (ias != null)
+ for (InterfaceAddress ia : ias)
+ sb.append(ni.getName())
+ .append(' ').append(ia.getAddress().getHostAddress())
+ .append('/').append(ia.getNetworkPrefixLength())
+ .append(' ').append(ni.getMTU())
+ .append(' ').append(ni.isUp() ? '^' : 'v')
+ .append("\r\n");
+ }
+ }
+ } catch (Throwable ex) {
+ sb.append(ex.toString()).append("\r\n");
+ }
+
+ if (sb.length() > 2)
+ sb.setLength(sb.length() - 2);
+
+ return sb.toString();
+ }
+
+ @TargetApi(Build.VERSION_CODES.M)
+ public static boolean batteryOptimizing(Context context) {
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ return !pm.isIgnoringBatteryOptimizations(context.getPackageName());
+ }
+
+ @TargetApi(Build.VERSION_CODES.N)
+ public static boolean dataSaving(Context context) {
+ ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ return (cm.getRestrictBackgroundStatus() == ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED);
+ }
+
+ public static void sendLogcat(final Uri uri, final Context context) {
+ AsyncTask task = new AsyncTask() {
+ @Override
+ protected Intent doInBackground(Object... objects) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(context.getString(R.string.msg_issue));
+ sb.append("\r\n\r\n\r\n\r\n");
+
+ // Get version info
+ String version = getSelfVersionName(context);
+ sb.append(String.format("NetGuard: %s/%d\r\n", version, getSelfVersionCode(context)));
+ sb.append(String.format("Android: %s (SDK %d)\r\n", Build.VERSION.RELEASE, Build.VERSION.SDK_INT));
+ sb.append("\r\n");
+
+ // Get device info
+ sb.append(String.format("Brand: %s\r\n", Build.BRAND));
+ sb.append(String.format("Manufacturer: %s\r\n", Build.MANUFACTURER));
+ sb.append(String.format("Model: %s\r\n", Build.MODEL));
+ sb.append(String.format("Product: %s\r\n", Build.PRODUCT));
+ sb.append(String.format("Device: %s\r\n", Build.DEVICE));
+ sb.append(String.format("Host: %s\r\n", Build.HOST));
+ sb.append(String.format("Display: %s\r\n", Build.DISPLAY));
+ sb.append(String.format("Id: %s\r\n", Build.ID));
+ sb.append(String.format("Fingerprint: %B\r\n", hasValidFingerprint(context)));
+
+ String abi;
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
+ abi = Build.CPU_ABI;
+ else
+ abi = (Build.SUPPORTED_ABIS.length > 0 ? Build.SUPPORTED_ABIS[0] : "?");
+ sb.append(String.format("ABI: %s\r\n", abi));
+
+ Runtime rt = Runtime.getRuntime();
+ long hused = (rt.totalMemory() - rt.freeMemory()) / 1024L;
+ long hmax = rt.maxMemory() / 1024L;
+ long nheap = Debug.getNativeHeapAllocatedSize() / 1024L;
+ NumberFormat nf = NumberFormat.getIntegerInstance();
+ sb.append(String.format("Heap usage: %s/%s KiB native: %s KiB\r\n",
+ nf.format(hused), nf.format(hmax), nf.format(nheap)));
+
+ sb.append("\r\n");
+
+ sb.append(String.format("VPN dialogs: %B\r\n", isPackageInstalled("com.android.vpndialogs", context)));
+ try {
+ sb.append(String.format("Prepared: %B\r\n", VpnService.prepare(context) == null));
+ } catch (Throwable ex) {
+ sb.append("Prepared: ").append((ex.toString())).append("\r\n").append(Log.getStackTraceString(ex));
+ }
+ sb.append("\r\n");
+
+ sb.append(getGeneralInfo(context));
+ sb.append("\r\n\r\n");
+ sb.append(getNetworkInfo(context));
+ sb.append("\r\n\r\n");
+
+ // Get DNS
+ sb.append("DNS system:\r\n");
+ for (String dns : getDefaultDNS(context))
+ sb.append("- ").append(dns).append("\r\n");
+ sb.append("DNS VPN:\r\n");
+ for (InetAddress dns : ServiceSinkhole.getDns(context))
+ sb.append("- ").append(dns).append("\r\n");
+ sb.append("\r\n");
+
+ // Get TCP connection info
+ String line;
+ BufferedReader in;
+ try {
+ sb.append("/proc/net/tcp:\r\n");
+ in = new BufferedReader(new FileReader("/proc/net/tcp"));
+ while ((line = in.readLine()) != null)
+ sb.append(line).append("\r\n");
+ in.close();
+ sb.append("\r\n");
+
+ sb.append("/proc/net/tcp6:\r\n");
+ in = new BufferedReader(new FileReader("/proc/net/tcp6"));
+ while ((line = in.readLine()) != null)
+ sb.append(line).append("\r\n");
+ in.close();
+ sb.append("\r\n");
+
+ } catch (IOException ex) {
+ sb.append(ex.toString()).append("\r\n");
+ }
+
+ // Get settings
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ Map all = prefs.getAll();
+ for (String key : all.keySet())
+ sb.append("Setting: ").append(key).append('=').append(all.get(key)).append("\r\n");
+ sb.append("\r\n");
+
+ // Write logcat
+ dump_memory_profile();
+ OutputStream out = null;
+ try {
+ Log.i(TAG, "Writing logcat URI=" + uri);
+ out = context.getContentResolver().openOutputStream(uri);
+ out.write(getLogcat().toString().getBytes());
+ out.write(getTrafficLog(context).toString().getBytes());
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ sb.append(ex.toString()).append("\r\n").append(Log.getStackTraceString(ex)).append("\r\n");
+ } finally {
+ if (out != null)
+ try {
+ out.close();
+ } catch (IOException ignored) {
+ }
+ }
+
+ // Build intent
+ Intent sendEmail = new Intent(Intent.ACTION_SEND);
+ sendEmail.setType("message/rfc822");
+ sendEmail.putExtra(Intent.EXTRA_EMAIL, new String[]{"marcel+netguard@faircode.eu"});
+ sendEmail.putExtra(Intent.EXTRA_SUBJECT, "NetGuard " + version + " logcat");
+ sendEmail.putExtra(Intent.EXTRA_TEXT, sb.toString());
+ sendEmail.putExtra(Intent.EXTRA_STREAM, uri);
+ return sendEmail;
+ }
+
+ @Override
+ protected void onPostExecute(Intent sendEmail) {
+ if (sendEmail != null)
+ try {
+ context.startActivity(sendEmail);
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+ };
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ private static StringBuilder getTrafficLog(Context context) {
+ StringBuilder sb = new StringBuilder();
+
+ try (Cursor cursor = DatabaseHelper.getInstance(context).getLog(true, true, true, true, true)) {
+
+ int colTime = cursor.getColumnIndex("time");
+ int colVersion = cursor.getColumnIndex("version");
+ int colProtocol = cursor.getColumnIndex("protocol");
+ int colFlags = cursor.getColumnIndex("flags");
+ int colSAddr = cursor.getColumnIndex("saddr");
+ int colSPort = cursor.getColumnIndex("sport");
+ int colDAddr = cursor.getColumnIndex("daddr");
+ int colDPort = cursor.getColumnIndex("dport");
+ int colDName = cursor.getColumnIndex("dname");
+ int colUid = cursor.getColumnIndex("uid");
+ int colData = cursor.getColumnIndex("data");
+ int colAllowed = cursor.getColumnIndex("allowed");
+ int colConnection = cursor.getColumnIndex("connection");
+ int colInteractive = cursor.getColumnIndex("interactive");
+
+ DateFormat format = SimpleDateFormat.getDateTimeInstance();
+
+ int count = 0;
+ while (cursor.moveToNext() && ++count < 250) {
+ sb.append(format.format(cursor.getLong(colTime)));
+ sb.append(" v").append(cursor.getInt(colVersion));
+ sb.append(" p").append(cursor.getInt(colProtocol));
+ sb.append(' ').append(cursor.getString(colFlags));
+ sb.append(' ').append(cursor.getString(colSAddr));
+ sb.append('/').append(cursor.getInt(colSPort));
+ sb.append(" > ").append(cursor.getString(colDAddr));
+ sb.append('/').append(cursor.getString(colDName));
+ sb.append('/').append(cursor.getInt(colDPort));
+ sb.append(" u").append(cursor.getInt(colUid));
+ sb.append(" a").append(cursor.getInt(colAllowed));
+ sb.append(" c").append(cursor.getInt(colConnection));
+ sb.append(" i").append(cursor.getInt(colInteractive));
+ sb.append(' ').append(cursor.getString(colData));
+ sb.append("\r\n");
+ }
+ }
+
+ return sb;
+ }
+
+ private static StringBuilder getLogcat() {
+ StringBuilder builder = new StringBuilder();
+ Process process1 = null;
+ Process process2 = null;
+ BufferedReader br = null;
+ try {
+ String[] command1 = new String[]{"logcat", "-d", "-v", "threadtime"};
+ process1 = Runtime.getRuntime().exec(command1);
+ br = new BufferedReader(new InputStreamReader(process1.getInputStream()));
+ int count = 0;
+ String line;
+ while ((line = br.readLine()) != null) {
+ count++;
+ builder.append(line).append("\r\n");
+ }
+ Log.i(TAG, "Logcat lines=" + count);
+
+ } catch (IOException ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ } finally {
+ if (br != null)
+ try {
+ br.close();
+ } catch (IOException ignored) {
+ }
+ if (process2 != null)
+ try {
+ process2.destroy();
+ } catch (Throwable ex) {
+ Log.w(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ if (process1 != null)
+ try {
+ process1.destroy();
+ } catch (Throwable ex) {
+ Log.w(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+ return builder;
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/Version.java b/NetGuard/app/src/main/java/eu/faircode/netguard/Version.java
new file mode 100644
index 0000000..7d79191
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/Version.java
@@ -0,0 +1,50 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+public class Version implements Comparable {
+
+ private String version;
+
+ public Version(String version) {
+ this.version = version.replace("-beta", "");
+ }
+
+ @Override
+ public int compareTo(Version other) {
+ String[] lhs = this.version.split("\\.");
+ String[] rhs = other.version.split("\\.");
+ int length = Math.max(lhs.length, rhs.length);
+ for (int i = 0; i < length; i++) {
+ int vLhs = (i < lhs.length ? Integer.parseInt(lhs[i]) : 0);
+ int vRhs = (i < rhs.length ? Integer.parseInt(rhs[i]) : 0);
+ if (vLhs < vRhs)
+ return -1;
+ if (vLhs > vRhs)
+ return 1;
+ }
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return version;
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/WidgetAdmin.java b/NetGuard/app/src/main/java/eu/faircode/netguard/WidgetAdmin.java
new file mode 100644
index 0000000..02b4c98
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/WidgetAdmin.java
@@ -0,0 +1,99 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Build;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
+import android.util.Log;
+
+import androidx.preference.PreferenceManager;
+
+import java.util.Date;
+
+public class WidgetAdmin extends ReceiverAutostart {
+ private static final String TAG = "NetGuard.Widget";
+
+ public static final String INTENT_ON = "eu.faircode.netguard.ON";
+ public static final String INTENT_OFF = "eu.faircode.netguard.OFF";
+
+ public static final String INTENT_LOCKDOWN_ON = "eu.faircode.netguard.LOCKDOWN_ON";
+ public static final String INTENT_LOCKDOWN_OFF = "eu.faircode.netguard.LOCKDOWN_OFF";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ super.onReceive(context, intent);
+
+ Log.i(TAG, "Received " + intent);
+ Util.logExtras(intent);
+
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+
+ // Cancel set alarm
+ AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ Intent i = new Intent(INTENT_ON);
+ i.setPackage(context.getPackageName());
+ PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+ if (INTENT_ON.equals(intent.getAction()) || INTENT_OFF.equals(intent.getAction()))
+ am.cancel(pi);
+
+ // Vibrate
+ Vibrator vs = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
+ if (vs.hasVibrator())
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ vs.vibrate(VibrationEffect.createOneShot(50, VibrationEffect.DEFAULT_AMPLITUDE));
+ else
+ vs.vibrate(50);
+
+ try {
+ if (INTENT_ON.equals(intent.getAction()) || INTENT_OFF.equals(intent.getAction())) {
+ boolean enabled = INTENT_ON.equals(intent.getAction());
+ prefs.edit().putBoolean("enabled", enabled).apply();
+ if (enabled)
+ ServiceSinkhole.start("widget", context);
+ else
+ ServiceSinkhole.stop("widget", context, false);
+
+ // Auto enable
+ int auto = Integer.parseInt(prefs.getString("auto_enable", "0"));
+ if (!enabled && auto > 0) {
+ Log.i(TAG, "Scheduling enabled after minutes=" + auto);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
+ am.set(AlarmManager.RTC_WAKEUP, new Date().getTime() + auto * 60 * 1000L, pi);
+ else
+ am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, new Date().getTime() + auto * 60 * 1000L, pi);
+ }
+
+ } else if (INTENT_LOCKDOWN_ON.equals(intent.getAction()) || INTENT_LOCKDOWN_OFF.equals(intent.getAction())) {
+ boolean lockdown = INTENT_LOCKDOWN_ON.equals(intent.getAction());
+ prefs.edit().putBoolean("lockdown", lockdown).apply();
+ ServiceSinkhole.reload("widget", context, false);
+ WidgetLockdown.updateWidgets(context);
+ }
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/WidgetLockdown.java b/NetGuard/app/src/main/java/eu/faircode/netguard/WidgetLockdown.java
new file mode 100644
index 0000000..a35c01c
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/WidgetLockdown.java
@@ -0,0 +1,70 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.util.Log;
+import android.widget.RemoteViews;
+
+import androidx.preference.PreferenceManager;
+
+public class WidgetLockdown extends AppWidgetProvider {
+ private static final String TAG = "NetGuard.WidgetLock";
+
+ @Override
+ public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
+ update(appWidgetIds, appWidgetManager, context);
+ }
+
+ private static void update(int[] appWidgetIds, AppWidgetManager appWidgetManager, Context context) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ boolean lockdown = prefs.getBoolean("lockdown", false);
+
+ try {
+ try {
+ Intent intent = new Intent(lockdown ? WidgetAdmin.INTENT_LOCKDOWN_OFF : WidgetAdmin.INTENT_LOCKDOWN_ON);
+ intent.setPackage(context.getPackageName());
+ PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+ for (int id : appWidgetIds) {
+ RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widgetlockdown);
+ views.setOnClickPendingIntent(R.id.ivEnabled, pi);
+ views.setImageViewResource(R.id.ivEnabled, lockdown ? R.drawable.ic_lock_outline_white_24dp : R.drawable.ic_lock_open_white_24dp);
+ appWidgetManager.updateAppWidget(id, views);
+ }
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+
+ public static void updateWidgets(Context context) {
+ AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
+ int appWidgetIds[] = AppWidgetManager.getInstance(context).getAppWidgetIds(new ComponentName(context, WidgetLockdown.class));
+ update(appWidgetIds, appWidgetManager, context);
+ }
+}
diff --git a/NetGuard/app/src/main/java/eu/faircode/netguard/WidgetMain.java b/NetGuard/app/src/main/java/eu/faircode/netguard/WidgetMain.java
new file mode 100644
index 0000000..9e557fd
--- /dev/null
+++ b/NetGuard/app/src/main/java/eu/faircode/netguard/WidgetMain.java
@@ -0,0 +1,70 @@
+package eu.faircode.netguard;
+
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.util.Log;
+import android.widget.RemoteViews;
+
+import androidx.preference.PreferenceManager;
+
+public class WidgetMain extends AppWidgetProvider {
+ private static final String TAG = "NetGuard.Widget";
+
+ @Override
+ public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
+ update(appWidgetIds, appWidgetManager, context);
+ }
+
+ private static void update(int[] appWidgetIds, AppWidgetManager appWidgetManager, Context context) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ boolean enabled = prefs.getBoolean("enabled", false);
+
+ try {
+ try {
+ Intent intent = new Intent(enabled ? WidgetAdmin.INTENT_OFF : WidgetAdmin.INTENT_ON);
+ intent.setPackage(context.getPackageName());
+ PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+ for (int id : appWidgetIds) {
+ RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widgetmain);
+ views.setOnClickPendingIntent(R.id.ivEnabled, pi);
+ views.setImageViewResource(R.id.ivEnabled, enabled ? R.drawable.ic_security_color_24dp : R.drawable.ic_security_white_24dp_60);
+ appWidgetManager.updateAppWidget(id, views);
+ }
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ } catch (Throwable ex) {
+ Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
+ }
+ }
+
+ public static void updateWidgets(Context context) {
+ AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
+ int appWidgetIds[] = AppWidgetManager.getInstance(context).getAppWidgetIds(new ComponentName(context, WidgetMain.class));
+ update(appWidgetIds, appWidgetManager, context);
+ }
+}
diff --git a/NetGuard/app/src/main/jni/netguard/dhcp.c b/NetGuard/app/src/main/jni/netguard/dhcp.c
new file mode 100644
index 0000000..f7bf389
--- /dev/null
+++ b/NetGuard/app/src/main/jni/netguard/dhcp.c
@@ -0,0 +1,143 @@
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+#include "netguard.h"
+
+int check_dhcp(const struct arguments *args, const struct udp_session *u,
+ const uint8_t *data, const size_t datalen) {
+
+ // This is untested
+ // Android routing of DHCP is erroneous
+
+ log_android(ANDROID_LOG_WARN, "DHCP check");
+
+ if (datalen < sizeof(struct dhcp_packet)) {
+ log_android(ANDROID_LOG_WARN, "DHCP packet size %d", datalen);
+ return -1;
+ }
+
+ const struct dhcp_packet *request = (struct dhcp_packet *) data;
+
+ if (ntohl(request->option_format) != DHCP_OPTION_MAGIC_NUMBER) {
+ log_android(ANDROID_LOG_WARN, "DHCP invalid magic %x", request->option_format);
+ return -1;
+ }
+
+ if (request->htype != 1 || request->hlen != 6) {
+ log_android(ANDROID_LOG_WARN, "DHCP unknown hardware htype %d hlen %d",
+ request->htype, request->hlen);
+ return -1;
+ }
+
+ log_android(ANDROID_LOG_WARN, "DHCP opcode", request->opcode);
+
+ // Discover: source 0.0.0.0:68 destination 255.255.255.255:67
+ // Offer: source 10.1.10.1:67 destination 255.255.255.255:68
+ // Request: source 0.0.0.0:68 destination 255.255.255.255:67
+ // Ack: source: 10.1.10.1 destination: 255.255.255.255
+
+ if (request->opcode == 1) { // Discover/request
+ struct dhcp_packet *response = ng_calloc(500, 1, "dhcp");
+
+ // Hack
+ inet_pton(AF_INET, "10.1.10.1", (void *) &u->saddr);
+
+ /*
+ Discover:
+ DHCP option 53: DHCP Discover
+ DHCP option 50: 192.168.1.100 requested
+ DHCP option 55: Parameter Request List:
+ Request Subnet Mask (1), Router (3), Domain Name (15), Domain Name Server (6)
+
+ Request
+ DHCP option 53: DHCP Request
+ DHCP option 50: 192.168.1.100 requested
+ DHCP option 54: 192.168.1.1 DHCP server.
+ */
+
+ memcpy(response, request, sizeof(struct dhcp_packet));
+ response->opcode = (uint8_t) (request->siaddr == 0 ? 2 /* Offer */ : /* Ack */ 4);
+ response->secs = 0;
+ response->flags = 0;
+ memset(&response->ciaddr, 0, sizeof(response->ciaddr));
+ inet_pton(AF_INET, "10.1.10.2", &response->yiaddr);
+ inet_pton(AF_INET, "10.1.10.1", &response->siaddr);
+ memset(&response->giaddr, 0, sizeof(response->giaddr));
+
+ // https://tools.ietf.org/html/rfc2132
+ uint8_t *options = (uint8_t *) (response + sizeof(struct dhcp_packet));
+
+ int idx = 0;
+ *(options + idx++) = 53; // Message type
+ *(options + idx++) = 1;
+ *(options + idx++) = (uint8_t) (request->siaddr == 0 ? 2 : 5);
+ /*
+ 1 DHCPDISCOVER
+ 2 DHCPOFFER
+ 3 DHCPREQUEST
+ 4 DHCPDECLINE
+ 5 DHCPACK
+ 6 DHCPNAK
+ 7 DHCPRELEASE
+ 8 DHCPINFORM
+ */
+
+ *(options + idx++) = 1; // subnet mask
+ *(options + idx++) = 4; // IP4 length
+ inet_pton(AF_INET, "255.255.255.0", options + idx);
+ idx += 4;
+
+ *(options + idx++) = 3; // gateway
+ *(options + idx++) = 4; // IP4 length
+ inet_pton(AF_INET, "10.1.10.1", options + idx);
+ idx += 4;
+
+ *(options + idx++) = 51; // lease time
+ *(options + idx++) = 4; // quad
+ *((uint32_t *) (options + idx)) = 3600;
+ idx += 4;
+
+ *(options + idx++) = 54; // DHCP
+ *(options + idx++) = 4; // IP4 length
+ inet_pton(AF_INET, "10.1.10.1", options + idx);
+ idx += 4;
+
+ *(options + idx++) = 6; // DNS
+ *(options + idx++) = 4; // IP4 length
+ inet_pton(AF_INET, "8.8.8.8", options + idx);
+ idx += 4;
+
+ *(options + idx++) = 255; // End
+
+ /*
+ DHCP option 53: DHCP Offer
+ DHCP option 1: 255.255.255.0 subnet mask
+ DHCP option 3: 192.168.1.1 router
+ DHCP option 51: 86400s (1 day) IP address lease time
+ DHCP option 54: 192.168.1.1 DHCP server
+ DHCP option 6: DNS servers 9.7.10.15
+ */
+
+ write_udp(args, u, (uint8_t *) response, 500);
+
+ ng_free(response, __FILE__, __LINE__);
+ }
+
+ return 0;
+}
diff --git a/NetGuard/app/src/main/jni/netguard/dns.c b/NetGuard/app/src/main/jni/netguard/dns.c
new file mode 100644
index 0000000..b61927d
--- /dev/null
+++ b/NetGuard/app/src/main/jni/netguard/dns.c
@@ -0,0 +1,239 @@
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+#include "netguard.h"
+
+int32_t get_qname(const uint8_t *data, const size_t datalen, uint16_t off, char *qname) {
+ *qname = 0;
+
+ if (off >= datalen)
+ return -1;
+
+ uint16_t c = 0;
+ uint8_t noff = 0;
+ uint16_t ptr = off;
+ uint8_t len = *(data + ptr);
+ uint8_t count = 0;
+ while (len) {
+ if (count++ > 25)
+ break;
+
+ if (ptr + 1 < datalen && (len & 0xC0)) {
+ uint16_t jump = (uint16_t) ((len & 0x3F) * 256 + *(data + ptr + 1));
+ if (jump >= datalen) {
+ log_android(ANDROID_LOG_DEBUG, "DNS invalid jump");
+ break;
+ }
+ ptr = jump;
+ len = *(data + ptr);
+ log_android(ANDROID_LOG_DEBUG, "DNS qname compression ptr %d len %d", ptr, len);
+ if (!c) {
+ c = 1;
+ off += 2;
+ }
+ } else if (ptr + 1 + len < datalen && noff + len <= DNS_QNAME_MAX) {
+ memcpy(qname + noff, data + ptr + 1, len);
+ *(qname + noff + len) = '.';
+ noff += (len + 1);
+
+ uint16_t jump = (uint16_t) (ptr + 1 + len);
+ if (jump >= datalen) {
+ log_android(ANDROID_LOG_DEBUG, "DNS invalid jump");
+ break;
+ }
+ ptr = jump;
+ len = *(data + ptr);
+ } else
+ break;
+ }
+ ptr++;
+
+ if (len > 0 || noff == 0) {
+ log_android(ANDROID_LOG_ERROR, "DNS qname invalid len %d noff %d", len, noff);
+ return -1;
+ }
+
+ *(qname + noff - 1) = 0;
+ log_android(ANDROID_LOG_DEBUG, "qname %s", qname);
+
+ return (c ? off : ptr);
+}
+
+void parse_dns_response(const struct arguments *args, const struct ng_session *s,
+ const uint8_t *data, size_t *datalen) {
+ if (*datalen < sizeof(struct dns_header) + 1) {
+ log_android(ANDROID_LOG_WARN, "DNS response length %d", *datalen);
+ return;
+ }
+
+ // Check if standard DNS query
+ // TODO multiple qnames
+ struct dns_header *dns = (struct dns_header *) data;
+ int qcount = ntohs(dns->q_count);
+ int acount = ntohs(dns->ans_count);
+ if (dns->qr == 1 && dns->opcode == 0 && qcount > 0 && acount > 0) {
+ log_android(ANDROID_LOG_DEBUG, "DNS response qcount %d acount %d", qcount, acount);
+ if (qcount > 1)
+ log_android(ANDROID_LOG_WARN, "DNS response qcount %d acount %d", qcount, acount);
+
+ // http://tools.ietf.org/html/rfc1035
+ char name[DNS_QNAME_MAX + 1];
+ int32_t off = sizeof(struct dns_header);
+
+ uint16_t qtype;
+ uint16_t qclass;
+ char qname[DNS_QNAME_MAX + 1];
+
+ for (int q = 0; q < 1; q++) {
+ off = get_qname(data, *datalen, (uint16_t) off, name);
+ if (off > 0 && off + 4 <= *datalen) {
+ // TODO multiple qnames?
+ if (q == 0) {
+ strcpy(qname, name);
+ qtype = ntohs(*((uint16_t *) (data + off)));
+ qclass = ntohs(*((uint16_t *) (data + off + 2)));
+ log_android(ANDROID_LOG_DEBUG,
+ "DNS question %d qtype %d qclass %d qname %s",
+ q, qtype, qclass, qname);
+ }
+ off += 4;
+ } else {
+ log_android(ANDROID_LOG_WARN,
+ "DNS response Q invalid off %d datalen %d", off, *datalen);
+ return;
+ }
+ }
+
+ short svcb = 0;
+ int32_t aoff = off;
+ for (int a = 0; a < acount; a++) {
+ off = get_qname(data, *datalen, (uint16_t) off, name);
+ if (off > 0 && off + 10 <= *datalen) {
+ uint16_t qtype = ntohs(*((uint16_t *) (data + off)));
+ uint16_t qclass = ntohs(*((uint16_t *) (data + off + 2)));
+ uint32_t ttl = ntohl(*((uint32_t *) (data + off + 4)));
+ uint16_t rdlength = ntohs(*((uint16_t *) (data + off + 8)));
+ off += 10;
+
+ if (off + rdlength <= *datalen) {
+ if (qclass == DNS_QCLASS_IN &&
+ (qtype == DNS_QTYPE_A || qtype == DNS_QTYPE_AAAA)) {
+
+ char rd[INET6_ADDRSTRLEN + 1];
+ if (qtype == DNS_QTYPE_A) {
+ if (off + sizeof(__be32) <= *datalen)
+ inet_ntop(AF_INET, data + off, rd, sizeof(rd));
+ else
+ return;
+ } else if (qclass == DNS_QCLASS_IN && qtype == DNS_QTYPE_AAAA) {
+ if (off + sizeof(struct in6_addr) <= *datalen)
+ inet_ntop(AF_INET6, data + off, rd, sizeof(rd));
+ else
+ return;
+ }
+
+ dns_resolved(args, qname, name, rd, ttl);
+ log_android(ANDROID_LOG_DEBUG,
+ "DNS answer %d qname %s qtype %d ttl %d data %s",
+ a, name, qtype, ttl, rd);
+ } else if (qclass == DNS_QCLASS_IN &&
+ (qtype == DNS_SVCB || qtype == DNS_HTTPS)) {
+ // https://tools.ietf.org/id/draft-ietf-dnsop-svcb-https-01.html
+ svcb = 1;
+ log_android(ANDROID_LOG_WARN,
+ "SVCB answer %d qname %s qtype %d", a, name, qtype);
+ } else
+ log_android(ANDROID_LOG_DEBUG,
+ "DNS answer %d qname %s qclass %d qtype %d ttl %d length %d",
+ a, name, qclass, qtype, ttl, rdlength);
+
+ off += rdlength;
+ } else {
+ log_android(ANDROID_LOG_WARN,
+ "DNS response A invalid off %d rdlength %d datalen %d",
+ off, rdlength, *datalen);
+ return;
+ }
+ } else {
+ log_android(ANDROID_LOG_WARN,
+ "DNS response A invalid off %d datalen %d", off, *datalen);
+ return;
+ }
+ }
+
+ if (qcount > 0 &&
+ (svcb || is_domain_blocked(args, qname))) {
+ dns->qr = 1;
+ dns->aa = 0;
+ dns->tc = 0;
+ dns->rd = 0;
+ dns->ra = 0;
+ dns->z = 0;
+ dns->ad = 0;
+ dns->cd = 0;
+ dns->rcode = (uint16_t) args->rcode;
+ dns->ans_count = 0;
+ dns->auth_count = 0;
+ dns->add_count = 0;
+ *datalen = aoff;
+
+ int version;
+ char source[INET6_ADDRSTRLEN + 1];
+ char dest[INET6_ADDRSTRLEN + 1];
+ uint16_t sport;
+ uint16_t dport;
+
+ if (s->protocol == IPPROTO_UDP) {
+ version = s->udp.version;
+ sport = ntohs(s->udp.source);
+ dport = ntohs(s->udp.dest);
+ if (s->udp.version == 4) {
+ inet_ntop(AF_INET, &s->udp.saddr.ip4, source, sizeof(source));
+ inet_ntop(AF_INET, &s->udp.daddr.ip4, dest, sizeof(dest));
+ } else {
+ inet_ntop(AF_INET6, &s->udp.saddr.ip6, source, sizeof(source));
+ inet_ntop(AF_INET6, &s->udp.daddr.ip6, dest, sizeof(dest));
+ }
+ } else {
+ version = s->tcp.version;
+ sport = ntohs(s->tcp.source);
+ dport = ntohs(s->tcp.dest);
+ if (s->tcp.version == 4) {
+ inet_ntop(AF_INET, &s->tcp.saddr.ip4, source, sizeof(source));
+ inet_ntop(AF_INET, &s->tcp.daddr.ip4, dest, sizeof(dest));
+ } else {
+ inet_ntop(AF_INET6, &s->tcp.saddr.ip6, source, sizeof(source));
+ inet_ntop(AF_INET6, &s->tcp.daddr.ip6, dest, sizeof(dest));
+ }
+ }
+
+ // Log qname
+ char name[DNS_QNAME_MAX + 40 + 1];
+ sprintf(name, "qtype %d qname %s rcode %d", qtype, qname, dns->rcode);
+ jobject objPacket = create_packet(
+ args, version, s->protocol, "",
+ source, sport, dest, dport,
+ name, 0, 0);
+ log_packet(args, objPacket);
+ }
+ } else if (acount > 0)
+ log_android(ANDROID_LOG_WARN,
+ "DNS response qr %d opcode %d qcount %d acount %d",
+ dns->qr, dns->opcode, qcount, acount);
+}
diff --git a/NetGuard/app/src/main/jni/netguard/icmp.c b/NetGuard/app/src/main/jni/netguard/icmp.c
new file mode 100644
index 0000000..c4fbf0a
--- /dev/null
+++ b/NetGuard/app/src/main/jni/netguard/icmp.c
@@ -0,0 +1,374 @@
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+#include "netguard.h"
+
+extern FILE *pcap_file;
+
+int get_icmp_timeout(const struct icmp_session *u, int sessions, int maxsessions) {
+ int timeout = ICMP_TIMEOUT;
+
+ int scale = 100 - sessions * 100 / maxsessions;
+ timeout = timeout * scale / 100;
+
+ return timeout;
+}
+
+int check_icmp_session(const struct arguments *args, struct ng_session *s,
+ int sessions, int maxsessions) {
+ time_t now = time(NULL);
+
+ int timeout = get_icmp_timeout(&s->icmp, sessions, maxsessions);
+ if (s->icmp.stop || s->icmp.time + timeout < now) {
+ char source[INET6_ADDRSTRLEN + 1];
+ char dest[INET6_ADDRSTRLEN + 1];
+ if (s->icmp.version == 4) {
+ inet_ntop(AF_INET, &s->icmp.saddr.ip4, source, sizeof(source));
+ inet_ntop(AF_INET, &s->icmp.daddr.ip4, dest, sizeof(dest));
+ } else {
+ inet_ntop(AF_INET6, &s->icmp.saddr.ip6, source, sizeof(source));
+ inet_ntop(AF_INET6, &s->icmp.daddr.ip6, dest, sizeof(dest));
+ }
+ log_android(ANDROID_LOG_WARN, "ICMP idle %d/%d sec stop %d from %s to %s",
+ now - s->icmp.time, timeout, s->icmp.stop, dest, source);
+
+ if (close(s->socket))
+ log_android(ANDROID_LOG_ERROR, "ICMP close %d error %d: %s",
+ s->socket, errno, strerror(errno));
+ s->socket = -1;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+void check_icmp_socket(const struct arguments *args, const struct epoll_event *ev) {
+ struct ng_session *s = (struct ng_session *) ev->data.ptr;
+
+ // Check socket error
+ if (ev->events & EPOLLERR) {
+ s->icmp.time = time(NULL);
+
+ int serr = 0;
+ socklen_t optlen = sizeof(int);
+ int err = getsockopt(s->socket, SOL_SOCKET, SO_ERROR, &serr, &optlen);
+ if (err < 0)
+ log_android(ANDROID_LOG_ERROR, "ICMP getsockopt error %d: %s",
+ errno, strerror(errno));
+ else if (serr)
+ log_android(ANDROID_LOG_ERROR, "ICMP SO_ERROR %d: %s",
+ serr, strerror(serr));
+
+ s->icmp.stop = 1;
+ } else {
+ // Check socket read
+ if (ev->events & EPOLLIN) {
+ s->icmp.time = time(NULL);
+
+ uint16_t blen = (uint16_t) (s->icmp.version == 4 ? ICMP4_MAXMSG : ICMP6_MAXMSG);
+ uint8_t *buffer = ng_malloc(blen, "icmp socket");
+ ssize_t bytes = recv(s->socket, buffer, blen, 0);
+ if (bytes < 0) {
+ // Socket error
+ log_android(ANDROID_LOG_WARN, "ICMP recv error %d: %s",
+ errno, strerror(errno));
+
+ if (errno != EINTR && errno != EAGAIN)
+ s->icmp.stop = 1;
+ } else if (bytes == 0) {
+ log_android(ANDROID_LOG_WARN, "ICMP recv eof");
+ s->icmp.stop = 1;
+
+ } else {
+ // Socket read data
+ char dest[INET6_ADDRSTRLEN + 1];
+ if (s->icmp.version == 4)
+ inet_ntop(AF_INET, &s->icmp.daddr.ip4, dest, sizeof(dest));
+ else
+ inet_ntop(AF_INET6, &s->icmp.daddr.ip6, dest, sizeof(dest));
+
+ // cur->id should be equal to icmp->icmp_id
+ // but for some unexplained reason this is not the case
+ // some bits seems to be set extra
+ struct icmp *icmp = (struct icmp *) buffer;
+ log_android(
+ s->icmp.id == icmp->icmp_id ? ANDROID_LOG_INFO : ANDROID_LOG_WARN,
+ "ICMP recv bytes %d from %s for tun type %d code %d id %x/%x seq %d",
+ bytes, dest,
+ icmp->icmp_type, icmp->icmp_code,
+ s->icmp.id, icmp->icmp_id, icmp->icmp_seq);
+
+ // restore original ID
+ icmp->icmp_id = s->icmp.id;
+ uint16_t csum = 0;
+ if (s->icmp.version == 6) {
+ // Untested
+ struct ip6_hdr_pseudo pseudo;
+ memset(&pseudo, 0, sizeof(struct ip6_hdr_pseudo));
+ memcpy(&pseudo.ip6ph_src, &s->icmp.daddr.ip6, 16);
+ memcpy(&pseudo.ip6ph_dst, &s->icmp.saddr.ip6, 16);
+ pseudo.ip6ph_len = bytes - sizeof(struct ip6_hdr);
+ pseudo.ip6ph_nxt = IPPROTO_ICMPV6;
+ csum = calc_checksum(
+ 0, (uint8_t *) &pseudo, sizeof(struct ip6_hdr_pseudo));
+ }
+ icmp->icmp_cksum = 0;
+ icmp->icmp_cksum = ~calc_checksum(csum, buffer, (size_t) bytes);
+
+ // Forward to tun
+ if (write_icmp(args, &s->icmp, buffer, (size_t) bytes) < 0)
+ s->icmp.stop = 1;
+ }
+ ng_free(buffer, __FILE__, __LINE__);
+ }
+ }
+}
+
+jboolean handle_icmp(const struct arguments *args,
+ const uint8_t *pkt, size_t length,
+ const uint8_t *payload,
+ int uid,
+ const int epoll_fd) {
+ // Get headers
+ const uint8_t version = (*pkt) >> 4;
+ const struct iphdr *ip4 = (struct iphdr *) pkt;
+ const struct ip6_hdr *ip6 = (struct ip6_hdr *) pkt;
+ struct icmp *icmp = (struct icmp *) payload;
+ size_t icmplen = length - (payload - pkt);
+
+ char source[INET6_ADDRSTRLEN + 1];
+ char dest[INET6_ADDRSTRLEN + 1];
+ if (version == 4) {
+ inet_ntop(AF_INET, &ip4->saddr, source, sizeof(source));
+ inet_ntop(AF_INET, &ip4->daddr, dest, sizeof(dest));
+ } else {
+ inet_ntop(AF_INET6, &ip6->ip6_src, source, sizeof(source));
+ inet_ntop(AF_INET6, &ip6->ip6_dst, dest, sizeof(dest));
+ }
+
+ if (icmp->icmp_type != ICMP_ECHO) {
+ log_android(ANDROID_LOG_WARN, "ICMP type %d code %d from %s to %s not supported",
+ icmp->icmp_type, icmp->icmp_code, source, dest);
+ return 0;
+ }
+
+ // Search session
+ struct ng_session *cur = args->ctx->ng_session;
+ while (cur != NULL &&
+ !((cur->protocol == IPPROTO_ICMP || cur->protocol == IPPROTO_ICMPV6) &&
+ !cur->icmp.stop && cur->icmp.version == version &&
+ (version == 4 ? cur->icmp.saddr.ip4 == ip4->saddr &&
+ cur->icmp.daddr.ip4 == ip4->daddr
+ : memcmp(&cur->icmp.saddr.ip6, &ip6->ip6_src, 16) == 0 &&
+ memcmp(&cur->icmp.daddr.ip6, &ip6->ip6_dst, 16) == 0)))
+ cur = cur->next;
+
+ // Create new session if needed
+ if (cur == NULL) {
+ log_android(ANDROID_LOG_INFO, "ICMP new session from %s to %s", source, dest);
+
+ // Register session
+ struct ng_session *s = ng_malloc(sizeof(struct ng_session), "icmp session");
+ s->protocol = (uint8_t) (version == 4 ? IPPROTO_ICMP : IPPROTO_ICMPV6);
+
+ s->icmp.time = time(NULL);
+ s->icmp.uid = uid;
+ s->icmp.version = version;
+
+ if (version == 4) {
+ s->icmp.saddr.ip4 = (__be32) ip4->saddr;
+ s->icmp.daddr.ip4 = (__be32) ip4->daddr;
+ } else {
+ memcpy(&s->icmp.saddr.ip6, &ip6->ip6_src, 16);
+ memcpy(&s->icmp.daddr.ip6, &ip6->ip6_dst, 16);
+ }
+
+ s->icmp.id = icmp->icmp_id; // store original ID
+
+ s->icmp.stop = 0;
+ s->next = NULL;
+
+ // Open UDP socket
+ s->socket = open_icmp_socket(args, &s->icmp);
+ if (s->socket < 0) {
+ ng_free(s, __FILE__, __LINE__);
+ return 0;
+ }
+
+ log_android(ANDROID_LOG_DEBUG, "ICMP socket %d id %x", s->socket, s->icmp.id);
+
+ // Monitor events
+ memset(&s->ev, 0, sizeof(struct epoll_event));
+ s->ev.events = EPOLLIN | EPOLLERR;
+ s->ev.data.ptr = s;
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, s->socket, &s->ev))
+ log_android(ANDROID_LOG_ERROR, "epoll add icmp error %d: %s", errno, strerror(errno));
+
+ s->next = args->ctx->ng_session;
+ args->ctx->ng_session = s;
+
+ cur = s;
+ }
+
+ // Modify ID
+ // http://lwn.net/Articles/443051/
+ icmp->icmp_id = ~icmp->icmp_id;
+ uint16_t csum = 0;
+ if (version == 6) {
+ // Untested
+ struct ip6_hdr_pseudo pseudo;
+ memset(&pseudo, 0, sizeof(struct ip6_hdr_pseudo));
+ memcpy(&pseudo.ip6ph_src, &ip6->ip6_dst, 16);
+ memcpy(&pseudo.ip6ph_dst, &ip6->ip6_src, 16);
+ pseudo.ip6ph_len = ip6->ip6_ctlun.ip6_un1.ip6_un1_plen;
+ pseudo.ip6ph_nxt = ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
+ csum = calc_checksum(0, (uint8_t *) &pseudo, sizeof(struct ip6_hdr_pseudo));
+ }
+ icmp->icmp_cksum = 0;
+ icmp->icmp_cksum = ~calc_checksum(csum, (uint8_t *) icmp, icmplen);
+
+ log_android(ANDROID_LOG_INFO,
+ "ICMP forward from tun %s to %s type %d code %d id %x seq %d data %d",
+ source, dest,
+ icmp->icmp_type, icmp->icmp_code, icmp->icmp_id, icmp->icmp_seq, icmplen);
+
+ cur->icmp.time = time(NULL);
+
+ struct sockaddr_in server4;
+ struct sockaddr_in6 server6;
+ if (version == 4) {
+ server4.sin_family = AF_INET;
+ server4.sin_addr.s_addr = (__be32) ip4->daddr;
+ server4.sin_port = 0;
+ } else {
+ server6.sin6_family = AF_INET6;
+ memcpy(&server6.sin6_addr, &ip6->ip6_dst, 16);
+ server6.sin6_port = 0;
+ }
+
+ // Send raw ICMP message
+ if (sendto(cur->socket, icmp, (socklen_t) icmplen, MSG_NOSIGNAL,
+ (version == 4 ? (const struct sockaddr *) &server4
+ : (const struct sockaddr *) &server6),
+ (socklen_t) (version == 4 ? sizeof(server4) : sizeof(server6))) != icmplen) {
+ log_android(ANDROID_LOG_ERROR, "ICMP sendto error %d: %s", errno, strerror(errno));
+ if (errno != EINTR && errno != EAGAIN) {
+ cur->icmp.stop = 1;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int open_icmp_socket(const struct arguments *args, const struct icmp_session *cur) {
+ int sock;
+
+ // Get UDP socket
+ sock = socket(cur->version == 4 ? PF_INET : PF_INET6, SOCK_DGRAM, IPPROTO_ICMP);
+ if (sock < 0) {
+ log_android(ANDROID_LOG_ERROR, "ICMP socket error %d: %s", errno, strerror(errno));
+ return -1;
+ }
+
+ // Protect socket
+ if (protect_socket(args, sock) < 0)
+ return -1;
+
+ return sock;
+}
+
+ssize_t write_icmp(const struct arguments *args, const struct icmp_session *cur,
+ uint8_t *data, size_t datalen) {
+ size_t len;
+ u_int8_t *buffer;
+ struct icmp *icmp = (struct icmp *) data;
+ char source[INET6_ADDRSTRLEN + 1];
+ char dest[INET6_ADDRSTRLEN + 1];
+
+ // Build packet
+ if (cur->version == 4) {
+ len = sizeof(struct iphdr) + datalen;
+ buffer = ng_malloc(len, "icmp write4");
+ struct iphdr *ip4 = (struct iphdr *) buffer;
+ if (datalen)
+ memcpy(buffer + sizeof(struct iphdr), data, datalen);
+
+ // Build IP4 header
+ memset(ip4, 0, sizeof(struct iphdr));
+ ip4->version = 4;
+ ip4->ihl = sizeof(struct iphdr) >> 2;
+ ip4->tot_len = htons(len);
+ ip4->ttl = IPDEFTTL;
+ ip4->protocol = IPPROTO_ICMP;
+ ip4->saddr = cur->daddr.ip4;
+ ip4->daddr = cur->saddr.ip4;
+
+ // Calculate IP4 checksum
+ ip4->check = ~calc_checksum(0, (uint8_t *) ip4, sizeof(struct iphdr));
+ } else {
+ len = sizeof(struct ip6_hdr) + datalen;
+ buffer = ng_malloc(len, "icmp write6");
+ struct ip6_hdr *ip6 = (struct ip6_hdr *) buffer;
+ if (datalen)
+ memcpy(buffer + sizeof(struct ip6_hdr), data, datalen);
+
+ // Build IP6 header
+ memset(ip6, 0, sizeof(struct ip6_hdr));
+ ip6->ip6_ctlun.ip6_un1.ip6_un1_flow = 0;
+ ip6->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(len - sizeof(struct ip6_hdr));
+ ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_ICMPV6;
+ ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim = IPDEFTTL;
+ ip6->ip6_ctlun.ip6_un2_vfc = IPV6_VERSION;
+ memcpy(&(ip6->ip6_src), &cur->daddr.ip6, 16);
+ memcpy(&(ip6->ip6_dst), &cur->saddr.ip6, 16);
+ }
+
+ inet_ntop(cur->version == 4 ? AF_INET : AF_INET6,
+ cur->version == 4 ? (const void *) &cur->saddr.ip4 : (const void *) &cur->saddr.ip6,
+ source, sizeof(source));
+ inet_ntop(cur->version == 4 ? AF_INET : AF_INET6,
+ cur->version == 4 ? (const void *) &cur->daddr.ip4 : (const void *) &cur->daddr.ip6,
+ dest, sizeof(dest));
+
+ // Send raw ICMP message
+ log_android(ANDROID_LOG_WARN,
+ "ICMP sending to tun %d from %s to %s data %u type %d code %d id %x seq %d",
+ args->tun, dest, source, datalen,
+ icmp->icmp_type, icmp->icmp_code, icmp->icmp_id, icmp->icmp_seq);
+
+ ssize_t res = write(args->tun, buffer, len);
+
+ // Write PCAP record
+ if (res >= 0) {
+ if (pcap_file != NULL)
+ write_pcap_rec(buffer, (size_t) res);
+ } else
+ log_android(ANDROID_LOG_WARN, "ICMP write error %d: %s", errno, strerror(errno));
+
+ ng_free(buffer, __FILE__, __LINE__);
+
+ if (res != len) {
+ log_android(ANDROID_LOG_ERROR, "write %d/%d", res, len);
+ return -1;
+ }
+
+ return res;
+}
diff --git a/NetGuard/app/src/main/jni/netguard/ip.c b/NetGuard/app/src/main/jni/netguard/ip.c
new file mode 100644
index 0000000..c87d727
--- /dev/null
+++ b/NetGuard/app/src/main/jni/netguard/ip.c
@@ -0,0 +1,513 @@
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+#include "netguard.h"
+
+int max_tun_msg = 0;
+extern int loglevel;
+extern FILE *pcap_file;
+
+uint16_t get_mtu() {
+ return 10000;
+}
+
+uint16_t get_default_mss(int version) {
+ if (version == 4)
+ return (uint16_t) (get_mtu() - sizeof(struct iphdr) - sizeof(struct tcphdr));
+ else
+ return (uint16_t) (get_mtu() - sizeof(struct ip6_hdr) - sizeof(struct tcphdr));
+}
+
+int check_tun(const struct arguments *args,
+ const struct epoll_event *ev,
+ const int epoll_fd,
+ int sessions, int maxsessions) {
+ // Check tun error
+ if (ev->events & EPOLLERR) {
+ log_android(ANDROID_LOG_ERROR, "tun %d exception", args->tun);
+ if (fcntl(args->tun, F_GETFL) < 0) {
+ log_android(ANDROID_LOG_ERROR, "fcntl tun %d F_GETFL error %d: %s",
+ args->tun, errno, strerror(errno));
+ report_exit(args, "fcntl tun %d F_GETFL error %d: %s",
+ args->tun, errno, strerror(errno));
+ } else
+ report_exit(args, "tun %d exception", args->tun);
+ return -1;
+ }
+
+ // Check tun read
+ if (ev->events & EPOLLIN) {
+ uint8_t *buffer = ng_malloc(get_mtu(), "tun read");
+ ssize_t length = read(args->tun, buffer, get_mtu());
+ if (length < 0) {
+ ng_free(buffer, __FILE__, __LINE__);
+
+ log_android(ANDROID_LOG_ERROR, "tun %d read error %d: %s",
+ args->tun, errno, strerror(errno));
+ if (errno == EINTR || errno == EAGAIN)
+ // Retry later
+ return 0;
+ else {
+ report_exit(args, "tun %d read error %d: %s",
+ args->tun, errno, strerror(errno));
+ return -1;
+ }
+ } else if (length > 0) {
+ // Write pcap record
+ if (pcap_file != NULL)
+ write_pcap_rec(buffer, (size_t) length);
+
+ if (length > max_tun_msg) {
+ max_tun_msg = length;
+ log_android(ANDROID_LOG_WARN, "Maximum tun msg length %d", max_tun_msg);
+ }
+
+ // Handle IP from tun
+ handle_ip(args, buffer, (size_t) length, epoll_fd, sessions, maxsessions);
+
+ ng_free(buffer, __FILE__, __LINE__);
+ } else {
+ // tun eof
+ ng_free(buffer, __FILE__, __LINE__);
+
+ log_android(ANDROID_LOG_ERROR, "tun %d empty read", args->tun);
+ report_exit(args, "tun %d empty read", args->tun);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+// https://en.wikipedia.org/wiki/IPv6_packet#Extension_headers
+// http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
+int is_lower_layer(int protocol) {
+ // No next header = 59
+ return (protocol == 0 || // Hop-by-Hop Options
+ protocol == 60 || // Destination Options (before routing header)
+ protocol == 43 || // Routing
+ protocol == 44 || // Fragment
+ protocol == 51 || // Authentication Header (AH)
+ protocol == 50 || // Encapsulating Security Payload (ESP)
+ protocol == 60 || // Destination Options (before upper-layer header)
+ protocol == 135); // Mobility
+}
+
+int is_upper_layer(int protocol) {
+ return (protocol == IPPROTO_TCP ||
+ protocol == IPPROTO_UDP ||
+ protocol == IPPROTO_ICMP ||
+ protocol == IPPROTO_ICMPV6);
+}
+
+void handle_ip(const struct arguments *args,
+ const uint8_t *pkt, const size_t length,
+ const int epoll_fd,
+ int sessions, int maxsessions) {
+ uint8_t protocol;
+ void *saddr;
+ void *daddr;
+ char source[INET6_ADDRSTRLEN + 1];
+ char dest[INET6_ADDRSTRLEN + 1];
+ char flags[10];
+ char data[16];
+ int flen = 0;
+ uint8_t *payload;
+
+ // Get protocol, addresses & payload
+ uint8_t version = (*pkt) >> 4;
+ if (version == 4) {
+ if (length < sizeof(struct iphdr)) {
+ log_android(ANDROID_LOG_WARN, "IP4 packet too short length %d", length);
+ return;
+ }
+
+ struct iphdr *ip4hdr = (struct iphdr *) pkt;
+
+ protocol = ip4hdr->protocol;
+ saddr = &ip4hdr->saddr;
+ daddr = &ip4hdr->daddr;
+
+ if (ip4hdr->frag_off & IP_MF) {
+ log_android(ANDROID_LOG_ERROR, "IP fragment offset %u",
+ (ip4hdr->frag_off & IP_OFFMASK) * 8);
+ return;
+ }
+
+ uint8_t ipoptlen = (uint8_t) ((ip4hdr->ihl - 5) * 4);
+ payload = (uint8_t *) (pkt + sizeof(struct iphdr) + ipoptlen);
+
+ if (ntohs(ip4hdr->tot_len) != length) {
+ log_android(ANDROID_LOG_ERROR, "Invalid length %u header length %u",
+ length, ntohs(ip4hdr->tot_len));
+ return;
+ }
+
+ if (loglevel < ANDROID_LOG_WARN) {
+ if (!calc_checksum(0, (uint8_t *) ip4hdr, sizeof(struct iphdr))) {
+ log_android(ANDROID_LOG_ERROR, "Invalid IP checksum");
+ return;
+ }
+ }
+ } else if (version == 6) {
+ if (length < sizeof(struct ip6_hdr)) {
+ log_android(ANDROID_LOG_WARN, "IP6 packet too short length %d", length);
+ return;
+ }
+
+ struct ip6_hdr *ip6hdr = (struct ip6_hdr *) pkt;
+
+ // Skip extension headers
+ uint16_t off = 0;
+ protocol = ip6hdr->ip6_nxt;
+ if (!is_upper_layer(protocol)) {
+ log_android(ANDROID_LOG_WARN, "IP6 extension %d", protocol);
+ off = sizeof(struct ip6_hdr);
+ struct ip6_ext *ext = (struct ip6_ext *) (pkt + off);
+ while (is_lower_layer(ext->ip6e_nxt) && !is_upper_layer(protocol)) {
+ protocol = ext->ip6e_nxt;
+ log_android(ANDROID_LOG_WARN, "IP6 extension %d", protocol);
+
+ off += (8 + ext->ip6e_len);
+ ext = (struct ip6_ext *) (pkt + off);
+ }
+ if (!is_upper_layer(protocol)) {
+ off = 0;
+ protocol = ip6hdr->ip6_nxt;
+ log_android(ANDROID_LOG_WARN, "IP6 final extension %d", protocol);
+ }
+ }
+
+ saddr = &ip6hdr->ip6_src;
+ daddr = &ip6hdr->ip6_dst;
+
+ payload = (uint8_t *) (pkt + sizeof(struct ip6_hdr) + off);
+
+ // TODO checksum
+ } else {
+ log_android(ANDROID_LOG_ERROR, "Unknown version %d", version);
+ return;
+ }
+
+ inet_ntop(version == 4 ? AF_INET : AF_INET6, saddr, source, sizeof(source));
+ inet_ntop(version == 4 ? AF_INET : AF_INET6, daddr, dest, sizeof(dest));
+
+ // Get ports & flags
+ int syn = 0;
+ uint16_t sport = 0;
+ uint16_t dport = 0;
+ *data = 0;
+ if (protocol == IPPROTO_ICMP || protocol == IPPROTO_ICMPV6) {
+ if (length - (payload - pkt) < ICMP_MINLEN) {
+ log_android(ANDROID_LOG_WARN, "ICMP packet too short");
+ return;
+ }
+
+ struct icmp *icmp = (struct icmp *) payload;
+
+ sprintf(data, "type %d/%d", icmp->icmp_type, icmp->icmp_code);
+
+ // http://lwn.net/Articles/443051/
+ sport = ntohs(icmp->icmp_id);
+ dport = ntohs(icmp->icmp_id);
+
+ } else if (protocol == IPPROTO_UDP) {
+ if (length - (payload - pkt) < sizeof(struct udphdr)) {
+ log_android(ANDROID_LOG_WARN, "UDP packet too short");
+ return;
+ }
+
+ struct udphdr *udp = (struct udphdr *) payload;
+
+ sport = ntohs(udp->source);
+ dport = ntohs(udp->dest);
+
+ // TODO checksum (IPv6)
+ } else if (protocol == IPPROTO_TCP) {
+ if (length - (payload - pkt) < sizeof(struct tcphdr)) {
+ log_android(ANDROID_LOG_WARN, "TCP packet too short");
+ return;
+ }
+
+ struct tcphdr *tcp = (struct tcphdr *) payload;
+
+ sport = ntohs(tcp->source);
+ dport = ntohs(tcp->dest);
+
+ if (tcp->syn) {
+ syn = 1;
+ flags[flen++] = 'S';
+ }
+ if (tcp->ack)
+ flags[flen++] = 'A';
+ if (tcp->psh)
+ flags[flen++] = 'P';
+ if (tcp->fin)
+ flags[flen++] = 'F';
+ if (tcp->rst)
+ flags[flen++] = 'R';
+
+ // TODO checksum
+ } else if (protocol != IPPROTO_HOPOPTS && protocol != IPPROTO_IGMP && protocol != IPPROTO_ESP)
+ log_android(ANDROID_LOG_WARN, "Unknown protocol %d", protocol);
+
+ flags[flen] = 0;
+
+ // Limit number of sessions
+ if (sessions >= maxsessions) {
+ if ((protocol == IPPROTO_ICMP || protocol == IPPROTO_ICMPV6) ||
+ (protocol == IPPROTO_UDP && !has_udp_session(args, pkt, payload)) ||
+ (protocol == IPPROTO_TCP && syn)) {
+ log_android(ANDROID_LOG_ERROR,
+ "%d of max %d sessions, dropping version %d protocol %d",
+ sessions, maxsessions, protocol, version);
+ return;
+ }
+ }
+
+ // Get uid
+ jint uid = -1;
+ if (protocol == IPPROTO_ICMP || protocol == IPPROTO_ICMPV6 ||
+ (protocol == IPPROTO_UDP && !has_udp_session(args, pkt, payload)) ||
+ (protocol == IPPROTO_TCP && syn)) {
+ if (args->ctx->sdk <= 28) // Android 9 Pie
+ uid = get_uid(version, protocol, saddr, sport, daddr, dport);
+ else
+ uid = get_uid_q(args, version, protocol, source, sport, dest, dport);
+ }
+
+ log_android(ANDROID_LOG_DEBUG,
+ "Packet v%d %s/%u > %s/%u proto %d flags %s uid %d",
+ version, source, sport, dest, dport, protocol, flags, uid);
+
+ // Check if allowed
+ int allowed = 0;
+ struct allowed *redirect = NULL;
+ if (protocol == IPPROTO_UDP && has_udp_session(args, pkt, payload))
+ allowed = 1; // could be a lingering/blocked session
+ else if (protocol == IPPROTO_TCP && (!syn || (uid == 0 && dport == 53)))
+ allowed = 1; // assume existing session
+ else {
+ jobject objPacket = create_packet(
+ args, version, protocol, flags, source, sport, dest, dport, data, uid, 0);
+ redirect = is_address_allowed(args, objPacket);
+ allowed = (redirect != NULL);
+ if (redirect != NULL && (*redirect->raddr == 0 || redirect->rport == 0))
+ redirect = NULL;
+ }
+
+ // Handle allowed traffic
+ if (allowed) {
+ if (protocol == IPPROTO_ICMP || protocol == IPPROTO_ICMPV6)
+ handle_icmp(args, pkt, length, payload, uid, epoll_fd);
+ else if (protocol == IPPROTO_UDP)
+ handle_udp(args, pkt, length, payload, uid, redirect, epoll_fd);
+ else if (protocol == IPPROTO_TCP)
+ handle_tcp(args, pkt, length, payload, uid, allowed, redirect, epoll_fd);
+ } else {
+ if (protocol == IPPROTO_UDP)
+ block_udp(args, pkt, length, payload, uid);
+
+ log_android(ANDROID_LOG_WARN, "Address v%d p%d %s/%u syn %d not allowed",
+ version, protocol, dest, dport, syn);
+ }
+}
+
+jint get_uid(const int version, const int protocol,
+ const void *saddr, const uint16_t sport,
+ const void *daddr, const uint16_t dport) {
+ jint uid = -1;
+
+ char source[INET6_ADDRSTRLEN + 1];
+ char dest[INET6_ADDRSTRLEN + 1];
+ inet_ntop(version == 4 ? AF_INET : AF_INET6, saddr, source, sizeof(source));
+ inet_ntop(version == 4 ? AF_INET : AF_INET6, daddr, dest, sizeof(dest));
+
+ struct timeval time;
+ gettimeofday(&time, NULL);
+ long now = (time.tv_sec * 1000) + (time.tv_usec / 1000);
+
+ // Check IPv6 table first
+ if (version == 4) {
+ int8_t saddr128[16];
+ memset(saddr128, 0, 10);
+ saddr128[10] = (uint8_t) 0xFF;
+ saddr128[11] = (uint8_t) 0xFF;
+ memcpy(saddr128 + 12, saddr, 4);
+
+ int8_t daddr128[16];
+ memset(daddr128, 0, 10);
+ daddr128[10] = (uint8_t) 0xFF;
+ daddr128[11] = (uint8_t) 0xFF;
+ memcpy(daddr128 + 12, daddr, 4);
+
+ uid = get_uid_sub(6, protocol, saddr128, sport, daddr128, dport, source, dest, now);
+ log_android(ANDROID_LOG_DEBUG, "uid v%d p%d %s/%u > %s/%u => %d as inet6",
+ version, protocol, source, sport, dest, dport, uid);
+ }
+
+ if (uid == -1) {
+ uid = get_uid_sub(version, protocol, saddr, sport, daddr, dport, source, dest, now);
+ log_android(ANDROID_LOG_DEBUG, "uid v%d p%d %s/%u > %s/%u => %d fallback",
+ version, protocol, source, sport, dest, dport, uid);
+ }
+
+ if (uid == -1)
+ log_android(ANDROID_LOG_WARN, "uid v%d p%d %s/%u > %s/%u => not found",
+ version, protocol, source, sport, dest, dport);
+ else if (uid >= 0)
+ log_android(ANDROID_LOG_INFO, "uid v%d p%d %s/%u > %s/%u => %d",
+ version, protocol, source, sport, dest, dport, uid);
+
+ return uid;
+}
+
+int uid_cache_size = 0;
+struct uid_cache_entry *uid_cache = NULL;
+
+jint get_uid_sub(const int version, const int protocol,
+ const void *saddr, const uint16_t sport,
+ const void *daddr, const uint16_t dport,
+ const char *source, const char *dest,
+ long now) {
+ // NETLINK is not available on Android due to SELinux policies :-(
+ // http://stackoverflow.com/questions/27148536/netlink-implementation-for-the-android-ndk
+ // https://android.googlesource.com/platform/system/sepolicy/+/master/private/app.te (netlink_tcpdiag_socket)
+
+ static uint8_t zero[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ int ws = (version == 4 ? 1 : 4);
+
+ // Check cache
+ for (int i = 0; i < uid_cache_size; i++)
+ if (now - uid_cache[i].time <= UID_MAX_AGE &&
+ uid_cache[i].version == version &&
+ uid_cache[i].protocol == protocol &&
+ uid_cache[i].sport == sport &&
+ (uid_cache[i].dport == dport || uid_cache[i].dport == 0) &&
+ (memcmp(uid_cache[i].saddr, saddr, (size_t) (ws * 4)) == 0 ||
+ memcmp(uid_cache[i].saddr, zero, (size_t) (ws * 4)) == 0) &&
+ (memcmp(uid_cache[i].daddr, daddr, (size_t) (ws * 4)) == 0 ||
+ memcmp(uid_cache[i].daddr, zero, (size_t) (ws * 4)) == 0)) {
+
+ log_android(ANDROID_LOG_INFO, "uid v%d p%d %s/%u > %s/%u => %d (from cache)",
+ version, protocol, source, sport, dest, dport, uid_cache[i].uid);
+
+ return uid_cache[i].uid;
+ }
+
+ // Get proc file name
+ char *fn = NULL;
+ if (protocol == IPPROTO_ICMP && version == 4)
+ fn = "/proc/net/icmp";
+ else if (protocol == IPPROTO_ICMPV6 && version == 6)
+ fn = "/proc/net/icmp6";
+ else if (protocol == IPPROTO_TCP)
+ fn = (version == 4 ? "/proc/net/tcp" : "/proc/net/tcp6");
+ else if (protocol == IPPROTO_UDP)
+ fn = (version == 4 ? "/proc/net/udp" : "/proc/net/udp6");
+ else
+ return -1;
+
+ // Open proc file
+ FILE *fd = fopen(fn, "r");
+ if (fd == NULL) {
+ log_android(ANDROID_LOG_ERROR, "fopen %s error %d: %s", fn, errno, strerror(errno));
+ return -2;
+ }
+
+ jint uid = -1;
+
+ char line[250];
+ int fields;
+
+ char shex[16 * 2 + 1];
+ uint8_t _saddr[16];
+ int _sport;
+
+ char dhex[16 * 2 + 1];
+ uint8_t _daddr[16];
+ int _dport;
+
+ jint _uid;
+
+ // Scan proc file
+ int l = 0;
+ *line = 0;
+ int c = 0;
+ const char *fmt = (version == 4
+ ? "%*d: %8s:%X %8s:%X %*X %*lX:%*lX %*X:%*X %*X %d %*d %*ld"
+ : "%*d: %32s:%X %32s:%X %*X %*lX:%*lX %*X:%*X %*X %d %*d %*ld");
+ while (fgets(line, sizeof(line), fd) != NULL) {
+ if (!l++)
+ continue;
+
+ fields = sscanf(line, fmt, shex, &_sport, dhex, &_dport, &_uid);
+ if (fields == 5 && strlen(shex) == ws * 8 && strlen(dhex) == ws * 8) {
+ hex2bytes(shex, _saddr);
+ hex2bytes(dhex, _daddr);
+
+ for (int w = 0; w < ws; w++)
+ ((uint32_t *) _saddr)[w] = htonl(((uint32_t *) _saddr)[w]);
+
+ for (int w = 0; w < ws; w++)
+ ((uint32_t *) _daddr)[w] = htonl(((uint32_t *) _daddr)[w]);
+
+ if (_sport == sport &&
+ (_dport == dport || _dport == 0) &&
+ (memcmp(_saddr, saddr, (size_t) (ws * 4)) == 0 ||
+ memcmp(_saddr, zero, (size_t) (ws * 4)) == 0) &&
+ (memcmp(_daddr, daddr, (size_t) (ws * 4)) == 0 ||
+ memcmp(_daddr, zero, (size_t) (ws * 4)) == 0))
+ uid = _uid;
+
+ for (; c < uid_cache_size; c++)
+ if (now - uid_cache[c].time > UID_MAX_AGE)
+ break;
+
+ if (c >= uid_cache_size) {
+ if (uid_cache_size == 0)
+ uid_cache = ng_malloc(sizeof(struct uid_cache_entry), "uid_cache init");
+ else
+ uid_cache = ng_realloc(uid_cache,
+ sizeof(struct uid_cache_entry) *
+ (uid_cache_size + 1), "uid_cache extend");
+ c = uid_cache_size;
+ uid_cache_size++;
+ }
+
+ uid_cache[c].version = (uint8_t) version;
+ uid_cache[c].protocol = (uint8_t) protocol;
+ memcpy(uid_cache[c].saddr, _saddr, (size_t) (ws * 4));
+ uid_cache[c].sport = (uint16_t) _sport;
+ memcpy(uid_cache[c].daddr, _daddr, (size_t) (ws * 4));
+ uid_cache[c].dport = (uint16_t) _dport;
+ uid_cache[c].uid = _uid;
+ uid_cache[c].time = now;
+ } else {
+ log_android(ANDROID_LOG_ERROR, "Invalid field #%d: %s", fields, line);
+ return -2;
+ }
+ }
+
+ if (fclose(fd))
+ log_android(ANDROID_LOG_ERROR, "fclose %s error %d: %s", fn, errno, strerror(errno));
+
+ return uid;
+}
diff --git a/NetGuard/app/src/main/jni/netguard/netguard.c b/NetGuard/app/src/main/jni/netguard/netguard.c
new file mode 100644
index 0000000..51add91
--- /dev/null
+++ b/NetGuard/app/src/main/jni/netguard/netguard.c
@@ -0,0 +1,1113 @@
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+#include "netguard.h"
+
+// It is assumed that no packets will get lost and that packets arrive in order
+// https://android.googlesource.com/platform/frameworks/base.git/+/master/services/core/jni/com_android_server_connectivity_Vpn.cpp
+
+// Global variables
+
+char socks5_addr[INET6_ADDRSTRLEN + 1];
+int socks5_port = 0;
+char socks5_username[127 + 1];
+char socks5_password[127 + 1];
+int loglevel = ANDROID_LOG_WARN;
+
+extern int max_tun_msg;
+
+extern FILE *pcap_file;
+extern size_t pcap_record_size;
+extern long pcap_file_size;
+
+extern int uid_cache_size;
+extern struct uid_cache_entry *uid_cache;
+
+// JNI
+
+jclass clsPacket;
+jclass clsAllowed;
+jclass clsRR;
+jclass clsUsage;
+
+jint JNI_OnLoad(JavaVM *vm, void *reserved) {
+ log_android(ANDROID_LOG_INFO, "JNI load");
+
+ JNIEnv *env;
+ if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK) {
+ log_android(ANDROID_LOG_INFO, "JNI load GetEnv failed");
+ return -1;
+ }
+
+ const char *packet = "eu/faircode/netguard/Packet";
+ clsPacket = jniGlobalRef(env, jniFindClass(env, packet));
+ ng_add_alloc(clsPacket, "clsPacket");
+
+ const char *allowed = "eu/faircode/netguard/Allowed";
+ clsAllowed = jniGlobalRef(env, jniFindClass(env, allowed));
+ ng_add_alloc(clsAllowed, "clsAllowed");
+
+ const char *rr = "eu/faircode/netguard/ResourceRecord";
+ clsRR = jniGlobalRef(env, jniFindClass(env, rr));
+ ng_add_alloc(clsRR, "clsRR");
+
+ const char *usage = "eu/faircode/netguard/Usage";
+ clsUsage = jniGlobalRef(env, jniFindClass(env, usage));
+ ng_add_alloc(clsUsage, "clsUsage");
+
+ // Raise file number limit to maximum
+ struct rlimit rlim;
+ if (getrlimit(RLIMIT_NOFILE, &rlim))
+ log_android(ANDROID_LOG_WARN, "getrlimit error %d: %s", errno, strerror(errno));
+ else {
+ rlim_t soft = rlim.rlim_cur;
+ rlim.rlim_cur = rlim.rlim_max;
+ if (setrlimit(RLIMIT_NOFILE, &rlim))
+ log_android(ANDROID_LOG_WARN, "setrlimit error %d: %s", errno, strerror(errno));
+ else
+ log_android(ANDROID_LOG_WARN, "raised file limit from %d to %d", soft, rlim.rlim_cur);
+ }
+
+ return JNI_VERSION_1_6;
+}
+
+void JNI_OnUnload(JavaVM *vm, void *reserved) {
+ log_android(ANDROID_LOG_INFO, "JNI unload");
+
+ JNIEnv *env;
+ if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK)
+ log_android(ANDROID_LOG_INFO, "JNI load GetEnv failed");
+ else {
+ (*env)->DeleteGlobalRef(env, clsPacket);
+ (*env)->DeleteGlobalRef(env, clsAllowed);
+ (*env)->DeleteGlobalRef(env, clsRR);
+ (*env)->DeleteGlobalRef(env, clsUsage);
+ ng_delete_alloc(clsPacket, __FILE__, __LINE__);
+ ng_delete_alloc(clsAllowed, __FILE__, __LINE__);
+ ng_delete_alloc(clsRR, __FILE__, __LINE__);
+ ng_delete_alloc(clsUsage, __FILE__, __LINE__);
+ }
+}
+
+// JNI ServiceSinkhole
+
+JNIEXPORT jlong JNICALL
+Java_eu_faircode_netguard_ServiceSinkhole_jni_1init(
+ JNIEnv *env, jobject instance, jint sdk) {
+ struct context *ctx = ng_calloc(1, sizeof(struct context), "init");
+ ctx->sdk = sdk;
+
+ loglevel = ANDROID_LOG_WARN;
+
+ *socks5_addr = 0;
+ socks5_port = 0;
+ *socks5_username = 0;
+ *socks5_password = 0;
+ pcap_file = NULL;
+
+ if (pthread_mutex_init(&ctx->lock, NULL))
+ log_android(ANDROID_LOG_ERROR, "pthread_mutex_init failed");
+
+ // Create signal pipe
+ if (pipe(ctx->pipefds))
+ log_android(ANDROID_LOG_ERROR, "Create pipe error %d: %s", errno, strerror(errno));
+ else
+ for (int i = 0; i < 2; i++) {
+ int flags = fcntl(ctx->pipefds[i], F_GETFL, 0);
+ if (flags < 0 || fcntl(ctx->pipefds[i], F_SETFL, flags | O_NONBLOCK) < 0)
+ log_android(ANDROID_LOG_ERROR, "fcntl pipefds[%d] O_NONBLOCK error %d: %s",
+ i, errno, strerror(errno));
+ }
+
+ return (jlong) ctx;
+}
+
+JNIEXPORT void JNICALL
+Java_eu_faircode_netguard_ServiceSinkhole_jni_1start(
+ JNIEnv *env, jobject instance, jlong context, jint loglevel_) {
+ struct context *ctx = (struct context *) context;
+
+ loglevel = loglevel_;
+ max_tun_msg = 0;
+ ctx->stopping = 0;
+
+ log_android(ANDROID_LOG_WARN, "Starting level %d", loglevel);
+
+}
+
+JNIEXPORT void JNICALL
+Java_eu_faircode_netguard_ServiceSinkhole_jni_1run(
+ JNIEnv *env, jobject instance, jlong context, jint tun, jboolean fwd53, jint rcode) {
+ struct context *ctx = (struct context *) context;
+
+ log_android(ANDROID_LOG_WARN, "Running tun %d fwd53 %d level %d", tun, fwd53, loglevel);
+
+ // Set blocking
+ int flags = fcntl(tun, F_GETFL, 0);
+ if (flags < 0 || fcntl(tun, F_SETFL, flags & ~O_NONBLOCK) < 0)
+ log_android(ANDROID_LOG_ERROR, "fcntl tun ~O_NONBLOCK error %d: %s",
+ errno, strerror(errno));
+
+ // Get arguments
+ struct arguments *args = ng_malloc(sizeof(struct arguments), "arguments");
+ args->env = env;
+ args->instance = instance;
+ args->tun = tun;
+ args->fwd53 = fwd53;
+ args->rcode = rcode;
+ args->ctx = ctx;
+ handle_events(args);
+}
+
+JNIEXPORT void JNICALL
+Java_eu_faircode_netguard_ServiceSinkhole_jni_1stop(
+ JNIEnv *env, jobject instance, jlong context) {
+ struct context *ctx = (struct context *) context;
+ ctx->stopping = 1;
+
+ log_android(ANDROID_LOG_WARN, "Write pipe wakeup");
+ if (write(ctx->pipefds[1], "w", 1) < 0)
+ log_android(ANDROID_LOG_WARN, "Write pipe error %d: %s", errno, strerror(errno));
+}
+
+JNIEXPORT void JNICALL
+Java_eu_faircode_netguard_ServiceSinkhole_jni_1clear(
+ JNIEnv *env, jobject instance, jlong context) {
+ struct context *ctx = (struct context *) context;
+ clear(ctx);
+}
+
+JNIEXPORT jint JNICALL
+Java_eu_faircode_netguard_ServiceSinkhole_jni_1get_1mtu(JNIEnv *env, jobject instance) {
+ return get_mtu();
+}
+
+JNIEXPORT jintArray JNICALL
+Java_eu_faircode_netguard_ServiceSinkhole_jni_1get_1stats(
+ JNIEnv *env, jobject instance, jlong context) {
+ struct context *ctx = (struct context *) context;
+
+ if (pthread_mutex_lock(&ctx->lock))
+ log_android(ANDROID_LOG_ERROR, "pthread_mutex_lock failed");
+
+ jintArray jarray = (*env)->NewIntArray(env, 5);
+ jint *jcount = (*env)->GetIntArrayElements(env, jarray, NULL);
+
+ struct ng_session *s = ctx->ng_session;
+ while (s != NULL) {
+ if (s->protocol == IPPROTO_ICMP || s->protocol == IPPROTO_ICMPV6) {
+ if (!s->icmp.stop)
+ jcount[0]++;
+ } else if (s->protocol == IPPROTO_UDP) {
+ if (s->udp.state == UDP_ACTIVE)
+ jcount[1]++;
+ } else if (s->protocol == IPPROTO_TCP) {
+ if (s->tcp.state != TCP_CLOSING && s->tcp.state != TCP_CLOSE)
+ jcount[2]++;
+ }
+ s = s->next;
+ }
+
+ if (pthread_mutex_unlock(&ctx->lock))
+ log_android(ANDROID_LOG_ERROR, "pthread_mutex_unlock failed");
+
+ jcount[3] = 0;
+ DIR *d = opendir("/proc/self/fd");
+ if (d) {
+ struct dirent *dir;
+ while ((dir = readdir(d)) != NULL)
+ if (dir->d_type != DT_DIR)
+ jcount[3]++;
+ closedir(d);
+ }
+
+ struct rlimit rlim;
+ memset(&rlim, 0, sizeof(struct rlimit));
+ getrlimit(RLIMIT_NOFILE, &rlim);
+ jcount[4] = (jint) rlim.rlim_cur;
+
+ (*env)->ReleaseIntArrayElements(env, jarray, jcount, 0);
+ return jarray;
+}
+
+JNIEXPORT void JNICALL
+Java_eu_faircode_netguard_ServiceSinkhole_jni_1pcap(
+ JNIEnv *env, jclass type,
+ jstring name_, jint record_size, jint file_size) {
+
+ pcap_record_size = (size_t) record_size;
+ pcap_file_size = file_size;
+
+ //if (pthread_mutex_lock(&lock))
+ // log_android(ANDROID_LOG_ERROR, "pthread_mutex_lock failed");
+
+ if (name_ == NULL) {
+ if (pcap_file != NULL) {
+ int flags = fcntl(fileno(pcap_file), F_GETFL, 0);
+ if (flags < 0 || fcntl(fileno(pcap_file), F_SETFL, flags & ~O_NONBLOCK) < 0)
+ log_android(ANDROID_LOG_ERROR, "PCAP fcntl ~O_NONBLOCK error %d: %s",
+ errno, strerror(errno));
+
+ if (fsync(fileno(pcap_file)))
+ log_android(ANDROID_LOG_ERROR, "PCAP fsync error %d: %s", errno, strerror(errno));
+
+ if (fclose(pcap_file))
+ log_android(ANDROID_LOG_ERROR, "PCAP fclose error %d: %s", errno, strerror(errno));
+
+ pcap_file = NULL;
+ }
+ log_android(ANDROID_LOG_WARN, "PCAP disabled");
+ } else {
+ const char *name = (*env)->GetStringUTFChars(env, name_, 0);
+ ng_add_alloc(name, "name");
+ log_android(ANDROID_LOG_WARN, "PCAP file %s record size %d truncate @%ld",
+ name, pcap_record_size, pcap_file_size);
+
+ pcap_file = fopen(name, "ab+");
+ if (pcap_file == NULL)
+ log_android(ANDROID_LOG_ERROR, "PCAP fopen error %d: %s", errno, strerror(errno));
+ else {
+ int flags = fcntl(fileno(pcap_file), F_GETFL, 0);
+ if (flags < 0 || fcntl(fileno(pcap_file), F_SETFL, flags | O_NONBLOCK) < 0)
+ log_android(ANDROID_LOG_ERROR, "PCAP fcntl O_NONBLOCK error %d: %s",
+ errno, strerror(errno));
+
+ long size = ftell(pcap_file);
+ if (size == 0) {
+ log_android(ANDROID_LOG_WARN, "PCAP initialize");
+ write_pcap_hdr();
+ } else
+ log_android(ANDROID_LOG_WARN, "PCAP current size %ld", size);
+ }
+
+ (*env)->ReleaseStringUTFChars(env, name_, name);
+ ng_delete_alloc(name, __FILE__, __LINE__);
+ }
+
+ //if (pthread_mutex_unlock(&lock))
+ // log_android(ANDROID_LOG_ERROR, "pthread_mutex_unlock failed");
+}
+
+JNIEXPORT void JNICALL
+Java_eu_faircode_netguard_ServiceSinkhole_jni_1socks5(JNIEnv *env, jobject instance, jstring addr_,
+ jint port, jstring username_,
+ jstring password_) {
+ const char *addr = (*env)->GetStringUTFChars(env, addr_, 0);
+ const char *username = (*env)->GetStringUTFChars(env, username_, 0);
+ const char *password = (*env)->GetStringUTFChars(env, password_, 0);
+ ng_add_alloc(addr, "addr");
+ ng_add_alloc(username, "username");
+ ng_add_alloc(password, "password");
+
+ strcpy(socks5_addr, addr);
+ socks5_port = port;
+ strcpy(socks5_username, username);
+ strcpy(socks5_password, password);
+
+ log_android(ANDROID_LOG_WARN, "SOCKS5 %s:%d user=%s",
+ socks5_addr, socks5_port, socks5_username);
+
+ (*env)->ReleaseStringUTFChars(env, addr_, addr);
+ (*env)->ReleaseStringUTFChars(env, username_, username);
+ (*env)->ReleaseStringUTFChars(env, password_, password);
+ ng_delete_alloc(addr, __FILE__, __LINE__);
+ ng_delete_alloc(username, __FILE__, __LINE__);
+ ng_delete_alloc(password, __FILE__, __LINE__);
+}
+
+JNIEXPORT void JNICALL
+Java_eu_faircode_netguard_ServiceSinkhole_jni_1done(
+ JNIEnv *env, jobject instance, jlong context) {
+ struct context *ctx = (struct context *) context;
+ log_android(ANDROID_LOG_INFO, "Done");
+
+ clear(ctx);
+
+ if (pthread_mutex_destroy(&ctx->lock))
+ log_android(ANDROID_LOG_ERROR, "pthread_mutex_destroy failed");
+
+ for (int i = 0; i < 2; i++)
+ if (close(ctx->pipefds[i]))
+ log_android(ANDROID_LOG_ERROR, "Close pipe error %d: %s", errno, strerror(errno));
+
+ if (uid_cache != NULL)
+ ng_free(uid_cache, __FILE__, __LINE__);
+ uid_cache_size = 0;
+ uid_cache = NULL;
+
+ ng_free(ctx, __FILE__, __LINE__);
+}
+
+// JNI Util
+
+JNIEXPORT jstring JNICALL
+Java_eu_faircode_netguard_Util_jni_1getprop(JNIEnv *env, jclass type, jstring name_) {
+ const char *name = (*env)->GetStringUTFChars(env, name_, 0);
+ ng_add_alloc(name, "name");
+
+ char value[PROP_VALUE_MAX + 1] = "";
+ __system_property_get(name, value);
+
+ (*env)->ReleaseStringUTFChars(env, name_, name);
+ ng_delete_alloc(name, __FILE__, __LINE__);
+
+ return (*env)->NewStringUTF(env, value); // Freed by Java
+}
+
+JNIEXPORT jboolean JNICALL
+Java_eu_faircode_netguard_Util_is_1numeric_1address(JNIEnv *env, jclass type, jstring ip_) {
+ jboolean numeric = 0;
+ const char *ip = (*env)->GetStringUTFChars(env, ip_, 0);
+ ng_add_alloc(ip, "ip");
+
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = AI_NUMERICHOST;
+ struct addrinfo *result;
+ int err = getaddrinfo(ip, NULL, &hints, &result);
+ if (err)
+ log_android(ANDROID_LOG_DEBUG, "getaddrinfo(%s) error %d: %s", ip, err, gai_strerror(err));
+ else
+ numeric = (jboolean) (result != NULL);
+
+ if (result != NULL)
+ freeaddrinfo(result);
+
+ (*env)->ReleaseStringUTFChars(env, ip_, ip);
+ ng_delete_alloc(ip, __FILE__, __LINE__);
+ return numeric;
+}
+
+void report_exit(const struct arguments *args, const char *fmt, ...) {
+ jclass cls = (*args->env)->GetObjectClass(args->env, args->instance);
+ ng_add_alloc(cls, "cls");
+ jmethodID mid = jniGetMethodID(args->env, cls, "nativeExit", "(Ljava/lang/String;)V");
+
+ jstring jreason = NULL;
+ if (fmt != NULL) {
+ char line[1024];
+ va_list argptr;
+ va_start(argptr, fmt);
+ vsprintf(line, fmt, argptr);
+ jreason = (*args->env)->NewStringUTF(args->env, line);
+ ng_add_alloc(jreason, "jreason");
+ va_end(argptr);
+ }
+
+ (*args->env)->CallVoidMethod(args->env, args->instance, mid, jreason);
+ jniCheckException(args->env);
+
+ if (jreason != NULL) {
+ (*args->env)->DeleteLocalRef(args->env, jreason);
+ ng_delete_alloc(jreason, __FILE__, __LINE__);
+ }
+ (*args->env)->DeleteLocalRef(args->env, cls);
+ ng_delete_alloc(cls, __FILE__, __LINE__);
+}
+
+void report_error(const struct arguments *args, jint error, const char *fmt, ...) {
+ jclass cls = (*args->env)->GetObjectClass(args->env, args->instance);
+ ng_add_alloc(cls, "cls");
+ jmethodID mid = jniGetMethodID(args->env, cls, "nativeError", "(ILjava/lang/String;)V");
+
+ jstring jreason = NULL;
+ if (fmt != NULL) {
+ char line[1024];
+ va_list argptr;
+ va_start(argptr, fmt);
+ vsprintf(line, fmt, argptr);
+ jreason = (*args->env)->NewStringUTF(args->env, line);
+ ng_add_alloc(jreason, "jreason");
+ va_end(argptr);
+ }
+
+ (*args->env)->CallVoidMethod(args->env, args->instance, mid, error, jreason);
+ jniCheckException(args->env);
+
+ if (jreason != NULL) {
+ (*args->env)->DeleteLocalRef(args->env, jreason);
+ ng_delete_alloc(jreason, __FILE__, __LINE__);
+ }
+ (*args->env)->DeleteLocalRef(args->env, cls);
+ ng_delete_alloc(cls, __FILE__, __LINE__);
+}
+
+static jmethodID midProtect = NULL;
+
+int protect_socket(const struct arguments *args, int socket) {
+ if (args->ctx->sdk >= 21)
+ return 0;
+
+ jclass cls = (*args->env)->GetObjectClass(args->env, args->instance);
+ ng_add_alloc(cls, "cls");
+ if (cls == NULL) {
+ log_android(ANDROID_LOG_ERROR, "protect socket failed to get class");
+ return -1;
+ }
+
+ if (midProtect == NULL)
+ midProtect = jniGetMethodID(args->env, cls, "protect", "(I)Z");
+ if (midProtect == NULL) {
+ log_android(ANDROID_LOG_ERROR, "protect socket failed to get method");
+ return -1;
+ }
+
+ jboolean isProtected = (*args->env)->CallBooleanMethod(
+ args->env, args->instance, midProtect, socket);
+ jniCheckException(args->env);
+
+ if (!isProtected) {
+ log_android(ANDROID_LOG_ERROR, "protect socket failed");
+ return -1;
+ }
+
+ (*args->env)->DeleteLocalRef(args->env, cls);
+ ng_delete_alloc(cls, __FILE__, __LINE__);
+
+ return 0;
+}
+
+// http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html
+// http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/index.html
+
+jobject jniGlobalRef(JNIEnv *env, jobject cls) {
+ jobject gcls = (*env)->NewGlobalRef(env, cls);
+ if (gcls == NULL)
+ log_android(ANDROID_LOG_ERROR, "Global ref failed (out of memory?)");
+ return gcls;
+}
+
+jclass jniFindClass(JNIEnv *env, const char *name) {
+ jclass cls = (*env)->FindClass(env, name);
+ if (cls == NULL)
+ log_android(ANDROID_LOG_ERROR, "Class %s not found", name);
+ else
+ jniCheckException(env);
+ return cls;
+}
+
+jmethodID jniGetMethodID(JNIEnv *env, jclass cls, const char *name, const char *signature) {
+ jmethodID method = (*env)->GetMethodID(env, cls, name, signature);
+ if (method == NULL) {
+ log_android(ANDROID_LOG_ERROR, "Method %s %s not found", name, signature);
+ jniCheckException(env);
+ }
+ return method;
+}
+
+jfieldID jniGetFieldID(JNIEnv *env, jclass cls, const char *name, const char *type) {
+ jfieldID field = (*env)->GetFieldID(env, cls, name, type);
+ if (field == NULL)
+ log_android(ANDROID_LOG_ERROR, "Field %s type %s not found", name, type);
+ return field;
+}
+
+jobject jniNewObject(JNIEnv *env, jclass cls, jmethodID constructor, const char *name) {
+ jobject object = (*env)->NewObject(env, cls, constructor);
+ if (object == NULL)
+ log_android(ANDROID_LOG_ERROR, "Create object %s failed", name);
+ else
+ jniCheckException(env);
+ return object;
+}
+
+int jniCheckException(JNIEnv *env) {
+ jthrowable ex = (*env)->ExceptionOccurred(env);
+ if (ex) {
+ (*env)->ExceptionDescribe(env);
+ (*env)->ExceptionClear(env);
+ (*env)->DeleteLocalRef(env, ex);
+ ng_delete_alloc(ex, __FILE__, __LINE__);
+ return 1;
+ }
+ return 0;
+}
+
+static jmethodID midLogPacket = NULL;
+
+void log_packet(const struct arguments *args, jobject jpacket) {
+#ifdef PROFILE_JNI
+ float mselapsed;
+ struct timeval start, end;
+ gettimeofday(&start, NULL);
+#endif
+
+ jclass clsService = (*args->env)->GetObjectClass(args->env, args->instance);
+ ng_add_alloc(clsService, "clsService");
+
+ const char *signature = "(Leu/faircode/netguard/Packet;)V";
+ if (midLogPacket == NULL)
+ midLogPacket = jniGetMethodID(args->env, clsService, "logPacket", signature);
+
+ (*args->env)->CallVoidMethod(args->env, args->instance, midLogPacket, jpacket);
+ jniCheckException(args->env);
+
+ (*args->env)->DeleteLocalRef(args->env, clsService);
+ (*args->env)->DeleteLocalRef(args->env, jpacket);
+ ng_delete_alloc(clsService, __FILE__, __LINE__);
+ ng_delete_alloc(jpacket, __FILE__, __LINE__);
+
+#ifdef PROFILE_JNI
+ gettimeofday(&end, NULL);
+ mselapsed = (end.tv_sec - start.tv_sec) * 1000.0 +
+ (end.tv_usec - start.tv_usec) / 1000.0;
+ if (mselapsed > PROFILE_JNI)
+ log_android(ANDROID_LOG_WARN, "log_packet %f", mselapsed);
+#endif
+}
+
+static jmethodID midDnsResolved = NULL;
+static jmethodID midInitRR = NULL;
+jfieldID fidQTime = NULL;
+jfieldID fidQName = NULL;
+jfieldID fidAName = NULL;
+jfieldID fidResource = NULL;
+jfieldID fidTTL = NULL;
+
+void dns_resolved(const struct arguments *args,
+ const char *qname, const char *aname, const char *resource, int ttl) {
+#ifdef PROFILE_JNI
+ float mselapsed;
+ struct timeval start, end;
+ gettimeofday(&start, NULL);
+#endif
+
+ jclass clsService = (*args->env)->GetObjectClass(args->env, args->instance);
+ ng_add_alloc(clsService, "clsService");
+
+ const char *signature = "(Leu/faircode/netguard/ResourceRecord;)V";
+ if (midDnsResolved == NULL)
+ midDnsResolved = jniGetMethodID(args->env, clsService, "dnsResolved", signature);
+
+ const char *rr = "eu/faircode/netguard/ResourceRecord";
+ if (midInitRR == NULL)
+ midInitRR = jniGetMethodID(args->env, clsRR, "", "()V");
+
+ jobject jrr = jniNewObject(args->env, clsRR, midInitRR, rr);
+ ng_add_alloc(jrr, "jrr");
+
+ if (fidQTime == NULL) {
+ const char *string = "Ljava/lang/String;";
+ fidQTime = jniGetFieldID(args->env, clsRR, "Time", "J");
+ fidQName = jniGetFieldID(args->env, clsRR, "QName", string);
+ fidAName = jniGetFieldID(args->env, clsRR, "AName", string);
+ fidResource = jniGetFieldID(args->env, clsRR, "Resource", string);
+ fidTTL = jniGetFieldID(args->env, clsRR, "TTL", "I");
+ }
+
+ jlong jtime = time(NULL) * 1000LL;
+ jstring jqname = (*args->env)->NewStringUTF(args->env, qname);
+ jstring janame = (*args->env)->NewStringUTF(args->env, aname);
+ jstring jresource = (*args->env)->NewStringUTF(args->env, resource);
+ ng_add_alloc(jqname, "jqname");
+ ng_add_alloc(janame, "janame");
+ ng_add_alloc(jresource, "jresource");
+
+ (*args->env)->SetLongField(args->env, jrr, fidQTime, jtime);
+ (*args->env)->SetObjectField(args->env, jrr, fidQName, jqname);
+ (*args->env)->SetObjectField(args->env, jrr, fidAName, janame);
+ (*args->env)->SetObjectField(args->env, jrr, fidResource, jresource);
+ (*args->env)->SetIntField(args->env, jrr, fidTTL, ttl);
+
+ (*args->env)->CallVoidMethod(args->env, args->instance, midDnsResolved, jrr);
+ jniCheckException(args->env);
+
+ (*args->env)->DeleteLocalRef(args->env, jresource);
+ (*args->env)->DeleteLocalRef(args->env, janame);
+ (*args->env)->DeleteLocalRef(args->env, jqname);
+ (*args->env)->DeleteLocalRef(args->env, jrr);
+ (*args->env)->DeleteLocalRef(args->env, clsService);
+ ng_delete_alloc(jresource, __FILE__, __LINE__);
+ ng_delete_alloc(janame, __FILE__, __LINE__);
+ ng_delete_alloc(jqname, __FILE__, __LINE__);
+ ng_delete_alloc(jrr, __FILE__, __LINE__);
+ ng_delete_alloc(clsService, __FILE__, __LINE__);
+
+#ifdef PROFILE_JNI
+ gettimeofday(&end, NULL);
+ mselapsed = (end.tv_sec - start.tv_sec) * 1000.0 +
+ (end.tv_usec - start.tv_usec) / 1000.0;
+ if (mselapsed > PROFILE_JNI)
+ log_android(ANDROID_LOG_WARN, "log_packet %f", mselapsed);
+#endif
+}
+
+static jmethodID midIsDomainBlocked = NULL;
+
+jboolean is_domain_blocked(const struct arguments *args, const char *name) {
+#ifdef PROFILE_JNI
+ float mselapsed;
+ struct timeval start, end;
+ gettimeofday(&start, NULL);
+#endif
+
+ jclass clsService = (*args->env)->GetObjectClass(args->env, args->instance);
+ ng_add_alloc(clsService, "clsService");
+
+ const char *signature = "(Ljava/lang/String;)Z";
+ if (midIsDomainBlocked == NULL)
+ midIsDomainBlocked = jniGetMethodID(args->env, clsService, "isDomainBlocked", signature);
+
+ jstring jname = (*args->env)->NewStringUTF(args->env, name);
+ ng_add_alloc(jname, "jname");
+
+ jboolean jallowed = (*args->env)->CallBooleanMethod(
+ args->env, args->instance, midIsDomainBlocked, jname);
+ jniCheckException(args->env);
+
+ (*args->env)->DeleteLocalRef(args->env, jname);
+ (*args->env)->DeleteLocalRef(args->env, clsService);
+ ng_delete_alloc(jname, __FILE__, __LINE__);
+ ng_delete_alloc(clsService, __FILE__, __LINE__);
+
+#ifdef PROFILE_JNI
+ gettimeofday(&end, NULL);
+ mselapsed = (end.tv_sec - start.tv_sec) * 1000.0 +
+ (end.tv_usec - start.tv_usec) / 1000.0;
+ if (mselapsed > PROFILE_JNI)
+ log_android(ANDROID_LOG_WARN, "is_domain_blocked %f", mselapsed);
+#endif
+
+ return jallowed;
+}
+
+static jmethodID midGetUidQ = NULL;
+
+jint get_uid_q(const struct arguments *args,
+ jint version, jint protocol,
+ const char *source, jint sport,
+ const char *dest, jint dport) {
+#ifdef PROFILE_JNI
+ float mselapsed;
+ struct timeval start, end;
+ gettimeofday(&start, NULL);
+#endif
+
+ jclass clsService = (*args->env)->GetObjectClass(args->env, args->instance);
+ ng_add_alloc(clsService, "clsService");
+
+ const char *signature = "(IILjava/lang/String;ILjava/lang/String;I)I";
+ if (midGetUidQ == NULL)
+ midGetUidQ = jniGetMethodID(args->env, clsService, "getUidQ", signature);
+
+ jstring jsource = (*args->env)->NewStringUTF(args->env, source);
+ jstring jdest = (*args->env)->NewStringUTF(args->env, dest);
+ ng_add_alloc(jsource, "jsource");
+ ng_add_alloc(jdest, "jdest");
+
+ jint juid = (*args->env)->CallIntMethod(
+ args->env, args->instance, midGetUidQ,
+ version, protocol, jsource, sport, jdest, dport);
+ jniCheckException(args->env);
+
+ (*args->env)->DeleteLocalRef(args->env, jdest);
+ (*args->env)->DeleteLocalRef(args->env, jsource);
+ (*args->env)->DeleteLocalRef(args->env, clsService);
+ ng_delete_alloc(jdest, __FILE__, __LINE__);
+ ng_delete_alloc(jsource, __FILE__, __LINE__);
+ ng_delete_alloc(clsService, __FILE__, __LINE__);
+
+#ifdef PROFILE_JNI
+ gettimeofday(&end, NULL);
+ mselapsed = (end.tv_sec - start.tv_sec) * 1000.0 +
+ (end.tv_usec - start.tv_usec) / 1000.0;
+ if (mselapsed > PROFILE_JNI)
+ log_android(ANDROID_LOG_WARN, "get_uid_q %f", mselapsed);
+#endif
+
+ return juid;
+}
+
+static jmethodID midIsAddressAllowed = NULL;
+jfieldID fidRaddr = NULL;
+jfieldID fidRport = NULL;
+struct allowed allowed;
+
+struct allowed *is_address_allowed(const struct arguments *args, jobject jpacket) {
+#ifdef PROFILE_JNI
+ float mselapsed;
+ struct timeval start, end;
+ gettimeofday(&start, NULL);
+#endif
+
+ jclass clsService = (*args->env)->GetObjectClass(args->env, args->instance);
+ ng_add_alloc(clsService, "clsService");
+
+ const char *signature = "(Leu/faircode/netguard/Packet;)Leu/faircode/netguard/Allowed;";
+ if (midIsAddressAllowed == NULL)
+ midIsAddressAllowed = jniGetMethodID(args->env, clsService, "isAddressAllowed", signature);
+
+ jobject jallowed = (*args->env)->CallObjectMethod(
+ args->env, args->instance, midIsAddressAllowed, jpacket);
+ ng_add_alloc(jallowed, "jallowed");
+ jniCheckException(args->env);
+
+ if (jallowed != NULL) {
+ if (fidRaddr == NULL) {
+ const char *string = "Ljava/lang/String;";
+ fidRaddr = jniGetFieldID(args->env, clsAllowed, "raddr", string);
+ fidRport = jniGetFieldID(args->env, clsAllowed, "rport", "I");
+ }
+
+ jstring jraddr = (*args->env)->GetObjectField(args->env, jallowed, fidRaddr);
+ ng_add_alloc(jraddr, "jraddr");
+ if (jraddr == NULL)
+ *allowed.raddr = 0;
+ else {
+ const char *raddr = (*args->env)->GetStringUTFChars(args->env, jraddr, NULL);
+ ng_add_alloc(raddr, "raddr");
+ strcpy(allowed.raddr, raddr);
+ (*args->env)->ReleaseStringUTFChars(args->env, jraddr, raddr);
+ ng_delete_alloc(raddr, __FILE__, __LINE__);
+ }
+ allowed.rport = (uint16_t) (*args->env)->GetIntField(args->env, jallowed, fidRport);
+
+ (*args->env)->DeleteLocalRef(args->env, jraddr);
+ ng_delete_alloc(jraddr, __FILE__, __LINE__);
+ }
+
+
+ (*args->env)->DeleteLocalRef(args->env, jpacket);
+ (*args->env)->DeleteLocalRef(args->env, clsService);
+ (*args->env)->DeleteLocalRef(args->env, jallowed);
+ ng_delete_alloc(jpacket, __FILE__, __LINE__);
+ ng_delete_alloc(clsService, __FILE__, __LINE__);
+ ng_delete_alloc(jallowed, __FILE__, __LINE__);
+
+#ifdef PROFILE_JNI
+ gettimeofday(&end, NULL);
+ mselapsed = (end.tv_sec - start.tv_sec) * 1000.0 +
+ (end.tv_usec - start.tv_usec) / 1000.0;
+ if (mselapsed > PROFILE_JNI)
+ log_android(ANDROID_LOG_WARN, "is_address_allowed %f", mselapsed);
+#endif
+
+ return (jallowed == NULL ? NULL : &allowed);
+}
+
+jmethodID midInitPacket = NULL;
+
+jfieldID fidTime = NULL;
+jfieldID fidVersion = NULL;
+jfieldID fidProtocol = NULL;
+jfieldID fidFlags = NULL;
+jfieldID fidSaddr = NULL;
+jfieldID fidSport = NULL;
+jfieldID fidDaddr = NULL;
+jfieldID fidDport = NULL;
+jfieldID fidData = NULL;
+jfieldID fidUid = NULL;
+jfieldID fidAllowed = NULL;
+
+jobject create_packet(const struct arguments *args,
+ jint version,
+ jint protocol,
+ const char *flags,
+ const char *source,
+ jint sport,
+ const char *dest,
+ jint dport,
+ const char *data,
+ jint uid,
+ jboolean allowed) {
+ JNIEnv *env = args->env;
+
+#ifdef PROFILE_JNI
+ float mselapsed;
+ struct timeval start, end;
+ gettimeofday(&start, NULL);
+#endif
+
+ /*
+ jbyte b[] = {1,2,3};
+ jbyteArray ret = env->NewByteArray(3);
+ env->SetByteArrayRegion (ret, 0, 3, b);
+ */
+
+ const char *packet = "eu/faircode/netguard/Packet";
+ if (midInitPacket == NULL)
+ midInitPacket = jniGetMethodID(env, clsPacket, "", "()V");
+ jobject jpacket = jniNewObject(env, clsPacket, midInitPacket, packet);
+ ng_add_alloc(jpacket, "jpacket");
+
+ if (fidTime == NULL) {
+ const char *string = "Ljava/lang/String;";
+ fidTime = jniGetFieldID(env, clsPacket, "time", "J");
+ fidVersion = jniGetFieldID(env, clsPacket, "version", "I");
+ fidProtocol = jniGetFieldID(env, clsPacket, "protocol", "I");
+ fidFlags = jniGetFieldID(env, clsPacket, "flags", string);
+ fidSaddr = jniGetFieldID(env, clsPacket, "saddr", string);
+ fidSport = jniGetFieldID(env, clsPacket, "sport", "I");
+ fidDaddr = jniGetFieldID(env, clsPacket, "daddr", string);
+ fidDport = jniGetFieldID(env, clsPacket, "dport", "I");
+ fidData = jniGetFieldID(env, clsPacket, "data", string);
+ fidUid = jniGetFieldID(env, clsPacket, "uid", "I");
+ fidAllowed = jniGetFieldID(env, clsPacket, "allowed", "Z");
+ }
+
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ jlong t = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
+ jstring jflags = (*env)->NewStringUTF(env, flags);
+ jstring jsource = (*env)->NewStringUTF(env, source);
+ jstring jdest = (*env)->NewStringUTF(env, dest);
+ jstring jdata = (*env)->NewStringUTF(env, data);
+ ng_add_alloc(jflags, "jflags");
+ ng_add_alloc(jsource, "jsource");
+ ng_add_alloc(jdest, "jdest");
+ ng_add_alloc(jdata, "jdata");
+
+ (*env)->SetLongField(env, jpacket, fidTime, t);
+ (*env)->SetIntField(env, jpacket, fidVersion, version);
+ (*env)->SetIntField(env, jpacket, fidProtocol, protocol);
+ (*env)->SetObjectField(env, jpacket, fidFlags, jflags);
+ (*env)->SetObjectField(env, jpacket, fidSaddr, jsource);
+ (*env)->SetIntField(env, jpacket, fidSport, sport);
+ (*env)->SetObjectField(env, jpacket, fidDaddr, jdest);
+ (*env)->SetIntField(env, jpacket, fidDport, dport);
+ (*env)->SetObjectField(env, jpacket, fidData, jdata);
+ (*env)->SetIntField(env, jpacket, fidUid, uid);
+ (*env)->SetBooleanField(env, jpacket, fidAllowed, allowed);
+
+ (*env)->DeleteLocalRef(env, jdata);
+ (*env)->DeleteLocalRef(env, jdest);
+ (*env)->DeleteLocalRef(env, jsource);
+ (*env)->DeleteLocalRef(env, jflags);
+ ng_delete_alloc(jdata, __FILE__, __LINE__);
+ ng_delete_alloc(jdest, __FILE__, __LINE__);
+ ng_delete_alloc(jsource, __FILE__, __LINE__);
+ ng_delete_alloc(jflags, __FILE__, __LINE__);
+ // Caller needs to delete reference to packet
+
+#ifdef PROFILE_JNI
+ gettimeofday(&end, NULL);
+ mselapsed = (end.tv_sec - start.tv_sec) * 1000.0 +
+ (end.tv_usec - start.tv_usec) / 1000.0;
+ if (mselapsed > PROFILE_JNI)
+ log_android(ANDROID_LOG_WARN, "create_packet %f", mselapsed);
+#endif
+
+ return jpacket;
+}
+
+jmethodID midAccountUsage = NULL;
+jmethodID midInitUsage = NULL;
+jfieldID fidUsageTime = NULL;
+jfieldID fidUsageVersion = NULL;
+jfieldID fidUsageProtocol = NULL;
+jfieldID fidUsageDAddr = NULL;
+jfieldID fidUsageDPort = NULL;
+jfieldID fidUsageUid = NULL;
+jfieldID fidUsageSent = NULL;
+jfieldID fidUsageReceived = NULL;
+
+void account_usage(const struct arguments *args, jint version, jint protocol,
+ const char *daddr, jint dport, jint uid, jlong sent, jlong received) {
+#ifdef PROFILE_JNI
+ float mselapsed;
+ struct timeval start, end;
+ gettimeofday(&start, NULL);
+#endif
+
+ jclass clsService = (*args->env)->GetObjectClass(args->env, args->instance);
+ ng_add_alloc(clsService, "clsService");
+
+ const char *signature = "(Leu/faircode/netguard/Usage;)V";
+ if (midAccountUsage == NULL)
+ midAccountUsage = jniGetMethodID(args->env, clsService, "accountUsage", signature);
+
+ const char *usage = "eu/faircode/netguard/Usage";
+ if (midInitUsage == NULL)
+ midInitUsage = jniGetMethodID(args->env, clsUsage, "", "()V");
+
+ jobject jusage = jniNewObject(args->env, clsUsage, midInitUsage, usage);
+ ng_add_alloc(jusage, "jusage");
+
+ if (fidUsageTime == NULL) {
+ const char *string = "Ljava/lang/String;";
+ fidUsageTime = jniGetFieldID(args->env, clsUsage, "Time", "J");
+ fidUsageVersion = jniGetFieldID(args->env, clsUsage, "Version", "I");
+ fidUsageProtocol = jniGetFieldID(args->env, clsUsage, "Protocol", "I");
+ fidUsageDAddr = jniGetFieldID(args->env, clsUsage, "DAddr", string);
+ fidUsageDPort = jniGetFieldID(args->env, clsUsage, "DPort", "I");
+ fidUsageUid = jniGetFieldID(args->env, clsUsage, "Uid", "I");
+ fidUsageSent = jniGetFieldID(args->env, clsUsage, "Sent", "J");
+ fidUsageReceived = jniGetFieldID(args->env, clsUsage, "Received", "J");
+ }
+
+ jlong jtime = time(NULL) * 1000LL;
+ jstring jdaddr = (*args->env)->NewStringUTF(args->env, daddr);
+ ng_add_alloc(jdaddr, "jdaddr");
+
+ (*args->env)->SetLongField(args->env, jusage, fidUsageTime, jtime);
+ (*args->env)->SetIntField(args->env, jusage, fidUsageVersion, version);
+ (*args->env)->SetIntField(args->env, jusage, fidUsageProtocol, protocol);
+ (*args->env)->SetObjectField(args->env, jusage, fidUsageDAddr, jdaddr);
+ (*args->env)->SetIntField(args->env, jusage, fidUsageDPort, dport);
+ (*args->env)->SetIntField(args->env, jusage, fidUsageUid, uid);
+ (*args->env)->SetLongField(args->env, jusage, fidUsageSent, sent);
+ (*args->env)->SetLongField(args->env, jusage, fidUsageReceived, received);
+
+ (*args->env)->CallVoidMethod(args->env, args->instance, midAccountUsage, jusage);
+ jniCheckException(args->env);
+
+ (*args->env)->DeleteLocalRef(args->env, jdaddr);
+ (*args->env)->DeleteLocalRef(args->env, jusage);
+ (*args->env)->DeleteLocalRef(args->env, clsService);
+ ng_delete_alloc(jdaddr, __FILE__, __LINE__);
+ ng_delete_alloc(jusage, __FILE__, __LINE__);
+ ng_delete_alloc(clsService, __FILE__, __LINE__);
+
+#ifdef PROFILE_JNI
+ gettimeofday(&end, NULL);
+ mselapsed = (end.tv_sec - start.tv_sec) * 1000.0 +
+ (end.tv_usec - start.tv_usec) / 1000.0;
+ if (mselapsed > PROFILE_JNI)
+ log_android(ANDROID_LOG_WARN, "log_packet %f", mselapsed);
+#endif
+}
+
+struct alloc_record {
+ const char *tag;
+ time_t time;
+ void *ptr;
+};
+
+int allocs = 0;
+int balance = 0;
+struct alloc_record *alloc = NULL;
+pthread_mutex_t *alock = NULL;
+
+void ng_add_alloc(void *ptr, const char *tag) {
+#ifdef PROFILE_MEMORY
+ if (ptr == NULL)
+ return;
+
+ if (alock == NULL) {
+ alock = malloc(sizeof(pthread_mutex_t));
+ if (pthread_mutex_init(alock, NULL))
+ log_android(ANDROID_LOG_ERROR, "pthread_mutex_init failed");
+ }
+
+ if (pthread_mutex_lock(alock))
+ log_android(ANDROID_LOG_ERROR, "pthread_mutex_lock failed");
+
+ int c = 0;
+ for (; c < allocs; c++)
+ if (alloc[c].ptr == NULL)
+ break;
+
+ if (c >= allocs) {
+ if (allocs == 0)
+ alloc = malloc(sizeof(struct alloc_record));
+ else
+ alloc = realloc(alloc, sizeof(struct alloc_record) * (allocs + 1));
+ c = allocs;
+ allocs++;
+ }
+
+ alloc[c].tag = tag;
+ alloc[c].time = time(NULL);
+ alloc[c].ptr = ptr;
+ balance++;
+
+ if (pthread_mutex_unlock(alock))
+ log_android(ANDROID_LOG_ERROR, "pthread_mutex_unlock failed");
+#endif
+}
+
+void ng_delete_alloc(void *ptr, const char *file, int line) {
+#ifdef PROFILE_MEMORY
+ if (ptr == NULL)
+ return;
+
+ if (pthread_mutex_lock(alock))
+ log_android(ANDROID_LOG_ERROR, "pthread_mutex_lock failed");
+
+ int found = 0;
+ for (int c = 0; c < allocs; c++)
+ if (alloc[c].ptr == ptr) {
+ found = 1;
+ alloc[c].tag = "[free]";
+ alloc[c].ptr = NULL;
+ break;
+ }
+
+ if (found == 1)
+ balance--;
+
+ log_android(found ? ANDROID_LOG_DEBUG : ANDROID_LOG_ERROR,
+ "alloc/free balance %d records %d found %d", balance, allocs, found);
+ if (found == 0)
+ log_android(ANDROID_LOG_ERROR, "Not found at %s:%d", file, line);
+
+ if (pthread_mutex_unlock(alock))
+ log_android(ANDROID_LOG_ERROR, "pthread_mutex_unlock failed");
+#endif
+}
+
+void *ng_malloc(size_t __byte_count, const char *tag) {
+ void *ptr = malloc(__byte_count);
+ ng_add_alloc(ptr, tag);
+ return ptr;
+}
+
+void *ng_calloc(size_t __item_count, size_t __item_size, const char *tag) {
+ void *ptr = calloc(__item_count, __item_size);
+ ng_add_alloc(ptr, tag);
+ return ptr;
+}
+
+void *ng_realloc(void *__ptr, size_t __byte_count, const char *tag) {
+ ng_delete_alloc(__ptr, NULL, 0);
+ void *ptr = realloc(__ptr, __byte_count);
+ ng_add_alloc(ptr, tag);
+ return ptr;
+}
+
+void ng_free(void *__ptr, const char *file, int line) {
+ ng_delete_alloc(__ptr, file, line);
+ free(__ptr);
+}
+
+void ng_dump() {
+ int r = 0;
+ for (int c = 0; c < allocs; c++)
+ if (alloc[c].ptr != NULL)
+ log_android(ANDROID_LOG_WARN,
+ "holding %d [%s] %s",
+ ++r, alloc[c].tag, ctime(&alloc[c].time));
+}
+
+JNIEXPORT void JNICALL
+Java_eu_faircode_netguard_Util_dump_1memory_1profile(JNIEnv *env, jclass type) {
+#ifdef PROFILE_MEMORY
+ log_android(ANDROID_LOG_DEBUG, "Dump memory profile");
+
+ if (pthread_mutex_lock(alock))
+ log_android(ANDROID_LOG_ERROR, "pthread_mutex_lock failed");
+
+ ng_dump();
+
+ if (pthread_mutex_unlock(alock))
+ log_android(ANDROID_LOG_ERROR, "pthread_mutex_unlock failed");
+
+#endif
+}
\ No newline at end of file
diff --git a/NetGuard/app/src/main/jni/netguard/netguard.h b/NetGuard/app/src/main/jni/netguard/netguard.h
new file mode 100644
index 0000000..2edd467
--- /dev/null
+++ b/NetGuard/app/src/main/jni/netguard/netguard.h
@@ -0,0 +1,571 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#define TAG "NetGuard.JNI"
+
+// #define PROFILE_JNI 5
+// #define PROFILE_MEMORY
+
+#define EPOLL_TIMEOUT 3600 // seconds
+#define EPOLL_EVENTS 20
+#define EPOLL_MIN_CHECK 100 // milliseconds
+
+#define TUN_YIELD 10 // packets
+
+#define ICMP4_MAXMSG (IP_MAXPACKET - 20 - 8) // bytes (socket)
+#define ICMP6_MAXMSG (IPV6_MAXPACKET - 40 - 8) // bytes (socket)
+#define UDP4_MAXMSG (IP_MAXPACKET - 20 - 8) // bytes (socket)
+#define UDP6_MAXMSG (IPV6_MAXPACKET - 40 - 8) // bytes (socket)
+
+#define ICMP_TIMEOUT 5 // seconds
+
+#define UDP_TIMEOUT_53 15 // seconds
+#define UDP_TIMEOUT_ANY 300 // seconds
+#define UDP_KEEP_TIMEOUT 60 // seconds
+#define UDP_YIELD 10 // packets
+
+#define TCP_INIT_TIMEOUT 20 // seconds ~net.inet.tcp.keepinit
+#define TCP_IDLE_TIMEOUT 3600 // seconds ~net.inet.tcp.keepidle
+#define TCP_CLOSE_TIMEOUT 20 // seconds
+#define TCP_KEEP_TIMEOUT 300 // seconds
+// https://en.wikipedia.org/wiki/Maximum_segment_lifetime
+
+#define SESSION_LIMIT 40 // percent
+#define SESSION_MAX (1024 * SESSION_LIMIT / 100) // number
+
+#define SEND_BUF_DEFAULT 163840 // bytes
+
+#define UID_MAX_AGE 30000 // milliseconds
+
+#define SOCKS5_NONE 1
+#define SOCKS5_HELLO 2
+#define SOCKS5_AUTH 3
+#define SOCKS5_CONNECT 4
+#define SOCKS5_CONNECTED 5
+
+struct context {
+ pthread_mutex_t lock;
+ int pipefds[2];
+ int stopping;
+ int sdk;
+ struct ng_session *ng_session;
+};
+
+struct arguments {
+ JNIEnv *env;
+ jobject instance;
+ int tun;
+ jboolean fwd53;
+ jint rcode;
+ struct context *ctx;
+};
+
+struct allowed {
+ char raddr[INET6_ADDRSTRLEN + 1];
+ uint16_t rport; // host notation
+};
+
+struct segment {
+ uint32_t seq;
+ uint16_t len;
+ uint16_t sent;
+ int psh;
+ uint8_t *data;
+ struct segment *next;
+};
+
+struct icmp_session {
+ time_t time;
+ jint uid;
+ int version;
+
+ union {
+ __be32 ip4; // network notation
+ struct in6_addr ip6;
+ } saddr;
+
+ union {
+ __be32 ip4; // network notation
+ struct in6_addr ip6;
+ } daddr;
+
+ uint16_t id;
+
+ uint8_t stop;
+};
+
+#define UDP_ACTIVE 0
+#define UDP_FINISHING 1
+#define UDP_CLOSED 2
+#define UDP_BLOCKED 3
+
+struct udp_session {
+ time_t time;
+ jint uid;
+ int version;
+ uint16_t mss;
+
+ uint64_t sent;
+ uint64_t received;
+
+ union {
+ __be32 ip4; // network notation
+ struct in6_addr ip6;
+ } saddr;
+ __be16 source; // network notation
+
+ union {
+ __be32 ip4; // network notation
+ struct in6_addr ip6;
+ } daddr;
+ __be16 dest; // network notation
+
+ uint8_t state;
+};
+
+struct tcp_session {
+ jint uid;
+ time_t time;
+ int version;
+ uint16_t mss;
+ uint8_t recv_scale;
+ uint8_t send_scale;
+ uint32_t recv_window; // host notation, scaled
+ uint32_t send_window; // host notation, scaled
+ uint16_t unconfirmed; // packets
+
+ uint32_t remote_seq; // confirmed bytes received, host notation
+ uint32_t local_seq; // confirmed bytes sent, host notation
+ uint32_t remote_start;
+ uint32_t local_start;
+
+ uint32_t acked; // host notation
+ long long last_keep_alive;
+
+ uint64_t sent;
+ uint64_t received;
+
+ union {
+ __be32 ip4; // network notation
+ struct in6_addr ip6;
+ } saddr;
+ __be16 source; // network notation
+
+ union {
+ __be32 ip4; // network notation
+ struct in6_addr ip6;
+ } daddr;
+ __be16 dest; // network notation
+
+ uint8_t state;
+ uint8_t socks5;
+ struct segment *forward;
+};
+
+struct ng_session {
+ uint8_t protocol;
+ union {
+ struct icmp_session icmp;
+ struct udp_session udp;
+ struct tcp_session tcp;
+ };
+ jint socket;
+ struct epoll_event ev;
+ struct ng_session *next;
+};
+
+struct uid_cache_entry {
+ uint8_t version;
+ uint8_t protocol;
+ uint8_t saddr[16];
+ uint16_t sport;
+ uint8_t daddr[16];
+ uint16_t dport;
+ jint uid;
+ long time;
+};
+
+// IPv6
+
+struct ip6_hdr_pseudo {
+ struct in6_addr ip6ph_src;
+ struct in6_addr ip6ph_dst;
+ u_int32_t ip6ph_len;
+ u_int8_t ip6ph_zero[3];
+ u_int8_t ip6ph_nxt;
+} __packed;
+
+// PCAP
+// https://wiki.wireshark.org/Development/LibpcapFileFormat
+
+typedef uint16_t guint16_t;
+typedef uint32_t guint32_t;
+typedef int32_t gint32_t;
+
+typedef struct pcap_hdr_s {
+ guint32_t magic_number;
+ guint16_t version_major;
+ guint16_t version_minor;
+ gint32_t thiszone;
+ guint32_t sigfigs;
+ guint32_t snaplen;
+ guint32_t network;
+} __packed pcap_hdr_s;
+
+typedef struct pcaprec_hdr_s {
+ guint32_t ts_sec;
+ guint32_t ts_usec;
+ guint32_t incl_len;
+ guint32_t orig_len;
+} __packed pcaprec_hdr_s;
+
+#define LINKTYPE_RAW 101
+
+// DNS
+
+#define DNS_QCLASS_IN 1
+#define DNS_QTYPE_A 1 // IPv4
+#define DNS_QTYPE_AAAA 28 // IPv6
+
+#define DNS_SVCB 64
+#define DNS_HTTPS 65
+
+#define DNS_QNAME_MAX 255
+#define DNS_TTL (10 * 60) // seconds
+
+struct dns_header {
+ uint16_t id; // identification number
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+ uint16_t rd :1; // recursion desired
+ uint16_t tc :1; // truncated message
+ uint16_t aa :1; // authoritive answer
+ uint16_t opcode :4; // purpose of message
+ uint16_t qr :1; // query/response flag
+ uint16_t rcode :4; // response code
+ uint16_t cd :1; // checking disabled
+ uint16_t ad :1; // authenticated data
+ uint16_t z :1; // its z! reserved
+ uint16_t ra :1; // recursion available
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ uint16_t qr :1; // query/response flag
+ uint16_t opcode :4; // purpose of message
+ uint16_t aa :1; // authoritive answer
+ uint16_t tc :1; // truncated message
+ uint16_t rd :1; // recursion desired
+ uint16_t ra :1; // recursion available
+ uint16_t z :1; // its z! reserved
+ uint16_t ad :1; // authenticated data
+ uint16_t cd :1; // checking disabled
+ uint16_t rcode :4; // response code
+# else
+# error "Adjust your defines"
+#endif
+ uint16_t q_count; // number of question entries
+ uint16_t ans_count; // number of answer entries
+ uint16_t auth_count; // number of authority entries
+ uint16_t add_count; // number of resource entries
+} __packed;
+
+typedef struct dns_rr {
+ __be16 qname_ptr;
+ __be16 qtype;
+ __be16 qclass;
+ __be32 ttl;
+ __be16 rdlength;
+} __packed dns_rr;
+
+// DHCP
+
+#define DHCP_OPTION_MAGIC_NUMBER (0x63825363)
+
+typedef struct dhcp_packet {
+ uint8_t opcode;
+ uint8_t htype;
+ uint8_t hlen;
+ uint8_t hops;
+ uint32_t xid;
+ uint16_t secs;
+ uint16_t flags;
+ uint32_t ciaddr;
+ uint32_t yiaddr;
+ uint32_t siaddr;
+ uint32_t giaddr;
+ uint8_t chaddr[16];
+ uint8_t sname[64];
+ uint8_t file[128];
+ uint32_t option_format;
+} __packed dhcp_packet;
+
+typedef struct dhcp_option {
+ uint8_t code;
+ uint8_t length;
+} __packed dhcp_option;
+
+// Prototypes
+
+void handle_signal(int sig, siginfo_t *info, void *context);
+
+void *handle_events(void *a);
+
+void report_exit(const struct arguments *args, const char *fmt, ...);
+
+void report_error(const struct arguments *args, jint error, const char *fmt, ...);
+
+void check_allowed(const struct arguments *args);
+
+void clear(struct context *ctx);
+
+int check_icmp_session(const struct arguments *args,
+ struct ng_session *s,
+ int sessions, int maxsessions);
+
+int check_udp_session(const struct arguments *args,
+ struct ng_session *s,
+ int sessions, int maxsessions);
+
+int check_tcp_session(const struct arguments *args,
+ struct ng_session *s,
+ int sessions, int maxsessions);
+
+int monitor_tcp_session(const struct arguments *args, struct ng_session *s, int epoll_fd);
+
+int get_icmp_timeout(const struct icmp_session *u, int sessions, int maxsessions);
+
+int get_udp_timeout(const struct udp_session *u, int sessions, int maxsessions);
+
+int get_tcp_timeout(const struct tcp_session *t, int sessions, int maxsessions);
+
+uint16_t get_mtu();
+
+uint16_t get_default_mss(int version);
+
+int check_tun(const struct arguments *args,
+ const struct epoll_event *ev,
+ const int epoll_fd,
+ int sessions, int maxsessions);
+
+void check_icmp_socket(const struct arguments *args, const struct epoll_event *ev);
+
+void check_udp_socket(const struct arguments *args, const struct epoll_event *ev);
+
+int32_t get_qname(const uint8_t *data, const size_t datalen, uint16_t off, char *qname);
+
+void parse_dns_response(const struct arguments *args, const struct ng_session *session,
+ const uint8_t *data, size_t *datalen);
+
+uint32_t get_send_window(const struct tcp_session *cur);
+
+uint32_t get_receive_buffer(const struct ng_session *cur);
+
+uint32_t get_receive_window(const struct ng_session *cur);
+
+void check_tcp_socket(const struct arguments *args,
+ const struct epoll_event *ev,
+ const int epoll_fd);
+
+int is_lower_layer(int protocol);
+
+int is_upper_layer(int protocol);
+
+void handle_ip(const struct arguments *args,
+ const uint8_t *buffer, size_t length,
+ const int epoll_fd,
+ int sessions, int maxsessions);
+
+jboolean handle_icmp(const struct arguments *args,
+ const uint8_t *pkt, size_t length,
+ const uint8_t *payload,
+ int uid,
+ const int epoll_fd);
+
+int has_udp_session(const struct arguments *args, const uint8_t *pkt, const uint8_t *payload);
+
+void block_udp(const struct arguments *args,
+ const uint8_t *pkt, size_t length,
+ const uint8_t *payload,
+ int uid);
+
+jboolean handle_udp(const struct arguments *args,
+ const uint8_t *pkt, size_t length,
+ const uint8_t *payload,
+ int uid, struct allowed *redirect,
+ const int epoll_fd);
+
+int check_dhcp(const struct arguments *args, const struct udp_session *u,
+ const uint8_t *data, const size_t datalen);
+
+void clear_tcp_data(struct tcp_session *cur);
+
+jboolean handle_tcp(const struct arguments *args,
+ const uint8_t *pkt, size_t length,
+ const uint8_t *payload,
+ int uid, int allowed, struct allowed *redirect,
+ const int epoll_fd);
+
+void queue_tcp(const struct arguments *args,
+ const struct tcphdr *tcphdr,
+ const char *session, struct tcp_session *cur,
+ const uint8_t *data, uint16_t datalen);
+
+int open_icmp_socket(const struct arguments *args, const struct icmp_session *cur);
+
+int open_udp_socket(const struct arguments *args,
+ const struct udp_session *cur, const struct allowed *redirect);
+
+int open_tcp_socket(const struct arguments *args,
+ const struct tcp_session *cur, const struct allowed *redirect);
+
+int32_t get_local_port(const int sock);
+
+int write_syn_ack(const struct arguments *args, struct tcp_session *cur);
+
+int write_ack(const struct arguments *args, struct tcp_session *cur);
+
+int write_data(const struct arguments *args, struct tcp_session *cur,
+ const uint8_t *buffer, size_t length);
+
+int write_fin_ack(const struct arguments *args, struct tcp_session *cur);
+
+void write_rst(const struct arguments *args, struct tcp_session *cur);
+
+void write_rst_ack(const struct arguments *args, struct tcp_session *cur);
+
+ssize_t write_icmp(const struct arguments *args, const struct icmp_session *cur,
+ uint8_t *data, size_t datalen);
+
+ssize_t write_udp(const struct arguments *args, const struct udp_session *cur,
+ uint8_t *data, size_t datalen);
+
+ssize_t write_tcp(const struct arguments *args, const struct tcp_session *cur,
+ const uint8_t *data, size_t datalen,
+ int syn, int ack, int fin, int rst);
+
+uint8_t char2nible(const char c);
+
+void hex2bytes(const char *hex, uint8_t *buffer);
+
+jint get_uid(const int version, const int protocol,
+ const void *saddr, const uint16_t sport,
+ const void *daddr, const uint16_t dport);
+
+jint get_uid_sub(const int version, const int protocol,
+ const void *saddr, const uint16_t sport,
+ const void *daddr, const uint16_t dport,
+ const char *source, const char *dest,
+ long now);
+
+int protect_socket(const struct arguments *args, int socket);
+
+uint16_t calc_checksum(uint16_t start, const uint8_t *buffer, size_t length);
+
+jobject jniGlobalRef(JNIEnv *env, jobject cls);
+
+jclass jniFindClass(JNIEnv *env, const char *name);
+
+jmethodID jniGetMethodID(JNIEnv *env, jclass cls, const char *name, const char *signature);
+
+jfieldID jniGetFieldID(JNIEnv *env, jclass cls, const char *name, const char *type);
+
+jobject jniNewObject(JNIEnv *env, jclass cls, jmethodID constructor, const char *name);
+
+int jniCheckException(JNIEnv *env);
+
+int sdk_int(JNIEnv *env);
+
+void log_android(int prio, const char *fmt, ...);
+
+void log_packet(const struct arguments *args, jobject jpacket);
+
+void dns_resolved(const struct arguments *args,
+ const char *qname, const char *aname, const char *resource, int ttl);
+
+jboolean is_domain_blocked(const struct arguments *args, const char *name);
+
+jint get_uid_q(const struct arguments *args,
+ jint version,
+ jint protocol,
+ const char *source,
+ jint sport,
+ const char *dest,
+ jint dport);
+
+struct allowed *is_address_allowed(const struct arguments *args, jobject objPacket);
+
+jobject create_packet(const struct arguments *args,
+ jint version,
+ jint protocol,
+ const char *flags,
+ const char *source,
+ jint sport,
+ const char *dest,
+ jint dport,
+ const char *data,
+ jint uid,
+ jboolean allowed);
+
+void account_usage(const struct arguments *args, jint version, jint protocol,
+ const char *daddr, jint dport, jint uid, jlong sent, jlong received);
+
+void write_pcap_hdr();
+
+void write_pcap_rec(const uint8_t *buffer, size_t len);
+
+void write_pcap(const void *ptr, size_t len);
+
+int compare_u32(uint32_t seq1, uint32_t seq2);
+
+const char *strstate(const int state);
+
+char *hex(const u_int8_t *data, const size_t len);
+
+int is_readable(int fd);
+
+int is_writable(int fd);
+
+long long get_ms();
+
+void ng_add_alloc(void *ptr, const char *tag);
+
+void ng_delete_alloc(void *ptr, const char *file, int line);
+
+void *ng_malloc(size_t __byte_count, const char *tag);
+
+void *ng_calloc(size_t __item_count, size_t __item_size, const char *tag);
+
+void *ng_realloc(void *__ptr, size_t __byte_count, const char *tag);
+
+void ng_free(void *__ptr, const char *file, int line);
+
+void ng_dump();
diff --git a/NetGuard/app/src/main/jni/netguard/pcap.c b/NetGuard/app/src/main/jni/netguard/pcap.c
new file mode 100644
index 0000000..134c49d
--- /dev/null
+++ b/NetGuard/app/src/main/jni/netguard/pcap.c
@@ -0,0 +1,78 @@
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+#include "netguard.h"
+
+FILE *pcap_file = NULL;
+size_t pcap_record_size = 64;
+long pcap_file_size = 2 * 1024 * 1024;
+
+void write_pcap_hdr() {
+ struct pcap_hdr_s pcap_hdr;
+ pcap_hdr.magic_number = 0xa1b2c3d4;
+ pcap_hdr.version_major = 2;
+ pcap_hdr.version_minor = 4;
+ pcap_hdr.thiszone = 0;
+ pcap_hdr.sigfigs = 0;
+ pcap_hdr.snaplen = pcap_record_size;
+ pcap_hdr.network = LINKTYPE_RAW;
+ write_pcap(&pcap_hdr, sizeof(struct pcap_hdr_s));
+}
+
+void write_pcap_rec(const uint8_t *buffer, size_t length) {
+ struct timespec ts;
+ if (clock_gettime(CLOCK_REALTIME, &ts))
+ log_android(ANDROID_LOG_ERROR, "clock_gettime error %d: %s", errno, strerror(errno));
+
+ size_t plen = (length < pcap_record_size ? length : pcap_record_size);
+ size_t rlen = sizeof(struct pcaprec_hdr_s) + plen;
+ struct pcaprec_hdr_s *pcap_rec = ng_malloc(rlen, "pcap");
+
+ pcap_rec->ts_sec = (guint32_t) ts.tv_sec;
+ pcap_rec->ts_usec = (guint32_t) (ts.tv_nsec / 1000);
+ pcap_rec->incl_len = (guint32_t) plen;
+ pcap_rec->orig_len = (guint32_t) length;
+
+ memcpy(((uint8_t *) pcap_rec) + sizeof(struct pcaprec_hdr_s), buffer, plen);
+
+ write_pcap(pcap_rec, rlen);
+
+ ng_free(pcap_rec, __FILE__, __LINE__);
+}
+
+void write_pcap(const void *ptr, size_t len) {
+ if (fwrite(ptr, len, 1, pcap_file) < 1)
+ log_android(ANDROID_LOG_ERROR, "PCAP fwrite error %d: %s", errno, strerror(errno));
+ else {
+ long fsize = ftell(pcap_file);
+ log_android(ANDROID_LOG_VERBOSE, "PCAP wrote %d @%ld", len, fsize);
+
+ if (fsize > pcap_file_size) {
+ log_android(ANDROID_LOG_WARN, "PCAP truncate @%ld", fsize);
+ if (ftruncate(fileno(pcap_file), sizeof(struct pcap_hdr_s)))
+ log_android(ANDROID_LOG_ERROR, "PCAP ftruncate error %d: %s",
+ errno, strerror(errno));
+ else {
+ if (!lseek(fileno(pcap_file), sizeof(struct pcap_hdr_s), SEEK_SET))
+ log_android(ANDROID_LOG_ERROR, "PCAP ftruncate error %d: %s",
+ errno, strerror(errno));
+ }
+ }
+ }
+}
diff --git a/NetGuard/app/src/main/jni/netguard/session.c b/NetGuard/app/src/main/jni/netguard/session.c
new file mode 100644
index 0000000..14e032f
--- /dev/null
+++ b/NetGuard/app/src/main/jni/netguard/session.c
@@ -0,0 +1,370 @@
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+#include "netguard.h"
+
+void clear(struct context *ctx) {
+ struct ng_session *s = ctx->ng_session;
+ while (s != NULL) {
+ if (s->socket >= 0 && close(s->socket))
+ log_android(ANDROID_LOG_ERROR, "close %d error %d: %s",
+ s->socket, errno, strerror(errno));
+ if (s->protocol == IPPROTO_TCP)
+ clear_tcp_data(&s->tcp);
+ struct ng_session *p = s;
+ s = s->next;
+ ng_free(p, __FILE__, __LINE__);
+ }
+ ctx->ng_session = NULL;
+}
+
+void *handle_events(void *a) {
+ struct arguments *args = (struct arguments *) a;
+ log_android(ANDROID_LOG_WARN, "Start events tun=%d", args->tun);
+
+ // Get max number of sessions
+ int maxsessions = SESSION_MAX;
+ struct rlimit rlim;
+ if (getrlimit(RLIMIT_NOFILE, &rlim))
+ log_android(ANDROID_LOG_WARN, "getrlimit error %d: %s", errno, strerror(errno));
+ else {
+ maxsessions = (int) (rlim.rlim_cur * SESSION_LIMIT / 100);
+ if (maxsessions > SESSION_MAX)
+ maxsessions = SESSION_MAX;
+ log_android(ANDROID_LOG_WARN, "getrlimit soft %d hard %d max sessions %d",
+ rlim.rlim_cur, rlim.rlim_max, maxsessions);
+ }
+
+ // Terminate existing sessions not allowed anymore
+ check_allowed(args);
+
+ // Open epoll file
+ int epoll_fd = epoll_create(1);
+ if (epoll_fd < 0) {
+ log_android(ANDROID_LOG_ERROR, "epoll create error %d: %s", errno, strerror(errno));
+ report_exit(args, "epoll create error %d: %s", errno, strerror(errno));
+ args->ctx->stopping = 1;
+ }
+
+ // Monitor stop events
+ struct epoll_event ev_pipe;
+ memset(&ev_pipe, 0, sizeof(struct epoll_event));
+ ev_pipe.events = EPOLLIN | EPOLLERR;
+ ev_pipe.data.ptr = &ev_pipe;
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, args->ctx->pipefds[0], &ev_pipe)) {
+ log_android(ANDROID_LOG_ERROR, "epoll add pipe error %d: %s", errno, strerror(errno));
+ report_exit(args, "epoll add pipe error %d: %s", errno, strerror(errno));
+ args->ctx->stopping = 1;
+ }
+
+ // Monitor tun events
+ struct epoll_event ev_tun;
+ memset(&ev_tun, 0, sizeof(struct epoll_event));
+ ev_tun.events = EPOLLIN | EPOLLERR;
+ ev_tun.data.ptr = NULL;
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, args->tun, &ev_tun)) {
+ log_android(ANDROID_LOG_ERROR, "epoll add tun error %d: %s", errno, strerror(errno));
+ report_exit(args, "epoll add tun error %d: %s", errno, strerror(errno));
+ args->ctx->stopping = 1;
+ }
+
+ // Loop
+ long long last_check = 0;
+ while (!args->ctx->stopping) {
+ log_android(ANDROID_LOG_DEBUG, "Loop");
+
+ int recheck = 0;
+ int timeout = EPOLL_TIMEOUT;
+
+ // Count sessions
+ int isessions = 0;
+ int usessions = 0;
+ int tsessions = 0;
+ struct ng_session *s = args->ctx->ng_session;
+ while (s != NULL) {
+ if (s->protocol == IPPROTO_ICMP || s->protocol == IPPROTO_ICMPV6) {
+ if (!s->icmp.stop)
+ isessions++;
+ } else if (s->protocol == IPPROTO_UDP) {
+ if (s->udp.state == UDP_ACTIVE)
+ usessions++;
+ } else if (s->protocol == IPPROTO_TCP) {
+ if (s->tcp.state != TCP_CLOSING && s->tcp.state != TCP_CLOSE)
+ tsessions++;
+ if (s->socket >= 0)
+ recheck = recheck | monitor_tcp_session(args, s, epoll_fd);
+ }
+ s = s->next;
+ }
+ int sessions = isessions + usessions + tsessions;
+
+ // Check sessions
+ long long ms = get_ms();
+ if (ms - last_check > EPOLL_MIN_CHECK) {
+ last_check = ms;
+
+ time_t now = time(NULL);
+ struct ng_session *sl = NULL;
+ s = args->ctx->ng_session;
+ while (s != NULL) {
+ int del = 0;
+ if (s->protocol == IPPROTO_ICMP || s->protocol == IPPROTO_ICMPV6) {
+ del = check_icmp_session(args, s, sessions, maxsessions);
+ if (!s->icmp.stop && !del) {
+ int stimeout = s->icmp.time +
+ get_icmp_timeout(&s->icmp, sessions, maxsessions) - now + 1;
+ if (stimeout > 0 && stimeout < timeout)
+ timeout = stimeout;
+ }
+ } else if (s->protocol == IPPROTO_UDP) {
+ del = check_udp_session(args, s, sessions, maxsessions);
+ if (s->udp.state == UDP_ACTIVE && !del) {
+ int stimeout = s->udp.time +
+ get_udp_timeout(&s->udp, sessions, maxsessions) - now + 1;
+ if (stimeout > 0 && stimeout < timeout)
+ timeout = stimeout;
+ }
+ } else if (s->protocol == IPPROTO_TCP) {
+ del = check_tcp_session(args, s, sessions, maxsessions);
+ if (s->tcp.state != TCP_CLOSING && s->tcp.state != TCP_CLOSE && !del) {
+ int stimeout = s->tcp.time +
+ get_tcp_timeout(&s->tcp, sessions, maxsessions) - now + 1;
+ if (stimeout > 0 && stimeout < timeout)
+ timeout = stimeout;
+ }
+ }
+
+ if (del) {
+ if (sl == NULL)
+ args->ctx->ng_session = s->next;
+ else
+ sl->next = s->next;
+
+ struct ng_session *c = s;
+ s = s->next;
+ if (c->protocol == IPPROTO_TCP)
+ clear_tcp_data(&c->tcp);
+ ng_free(c, __FILE__, __LINE__);
+ } else {
+ sl = s;
+ s = s->next;
+ }
+ }
+ } else {
+ recheck = 1;
+ log_android(ANDROID_LOG_DEBUG, "Skipped session checks");
+ }
+
+ log_android(ANDROID_LOG_DEBUG,
+ "sessions ICMP %d UDP %d TCP %d max %d/%d timeout %d recheck %d",
+ isessions, usessions, tsessions, sessions, maxsessions, timeout, recheck);
+
+ // Poll
+ struct epoll_event ev[EPOLL_EVENTS];
+ int ready = epoll_wait(epoll_fd, ev, EPOLL_EVENTS,
+ recheck ? EPOLL_MIN_CHECK : timeout * 1000);
+
+ if (ready < 0) {
+ if (errno == EINTR) {
+ log_android(ANDROID_LOG_DEBUG, "epoll interrupted tun %d", args->tun);
+ continue;
+ } else {
+ log_android(ANDROID_LOG_ERROR,
+ "epoll tun %d error %d: %s",
+ args->tun, errno, strerror(errno));
+ report_exit(args, "epoll tun %d error %d: %s",
+ args->tun, errno, strerror(errno));
+ break;
+ }
+ }
+
+ if (ready == 0)
+ log_android(ANDROID_LOG_DEBUG, "epoll timeout");
+ else {
+
+ if (pthread_mutex_lock(&args->ctx->lock))
+ log_android(ANDROID_LOG_ERROR, "pthread_mutex_lock failed");
+
+ int error = 0;
+
+ for (int i = 0; i < ready; i++) {
+ if (ev[i].data.ptr == &ev_pipe) {
+ // Check pipe
+ uint8_t buffer[1];
+ if (read(args->ctx->pipefds[0], buffer, 1) < 0)
+ log_android(ANDROID_LOG_WARN, "Read pipe error %d: %s",
+ errno, strerror(errno));
+ else
+ log_android(ANDROID_LOG_WARN, "Read pipe");
+
+ } else if (ev[i].data.ptr == NULL) {
+ // Check upstream
+ log_android(ANDROID_LOG_DEBUG, "epoll ready %d/%d in %d out %d err %d hup %d",
+ i, ready,
+ (ev[i].events & EPOLLIN) != 0,
+ (ev[i].events & EPOLLOUT) != 0,
+ (ev[i].events & EPOLLERR) != 0,
+ (ev[i].events & EPOLLHUP) != 0);
+
+ int count = 0;
+ while (count < TUN_YIELD && !error && !args->ctx->stopping &&
+ is_readable(args->tun)) {
+ count++;
+ if (check_tun(args, &ev[i], epoll_fd, sessions, maxsessions) < 0)
+ error = 1;
+ }
+
+ } else {
+ // Check downstream
+ log_android(ANDROID_LOG_DEBUG,
+ "epoll ready %d/%d in %d out %d err %d hup %d prot %d sock %d",
+ i, ready,
+ (ev[i].events & EPOLLIN) != 0,
+ (ev[i].events & EPOLLOUT) != 0,
+ (ev[i].events & EPOLLERR) != 0,
+ (ev[i].events & EPOLLHUP) != 0,
+ ((struct ng_session *) ev[i].data.ptr)->protocol,
+ ((struct ng_session *) ev[i].data.ptr)->socket);
+
+ struct ng_session *session = (struct ng_session *) ev[i].data.ptr;
+ if (session->protocol == IPPROTO_ICMP ||
+ session->protocol == IPPROTO_ICMPV6)
+ check_icmp_socket(args, &ev[i]);
+ else if (session->protocol == IPPROTO_UDP) {
+ int count = 0;
+ while (count < UDP_YIELD && !args->ctx->stopping &&
+ !(ev[i].events & EPOLLERR) && (ev[i].events & EPOLLIN) &&
+ is_readable(session->socket)) {
+ count++;
+ check_udp_socket(args, &ev[i]);
+ }
+ } else if (session->protocol == IPPROTO_TCP)
+ check_tcp_socket(args, &ev[i], epoll_fd);
+ }
+
+ if (error)
+ break;
+ }
+
+ if (pthread_mutex_unlock(&args->ctx->lock))
+ log_android(ANDROID_LOG_ERROR, "pthread_mutex_unlock failed");
+
+ if (error)
+ break;
+ }
+ }
+
+ // Close epoll file
+ if (epoll_fd >= 0 && close(epoll_fd))
+ log_android(ANDROID_LOG_ERROR,
+ "epoll close error %d: %s", errno, strerror(errno));
+
+ // Cleanup
+ ng_free(args, __FILE__, __LINE__);
+
+ log_android(ANDROID_LOG_WARN, "Stopped events tun=%d", args->tun);
+ return NULL;
+}
+
+void check_allowed(const struct arguments *args) {
+ char source[INET6_ADDRSTRLEN + 1];
+ char dest[INET6_ADDRSTRLEN + 1];
+
+ struct ng_session *l = NULL;
+ struct ng_session *s = args->ctx->ng_session;
+ while (s != NULL) {
+ if (s->protocol == IPPROTO_ICMP || s->protocol == IPPROTO_ICMPV6) {
+ if (!s->icmp.stop) {
+ if (s->icmp.version == 4) {
+ inet_ntop(AF_INET, &s->icmp.saddr.ip4, source, sizeof(source));
+ inet_ntop(AF_INET, &s->icmp.daddr.ip4, dest, sizeof(dest));
+ } else {
+ inet_ntop(AF_INET6, &s->icmp.saddr.ip6, source, sizeof(source));
+ inet_ntop(AF_INET6, &s->icmp.daddr.ip6, dest, sizeof(dest));
+ }
+
+ jobject objPacket = create_packet(
+ args, s->icmp.version, IPPROTO_ICMP, "",
+ source, 0, dest, 0, "", s->icmp.uid, 0);
+ if (is_address_allowed(args, objPacket) == NULL) {
+ s->icmp.stop = 1;
+ log_android(ANDROID_LOG_WARN, "ICMP terminate %d uid %d",
+ s->socket, s->icmp.uid);
+ }
+ }
+
+ } else if (s->protocol == IPPROTO_UDP) {
+ if (s->udp.state == UDP_ACTIVE) {
+ if (s->udp.version == 4) {
+ inet_ntop(AF_INET, &s->udp.saddr.ip4, source, sizeof(source));
+ inet_ntop(AF_INET, &s->udp.daddr.ip4, dest, sizeof(dest));
+ } else {
+ inet_ntop(AF_INET6, &s->udp.saddr.ip6, source, sizeof(source));
+ inet_ntop(AF_INET6, &s->udp.daddr.ip6, dest, sizeof(dest));
+ }
+
+ jobject objPacket = create_packet(
+ args, s->udp.version, IPPROTO_UDP, "",
+ source, ntohs(s->udp.source), dest, ntohs(s->udp.dest), "", s->udp.uid, 0);
+ if (is_address_allowed(args, objPacket) == NULL) {
+ s->udp.state = UDP_FINISHING;
+ log_android(ANDROID_LOG_WARN, "UDP terminate session socket %d uid %d",
+ s->socket, s->udp.uid);
+ }
+ } else if (s->udp.state == UDP_BLOCKED) {
+ log_android(ANDROID_LOG_WARN, "UDP remove blocked session uid %d", s->udp.uid);
+
+ if (l == NULL)
+ args->ctx->ng_session = s->next;
+ else
+ l->next = s->next;
+
+ struct ng_session *c = s;
+ s = s->next;
+ ng_free(c, __FILE__, __LINE__);
+ continue;
+ }
+
+ } else if (s->protocol == IPPROTO_TCP) {
+ if (s->tcp.state != TCP_CLOSING && s->tcp.state != TCP_CLOSE) {
+ if (s->tcp.version == 4) {
+ inet_ntop(AF_INET, &s->tcp.saddr.ip4, source, sizeof(source));
+ inet_ntop(AF_INET, &s->tcp.daddr.ip4, dest, sizeof(dest));
+ } else {
+ inet_ntop(AF_INET6, &s->tcp.saddr.ip6, source, sizeof(source));
+ inet_ntop(AF_INET6, &s->tcp.daddr.ip6, dest, sizeof(dest));
+ }
+
+ jobject objPacket = create_packet(
+ args, s->tcp.version, IPPROTO_TCP, "",
+ source, ntohs(s->tcp.source), dest, ntohs(s->tcp.dest), "", s->tcp.uid, 0);
+ if (is_address_allowed(args, objPacket) == NULL) {
+ write_rst(args, &s->tcp);
+ log_android(ANDROID_LOG_WARN, "TCP terminate socket %d uid %d",
+ s->socket, s->tcp.uid);
+ }
+ }
+
+ }
+
+ l = s;
+ s = s->next;
+ }
+}
+
diff --git a/NetGuard/app/src/main/jni/netguard/tcp.c b/NetGuard/app/src/main/jni/netguard/tcp.c
new file mode 100644
index 0000000..a0c76ed
--- /dev/null
+++ b/NetGuard/app/src/main/jni/netguard/tcp.c
@@ -0,0 +1,1327 @@
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+#include "netguard.h"
+
+extern char socks5_addr[INET6_ADDRSTRLEN + 1];
+extern int socks5_port;
+extern char socks5_username[127 + 1];
+extern char socks5_password[127 + 1];
+
+extern FILE *pcap_file;
+
+void clear_tcp_data(struct tcp_session *cur) {
+ struct segment *s = cur->forward;
+ while (s != NULL) {
+ struct segment *p = s;
+ s = s->next;
+ ng_free(p->data, __FILE__, __LINE__);
+ ng_free(p, __FILE__, __LINE__);
+ }
+}
+
+int get_tcp_timeout(const struct tcp_session *t, int sessions, int maxsessions) {
+ int timeout;
+ if (t->state == TCP_LISTEN || t->state == TCP_SYN_RECV)
+ timeout = TCP_INIT_TIMEOUT;
+ else if (t->state == TCP_ESTABLISHED)
+ timeout = TCP_IDLE_TIMEOUT;
+ else
+ timeout = TCP_CLOSE_TIMEOUT;
+
+ int scale = 100 - sessions * 100 / maxsessions;
+ timeout = timeout * scale / 100;
+
+ return timeout;
+}
+
+int check_tcp_session(const struct arguments *args, struct ng_session *s,
+ int sessions, int maxsessions) {
+ time_t now = time(NULL);
+
+ char source[INET6_ADDRSTRLEN + 1];
+ char dest[INET6_ADDRSTRLEN + 1];
+ if (s->tcp.version == 4) {
+ inet_ntop(AF_INET, &s->tcp.saddr.ip4, source, sizeof(source));
+ inet_ntop(AF_INET, &s->tcp.daddr.ip4, dest, sizeof(dest));
+ } else {
+ inet_ntop(AF_INET6, &s->tcp.saddr.ip6, source, sizeof(source));
+ inet_ntop(AF_INET6, &s->tcp.daddr.ip6, dest, sizeof(dest));
+ }
+
+ char session[250];
+ sprintf(session, "TCP socket from %s/%u to %s/%u %s socket %d",
+ source, ntohs(s->tcp.source), dest, ntohs(s->tcp.dest),
+ strstate(s->tcp.state), s->socket);
+
+ int timeout = get_tcp_timeout(&s->tcp, sessions, maxsessions);
+
+ // Check session timeout
+ if (s->tcp.state != TCP_CLOSING && s->tcp.state != TCP_CLOSE &&
+ s->tcp.time + timeout < now) {
+ log_android(ANDROID_LOG_WARN, "%s idle %d/%d sec ", session, now - s->tcp.time,
+ timeout);
+ if (s->tcp.state == TCP_LISTEN)
+ s->tcp.state = TCP_CLOSING;
+ else
+ write_rst(args, &s->tcp);
+ }
+
+ // Check closing sessions
+ if (s->tcp.state == TCP_CLOSING) {
+ // eof closes socket
+ if (s->socket >= 0) {
+ if (close(s->socket))
+ log_android(ANDROID_LOG_ERROR, "%s close error %d: %s",
+ session, errno, strerror(errno));
+ else
+ log_android(ANDROID_LOG_WARN, "%s close", session);
+ s->socket = -1;
+ }
+
+ s->tcp.time = time(NULL);
+ s->tcp.state = TCP_CLOSE;
+ }
+
+ if ((s->tcp.state == TCP_CLOSING || s->tcp.state == TCP_CLOSE) &&
+ (s->tcp.sent || s->tcp.received)) {
+ account_usage(args, s->tcp.version, IPPROTO_TCP,
+ dest, ntohs(s->tcp.dest), s->tcp.uid, s->tcp.sent, s->tcp.received);
+ s->tcp.sent = 0;
+ s->tcp.received = 0;
+ }
+
+ // Cleanup lingering sessions
+ if (s->tcp.state == TCP_CLOSE && s->tcp.time + TCP_KEEP_TIMEOUT < now)
+ return 1;
+
+ return 0;
+}
+
+int monitor_tcp_session(const struct arguments *args, struct ng_session *s, int epoll_fd) {
+ int recheck = 0;
+ unsigned int events = EPOLLERR;
+
+ if (s->tcp.state == TCP_LISTEN) {
+ // Check for connected = writable
+ if (s->tcp.socks5 == SOCKS5_NONE)
+ events = events | EPOLLOUT;
+ else
+ events = events | EPOLLIN;
+ } else if (s->tcp.state == TCP_ESTABLISHED || s->tcp.state == TCP_CLOSE_WAIT) {
+
+ // Check for incoming data
+ if (get_send_window(&s->tcp) > 0)
+ events = events | EPOLLIN;
+ else {
+ recheck = 1;
+
+ long long ms = get_ms();
+ if (ms - s->tcp.last_keep_alive > EPOLL_MIN_CHECK) {
+ s->tcp.last_keep_alive = ms;
+ log_android(ANDROID_LOG_WARN, "Sending keep alive to update send window");
+ s->tcp.remote_seq--;
+ write_ack(args, &s->tcp);
+ s->tcp.remote_seq++;
+ }
+ }
+
+ // Check for outgoing data
+ if (s->tcp.forward != NULL) {
+ uint32_t buffer_size = get_receive_buffer(s);
+ if (s->tcp.forward->seq == s->tcp.remote_seq &&
+ s->tcp.forward->len - s->tcp.forward->sent < buffer_size)
+ events = events | EPOLLOUT;
+ else
+ recheck = 1;
+ }
+ }
+
+ if (events != s->ev.events) {
+ s->ev.events = events;
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, s->socket, &s->ev)) {
+ s->tcp.state = TCP_CLOSING;
+ log_android(ANDROID_LOG_ERROR, "epoll mod tcp error %d: %s", errno, strerror(errno));
+ } else
+ log_android(ANDROID_LOG_DEBUG, "epoll mod tcp socket %d in %d out %d",
+ s->socket, (events & EPOLLIN) != 0, (events & EPOLLOUT) != 0);
+ }
+
+ return recheck;
+}
+
+uint32_t get_send_window(const struct tcp_session *cur) {
+ uint32_t behind;
+ if (cur->acked <= cur->local_seq)
+ behind = (cur->local_seq - cur->acked);
+ else
+ behind = (0x10000 + cur->local_seq - cur->acked);
+ behind += (cur->unconfirmed + 1) * 40; // Maximum header size
+
+ uint32_t total = (behind < cur->send_window ? cur->send_window - behind : 0);
+
+ log_android(ANDROID_LOG_DEBUG, "Send window behind %u window %u total %u",
+ behind, cur->send_window, total);
+
+ return total;
+}
+
+uint32_t get_receive_buffer(const struct ng_session *cur) {
+ if (cur->socket < 0)
+ return 0;
+
+ // Get send buffer size
+ // /proc/sys/net/core/wmem_default
+ int sendbuf = 0;
+ int sendbufsize = sizeof(sendbuf);
+ if (getsockopt(cur->socket, SOL_SOCKET, SO_SNDBUF, &sendbuf, (socklen_t *) &sendbufsize) < 0)
+ log_android(ANDROID_LOG_WARN, "getsockopt SO_RCVBUF %d: %s", errno, strerror(errno));
+
+ if (sendbuf == 0)
+ sendbuf = SEND_BUF_DEFAULT;
+
+ // Get unsent data size
+ int unsent = 0;
+ if (ioctl(cur->socket, SIOCOUTQ, &unsent))
+ log_android(ANDROID_LOG_WARN, "ioctl SIOCOUTQ %d: %s", errno, strerror(errno));
+
+ uint32_t total = (uint32_t) (unsent < sendbuf ? sendbuf - unsent : 0);
+
+ log_android(ANDROID_LOG_DEBUG, "Send buffer %u unsent %u total %u",
+ sendbuf, unsent, total);
+
+ return total;
+}
+
+uint32_t get_receive_window(const struct ng_session *cur) {
+ // Get data to forward size
+ uint32_t toforward = 0;
+ struct segment *q = cur->tcp.forward;
+ while (q != NULL) {
+ toforward += (q->len - q->sent);
+ q = q->next;
+ }
+
+ uint32_t window = get_receive_buffer(cur);
+
+ uint32_t max = ((uint32_t) 0xFFFF) << cur->tcp.recv_scale;
+ if (window > max) {
+ log_android(ANDROID_LOG_DEBUG, "Receive window %u > max %u", window, max);
+ window = max;
+ }
+
+ uint32_t total = (toforward < window ? window - toforward : 0);
+
+ log_android(ANDROID_LOG_DEBUG, "Receive window toforward %u window %u total %u",
+ toforward, window, total);
+
+ return total;
+}
+
+void check_tcp_socket(const struct arguments *args,
+ const struct epoll_event *ev,
+ const int epoll_fd) {
+ struct ng_session *s = (struct ng_session *) ev->data.ptr;
+
+ int oldstate = s->tcp.state;
+ uint32_t oldlocal = s->tcp.local_seq;
+ uint32_t oldremote = s->tcp.remote_seq;
+
+ char source[INET6_ADDRSTRLEN + 1];
+ char dest[INET6_ADDRSTRLEN + 1];
+ if (s->tcp.version == 4) {
+ inet_ntop(AF_INET, &s->tcp.saddr.ip4, source, sizeof(source));
+ inet_ntop(AF_INET, &s->tcp.daddr.ip4, dest, sizeof(dest));
+ } else {
+ inet_ntop(AF_INET6, &s->tcp.saddr.ip6, source, sizeof(source));
+ inet_ntop(AF_INET6, &s->tcp.daddr.ip6, dest, sizeof(dest));
+ }
+ char session[250];
+ sprintf(session, "TCP socket from %s/%u to %s/%u %s loc %u rem %u",
+ source, ntohs(s->tcp.source), dest, ntohs(s->tcp.dest),
+ strstate(s->tcp.state),
+ s->tcp.local_seq - s->tcp.local_start,
+ s->tcp.remote_seq - s->tcp.remote_start);
+
+ // Check socket error
+ if (ev->events & EPOLLERR) {
+ s->tcp.time = time(NULL);
+
+ int serr = 0;
+ socklen_t optlen = sizeof(int);
+ int err = getsockopt(s->socket, SOL_SOCKET, SO_ERROR, &serr, &optlen);
+ if (err < 0)
+ log_android(ANDROID_LOG_ERROR, "%s getsockopt error %d: %s",
+ session, errno, strerror(errno));
+ else if (serr)
+ log_android(ANDROID_LOG_ERROR, "%s SO_ERROR %d: %s",
+ session, serr, strerror(serr));
+
+ write_rst(args, &s->tcp);
+
+ // Connection refused
+ if (0)
+ if (err >= 0 && (serr == ECONNREFUSED || serr == EHOSTUNREACH)) {
+ struct icmp icmp;
+ memset(&icmp, 0, sizeof(struct icmp));
+ icmp.icmp_type = ICMP_UNREACH;
+ if (serr == ECONNREFUSED)
+ icmp.icmp_code = ICMP_UNREACH_PORT;
+ else
+ icmp.icmp_code = ICMP_UNREACH_HOST;
+ icmp.icmp_cksum = 0;
+ icmp.icmp_cksum = ~calc_checksum(0, (const uint8_t *) &icmp, 4);
+
+ struct icmp_session sicmp;
+ memset(&sicmp, 0, sizeof(struct icmp_session));
+ sicmp.version = s->tcp.version;
+ if (s->tcp.version == 4) {
+ sicmp.saddr.ip4 = (__be32) s->tcp.saddr.ip4;
+ sicmp.daddr.ip4 = (__be32) s->tcp.daddr.ip4;
+ } else {
+ memcpy(&sicmp.saddr.ip6, &s->tcp.saddr.ip6, 16);
+ memcpy(&sicmp.daddr.ip6, &s->tcp.daddr.ip6, 16);
+ }
+
+ write_icmp(args, &sicmp, (uint8_t *) &icmp, 8);
+ }
+ } else {
+ // Assume socket okay
+ if (s->tcp.state == TCP_LISTEN) {
+ // Check socket connect
+ if (s->tcp.socks5 == SOCKS5_NONE) {
+ if (ev->events & EPOLLOUT) {
+ log_android(ANDROID_LOG_INFO, "%s connected", session);
+
+ // https://tools.ietf.org/html/rfc1928
+ // https://tools.ietf.org/html/rfc1929
+ // https://en.wikipedia.org/wiki/SOCKS#SOCKS5
+ if (*socks5_addr && socks5_port)
+ s->tcp.socks5 = SOCKS5_HELLO;
+ else
+ s->tcp.socks5 = SOCKS5_CONNECTED;
+ }
+ } else {
+ if (ev->events & EPOLLIN) {
+ uint8_t buffer[32];
+ ssize_t bytes = recv(s->socket, buffer, sizeof(buffer), 0);
+ if (bytes < 0) {
+ log_android(ANDROID_LOG_ERROR, "%s recv SOCKS5 error %d: %s",
+ session, errno, strerror(errno));
+ write_rst(args, &s->tcp);
+ } else {
+ char *h = hex(buffer, (const size_t) bytes);
+ log_android(ANDROID_LOG_INFO, "%s recv SOCKS5 %s", session, h);
+ ng_free(h, __FILE__, __LINE__);
+
+ if (s->tcp.socks5 == SOCKS5_HELLO &&
+ bytes == 2 && buffer[0] == 5) {
+ if (buffer[1] == 0)
+ s->tcp.socks5 = SOCKS5_CONNECT;
+ else if (buffer[1] == 2)
+ s->tcp.socks5 = SOCKS5_AUTH;
+ else {
+ s->tcp.socks5 = 0;
+ log_android(ANDROID_LOG_ERROR, "%s SOCKS5 auth %d not supported",
+ session, buffer[1]);
+ write_rst(args, &s->tcp);
+ }
+
+ } else if (s->tcp.socks5 == SOCKS5_AUTH &&
+ bytes == 2 &&
+ (buffer[0] == 1 || buffer[0] == 5)) {
+ if (buffer[1] == 0) {
+ s->tcp.socks5 = SOCKS5_CONNECT;
+ log_android(ANDROID_LOG_WARN, "%s SOCKS5 auth OK", session);
+ } else {
+ s->tcp.socks5 = 0;
+ log_android(ANDROID_LOG_ERROR, "%s SOCKS5 auth error %d",
+ session, buffer[1]);
+ write_rst(args, &s->tcp);
+ }
+
+ } else if (s->tcp.socks5 == SOCKS5_CONNECT &&
+ bytes == 6 + (s->tcp.version == 4 ? 4 : 16) &&
+ buffer[0] == 5) {
+ if (buffer[1] == 0) {
+ s->tcp.socks5 = SOCKS5_CONNECTED;
+ log_android(ANDROID_LOG_WARN, "%s SOCKS5 connected", session);
+ } else {
+ s->tcp.socks5 = 0;
+ log_android(ANDROID_LOG_ERROR, "%s SOCKS5 connect error %d",
+ session, buffer[1]);
+ write_rst(args, &s->tcp);
+ /*
+ 0x00 = request granted
+ 0x01 = general failure
+ 0x02 = connection not allowed by ruleset
+ 0x03 = network unreachable
+ 0x04 = host unreachable
+ 0x05 = connection refused by destination host
+ 0x06 = TTL expired
+ 0x07 = command not supported / protocol error
+ 0x08 = address type not supported
+ */
+ }
+
+ } else {
+ s->tcp.socks5 = 0;
+ log_android(ANDROID_LOG_ERROR, "%s recv SOCKS5 state %d",
+ session, s->tcp.socks5);
+ write_rst(args, &s->tcp);
+ }
+ }
+ }
+ }
+
+ if (s->tcp.socks5 == SOCKS5_HELLO) {
+ uint8_t buffer[4] = {5, 2, 0, 2};
+ char *h = hex(buffer, sizeof(buffer));
+ log_android(ANDROID_LOG_INFO, "%s sending SOCKS5 hello: %s",
+ session, h);
+ ng_free(h, __FILE__, __LINE__);
+ ssize_t sent = send(s->socket, buffer, sizeof(buffer), MSG_NOSIGNAL);
+ if (sent < 0) {
+ log_android(ANDROID_LOG_ERROR, "%s send SOCKS5 hello error %d: %s",
+ session, errno, strerror(errno));
+ write_rst(args, &s->tcp);
+ }
+
+ } else if (s->tcp.socks5 == SOCKS5_AUTH) {
+ uint8_t ulen = strlen(socks5_username);
+ uint8_t plen = strlen(socks5_password);
+ uint8_t buffer[512];
+ *(buffer + 0) = 1; // Version
+ *(buffer + 1) = ulen;
+ memcpy(buffer + 2, socks5_username, ulen);
+ *(buffer + 2 + ulen) = plen;
+ memcpy(buffer + 2 + ulen + 1, socks5_password, plen);
+
+ size_t len = 2 + ulen + 1 + plen;
+
+ char *h = hex(buffer, len);
+ log_android(ANDROID_LOG_INFO, "%s sending SOCKS5 auth: %s",
+ session, h);
+ ng_free(h, __FILE__, __LINE__);
+ ssize_t sent = send(s->socket, buffer, len, MSG_NOSIGNAL);
+ if (sent < 0) {
+ log_android(ANDROID_LOG_ERROR,
+ "%s send SOCKS5 connect error %d: %s",
+ session, errno, strerror(errno));
+ write_rst(args, &s->tcp);
+ }
+
+ } else if (s->tcp.socks5 == SOCKS5_CONNECT) {
+ uint8_t buffer[22];
+ *(buffer + 0) = 5; // version
+ *(buffer + 1) = 1; // TCP/IP stream connection
+ *(buffer + 2) = 0; // reserved
+ *(buffer + 3) = (uint8_t) (s->tcp.version == 4 ? 1 : 4);
+ if (s->tcp.version == 4) {
+ memcpy(buffer + 4, &s->tcp.daddr.ip4, 4);
+ *((__be16 *) (buffer + 4 + 4)) = s->tcp.dest;
+ } else {
+ memcpy(buffer + 4, &s->tcp.daddr.ip6, 16);
+ *((__be16 *) (buffer + 4 + 16)) = s->tcp.dest;
+ }
+
+ size_t len = (s->tcp.version == 4 ? 10 : 22);
+
+ char *h = hex(buffer, len);
+ log_android(ANDROID_LOG_INFO, "%s sending SOCKS5 connect: %s",
+ session, h);
+ ng_free(h, __FILE__, __LINE__);
+ ssize_t sent = send(s->socket, buffer, len, MSG_NOSIGNAL);
+ if (sent < 0) {
+ log_android(ANDROID_LOG_ERROR,
+ "%s send SOCKS5 connect error %d: %s",
+ session, errno, strerror(errno));
+ write_rst(args, &s->tcp);
+ }
+
+ } else if (s->tcp.socks5 == SOCKS5_CONNECTED) {
+ s->tcp.remote_seq++; // remote SYN
+ if (write_syn_ack(args, &s->tcp) >= 0) {
+ s->tcp.time = time(NULL);
+ s->tcp.local_seq++; // local SYN
+ s->tcp.state = TCP_SYN_RECV;
+ }
+ }
+ } else {
+
+ // Always forward data
+ int fwd = 0;
+ if (ev->events & EPOLLOUT) {
+ // Forward data
+ uint32_t buffer_size = get_receive_buffer(s);
+ while (s->tcp.forward != NULL &&
+ s->tcp.forward->seq == s->tcp.remote_seq &&
+ s->tcp.forward->len - s->tcp.forward->sent < buffer_size) {
+ log_android(ANDROID_LOG_DEBUG, "%s fwd %u...%u sent %u",
+ session,
+ s->tcp.forward->seq - s->tcp.remote_start,
+ s->tcp.forward->seq + s->tcp.forward->len - s->tcp.remote_start,
+ s->tcp.forward->sent);
+
+ ssize_t sent = send(s->socket,
+ s->tcp.forward->data + s->tcp.forward->sent,
+ s->tcp.forward->len - s->tcp.forward->sent,
+ (unsigned int) (MSG_NOSIGNAL | (s->tcp.forward->psh
+ ? 0
+ : MSG_MORE)));
+ if (sent < 0) {
+ log_android(ANDROID_LOG_ERROR, "%s send error %d: %s",
+ session, errno, strerror(errno));
+ if (errno == EINTR || errno == EAGAIN) {
+ // Retry later
+ break;
+ } else {
+ write_rst(args, &s->tcp);
+ break;
+ }
+ } else {
+ fwd = 1;
+ buffer_size -= sent;
+ s->tcp.sent += sent;
+ s->tcp.forward->sent += sent;
+
+ if (s->tcp.forward->len == s->tcp.forward->sent) {
+ s->tcp.remote_seq = s->tcp.forward->seq + s->tcp.forward->sent;
+
+ struct segment *p = s->tcp.forward;
+ s->tcp.forward = s->tcp.forward->next;
+ ng_free(p->data, __FILE__, __LINE__);
+ ng_free(p, __FILE__, __LINE__);
+ } else {
+ log_android(ANDROID_LOG_WARN,
+ "%s partial send %u/%u",
+ session, s->tcp.forward->sent, s->tcp.forward->len);
+ break;
+ }
+ }
+ }
+
+ // Log data buffered
+ struct segment *seg = s->tcp.forward;
+ while (seg != NULL) {
+ log_android(ANDROID_LOG_WARN, "%s queued %u...%u sent %u",
+ session,
+ seg->seq - s->tcp.remote_start,
+ seg->seq + seg->len - s->tcp.remote_start,
+ seg->sent);
+ seg = seg->next;
+ }
+ }
+
+ // Get receive window
+ uint32_t window = get_receive_window(s);
+ uint32_t prev = s->tcp.recv_window;
+ s->tcp.recv_window = window;
+ if ((prev == 0 && window > 0) || (prev > 0 && window == 0))
+ log_android(ANDROID_LOG_WARN, "%s recv window %u > %u",
+ session, prev, window);
+
+ // Acknowledge forwarded data
+ if (fwd || (prev == 0 && window > 0)) {
+ if (fwd && s->tcp.forward == NULL && s->tcp.state == TCP_CLOSE_WAIT) {
+ log_android(ANDROID_LOG_WARN, "%s confirm FIN", session);
+ s->tcp.remote_seq++; // remote FIN
+ }
+ if (write_ack(args, &s->tcp) >= 0)
+ s->tcp.time = time(NULL);
+ }
+
+ if (s->tcp.state == TCP_ESTABLISHED || s->tcp.state == TCP_CLOSE_WAIT) {
+ // Check socket read
+ // Send window can be changed in the mean time
+
+ uint32_t send_window = get_send_window(&s->tcp);
+ if ((ev->events & EPOLLIN) && send_window > 0) {
+ s->tcp.time = time(NULL);
+
+ uint32_t buffer_size = (send_window > s->tcp.mss
+ ? s->tcp.mss : send_window);
+ uint8_t *buffer = ng_malloc(buffer_size, "tcp socket");
+ ssize_t bytes = recv(s->socket, buffer, (size_t) buffer_size, 0);
+ if (bytes < 0) {
+ // Socket error
+ log_android(ANDROID_LOG_ERROR, "%s recv error %d: %s",
+ session, errno, strerror(errno));
+
+ if (errno != EINTR && errno != EAGAIN)
+ write_rst(args, &s->tcp);
+ } else if (bytes == 0) {
+ log_android(ANDROID_LOG_WARN, "%s recv eof", session);
+
+ if (s->tcp.forward == NULL) {
+ if (write_fin_ack(args, &s->tcp) >= 0) {
+ log_android(ANDROID_LOG_WARN, "%s FIN sent", session);
+ s->tcp.local_seq++; // local FIN
+ }
+
+ if (s->tcp.state == TCP_ESTABLISHED)
+ s->tcp.state = TCP_FIN_WAIT1;
+ else if (s->tcp.state == TCP_CLOSE_WAIT)
+ s->tcp.state = TCP_LAST_ACK;
+ else
+ log_android(ANDROID_LOG_ERROR, "%s invalid close", session);
+ } else {
+ // There was still data to send
+ log_android(ANDROID_LOG_ERROR, "%s close with queue", session);
+ write_rst(args, &s->tcp);
+ }
+
+ if (close(s->socket))
+ log_android(ANDROID_LOG_ERROR, "%s close error %d: %s",
+ session, errno, strerror(errno));
+ s->socket = -1;
+
+ } else {
+ // Socket read data
+ log_android(ANDROID_LOG_DEBUG, "%s recv bytes %d", session, bytes);
+ s->tcp.received += bytes;
+
+ // Process DNS response
+ if (ntohs(s->tcp.dest) == 53 && bytes > 2) {
+ ssize_t dlen = bytes - 2;
+ parse_dns_response(args, s, buffer + 2, (size_t *) &dlen);
+ }
+
+ // Forward to tun
+ if (write_data(args, &s->tcp, buffer, (size_t) bytes) >= 0) {
+ s->tcp.local_seq += bytes;
+ s->tcp.unconfirmed++;
+ }
+ }
+ ng_free(buffer, __FILE__, __LINE__);
+ }
+ }
+ }
+ }
+
+ if (s->tcp.state != oldstate || s->tcp.local_seq != oldlocal ||
+ s->tcp.remote_seq != oldremote)
+ log_android(ANDROID_LOG_DEBUG, "%s new state", session);
+}
+
+jboolean handle_tcp(const struct arguments *args,
+ const uint8_t *pkt, size_t length,
+ const uint8_t *payload,
+ int uid, int allowed, struct allowed *redirect,
+ const int epoll_fd) {
+ // Get headers
+ const uint8_t version = (*pkt) >> 4;
+ const struct iphdr *ip4 = (struct iphdr *) pkt;
+ const struct ip6_hdr *ip6 = (struct ip6_hdr *) pkt;
+ const struct tcphdr *tcphdr = (struct tcphdr *) payload;
+ const uint8_t tcpoptlen = (uint8_t) ((tcphdr->doff - 5) * 4);
+ const uint8_t *tcpoptions = payload + sizeof(struct tcphdr);
+ const uint8_t *data = payload + sizeof(struct tcphdr) + tcpoptlen;
+ const uint16_t datalen = (const uint16_t) (length - (data - pkt));
+
+ // Search session
+ struct ng_session *cur = args->ctx->ng_session;
+ while (cur != NULL &&
+ !(cur->protocol == IPPROTO_TCP &&
+ cur->tcp.version == version &&
+ cur->tcp.source == tcphdr->source && cur->tcp.dest == tcphdr->dest &&
+ (version == 4 ? cur->tcp.saddr.ip4 == ip4->saddr &&
+ cur->tcp.daddr.ip4 == ip4->daddr
+ : memcmp(&cur->tcp.saddr.ip6, &ip6->ip6_src, 16) == 0 &&
+ memcmp(&cur->tcp.daddr.ip6, &ip6->ip6_dst, 16) == 0)))
+ cur = cur->next;
+
+ // Prepare logging
+ char source[INET6_ADDRSTRLEN + 1];
+ char dest[INET6_ADDRSTRLEN + 1];
+ if (version == 4) {
+ inet_ntop(AF_INET, &ip4->saddr, source, sizeof(source));
+ inet_ntop(AF_INET, &ip4->daddr, dest, sizeof(dest));
+ } else {
+ inet_ntop(AF_INET6, &ip6->ip6_src, source, sizeof(source));
+ inet_ntop(AF_INET6, &ip6->ip6_dst, dest, sizeof(dest));
+ }
+
+ char flags[10];
+ int flen = 0;
+ if (tcphdr->syn)
+ flags[flen++] = 'S';
+ if (tcphdr->ack)
+ flags[flen++] = 'A';
+ if (tcphdr->psh)
+ flags[flen++] = 'P';
+ if (tcphdr->fin)
+ flags[flen++] = 'F';
+ if (tcphdr->rst)
+ flags[flen++] = 'R';
+ if (tcphdr->urg)
+ flags[flen++] = 'U';
+ flags[flen] = 0;
+
+ char packet[250];
+ sprintf(packet,
+ "TCP %s %s/%u > %s/%u seq %u ack %u data %u win %u uid %d",
+ flags,
+ source, ntohs(tcphdr->source),
+ dest, ntohs(tcphdr->dest),
+ ntohl(tcphdr->seq) - (cur == NULL ? 0 : cur->tcp.remote_start),
+ tcphdr->ack ? ntohl(tcphdr->ack_seq) - (cur == NULL ? 0 : cur->tcp.local_start) : 0,
+ datalen, ntohs(tcphdr->window), uid);
+ log_android(tcphdr->urg ? ANDROID_LOG_WARN : ANDROID_LOG_DEBUG, packet);
+
+ // Drop URG data
+ if (tcphdr->urg)
+ return 1;
+
+ // Check session
+ if (cur == NULL) {
+ if (tcphdr->syn) {
+ // Decode options
+ // http://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml#tcp-parameters-1
+ uint16_t mss = get_default_mss(version);
+ uint8_t ws = 0;
+ int optlen = tcpoptlen;
+ uint8_t *options = (uint8_t *) tcpoptions;
+ while (optlen > 0) {
+ uint8_t kind = *options;
+ uint8_t len = *(options + 1);
+ if (kind == 0) // End of options list
+ break;
+
+ if (kind == 2 && len == 4)
+ mss = ntohs(*((uint16_t *) (options + 2)));
+
+ else if (kind == 3 && len == 3)
+ ws = *(options + 2);
+
+ if (kind == 1) {
+ optlen--;
+ options++;
+ } else {
+ optlen -= len;
+ options += len;
+ }
+ }
+
+ log_android(ANDROID_LOG_WARN, "%s new session mss %u ws %u window %u",
+ packet, mss, ws, ntohs(tcphdr->window) << ws);
+
+ // Register session
+ struct ng_session *s = ng_malloc(sizeof(struct ng_session), "tcp session");
+ s->protocol = IPPROTO_TCP;
+
+ s->tcp.time = time(NULL);
+ s->tcp.uid = uid;
+ s->tcp.version = version;
+ s->tcp.mss = mss;
+ s->tcp.recv_scale = ws;
+ s->tcp.send_scale = ws;
+ s->tcp.send_window = ((uint32_t) ntohs(tcphdr->window)) << s->tcp.send_scale;
+ s->tcp.unconfirmed = 0;
+ s->tcp.remote_seq = ntohl(tcphdr->seq); // ISN remote
+ s->tcp.local_seq = (uint32_t) rand(); // ISN local
+ s->tcp.remote_start = s->tcp.remote_seq;
+ s->tcp.local_start = s->tcp.local_seq;
+ s->tcp.acked = 0;
+ s->tcp.last_keep_alive = 0;
+ s->tcp.sent = 0;
+ s->tcp.received = 0;
+
+ if (version == 4) {
+ s->tcp.saddr.ip4 = (__be32) ip4->saddr;
+ s->tcp.daddr.ip4 = (__be32) ip4->daddr;
+ } else {
+ memcpy(&s->tcp.saddr.ip6, &ip6->ip6_src, 16);
+ memcpy(&s->tcp.daddr.ip6, &ip6->ip6_dst, 16);
+ }
+
+ s->tcp.source = tcphdr->source;
+ s->tcp.dest = tcphdr->dest;
+ s->tcp.state = TCP_LISTEN;
+ s->tcp.socks5 = SOCKS5_NONE;
+ s->tcp.forward = NULL;
+ s->next = NULL;
+
+ if (datalen) {
+ log_android(ANDROID_LOG_WARN, "%s SYN data", packet);
+ s->tcp.forward = ng_malloc(sizeof(struct segment), "syn segment");
+ s->tcp.forward->seq = s->tcp.remote_seq;
+ s->tcp.forward->len = datalen;
+ s->tcp.forward->sent = 0;
+ s->tcp.forward->psh = tcphdr->psh;
+ s->tcp.forward->data = ng_malloc(datalen, "syn segment data");
+ memcpy(s->tcp.forward->data, data, datalen);
+ s->tcp.forward->next = NULL;
+ }
+
+ // Open socket
+ s->socket = open_tcp_socket(args, &s->tcp, redirect);
+ if (s->socket < 0) {
+ // Remote might retry
+ ng_free(s, __FILE__, __LINE__);
+ return 0;
+ }
+
+ s->tcp.recv_window = get_receive_window(s);
+
+ log_android(ANDROID_LOG_DEBUG, "TCP socket %d lport %d",
+ s->socket, get_local_port(s->socket));
+
+ // Monitor events
+ memset(&s->ev, 0, sizeof(struct epoll_event));
+ s->ev.events = EPOLLOUT | EPOLLERR;
+ s->ev.data.ptr = s;
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, s->socket, &s->ev))
+ log_android(ANDROID_LOG_ERROR, "epoll add tcp error %d: %s",
+ errno, strerror(errno));
+
+ s->next = args->ctx->ng_session;
+ args->ctx->ng_session = s;
+
+ if (!allowed) {
+ log_android(ANDROID_LOG_WARN, "%s resetting blocked session", packet);
+ write_rst(args, &s->tcp);
+ }
+ } else {
+ log_android(ANDROID_LOG_WARN, "%s unknown session", packet);
+
+ struct tcp_session rst;
+ memset(&rst, 0, sizeof(struct tcp_session));
+ rst.version = version;
+ rst.local_seq = ntohl(tcphdr->ack_seq);
+ rst.remote_seq = ntohl(tcphdr->seq) + datalen + (tcphdr->syn || tcphdr->fin ? 1 : 0);
+
+ if (version == 4) {
+ rst.saddr.ip4 = (__be32) ip4->saddr;
+ rst.daddr.ip4 = (__be32) ip4->daddr;
+ } else {
+ memcpy(&rst.saddr.ip6, &ip6->ip6_src, 16);
+ memcpy(&rst.daddr.ip6, &ip6->ip6_dst, 16);
+ }
+
+ rst.source = tcphdr->source;
+ rst.dest = tcphdr->dest;
+
+ write_rst(args, &rst);
+ return 0;
+ }
+ } else {
+ char session[250];
+ sprintf(session,
+ "%s %s loc %u rem %u acked %u",
+ packet,
+ strstate(cur->tcp.state),
+ cur->tcp.local_seq - cur->tcp.local_start,
+ cur->tcp.remote_seq - cur->tcp.remote_start,
+ cur->tcp.acked - cur->tcp.local_start);
+
+ // Session found
+ if (cur->tcp.state == TCP_CLOSING || cur->tcp.state == TCP_CLOSE) {
+ log_android(ANDROID_LOG_WARN, "%s was closed", session);
+ write_rst(args, &cur->tcp);
+ return 0;
+ } else {
+ int oldstate = cur->tcp.state;
+ uint32_t oldlocal = cur->tcp.local_seq;
+ uint32_t oldremote = cur->tcp.remote_seq;
+
+ log_android(ANDROID_LOG_DEBUG, "%s handling", session);
+
+ if (!tcphdr->syn)
+ cur->tcp.time = time(NULL);
+ cur->tcp.send_window = ((uint32_t) ntohs(tcphdr->window)) << cur->tcp.send_scale;
+ cur->tcp.unconfirmed = 0;
+
+ // Do not change the order of the conditions
+
+ // Queue data to forward
+ if (datalen) {
+ if (cur->socket < 0) {
+ log_android(ANDROID_LOG_ERROR, "%s data while local closed", session);
+ write_rst(args, &cur->tcp);
+ return 0;
+ }
+ if (cur->tcp.state == TCP_CLOSE_WAIT) {
+ log_android(ANDROID_LOG_ERROR, "%s data while remote closed", session);
+ write_rst(args, &cur->tcp);
+ return 0;
+ }
+ queue_tcp(args, tcphdr, session, &cur->tcp, data, datalen);
+ }
+
+ if (tcphdr->rst /* +ACK */) {
+ // No sequence check
+ // http://tools.ietf.org/html/rfc1122#page-87
+ log_android(ANDROID_LOG_WARN, "%s received reset", session);
+ cur->tcp.state = TCP_CLOSING;
+ return 0;
+ } else {
+ if (!tcphdr->ack || ntohl(tcphdr->ack_seq) == cur->tcp.local_seq) {
+ if (tcphdr->syn) {
+ log_android(ANDROID_LOG_WARN, "%s repeated SYN", session);
+ // The socket is probably not opened yet
+
+ } else if (tcphdr->fin /* +ACK */) {
+ if (cur->tcp.state == TCP_ESTABLISHED) {
+ log_android(ANDROID_LOG_WARN, "%s FIN received", session);
+ if (cur->tcp.forward == NULL) {
+ cur->tcp.remote_seq++; // remote FIN
+ if (write_ack(args, &cur->tcp) >= 0)
+ cur->tcp.state = TCP_CLOSE_WAIT;
+ } else
+ cur->tcp.state = TCP_CLOSE_WAIT;
+ } else if (cur->tcp.state == TCP_CLOSE_WAIT) {
+ log_android(ANDROID_LOG_WARN, "%s repeated FIN", session);
+ // The socket is probably not closed yet
+ } else if (cur->tcp.state == TCP_FIN_WAIT1) {
+ log_android(ANDROID_LOG_WARN, "%s last ACK", session);
+ cur->tcp.remote_seq++; // remote FIN
+ if (write_ack(args, &cur->tcp) >= 0)
+ cur->tcp.state = TCP_CLOSE;
+ } else {
+ log_android(ANDROID_LOG_ERROR, "%s invalid FIN", session);
+ return 0;
+ }
+
+ } else if (tcphdr->ack) {
+ cur->tcp.acked = ntohl(tcphdr->ack_seq);
+
+ if (cur->tcp.state == TCP_SYN_RECV)
+ cur->tcp.state = TCP_ESTABLISHED;
+
+ else if (cur->tcp.state == TCP_ESTABLISHED) {
+ // Do nothing
+ } else if (cur->tcp.state == TCP_LAST_ACK)
+ cur->tcp.state = TCP_CLOSING;
+
+ else if (cur->tcp.state == TCP_CLOSE_WAIT) {
+ // ACK after FIN/ACK
+ } else if (cur->tcp.state == TCP_FIN_WAIT1) {
+ // Do nothing
+ } else {
+ log_android(ANDROID_LOG_ERROR, "%s invalid state", session);
+ return 0;
+ }
+ } else {
+ log_android(ANDROID_LOG_ERROR, "%s unknown packet", session);
+ return 0;
+ }
+ } else {
+ uint32_t ack = ntohl(tcphdr->ack_seq);
+ if ((uint32_t) (ack + 1) == cur->tcp.local_seq) {
+ // Keep alive
+ if (cur->tcp.state == TCP_ESTABLISHED) {
+ int on = 1;
+ if (setsockopt(cur->socket, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
+ log_android(ANDROID_LOG_ERROR,
+ "%s setsockopt SO_KEEPALIVE error %d: %s",
+ session, errno, strerror(errno));
+ else
+ log_android(ANDROID_LOG_WARN, "%s enabled keep alive", session);
+ } else
+ log_android(ANDROID_LOG_WARN, "%s keep alive", session);
+
+ } else if (compare_u32(ack, cur->tcp.local_seq) < 0) {
+ if (compare_u32(ack, cur->tcp.acked) <= 0)
+ log_android(
+ ack == cur->tcp.acked ? ANDROID_LOG_WARN : ANDROID_LOG_ERROR,
+ "%s repeated ACK %u/%u",
+ session,
+ ack - cur->tcp.local_start,
+ cur->tcp.acked - cur->tcp.local_start);
+ else {
+ log_android(ANDROID_LOG_WARN, "%s previous ACK %u",
+ session, ack - cur->tcp.local_seq);
+ cur->tcp.acked = ack;
+ }
+
+ return 1;
+ } else {
+ log_android(ANDROID_LOG_ERROR, "%s future ACK", session);
+ write_rst(args, &cur->tcp);
+ return 0;
+ }
+ }
+ }
+
+ if (cur->tcp.state != oldstate ||
+ cur->tcp.local_seq != oldlocal ||
+ cur->tcp.remote_seq != oldremote)
+ log_android(ANDROID_LOG_INFO, "%s > %s loc %u rem %u",
+ session,
+ strstate(cur->tcp.state),
+ cur->tcp.local_seq - cur->tcp.local_start,
+ cur->tcp.remote_seq - cur->tcp.remote_start);
+ }
+ }
+
+ return 1;
+}
+
+void queue_tcp(const struct arguments *args,
+ const struct tcphdr *tcphdr,
+ const char *session, struct tcp_session *cur,
+ const uint8_t *data, uint16_t datalen) {
+ uint32_t seq = ntohl(tcphdr->seq);
+ if (compare_u32(seq, cur->remote_seq) < 0)
+ log_android(ANDROID_LOG_WARN, "%s already forwarded %u..%u",
+ session,
+ seq - cur->remote_start, seq + datalen - cur->remote_start);
+ else {
+ struct segment *p = NULL;
+ struct segment *s = cur->forward;
+ while (s != NULL && compare_u32(s->seq, seq) < 0) {
+ p = s;
+ s = s->next;
+ }
+
+ if (s == NULL || compare_u32(s->seq, seq) > 0) {
+ log_android(ANDROID_LOG_DEBUG, "%s queuing %u...%u",
+ session,
+ seq - cur->remote_start, seq + datalen - cur->remote_start);
+ struct segment *n = ng_malloc(sizeof(struct segment), "tcp segment");
+ n->seq = seq;
+ n->len = datalen;
+ n->sent = 0;
+ n->psh = tcphdr->psh;
+ n->data = ng_malloc(datalen, "tcp segment");
+ memcpy(n->data, data, datalen);
+ n->next = s;
+ if (p == NULL)
+ cur->forward = n;
+ else
+ p->next = n;
+ } else if (s != NULL && s->seq == seq) {
+ if (s->len == datalen)
+ log_android(ANDROID_LOG_WARN, "%s segment already queued %u..%u",
+ session,
+ s->seq - cur->remote_start, s->seq + s->len - cur->remote_start);
+ else if (s->len < datalen) {
+ log_android(ANDROID_LOG_WARN, "%s segment smaller %u..%u > %u",
+ session,
+ s->seq - cur->remote_start, s->seq + s->len - cur->remote_start,
+ s->seq + datalen - cur->remote_start);
+ ng_free(s->data, __FILE__, __LINE__);
+ s->len = datalen;
+ s->data = ng_malloc(datalen, "tcp segment smaller");
+ memcpy(s->data, data, datalen);
+ } else {
+ log_android(ANDROID_LOG_ERROR, "%s segment larger %u..%u < %u",
+ session,
+ s->seq - cur->remote_start, s->seq + s->len - cur->remote_start,
+ s->seq + datalen - cur->remote_start);
+ ng_free(s->data, __FILE__, __LINE__);
+ s->len = datalen;
+ s->data = ng_malloc(datalen, "tcp segment larger");
+ memcpy(s->data, data, datalen);
+ }
+ }
+ }
+}
+
+int open_tcp_socket(const struct arguments *args,
+ const struct tcp_session *cur, const struct allowed *redirect) {
+ int sock;
+ int version;
+ if (redirect == NULL) {
+ if (*socks5_addr && socks5_port)
+ version = (strstr(socks5_addr, ":") == NULL ? 4 : 6);
+ else
+ version = cur->version;
+ } else
+ version = (strstr(redirect->raddr, ":") == NULL ? 4 : 6);
+
+ // Get TCP socket
+ if ((sock = socket(version == 4 ? PF_INET : PF_INET6, SOCK_STREAM, 0)) < 0) {
+ log_android(ANDROID_LOG_ERROR, "socket error %d: %s", errno, strerror(errno));
+ return -1;
+ }
+
+ // Protect
+ if (protect_socket(args, sock) < 0)
+ return -1;
+
+ int on = 1;
+ if (setsockopt(sock, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
+ log_android(ANDROID_LOG_ERROR, "setsockopt TCP_NODELAY error %d: %s",
+ errno, strerror(errno));
+
+ // Set non blocking
+ int flags = fcntl(sock, F_GETFL, 0);
+ if (flags < 0 || fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) {
+ log_android(ANDROID_LOG_ERROR, "fcntl socket O_NONBLOCK error %d: %s",
+ errno, strerror(errno));
+ return -1;
+ }
+
+ // Build target address
+ struct sockaddr_in addr4;
+ struct sockaddr_in6 addr6;
+ if (redirect == NULL) {
+ if (*socks5_addr && socks5_port) {
+ log_android(ANDROID_LOG_WARN, "TCP%d SOCKS5 to %s/%u",
+ version, socks5_addr, socks5_port);
+
+ if (version == 4) {
+ addr4.sin_family = AF_INET;
+ inet_pton(AF_INET, socks5_addr, &addr4.sin_addr);
+ addr4.sin_port = htons(socks5_port);
+ } else {
+ addr6.sin6_family = AF_INET6;
+ inet_pton(AF_INET6, socks5_addr, &addr6.sin6_addr);
+ addr6.sin6_port = htons(socks5_port);
+ }
+ } else {
+ if (version == 4) {
+ addr4.sin_family = AF_INET;
+ addr4.sin_addr.s_addr = (__be32) cur->daddr.ip4;
+ addr4.sin_port = cur->dest;
+ } else {
+ addr6.sin6_family = AF_INET6;
+ memcpy(&addr6.sin6_addr, &cur->daddr.ip6, 16);
+ addr6.sin6_port = cur->dest;
+ }
+ }
+ } else {
+ log_android(ANDROID_LOG_WARN, "TCP%d redirect to %s/%u",
+ version, redirect->raddr, redirect->rport);
+
+ if (version == 4) {
+ addr4.sin_family = AF_INET;
+ inet_pton(AF_INET, redirect->raddr, &addr4.sin_addr);
+ addr4.sin_port = htons(redirect->rport);
+ } else {
+ addr6.sin6_family = AF_INET6;
+ inet_pton(AF_INET6, redirect->raddr, &addr6.sin6_addr);
+ addr6.sin6_port = htons(redirect->rport);
+ }
+ }
+
+ // Initiate connect
+ int err = connect(sock,
+ (version == 4 ? (const struct sockaddr *) &addr4
+ : (const struct sockaddr *) &addr6),
+ (socklen_t) (version == 4
+ ? sizeof(struct sockaddr_in)
+ : sizeof(struct sockaddr_in6)));
+ if (err < 0 && errno != EINPROGRESS) {
+ log_android(ANDROID_LOG_ERROR, "connect error %d: %s", errno, strerror(errno));
+ return -1;
+ }
+
+ return sock;
+}
+
+int write_syn_ack(const struct arguments *args, struct tcp_session *cur) {
+ if (write_tcp(args, cur, NULL, 0, 1, 1, 0, 0) < 0) {
+ cur->state = TCP_CLOSING;
+ return -1;
+ }
+ return 0;
+}
+
+int write_ack(const struct arguments *args, struct tcp_session *cur) {
+ if (write_tcp(args, cur, NULL, 0, 0, 1, 0, 0) < 0) {
+ cur->state = TCP_CLOSING;
+ return -1;
+ }
+ return 0;
+}
+
+int write_data(const struct arguments *args, struct tcp_session *cur,
+ const uint8_t *buffer, size_t length) {
+ if (write_tcp(args, cur, buffer, length, 0, 1, 0, 0) < 0) {
+ cur->state = TCP_CLOSING;
+ return -1;
+ }
+ return 0;
+}
+
+int write_fin_ack(const struct arguments *args, struct tcp_session *cur) {
+ if (write_tcp(args, cur, NULL, 0, 0, 1, 1, 0) < 0) {
+ cur->state = TCP_CLOSING;
+ return -1;
+ }
+ return 0;
+}
+
+void write_rst(const struct arguments *args, struct tcp_session *cur) {
+ // https://www.snellman.net/blog/archive/2016-02-01-tcp-rst/
+ int ack = 0;
+ if (cur->state == TCP_LISTEN) {
+ ack = 1;
+ cur->remote_seq++; // SYN
+ }
+ write_tcp(args, cur, NULL, 0, 0, ack, 0, 1);
+ if (cur->state != TCP_CLOSE)
+ cur->state = TCP_CLOSING;
+}
+
+ssize_t write_tcp(const struct arguments *args, const struct tcp_session *cur,
+ const uint8_t *data, size_t datalen,
+ int syn, int ack, int fin, int rst) {
+ size_t len;
+ u_int8_t *buffer;
+ struct tcphdr *tcp;
+ uint16_t csum;
+ char source[INET6_ADDRSTRLEN + 1];
+ char dest[INET6_ADDRSTRLEN + 1];
+
+ // Build packet
+ int optlen = (syn ? 4 + 3 + 1 : 0);
+ uint8_t *options;
+ if (cur->version == 4) {
+ len = sizeof(struct iphdr) + sizeof(struct tcphdr) + optlen + datalen;
+ buffer = ng_malloc(len, "tcp write4");
+ struct iphdr *ip4 = (struct iphdr *) buffer;
+ tcp = (struct tcphdr *) (buffer + sizeof(struct iphdr));
+ options = buffer + sizeof(struct iphdr) + sizeof(struct tcphdr);
+ if (datalen)
+ memcpy(buffer + sizeof(struct iphdr) + sizeof(struct tcphdr) + optlen, data, datalen);
+
+ // Build IP4 header
+ memset(ip4, 0, sizeof(struct iphdr));
+ ip4->version = 4;
+ ip4->ihl = sizeof(struct iphdr) >> 2;
+ ip4->tot_len = htons(len);
+ ip4->ttl = IPDEFTTL;
+ ip4->protocol = IPPROTO_TCP;
+ ip4->saddr = cur->daddr.ip4;
+ ip4->daddr = cur->saddr.ip4;
+
+ // Calculate IP4 checksum
+ ip4->check = ~calc_checksum(0, (uint8_t *) ip4, sizeof(struct iphdr));
+
+ // Calculate TCP4 checksum
+ struct ippseudo pseudo;
+ memset(&pseudo, 0, sizeof(struct ippseudo));
+ pseudo.ippseudo_src.s_addr = (__be32) ip4->saddr;
+ pseudo.ippseudo_dst.s_addr = (__be32) ip4->daddr;
+ pseudo.ippseudo_p = ip4->protocol;
+ pseudo.ippseudo_len = htons(sizeof(struct tcphdr) + optlen + datalen);
+
+ csum = calc_checksum(0, (uint8_t *) &pseudo, sizeof(struct ippseudo));
+ } else {
+ len = sizeof(struct ip6_hdr) + sizeof(struct tcphdr) + optlen + datalen;
+ buffer = ng_malloc(len, "tcp write 6");
+ struct ip6_hdr *ip6 = (struct ip6_hdr *) buffer;
+ tcp = (struct tcphdr *) (buffer + sizeof(struct ip6_hdr));
+ options = buffer + sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
+ if (datalen)
+ memcpy(buffer + sizeof(struct ip6_hdr) + sizeof(struct tcphdr) + optlen, data, datalen);
+
+ // Build IP6 header
+ memset(ip6, 0, sizeof(struct ip6_hdr));
+ ip6->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(len - sizeof(struct ip6_hdr));
+ ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_TCP;
+ ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim = IPDEFTTL;
+ ip6->ip6_ctlun.ip6_un2_vfc = 0x60;
+ memcpy(&(ip6->ip6_src), &cur->daddr.ip6, 16);
+ memcpy(&(ip6->ip6_dst), &cur->saddr.ip6, 16);
+
+ // Calculate TCP6 checksum
+ struct ip6_hdr_pseudo pseudo;
+ memset(&pseudo, 0, sizeof(struct ip6_hdr_pseudo));
+ memcpy(&pseudo.ip6ph_src, &ip6->ip6_dst, 16);
+ memcpy(&pseudo.ip6ph_dst, &ip6->ip6_src, 16);
+ pseudo.ip6ph_len = ip6->ip6_ctlun.ip6_un1.ip6_un1_plen;
+ pseudo.ip6ph_nxt = ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
+
+ csum = calc_checksum(0, (uint8_t *) &pseudo, sizeof(struct ip6_hdr_pseudo));
+ }
+
+
+ // Build TCP header
+ memset(tcp, 0, sizeof(struct tcphdr));
+ tcp->source = cur->dest;
+ tcp->dest = cur->source;
+ tcp->seq = htonl(cur->local_seq);
+ tcp->ack_seq = htonl((uint32_t) (cur->remote_seq));
+ tcp->doff = (__u16) ((sizeof(struct tcphdr) + optlen) >> 2);
+ tcp->syn = (__u16) syn;
+ tcp->ack = (__u16) ack;
+ tcp->fin = (__u16) fin;
+ tcp->rst = (__u16) rst;
+ tcp->window = htons(cur->recv_window >> cur->recv_scale);
+
+ if (!tcp->ack)
+ tcp->ack_seq = 0;
+
+ // TCP options
+ if (syn) {
+ *(options) = 2; // MSS
+ *(options + 1) = 4; // total option length
+ *((uint16_t *) (options + 2)) = get_default_mss(cur->version);
+
+ *(options + 4) = 3; // window scale
+ *(options + 5) = 3; // total option length
+ *(options + 6) = cur->recv_scale;
+
+ *(options + 7) = 0; // End, padding
+ }
+
+ // Continue checksum
+ csum = calc_checksum(csum, (uint8_t *) tcp, sizeof(struct tcphdr));
+ csum = calc_checksum(csum, options, (size_t) optlen);
+ csum = calc_checksum(csum, data, datalen);
+ tcp->check = ~csum;
+
+ inet_ntop(cur->version == 4 ? AF_INET : AF_INET6,
+ cur->version == 4 ? (const void *) &cur->saddr.ip4 : (const void *) &cur->saddr.ip6,
+ source, sizeof(source));
+ inet_ntop(cur->version == 4 ? AF_INET : AF_INET6,
+ cur->version == 4 ? (const void *) &cur->daddr.ip4 : (const void *) &cur->daddr.ip6,
+ dest, sizeof(dest));
+
+ // Send packet
+ log_android(ANDROID_LOG_DEBUG,
+ "TCP sending%s%s%s%s to tun %s/%u seq %u ack %u data %u",
+ (tcp->syn ? " SYN" : ""),
+ (tcp->ack ? " ACK" : ""),
+ (tcp->fin ? " FIN" : ""),
+ (tcp->rst ? " RST" : ""),
+ dest, ntohs(tcp->dest),
+ ntohl(tcp->seq) - cur->local_start,
+ ntohl(tcp->ack_seq) - cur->remote_start,
+ datalen);
+
+ ssize_t res = write(args->tun, buffer, len);
+
+ // Write pcap record
+ if (res >= 0) {
+ if (pcap_file != NULL)
+ write_pcap_rec(buffer, (size_t) res);
+ } else
+ log_android(ANDROID_LOG_ERROR, "TCP write%s%s%s%s data %d error %d: %s",
+ (tcp->syn ? " SYN" : ""),
+ (tcp->ack ? " ACK" : ""),
+ (tcp->fin ? " FIN" : ""),
+ (tcp->rst ? " RST" : ""),
+ datalen,
+ errno, strerror((errno)));
+
+ ng_free(buffer, __FILE__, __LINE__);
+
+ if (res != len) {
+ log_android(ANDROID_LOG_ERROR, "TCP write %d/%d", res, len);
+ return -1;
+ }
+
+ return res;
+}
diff --git a/NetGuard/app/src/main/jni/netguard/udp.c b/NetGuard/app/src/main/jni/netguard/udp.c
new file mode 100644
index 0000000..b070c0d
--- /dev/null
+++ b/NetGuard/app/src/main/jni/netguard/udp.c
@@ -0,0 +1,549 @@
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+#include "netguard.h"
+
+extern FILE *pcap_file;
+
+int get_udp_timeout(const struct udp_session *u, int sessions, int maxsessions) {
+ int timeout = (ntohs(u->dest) == 53 ? UDP_TIMEOUT_53 : UDP_TIMEOUT_ANY);
+
+ int scale = 100 - sessions * 100 / maxsessions;
+ timeout = timeout * scale / 100;
+
+ return timeout;
+}
+
+int check_udp_session(const struct arguments *args, struct ng_session *s,
+ int sessions, int maxsessions) {
+ time_t now = time(NULL);
+
+ char source[INET6_ADDRSTRLEN + 1];
+ char dest[INET6_ADDRSTRLEN + 1];
+ if (s->udp.version == 4) {
+ inet_ntop(AF_INET, &s->udp.saddr.ip4, source, sizeof(source));
+ inet_ntop(AF_INET, &s->udp.daddr.ip4, dest, sizeof(dest));
+ } else {
+ inet_ntop(AF_INET6, &s->udp.saddr.ip6, source, sizeof(source));
+ inet_ntop(AF_INET6, &s->udp.daddr.ip6, dest, sizeof(dest));
+ }
+
+ // Check session timeout
+ int timeout = get_udp_timeout(&s->udp, sessions, maxsessions);
+ if (s->udp.state == UDP_ACTIVE && s->udp.time + timeout < now) {
+ log_android(ANDROID_LOG_WARN, "UDP idle %d/%d sec state %d from %s/%u to %s/%u",
+ now - s->udp.time, timeout, s->udp.state,
+ source, ntohs(s->udp.source), dest, ntohs(s->udp.dest));
+ s->udp.state = UDP_FINISHING;
+ }
+
+ // Check finished sessions
+ if (s->udp.state == UDP_FINISHING) {
+ log_android(ANDROID_LOG_INFO, "UDP close from %s/%u to %s/%u socket %d",
+ source, ntohs(s->udp.source), dest, ntohs(s->udp.dest), s->socket);
+
+ if (close(s->socket))
+ log_android(ANDROID_LOG_ERROR, "UDP close %d error %d: %s",
+ s->socket, errno, strerror(errno));
+ s->socket = -1;
+
+ s->udp.time = time(NULL);
+ s->udp.state = UDP_CLOSED;
+ }
+
+ if (s->udp.state == UDP_CLOSED && (s->udp.sent || s->udp.received)) {
+ account_usage(args, s->udp.version, IPPROTO_UDP,
+ dest, ntohs(s->udp.dest), s->udp.uid, s->udp.sent, s->udp.received);
+ s->udp.sent = 0;
+ s->udp.received = 0;
+ }
+
+ // Cleanup lingering sessions
+ if ((s->udp.state == UDP_CLOSED || s->udp.state == UDP_BLOCKED) &&
+ s->udp.time + UDP_KEEP_TIMEOUT < now)
+ return 1;
+
+ return 0;
+}
+
+void check_udp_socket(const struct arguments *args, const struct epoll_event *ev) {
+ struct ng_session *s = (struct ng_session *) ev->data.ptr;
+
+ // Check socket error
+ if (ev->events & EPOLLERR) {
+ s->udp.time = time(NULL);
+
+ int serr = 0;
+ socklen_t optlen = sizeof(int);
+ int err = getsockopt(s->socket, SOL_SOCKET, SO_ERROR, &serr, &optlen);
+ if (err < 0)
+ log_android(ANDROID_LOG_ERROR, "UDP getsockopt error %d: %s",
+ errno, strerror(errno));
+ else if (serr)
+ log_android(ANDROID_LOG_ERROR, "UDP SO_ERROR %d: %s", serr, strerror(serr));
+
+ s->udp.state = UDP_FINISHING;
+ } else {
+ // Check socket read
+ if (ev->events & EPOLLIN) {
+ s->udp.time = time(NULL);
+
+ uint8_t *buffer = ng_malloc(s->udp.mss, "udp recv");
+ ssize_t bytes = recv(s->socket, buffer, s->udp.mss, 0);
+ if (bytes < 0) {
+ // Socket error
+ log_android(ANDROID_LOG_WARN, "UDP recv error %d: %s",
+ errno, strerror(errno));
+
+ if (errno != EINTR && errno != EAGAIN)
+ s->udp.state = UDP_FINISHING;
+ } else if (bytes == 0) {
+ log_android(ANDROID_LOG_WARN, "UDP recv eof");
+ s->udp.state = UDP_FINISHING;
+
+ } else {
+ // Socket read data
+ char dest[INET6_ADDRSTRLEN + 1];
+ if (s->udp.version == 4)
+ inet_ntop(AF_INET, &s->udp.daddr.ip4, dest, sizeof(dest));
+ else
+ inet_ntop(AF_INET6, &s->udp.daddr.ip6, dest, sizeof(dest));
+ log_android(ANDROID_LOG_INFO, "UDP recv bytes %d from %s/%u for tun",
+ bytes, dest, ntohs(s->udp.dest));
+
+ s->udp.received += bytes;
+
+ // Process DNS response
+ if (ntohs(s->udp.dest) == 53)
+ parse_dns_response(args, s, buffer, (size_t *) &bytes);
+
+ // Forward to tun
+ if (write_udp(args, &s->udp, buffer, (size_t) bytes) < 0)
+ s->udp.state = UDP_FINISHING;
+ else {
+ // Prevent too many open files
+ if (ntohs(s->udp.dest) == 53)
+ s->udp.state = UDP_FINISHING;
+ }
+ }
+ ng_free(buffer, __FILE__, __LINE__);
+ }
+ }
+}
+
+int has_udp_session(const struct arguments *args, const uint8_t *pkt, const uint8_t *payload) {
+ // Get headers
+ const uint8_t version = (*pkt) >> 4;
+ const struct iphdr *ip4 = (struct iphdr *) pkt;
+ const struct ip6_hdr *ip6 = (struct ip6_hdr *) pkt;
+ const struct udphdr *udphdr = (struct udphdr *) payload;
+
+ if (ntohs(udphdr->dest) == 53 && !args->fwd53)
+ return 1;
+
+ // Search session
+ struct ng_session *cur = args->ctx->ng_session;
+ while (cur != NULL &&
+ !(cur->protocol == IPPROTO_UDP &&
+ cur->udp.version == version &&
+ cur->udp.source == udphdr->source && cur->udp.dest == udphdr->dest &&
+ (version == 4 ? cur->udp.saddr.ip4 == ip4->saddr &&
+ cur->udp.daddr.ip4 == ip4->daddr
+ : memcmp(&cur->udp.saddr.ip6, &ip6->ip6_src, 16) == 0 &&
+ memcmp(&cur->udp.daddr.ip6, &ip6->ip6_dst, 16) == 0)))
+ cur = cur->next;
+
+ return (cur != NULL);
+}
+
+void block_udp(const struct arguments *args,
+ const uint8_t *pkt, size_t length,
+ const uint8_t *payload,
+ int uid) {
+ // Get headers
+ const uint8_t version = (*pkt) >> 4;
+ const struct iphdr *ip4 = (struct iphdr *) pkt;
+ const struct ip6_hdr *ip6 = (struct ip6_hdr *) pkt;
+ const struct udphdr *udphdr = (struct udphdr *) payload;
+
+ char source[INET6_ADDRSTRLEN + 1];
+ char dest[INET6_ADDRSTRLEN + 1];
+ if (version == 4) {
+ inet_ntop(AF_INET, &ip4->saddr, source, sizeof(source));
+ inet_ntop(AF_INET, &ip4->daddr, dest, sizeof(dest));
+ } else {
+ inet_ntop(AF_INET6, &ip6->ip6_src, source, sizeof(source));
+ inet_ntop(AF_INET6, &ip6->ip6_dst, dest, sizeof(dest));
+ }
+
+ log_android(ANDROID_LOG_INFO, "UDP blocked session from %s/%u to %s/%u",
+ source, ntohs(udphdr->source), dest, ntohs(udphdr->dest));
+
+ // Register session
+ struct ng_session *s = ng_malloc(sizeof(struct ng_session), "udp session block");
+ s->protocol = IPPROTO_UDP;
+
+ s->udp.time = time(NULL);
+ s->udp.uid = uid;
+ s->udp.version = version;
+
+ if (version == 4) {
+ s->udp.saddr.ip4 = (__be32) ip4->saddr;
+ s->udp.daddr.ip4 = (__be32) ip4->daddr;
+ } else {
+ memcpy(&s->udp.saddr.ip6, &ip6->ip6_src, 16);
+ memcpy(&s->udp.daddr.ip6, &ip6->ip6_dst, 16);
+ }
+
+ s->udp.source = udphdr->source;
+ s->udp.dest = udphdr->dest;
+ s->udp.state = UDP_BLOCKED;
+ s->socket = -1;
+
+ s->next = args->ctx->ng_session;
+ args->ctx->ng_session = s;
+}
+
+jboolean handle_udp(const struct arguments *args,
+ const uint8_t *pkt, size_t length,
+ const uint8_t *payload,
+ int uid, struct allowed *redirect,
+ const int epoll_fd) {
+ // Get headers
+ const uint8_t version = (*pkt) >> 4;
+ const struct iphdr *ip4 = (struct iphdr *) pkt;
+ const struct ip6_hdr *ip6 = (struct ip6_hdr *) pkt;
+ const struct udphdr *udphdr = (struct udphdr *) payload;
+ const uint8_t *data = payload + sizeof(struct udphdr);
+ const size_t datalen = length - (data - pkt);
+
+ // Search session
+ struct ng_session *cur = args->ctx->ng_session;
+ while (cur != NULL &&
+ !(cur->protocol == IPPROTO_UDP &&
+ cur->udp.version == version &&
+ cur->udp.source == udphdr->source && cur->udp.dest == udphdr->dest &&
+ (version == 4 ? cur->udp.saddr.ip4 == ip4->saddr &&
+ cur->udp.daddr.ip4 == ip4->daddr
+ : memcmp(&cur->udp.saddr.ip6, &ip6->ip6_src, 16) == 0 &&
+ memcmp(&cur->udp.daddr.ip6, &ip6->ip6_dst, 16) == 0)))
+ cur = cur->next;
+
+ char source[INET6_ADDRSTRLEN + 1];
+ char dest[INET6_ADDRSTRLEN + 1];
+ if (version == 4) {
+ inet_ntop(AF_INET, &ip4->saddr, source, sizeof(source));
+ inet_ntop(AF_INET, &ip4->daddr, dest, sizeof(dest));
+ } else {
+ inet_ntop(AF_INET6, &ip6->ip6_src, source, sizeof(source));
+ inet_ntop(AF_INET6, &ip6->ip6_dst, dest, sizeof(dest));
+ }
+
+ if (cur != NULL && cur->udp.state != UDP_ACTIVE) {
+ log_android(ANDROID_LOG_INFO, "UDP ignore session from %s/%u to %s/%u state %d",
+ source, ntohs(udphdr->source), dest, ntohs(udphdr->dest), cur->udp.state);
+ return 0;
+ }
+
+ // Create new session if needed
+ if (cur == NULL) {
+ log_android(ANDROID_LOG_INFO, "UDP new session from %s/%u to %s/%u",
+ source, ntohs(udphdr->source), dest, ntohs(udphdr->dest));
+
+ // Register session
+ struct ng_session *s = ng_malloc(sizeof(struct ng_session), "udp session");
+ s->protocol = IPPROTO_UDP;
+
+ s->udp.time = time(NULL);
+ s->udp.uid = uid;
+ s->udp.version = version;
+
+ int rversion;
+ if (redirect == NULL)
+ rversion = s->udp.version;
+ else
+ rversion = (strstr(redirect->raddr, ":") == NULL ? 4 : 6);
+ s->udp.mss = (uint16_t) (rversion == 4 ? UDP4_MAXMSG : UDP6_MAXMSG);
+
+ s->udp.sent = 0;
+ s->udp.received = 0;
+
+ if (version == 4) {
+ s->udp.saddr.ip4 = (__be32) ip4->saddr;
+ s->udp.daddr.ip4 = (__be32) ip4->daddr;
+ } else {
+ memcpy(&s->udp.saddr.ip6, &ip6->ip6_src, 16);
+ memcpy(&s->udp.daddr.ip6, &ip6->ip6_dst, 16);
+ }
+
+ s->udp.source = udphdr->source;
+ s->udp.dest = udphdr->dest;
+ s->udp.state = UDP_ACTIVE;
+ s->next = NULL;
+
+ // Open UDP socket
+ s->socket = open_udp_socket(args, &s->udp, redirect);
+ if (s->socket < 0) {
+ ng_free(s, __FILE__, __LINE__);
+ return 0;
+ }
+
+ log_android(ANDROID_LOG_DEBUG, "UDP socket %d", s->socket);
+
+ // Monitor events
+ memset(&s->ev, 0, sizeof(struct epoll_event));
+ s->ev.events = EPOLLIN | EPOLLERR;
+ s->ev.data.ptr = s;
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, s->socket, &s->ev))
+ log_android(ANDROID_LOG_ERROR, "epoll add udp error %d: %s", errno, strerror(errno));
+
+ s->next = args->ctx->ng_session;
+ args->ctx->ng_session = s;
+
+ cur = s;
+ }
+
+ // Check for DHCP (tethering)
+ if (ntohs(udphdr->source) == 68 || ntohs(udphdr->dest) == 67) {
+ if (check_dhcp(args, &cur->udp, data, datalen) >= 0)
+ return 1;
+ }
+
+ log_android(ANDROID_LOG_INFO, "UDP forward from tun %s/%u to %s/%u data %d",
+ source, ntohs(udphdr->source), dest, ntohs(udphdr->dest), datalen);
+
+ cur->udp.time = time(NULL);
+
+ int rversion;
+ struct sockaddr_in addr4;
+ struct sockaddr_in6 addr6;
+ if (redirect == NULL) {
+ rversion = cur->udp.version;
+ if (cur->udp.version == 4) {
+ addr4.sin_family = AF_INET;
+ addr4.sin_addr.s_addr = (__be32) cur->udp.daddr.ip4;
+ addr4.sin_port = cur->udp.dest;
+ } else {
+ addr6.sin6_family = AF_INET6;
+ memcpy(&addr6.sin6_addr, &cur->udp.daddr.ip6, 16);
+ addr6.sin6_port = cur->udp.dest;
+ }
+ } else {
+ rversion = (strstr(redirect->raddr, ":") == NULL ? 4 : 6);
+ log_android(ANDROID_LOG_WARN, "UDP%d redirect to %s/%u",
+ rversion, redirect->raddr, redirect->rport);
+
+ if (rversion == 4) {
+ addr4.sin_family = AF_INET;
+ inet_pton(AF_INET, redirect->raddr, &addr4.sin_addr);
+ addr4.sin_port = htons(redirect->rport);
+ } else {
+ addr6.sin6_family = AF_INET6;
+ inet_pton(AF_INET6, redirect->raddr, &addr6.sin6_addr);
+ addr6.sin6_port = htons(redirect->rport);
+ }
+ }
+
+ if (sendto(cur->socket, data, (socklen_t) datalen, MSG_NOSIGNAL,
+ (rversion == 4 ? (const struct sockaddr *) &addr4
+ : (const struct sockaddr *) &addr6),
+ (socklen_t) (rversion == 4 ? sizeof(addr4) : sizeof(addr6))) != datalen) {
+ log_android(ANDROID_LOG_ERROR, "UDP sendto error %d: %s", errno, strerror(errno));
+ if (errno != EINTR && errno != EAGAIN) {
+ cur->udp.state = UDP_FINISHING;
+ return 0;
+ }
+ } else
+ cur->udp.sent += datalen;
+
+ return 1;
+}
+
+int open_udp_socket(const struct arguments *args,
+ const struct udp_session *cur, const struct allowed *redirect) {
+ int sock;
+ int version;
+ if (redirect == NULL)
+ version = cur->version;
+ else
+ version = (strstr(redirect->raddr, ":") == NULL ? 4 : 6);
+
+ // Get UDP socket
+ sock = socket(version == 4 ? PF_INET : PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock < 0) {
+ log_android(ANDROID_LOG_ERROR, "UDP socket error %d: %s", errno, strerror(errno));
+ return -1;
+ }
+
+ // Protect socket
+ if (protect_socket(args, sock) < 0)
+ return -1;
+
+ // Check for broadcast/multicast
+ if (cur->version == 4) {
+ uint32_t broadcast4 = INADDR_BROADCAST;
+ if (memcmp(&cur->daddr.ip4, &broadcast4, sizeof(broadcast4)) == 0) {
+ log_android(ANDROID_LOG_WARN, "UDP4 broadcast");
+ int on = 1;
+ if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)))
+ log_android(ANDROID_LOG_ERROR, "UDP setsockopt SO_BROADCAST error %d: %s",
+ errno, strerror(errno));
+ }
+ } else {
+ // http://man7.org/linux/man-pages/man7/ipv6.7.html
+ if (*((uint8_t *) &cur->daddr.ip6) == 0xFF) {
+ log_android(ANDROID_LOG_WARN, "UDP6 broadcast");
+
+ int loop = 1; // true
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof(loop)))
+ log_android(ANDROID_LOG_ERROR,
+ "UDP setsockopt IPV6_MULTICAST_LOOP error %d: %s",
+ errno, strerror(errno));
+
+ int ttl = -1; // route default
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)))
+ log_android(ANDROID_LOG_ERROR,
+ "UDP setsockopt IPV6_MULTICAST_HOPS error %d: %s",
+ errno, strerror(errno));
+
+ struct ipv6_mreq mreq6;
+ memcpy(&mreq6.ipv6mr_multiaddr, &cur->daddr.ip6, sizeof(struct in6_addr));
+ mreq6.ipv6mr_interface = INADDR_ANY;
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6)))
+ log_android(ANDROID_LOG_ERROR,
+ "UDP setsockopt IPV6_ADD_MEMBERSHIP error %d: %s",
+ errno, strerror(errno));
+ }
+ }
+
+ return sock;
+}
+
+ssize_t write_udp(const struct arguments *args, const struct udp_session *cur,
+ uint8_t *data, size_t datalen) {
+ size_t len;
+ u_int8_t *buffer;
+ struct udphdr *udp;
+ uint16_t csum;
+ char source[INET6_ADDRSTRLEN + 1];
+ char dest[INET6_ADDRSTRLEN + 1];
+
+ // Build packet
+ if (cur->version == 4) {
+ len = sizeof(struct iphdr) + sizeof(struct udphdr) + datalen;
+ buffer = ng_malloc(len, "udp write4");
+ struct iphdr *ip4 = (struct iphdr *) buffer;
+ udp = (struct udphdr *) (buffer + sizeof(struct iphdr));
+ if (datalen)
+ memcpy(buffer + sizeof(struct iphdr) + sizeof(struct udphdr), data, datalen);
+
+ // Build IP4 header
+ memset(ip4, 0, sizeof(struct iphdr));
+ ip4->version = 4;
+ ip4->ihl = sizeof(struct iphdr) >> 2;
+ ip4->tot_len = htons(len);
+ ip4->ttl = IPDEFTTL;
+ ip4->protocol = IPPROTO_UDP;
+ ip4->saddr = cur->daddr.ip4;
+ ip4->daddr = cur->saddr.ip4;
+
+ // Calculate IP4 checksum
+ ip4->check = ~calc_checksum(0, (uint8_t *) ip4, sizeof(struct iphdr));
+
+ // Calculate UDP4 checksum
+ struct ippseudo pseudo;
+ memset(&pseudo, 0, sizeof(struct ippseudo));
+ pseudo.ippseudo_src.s_addr = (__be32) ip4->saddr;
+ pseudo.ippseudo_dst.s_addr = (__be32) ip4->daddr;
+ pseudo.ippseudo_p = ip4->protocol;
+ pseudo.ippseudo_len = htons(sizeof(struct udphdr) + datalen);
+
+ csum = calc_checksum(0, (uint8_t *) &pseudo, sizeof(struct ippseudo));
+ } else {
+ len = sizeof(struct ip6_hdr) + sizeof(struct udphdr) + datalen;
+ buffer = ng_malloc(len, "udp write6");
+ struct ip6_hdr *ip6 = (struct ip6_hdr *) buffer;
+ udp = (struct udphdr *) (buffer + sizeof(struct ip6_hdr));
+ if (datalen)
+ memcpy(buffer + sizeof(struct ip6_hdr) + sizeof(struct udphdr), data, datalen);
+
+ // Build IP6 header
+ memset(ip6, 0, sizeof(struct ip6_hdr));
+ ip6->ip6_ctlun.ip6_un1.ip6_un1_flow = 0;
+ ip6->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(len - sizeof(struct ip6_hdr));
+ ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_UDP;
+ ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim = IPDEFTTL;
+ ip6->ip6_ctlun.ip6_un2_vfc = IPV6_VERSION;
+ memcpy(&(ip6->ip6_src), &cur->daddr.ip6, 16);
+ memcpy(&(ip6->ip6_dst), &cur->saddr.ip6, 16);
+
+ // Calculate UDP6 checksum
+ struct ip6_hdr_pseudo pseudo;
+ memset(&pseudo, 0, sizeof(struct ip6_hdr_pseudo));
+ memcpy(&pseudo.ip6ph_src, &ip6->ip6_dst, 16);
+ memcpy(&pseudo.ip6ph_dst, &ip6->ip6_src, 16);
+ pseudo.ip6ph_len = ip6->ip6_ctlun.ip6_un1.ip6_un1_plen;
+ pseudo.ip6ph_nxt = ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
+
+ csum = calc_checksum(0, (uint8_t *) &pseudo, sizeof(struct ip6_hdr_pseudo));
+ }
+
+ // Build UDP header
+ memset(udp, 0, sizeof(struct udphdr));
+ udp->source = cur->dest;
+ udp->dest = cur->source;
+ udp->len = htons(sizeof(struct udphdr) + datalen);
+
+ // Continue checksum
+ csum = calc_checksum(csum, (uint8_t *) udp, sizeof(struct udphdr));
+ csum = calc_checksum(csum, data, datalen);
+ udp->check = ~csum;
+
+ inet_ntop(cur->version == 4 ? AF_INET : AF_INET6,
+ (cur->version == 4 ? (const void *) &cur->saddr.ip4 : (const void *) &cur->saddr.ip6),
+ source,
+ sizeof(source));
+ inet_ntop(cur->version == 4 ? AF_INET : AF_INET6,
+ (cur->version == 4 ? (const void *) &cur->daddr.ip4 : (const void *) &cur->daddr.ip6),
+ dest,
+ sizeof(dest));
+
+ // Send packet
+ log_android(ANDROID_LOG_DEBUG,
+ "UDP sending to tun %d from %s/%u to %s/%u data %u",
+ args->tun, dest, ntohs(cur->dest), source, ntohs(cur->source), len);
+
+ ssize_t res = write(args->tun, buffer, len);
+
+ // Write PCAP record
+ if (res >= 0) {
+ if (pcap_file != NULL)
+ write_pcap_rec(buffer, (size_t) res);
+ } else
+ log_android(ANDROID_LOG_WARN, "UDP write error %d: %s", errno, strerror(errno));
+
+ ng_free(buffer, __FILE__, __LINE__);
+
+ if (res != len) {
+ log_android(ANDROID_LOG_ERROR, "write %d/%d", res, len);
+ return -1;
+ }
+
+ return res;
+}
diff --git a/NetGuard/app/src/main/jni/netguard/util.c b/NetGuard/app/src/main/jni/netguard/util.c
new file mode 100644
index 0000000..c81bdfe
--- /dev/null
+++ b/NetGuard/app/src/main/jni/netguard/util.c
@@ -0,0 +1,182 @@
+/*
+ This file is part of NetGuard.
+
+ NetGuard 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.
+
+ NetGuard 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 NetGuard. If not, see .
+
+ Copyright 2015-2019 by Marcel Bokhorst (M66B)
+*/
+
+#include "netguard.h"
+
+extern int loglevel;
+
+uint16_t calc_checksum(uint16_t start, const uint8_t *buffer, size_t length) {
+ register uint32_t sum = start;
+ register uint16_t *buf = (uint16_t *) buffer;
+ register size_t len = length;
+
+ while (len > 1) {
+ sum += *buf++;
+ len -= 2;
+ }
+
+ if (len > 0)
+ sum += *((uint8_t *) buf);
+
+ while (sum >> 16)
+ sum = (sum & 0xFFFF) + (sum >> 16);
+
+ return (uint16_t) sum;
+}
+
+int compare_u32(uint32_t s1, uint32_t s2) {
+ // https://tools.ietf.org/html/rfc1982
+ if (s1 == s2)
+ return 0;
+
+ uint32_t i1 = s1;
+ uint32_t i2 = s2;
+ if ((i1 < i2 && i2 - i1 < 0x7FFFFFFF) ||
+ (i1 > i2 && i1 - i2 > 0x7FFFFFFF))
+ return -1;
+ else
+ return 1;
+}
+
+int sdk_int(JNIEnv *env) {
+ jclass clsVersion = jniFindClass(env, "android/os/Build$VERSION");
+ jfieldID fid = (*env)->GetStaticFieldID(env, clsVersion, "SDK_INT", "I");
+ return (*env)->GetStaticIntField(env, clsVersion, fid);
+}
+
+void log_android(int prio, const char *fmt, ...) {
+ if (prio >= loglevel) {
+ char line[1024];
+ va_list argptr;
+ va_start(argptr, fmt);
+ vsprintf(line, fmt, argptr);
+ __android_log_print(prio, TAG, "%s", line);
+ va_end(argptr);
+ }
+}
+
+uint8_t char2nible(const char c) {
+ if (c >= '0' && c <= '9') return (uint8_t) (c - '0');
+ if (c >= 'a' && c <= 'f') return (uint8_t) ((c - 'a') + 10);
+ if (c >= 'A' && c <= 'F') return (uint8_t) ((c - 'A') + 10);
+ return 255;
+}
+
+void hex2bytes(const char *hex, uint8_t *buffer) {
+ size_t len = strlen(hex);
+ for (int i = 0; i < len; i += 2)
+ buffer[i / 2] = (char2nible(hex[i]) << 4) | char2nible(hex[i + 1]);
+}
+
+char *trim(char *str) {
+ while (isspace(*str))
+ str++;
+ if (*str == 0)
+ return str;
+
+ char *end = str + strlen(str) - 1;
+ while (end > str && isspace(*end))
+ end--;
+ *(end + 1) = 0;
+ return str;
+}
+
+const char *strstate(const int state) {
+ switch (state) {
+ case TCP_ESTABLISHED:
+ return "ESTABLISHED";
+ case TCP_SYN_SENT:
+ return "SYN_SENT";
+ case TCP_SYN_RECV:
+ return "SYN_RECV";
+ case TCP_FIN_WAIT1:
+ return "FIN_WAIT1";
+ case TCP_FIN_WAIT2:
+ return "FIN_WAIT2";
+ case TCP_TIME_WAIT:
+ return "TIME_WAIT";
+ case TCP_CLOSE:
+ return "CLOSE";
+ case TCP_CLOSE_WAIT:
+ return "CLOSE_WAIT";
+ case TCP_LAST_ACK:
+ return "LAST_ACK";
+ case TCP_LISTEN:
+ return "LISTEN";
+ case TCP_CLOSING:
+ return "CLOSING";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+char *hex(const u_int8_t *data, const size_t len) {
+ char hex_str[] = "0123456789ABCDEF";
+
+ char *hexout;
+ hexout = (char *) ng_malloc(len * 3 + 1, "hex"); // TODO free
+
+ for (size_t i = 0; i < len; i++) {
+ hexout[i * 3 + 0] = hex_str[(data[i] >> 4) & 0x0F];
+ hexout[i * 3 + 1] = hex_str[(data[i]) & 0x0F];
+ hexout[i * 3 + 2] = ' ';
+ }
+ hexout[len * 3] = 0;
+
+ return hexout;
+}
+
+int32_t get_local_port(const int sock) {
+ struct sockaddr_in sin;
+ socklen_t len = sizeof(sin);
+ if (getsockname(sock, (struct sockaddr *) &sin, &len) < 0) {
+ log_android(ANDROID_LOG_ERROR, "getsockname error %d: %s", errno, strerror(errno));
+ return -1;
+ } else
+ return ntohs(sin.sin_port);
+}
+
+int is_event(int fd, short event) {
+ struct pollfd p;
+ p.fd = fd;
+ p.events = event;
+ p.revents = 0;
+ int r = poll(&p, 1, 0);
+ if (r < 0) {
+ log_android(ANDROID_LOG_ERROR, "poll readable error %d: %s", errno, strerror(errno));
+ return 0;
+ } else if (r == 0)
+ return 0;
+ else
+ return (p.revents & event);
+}
+
+int is_readable(int fd) {
+ return is_event(fd, POLLIN);
+}
+
+int is_writable(int fd) {
+ return is_event(fd, POLLOUT);
+}
+
+long long get_ms() {
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return ts.tv_sec * 1000LL + ts.tv_nsec / 1e6;
+}
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_add_circle_outline_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_add_circle_outline_white_24dp.png
new file mode 100644
index 0000000..67e53a6
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_add_circle_outline_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_attach_money_black_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_attach_money_black_24dp.png
new file mode 100644
index 0000000..ad0f76c
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_attach_money_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_attach_money_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_attach_money_white_24dp.png
new file mode 100644
index 0000000..ee833c6
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_attach_money_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_check_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_check_white_24dp.png
new file mode 100644
index 0000000..729f290
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_check_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_close_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_close_white_24dp.png
new file mode 100644
index 0000000..ceb1a1e
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_close_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_cloud_upload_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_cloud_upload_white_24dp.png
new file mode 100644
index 0000000..5e0b464
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_cloud_upload_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_delete_black_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_delete_black_24dp.png
new file mode 100644
index 0000000..dbbb602
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_delete_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_delete_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_delete_white_24dp.png
new file mode 100644
index 0000000..4a9f769
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_delete_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_equalizer_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_equalizer_white_24dp.png
new file mode 100644
index 0000000..aa343b5
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_equalizer_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_equalizer_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_equalizer_white_24dp_60.png
new file mode 100644
index 0000000..933a198
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_equalizer_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_error_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_error_white_24dp.png
new file mode 100644
index 0000000..69cbb1e
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_error_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_expand_less_black_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_expand_less_black_24dp.png
new file mode 100644
index 0000000..57139a7
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_expand_less_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_expand_less_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_expand_less_white_24dp.png
new file mode 100644
index 0000000..dea8988
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_expand_less_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_expand_more_black_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_expand_more_black_24dp.png
new file mode 100644
index 0000000..9625f14
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_expand_more_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_expand_more_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_expand_more_white_24dp.png
new file mode 100644
index 0000000..022e057
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_expand_more_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_file_download_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_file_download_white_24dp.png
new file mode 100644
index 0000000..c8a2039
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_file_download_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_filter_list_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_filter_list_white_24dp.png
new file mode 100644
index 0000000..7e8a6b5
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_filter_list_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_filter_list_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_filter_list_white_24dp_60.png
new file mode 100644
index 0000000..8c2d618
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_filter_list_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_hourglass_empty_black_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_hourglass_empty_black_24dp.png
new file mode 100644
index 0000000..22fe56d
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_hourglass_empty_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_hourglass_empty_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_hourglass_empty_white_24dp.png
new file mode 100644
index 0000000..5b8b684
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_hourglass_empty_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_launch_black_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_launch_black_24dp.png
new file mode 100644
index 0000000..4cfcf84
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_launch_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_launch_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_launch_white_24dp.png
new file mode 100644
index 0000000..49726bc
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_launch_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_lock_open_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_lock_open_white_24dp.png
new file mode 100644
index 0000000..6bae68f
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_lock_open_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_lock_outline_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_lock_outline_white_24dp.png
new file mode 100644
index 0000000..e53f541
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_lock_outline_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_lock_outline_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_lock_outline_white_24dp_60.png
new file mode 100644
index 0000000..0e8a7cf
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_lock_outline_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_pause_black_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_pause_black_24dp.png
new file mode 100644
index 0000000..3539b4e
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_pause_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_pause_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_pause_white_24dp.png
new file mode 100644
index 0000000..4d2ea05
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_pause_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_perm_data_setting_black_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_perm_data_setting_black_24dp.png
new file mode 100644
index 0000000..1643436
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_perm_data_setting_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_perm_data_setting_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_perm_data_setting_white_24dp.png
new file mode 100644
index 0000000..ba7e1fe
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_perm_data_setting_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_perm_identity_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_perm_identity_white_24dp.png
new file mode 100644
index 0000000..78d43f0
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_perm_identity_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_play_arrow_black_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_play_arrow_black_24dp.png
new file mode 100644
index 0000000..e9c288c
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_play_arrow_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png
new file mode 100644
index 0000000..57c9fa5
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_search_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_search_white_24dp.png
new file mode 100644
index 0000000..bbfbc96
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_search_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_security_color_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_security_color_24dp.png
new file mode 100644
index 0000000..73e31c1
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_security_color_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_security_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_security_white_24dp.png
new file mode 100644
index 0000000..262800a
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_security_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_security_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_security_white_24dp_60.png
new file mode 100644
index 0000000..d559fee
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_security_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_settings_black_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_settings_black_24dp.png
new file mode 100644
index 0000000..acf1ddf
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_settings_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_settings_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_settings_white_24dp.png
new file mode 100644
index 0000000..97ded33
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_settings_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_shopping_cart_black_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_shopping_cart_black_24dp.png
new file mode 100644
index 0000000..c2422ce
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_shopping_cart_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_shopping_cart_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_shopping_cart_white_24dp.png
new file mode 100644
index 0000000..a68ce43
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_shopping_cart_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_signal_cellular_4_bar_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_signal_cellular_4_bar_white_24dp.png
new file mode 100644
index 0000000..1765e94
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_signal_cellular_4_bar_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_signal_cellular_off_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_signal_cellular_off_white_24dp.png
new file mode 100644
index 0000000..12704b3
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_signal_cellular_off_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_signal_wifi_4_bar_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_signal_wifi_4_bar_white_24dp.png
new file mode 100644
index 0000000..5a53192
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_signal_wifi_4_bar_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_signal_wifi_off_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_signal_wifi_off_white_24dp.png
new file mode 100644
index 0000000..996d8a3
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_signal_wifi_off_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-hdpi/ic_sort_white_24dp.png b/NetGuard/app/src/main/res/drawable-hdpi/ic_sort_white_24dp.png
new file mode 100644
index 0000000..55a429b
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-hdpi/ic_sort_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_add_circle_outline_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_add_circle_outline_white_24dp.png
new file mode 100644
index 0000000..803fc97
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_add_circle_outline_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_attach_money_black_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_attach_money_black_24dp.png
new file mode 100644
index 0000000..2ae5e6d
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_attach_money_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_attach_money_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_attach_money_white_24dp.png
new file mode 100644
index 0000000..707d167
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_attach_money_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_check_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_check_white_24dp.png
new file mode 100644
index 0000000..dfcb55d
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_check_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_close_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_close_white_24dp.png
new file mode 100644
index 0000000..af7f828
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_close_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_cloud_upload_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_cloud_upload_white_24dp.png
new file mode 100644
index 0000000..aa64062
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_cloud_upload_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_delete_black_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_delete_black_24dp.png
new file mode 100644
index 0000000..999aa4c
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_delete_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_delete_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_delete_white_24dp.png
new file mode 100644
index 0000000..e2f5f35
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_delete_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_equalizer_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_equalizer_white_24dp.png
new file mode 100644
index 0000000..bc600d3
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_equalizer_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_equalizer_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_equalizer_white_24dp_60.png
new file mode 100644
index 0000000..90ef1df
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_equalizer_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_error_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_error_white_24dp.png
new file mode 100644
index 0000000..ca148fc
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_error_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_expand_less_black_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_expand_less_black_24dp.png
new file mode 100644
index 0000000..08c16a3
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_expand_less_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_expand_less_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_expand_less_white_24dp.png
new file mode 100644
index 0000000..a2e4baa
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_expand_less_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_expand_more_black_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_expand_more_black_24dp.png
new file mode 100644
index 0000000..feb85a7
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_expand_more_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_expand_more_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_expand_more_white_24dp.png
new file mode 100644
index 0000000..910bb2a
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_expand_more_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_file_download_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_file_download_white_24dp.png
new file mode 100644
index 0000000..d400472
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_file_download_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_filter_list_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_filter_list_white_24dp.png
new file mode 100644
index 0000000..59a2ec7
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_filter_list_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_filter_list_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_filter_list_white_24dp_60.png
new file mode 100644
index 0000000..7b75cca
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_filter_list_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_hourglass_empty_black_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_hourglass_empty_black_24dp.png
new file mode 100644
index 0000000..ce8b8b0
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_hourglass_empty_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_hourglass_empty_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_hourglass_empty_white_24dp.png
new file mode 100644
index 0000000..616df09
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_hourglass_empty_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_launch_black_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_launch_black_24dp.png
new file mode 100644
index 0000000..cc2892d
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_launch_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_launch_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_launch_white_24dp.png
new file mode 100644
index 0000000..474cc80
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_launch_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_lock_open_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_lock_open_white_24dp.png
new file mode 100644
index 0000000..3f47b54
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_lock_open_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_lock_outline_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_lock_outline_white_24dp.png
new file mode 100644
index 0000000..13f432f
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_lock_outline_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_lock_outline_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_lock_outline_white_24dp_60.png
new file mode 100644
index 0000000..19c3962
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_lock_outline_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_pause_black_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_pause_black_24dp.png
new file mode 100644
index 0000000..6145664
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_pause_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_pause_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_pause_white_24dp.png
new file mode 100644
index 0000000..2272d47
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_pause_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_perm_data_setting_black_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_perm_data_setting_black_24dp.png
new file mode 100644
index 0000000..6686406
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_perm_data_setting_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_perm_data_setting_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_perm_data_setting_white_24dp.png
new file mode 100644
index 0000000..b2249e0
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_perm_data_setting_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_perm_identity_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_perm_identity_white_24dp.png
new file mode 100644
index 0000000..f00e3f3
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_perm_identity_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_play_arrow_black_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_play_arrow_black_24dp.png
new file mode 100644
index 0000000..d78c57b
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_play_arrow_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_play_arrow_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_play_arrow_white_24dp.png
new file mode 100644
index 0000000..c61e948
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_play_arrow_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_search_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_search_white_24dp.png
new file mode 100644
index 0000000..faefc59
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_search_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_security_color_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_security_color_24dp.png
new file mode 100644
index 0000000..d023f2f
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_security_color_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_security_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_security_white_24dp.png
new file mode 100644
index 0000000..44ee734
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_security_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_security_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_security_white_24dp_60.png
new file mode 100644
index 0000000..93e76da
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_security_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_settings_black_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_settings_black_24dp.png
new file mode 100644
index 0000000..c59419c
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_settings_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_settings_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_settings_white_24dp.png
new file mode 100644
index 0000000..8909c35
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_settings_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_shopping_cart_black_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_shopping_cart_black_24dp.png
new file mode 100644
index 0000000..f56585b
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_shopping_cart_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_shopping_cart_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_shopping_cart_white_24dp.png
new file mode 100644
index 0000000..9d9fdbb
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_shopping_cart_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_signal_cellular_4_bar_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_signal_cellular_4_bar_white_24dp.png
new file mode 100644
index 0000000..8d76fd4
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_signal_cellular_4_bar_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_signal_cellular_off_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_signal_cellular_off_white_24dp.png
new file mode 100644
index 0000000..eaaa180
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_signal_cellular_off_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_signal_wifi_4_bar_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_signal_wifi_4_bar_white_24dp.png
new file mode 100644
index 0000000..dd5a42f
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_signal_wifi_4_bar_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_signal_wifi_off_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_signal_wifi_off_white_24dp.png
new file mode 100644
index 0000000..5295ecd
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_signal_wifi_off_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-mdpi/ic_sort_white_24dp.png b/NetGuard/app/src/main/res/drawable-mdpi/ic_sort_white_24dp.png
new file mode 100644
index 0000000..3d84a44
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-mdpi/ic_sort_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_add_circle_outline_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_add_circle_outline_white_24dp.png
new file mode 100644
index 0000000..ac94274
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_add_circle_outline_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_attach_money_black_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_attach_money_black_24dp.png
new file mode 100644
index 0000000..c94dc6a
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_attach_money_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_attach_money_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_attach_money_white_24dp.png
new file mode 100644
index 0000000..20efc6c
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_attach_money_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_check_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_check_white_24dp.png
new file mode 100644
index 0000000..3b2b65d
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_check_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_close_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_close_white_24dp.png
new file mode 100644
index 0000000..b7c7ffd
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_close_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_cloud_upload_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_cloud_upload_white_24dp.png
new file mode 100644
index 0000000..a9602d1
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_cloud_upload_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_delete_black_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_delete_black_24dp.png
new file mode 100644
index 0000000..796ccd2
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_delete_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_delete_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_delete_white_24dp.png
new file mode 100644
index 0000000..388b5b0
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_delete_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_equalizer_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_equalizer_white_24dp.png
new file mode 100644
index 0000000..40c572c
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_equalizer_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_equalizer_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_equalizer_white_24dp_60.png
new file mode 100644
index 0000000..1d849fc
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_equalizer_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_error_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_error_white_24dp.png
new file mode 100644
index 0000000..9829698
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_error_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_expand_less_black_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_expand_less_black_24dp.png
new file mode 100644
index 0000000..323360e
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_expand_less_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_expand_less_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_expand_less_white_24dp.png
new file mode 100644
index 0000000..ae36d91
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_expand_less_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_expand_more_black_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_expand_more_black_24dp.png
new file mode 100644
index 0000000..d3ee65e
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_expand_more_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_expand_more_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_expand_more_white_24dp.png
new file mode 100644
index 0000000..c42e2a0
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_expand_more_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_file_download_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_file_download_white_24dp.png
new file mode 100644
index 0000000..f53cc0c
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_file_download_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_filter_list_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_filter_list_white_24dp.png
new file mode 100644
index 0000000..9416c70
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_filter_list_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_filter_list_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_filter_list_white_24dp_60.png
new file mode 100644
index 0000000..f8c9122
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_filter_list_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_hourglass_empty_black_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_hourglass_empty_black_24dp.png
new file mode 100644
index 0000000..e63d9cd
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_hourglass_empty_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_hourglass_empty_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_hourglass_empty_white_24dp.png
new file mode 100644
index 0000000..35b7eef
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_hourglass_empty_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_launch_black_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_launch_black_24dp.png
new file mode 100644
index 0000000..4ebc46b
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_launch_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_launch_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_launch_white_24dp.png
new file mode 100644
index 0000000..a2caac5
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_launch_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_lock_open_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_lock_open_white_24dp.png
new file mode 100644
index 0000000..cbe9e1c
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_lock_open_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_lock_outline_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_lock_outline_white_24dp.png
new file mode 100644
index 0000000..e2d1091
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_lock_outline_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_lock_outline_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_lock_outline_white_24dp_60.png
new file mode 100644
index 0000000..0b61001
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_lock_outline_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_pause_black_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_pause_black_24dp.png
new file mode 100644
index 0000000..74068ea
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_pause_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_pause_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_pause_white_24dp.png
new file mode 100644
index 0000000..f49aed7
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_pause_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_perm_data_setting_black_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_perm_data_setting_black_24dp.png
new file mode 100644
index 0000000..a8a97f2
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_perm_data_setting_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_perm_data_setting_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_perm_data_setting_white_24dp.png
new file mode 100644
index 0000000..e444922
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_perm_data_setting_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_perm_identity_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_perm_identity_white_24dp.png
new file mode 100644
index 0000000..e344ea9
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_perm_identity_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_play_arrow_black_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_play_arrow_black_24dp.png
new file mode 100644
index 0000000..f208795
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_play_arrow_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png
new file mode 100644
index 0000000..a3c80e7
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_search_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_search_white_24dp.png
new file mode 100644
index 0000000..bfc3e39
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_search_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_security_color_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_security_color_24dp.png
new file mode 100644
index 0000000..6f25407
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_security_color_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_security_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_security_white_24dp.png
new file mode 100644
index 0000000..7e306c3
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_security_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_security_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_security_white_24dp_60.png
new file mode 100644
index 0000000..8ed175d
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_security_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_settings_black_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_settings_black_24dp.png
new file mode 100644
index 0000000..e84e188
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_settings_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_settings_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_settings_white_24dp.png
new file mode 100644
index 0000000..5caedc8
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_settings_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_shopping_cart_black_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_shopping_cart_black_24dp.png
new file mode 100644
index 0000000..3da6027
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_shopping_cart_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_shopping_cart_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_shopping_cart_white_24dp.png
new file mode 100644
index 0000000..16b6cd0
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_shopping_cart_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_signal_cellular_4_bar_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_signal_cellular_4_bar_white_24dp.png
new file mode 100644
index 0000000..62501b0
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_signal_cellular_4_bar_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_signal_cellular_off_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_signal_cellular_off_white_24dp.png
new file mode 100644
index 0000000..8ed814e
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_signal_cellular_off_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_signal_wifi_4_bar_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_signal_wifi_4_bar_white_24dp.png
new file mode 100644
index 0000000..28b5afa
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_signal_wifi_4_bar_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_signal_wifi_off_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_signal_wifi_off_white_24dp.png
new file mode 100644
index 0000000..480145c
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_signal_wifi_off_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xhdpi/ic_sort_white_24dp.png b/NetGuard/app/src/main/res/drawable-xhdpi/ic_sort_white_24dp.png
new file mode 100644
index 0000000..6d4af1b
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xhdpi/ic_sort_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_add_circle_outline_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_add_circle_outline_white_24dp.png
new file mode 100644
index 0000000..fdad9ba
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_add_circle_outline_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_attach_money_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_attach_money_black_24dp.png
new file mode 100644
index 0000000..a9478a6
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_attach_money_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_attach_money_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_attach_money_white_24dp.png
new file mode 100644
index 0000000..d4bde81
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_attach_money_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_check_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_check_white_24dp.png
new file mode 100644
index 0000000..2c2ad77
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_check_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_close_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_close_white_24dp.png
new file mode 100644
index 0000000..6b717e0
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_close_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_cloud_upload_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_cloud_upload_white_24dp.png
new file mode 100644
index 0000000..3ff57ad
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_cloud_upload_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_delete_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_delete_black_24dp.png
new file mode 100644
index 0000000..6d7cb81
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_delete_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_delete_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_delete_white_24dp.png
new file mode 100644
index 0000000..3fcdfdb
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_delete_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_equalizer_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_equalizer_white_24dp.png
new file mode 100644
index 0000000..d603c4f
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_equalizer_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_equalizer_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_equalizer_white_24dp_60.png
new file mode 100644
index 0000000..f23c2db
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_equalizer_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_error_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_error_white_24dp.png
new file mode 100644
index 0000000..abe2573
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_error_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_expand_less_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_expand_less_black_24dp.png
new file mode 100644
index 0000000..ee92f4e
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_expand_less_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_expand_less_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_expand_less_white_24dp.png
new file mode 100644
index 0000000..62fc386
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_expand_less_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_expand_more_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_expand_more_black_24dp.png
new file mode 100644
index 0000000..5cd142c
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_expand_more_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_expand_more_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_expand_more_white_24dp.png
new file mode 100644
index 0000000..dbc0b20
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_expand_more_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_file_download_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_file_download_white_24dp.png
new file mode 100644
index 0000000..78aa591
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_file_download_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_filter_list_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_filter_list_white_24dp.png
new file mode 100644
index 0000000..1263ae8
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_filter_list_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_filter_list_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_filter_list_white_24dp_60.png
new file mode 100644
index 0000000..cf26ba5
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_filter_list_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_hourglass_empty_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_hourglass_empty_black_24dp.png
new file mode 100644
index 0000000..47efe9d
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_hourglass_empty_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_hourglass_empty_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_hourglass_empty_white_24dp.png
new file mode 100644
index 0000000..8f67bc6
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_hourglass_empty_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_launch_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_launch_black_24dp.png
new file mode 100644
index 0000000..4305f56
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_launch_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_launch_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_launch_white_24dp.png
new file mode 100644
index 0000000..2ed5b0e
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_launch_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_lock_open_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_lock_open_white_24dp.png
new file mode 100644
index 0000000..1d1b0f4
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_lock_open_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_lock_outline_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_lock_outline_white_24dp.png
new file mode 100644
index 0000000..bd2cf4d
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_lock_outline_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_lock_outline_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_lock_outline_white_24dp_60.png
new file mode 100644
index 0000000..16e2fc3
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_lock_outline_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_pause_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_pause_black_24dp.png
new file mode 100644
index 0000000..bb707ea
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_pause_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_pause_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_pause_white_24dp.png
new file mode 100644
index 0000000..7192ad4
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_pause_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_perm_data_setting_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_perm_data_setting_black_24dp.png
new file mode 100644
index 0000000..d9e712d
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_perm_data_setting_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_perm_data_setting_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_perm_data_setting_white_24dp.png
new file mode 100644
index 0000000..60257de
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_perm_data_setting_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_perm_identity_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_perm_identity_white_24dp.png
new file mode 100644
index 0000000..b08402a
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_perm_identity_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_play_arrow_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_play_arrow_black_24dp.png
new file mode 100644
index 0000000..5345ee3
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_play_arrow_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png
new file mode 100644
index 0000000..547ef30
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_search_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_search_white_24dp.png
new file mode 100644
index 0000000..abbb989
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_search_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_security_color_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_security_color_24dp.png
new file mode 100644
index 0000000..c0950f3
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_security_color_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_security_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_security_white_24dp.png
new file mode 100644
index 0000000..7bcb2fd
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_security_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_security_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_security_white_24dp_60.png
new file mode 100644
index 0000000..e8f3b25
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_security_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.png
new file mode 100644
index 0000000..3023ff8
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png
new file mode 100644
index 0000000..eabb0a2
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_shopping_cart_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_shopping_cart_black_24dp.png
new file mode 100644
index 0000000..f9121f5
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_shopping_cart_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_shopping_cart_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_shopping_cart_white_24dp.png
new file mode 100644
index 0000000..bcfb493
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_shopping_cart_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_signal_cellular_4_bar_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_signal_cellular_4_bar_white_24dp.png
new file mode 100644
index 0000000..b191b9d
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_signal_cellular_4_bar_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_signal_cellular_off_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_signal_cellular_off_white_24dp.png
new file mode 100644
index 0000000..dedee39
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_signal_cellular_off_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_signal_wifi_4_bar_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_signal_wifi_4_bar_white_24dp.png
new file mode 100644
index 0000000..f4105ec
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_signal_wifi_4_bar_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_signal_wifi_off_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_signal_wifi_off_white_24dp.png
new file mode 100644
index 0000000..f2023bf
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_signal_wifi_off_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxhdpi/ic_sort_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_sort_white_24dp.png
new file mode 100644
index 0000000..b8ef105
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxhdpi/ic_sort_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_add_circle_outline_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_add_circle_outline_white_24dp.png
new file mode 100644
index 0000000..573aefe
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_add_circle_outline_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_attach_money_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_attach_money_black_24dp.png
new file mode 100644
index 0000000..49956bf
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_attach_money_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_attach_money_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_attach_money_white_24dp.png
new file mode 100644
index 0000000..f3c5685
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_attach_money_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_check_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_check_white_24dp.png
new file mode 100644
index 0000000..d670618
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_check_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_close_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_close_white_24dp.png
new file mode 100644
index 0000000..3964192
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_close_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_cloud_upload_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_cloud_upload_white_24dp.png
new file mode 100644
index 0000000..2180f73
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_cloud_upload_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_delete_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_delete_black_24dp.png
new file mode 100644
index 0000000..f2b75c3
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_delete_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_delete_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_delete_white_24dp.png
new file mode 100644
index 0000000..8d322aa
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_delete_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_equalizer_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_equalizer_white_24dp.png
new file mode 100644
index 0000000..fa8d522
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_equalizer_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_equalizer_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_equalizer_white_24dp_60.png
new file mode 100644
index 0000000..31cee03
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_equalizer_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_error_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_error_white_24dp.png
new file mode 100644
index 0000000..830fb7e
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_error_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_expand_less_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_expand_less_black_24dp.png
new file mode 100644
index 0000000..99c6e3e
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_expand_less_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_expand_less_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_expand_less_white_24dp.png
new file mode 100644
index 0000000..4261551
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_expand_less_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_expand_more_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_expand_more_black_24dp.png
new file mode 100644
index 0000000..ad852e3
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_expand_more_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_expand_more_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_expand_more_white_24dp.png
new file mode 100644
index 0000000..2859a6f
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_expand_more_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_file_download_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_file_download_white_24dp.png
new file mode 100644
index 0000000..ded5652
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_file_download_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_filter_list_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_filter_list_white_24dp.png
new file mode 100644
index 0000000..cb2207f
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_filter_list_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_filter_list_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_filter_list_white_24dp_60.png
new file mode 100644
index 0000000..e66a5d9
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_filter_list_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_hourglass_empty_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_hourglass_empty_black_24dp.png
new file mode 100644
index 0000000..74b4072
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_hourglass_empty_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_hourglass_empty_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_hourglass_empty_white_24dp.png
new file mode 100644
index 0000000..b0bda26
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_hourglass_empty_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_launch_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_launch_black_24dp.png
new file mode 100644
index 0000000..4eb7b16
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_launch_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_launch_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_launch_white_24dp.png
new file mode 100644
index 0000000..bab25f3
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_launch_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_lock_open_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_lock_open_white_24dp.png
new file mode 100644
index 0000000..8ab4107
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_lock_open_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_lock_outline_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_lock_outline_white_24dp.png
new file mode 100644
index 0000000..de1d564
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_lock_outline_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_lock_outline_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_lock_outline_white_24dp_60.png
new file mode 100644
index 0000000..9f3f1f7
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_lock_outline_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_pause_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_pause_black_24dp.png
new file mode 100644
index 0000000..792104f
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_pause_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_pause_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_pause_white_24dp.png
new file mode 100644
index 0000000..660ac65
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_pause_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_perm_data_setting_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_perm_data_setting_black_24dp.png
new file mode 100644
index 0000000..a451d53
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_perm_data_setting_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_perm_data_setting_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_perm_data_setting_white_24dp.png
new file mode 100644
index 0000000..1916017
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_perm_data_setting_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_perm_identity_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_perm_identity_white_24dp.png
new file mode 100644
index 0000000..9717ab4
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_perm_identity_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_play_arrow_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_play_arrow_black_24dp.png
new file mode 100644
index 0000000..d12d495
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_play_arrow_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_24dp.png
new file mode 100644
index 0000000..be5c062
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_search_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_search_white_24dp.png
new file mode 100644
index 0000000..dd5adfc
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_search_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_security_color_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_security_color_24dp.png
new file mode 100644
index 0000000..194e70a
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_security_color_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_security_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_security_white_24dp.png
new file mode 100644
index 0000000..b1eddbd
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_security_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_security_white_24dp_60.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_security_white_24dp_60.png
new file mode 100644
index 0000000..f226c1b
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_security_white_24dp_60.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.png
new file mode 100644
index 0000000..476d5c9
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_settings_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_settings_white_24dp.png
new file mode 100644
index 0000000..507c5ed
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_settings_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_shopping_cart_black_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_shopping_cart_black_24dp.png
new file mode 100644
index 0000000..6edc956
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_shopping_cart_black_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_shopping_cart_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_shopping_cart_white_24dp.png
new file mode 100644
index 0000000..8c3323e
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_shopping_cart_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_signal_cellular_4_bar_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_signal_cellular_4_bar_white_24dp.png
new file mode 100644
index 0000000..4a3ac28
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_signal_cellular_4_bar_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_signal_cellular_off_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_signal_cellular_off_white_24dp.png
new file mode 100644
index 0000000..b6adb4e
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_signal_cellular_off_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_signal_wifi_4_bar_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_signal_wifi_4_bar_white_24dp.png
new file mode 100644
index 0000000..58a4f9c
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_signal_wifi_4_bar_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_signal_wifi_off_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_signal_wifi_off_white_24dp.png
new file mode 100644
index 0000000..6df209e
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_signal_wifi_off_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_sort_white_24dp.png b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_sort_white_24dp.png
new file mode 100644
index 0000000..4796c33
Binary files /dev/null and b/NetGuard/app/src/main/res/drawable-xxxhdpi/ic_sort_white_24dp.png differ
diff --git a/NetGuard/app/src/main/res/drawable/baseline_file_copy_24.xml b/NetGuard/app/src/main/res/drawable/baseline_file_copy_24.xml
new file mode 100644
index 0000000..f52fd86
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/baseline_file_copy_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/NetGuard/app/src/main/res/drawable/expander_black.xml b/NetGuard/app/src/main/res/drawable/expander_black.xml
new file mode 100644
index 0000000..c9b36b1
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/expander_black.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/expander_white.xml b/NetGuard/app/src/main/res/drawable/expander_white.xml
new file mode 100644
index 0000000..7a2a352
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/expander_white.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/host_allowed.xml b/NetGuard/app/src/main/res/drawable/host_allowed.xml
new file mode 100644
index 0000000..5ecc890
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/host_allowed.xml
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/host_blocked.xml b/NetGuard/app/src/main/res/drawable/host_blocked.xml
new file mode 100644
index 0000000..7ed46a8
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/host_blocked.xml
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/lockdown.xml b/NetGuard/app/src/main/res/drawable/lockdown.xml
new file mode 100644
index 0000000..bcb8f1a
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/lockdown.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/drawable/lockdown_disabled.xml b/NetGuard/app/src/main/res/drawable/lockdown_disabled.xml
new file mode 100644
index 0000000..3c12ace
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/lockdown_disabled.xml
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/lockdown_off.xml b/NetGuard/app/src/main/res/drawable/lockdown_off.xml
new file mode 100644
index 0000000..b411d82
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/lockdown_off.xml
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/lockdown_on.xml b/NetGuard/app/src/main/res/drawable/lockdown_on.xml
new file mode 100644
index 0000000..dca4c4d
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/lockdown_on.xml
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/other.xml b/NetGuard/app/src/main/res/drawable/other.xml
new file mode 100644
index 0000000..8ddba52
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/other.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/other_off.xml b/NetGuard/app/src/main/res/drawable/other_off.xml
new file mode 100644
index 0000000..e3bf1ed
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/other_off.xml
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/other_off_disabled.xml b/NetGuard/app/src/main/res/drawable/other_off_disabled.xml
new file mode 100644
index 0000000..6e1f626
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/other_off_disabled.xml
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/other_on.xml b/NetGuard/app/src/main/res/drawable/other_on.xml
new file mode 100644
index 0000000..1ee225f
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/other_on.xml
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/other_on_disabled.xml b/NetGuard/app/src/main/res/drawable/other_on_disabled.xml
new file mode 100644
index 0000000..3ea13c9
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/other_on_disabled.xml
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/screen.xml b/NetGuard/app/src/main/res/drawable/screen.xml
new file mode 100644
index 0000000..43e91df
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/screen.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/screen_on.xml b/NetGuard/app/src/main/res/drawable/screen_on.xml
new file mode 100644
index 0000000..5abceeb
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/screen_on.xml
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/screen_on_disabled.xml b/NetGuard/app/src/main/res/drawable/screen_on_disabled.xml
new file mode 100644
index 0000000..dec83be
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/screen_on_disabled.xml
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/wifi.xml b/NetGuard/app/src/main/res/drawable/wifi.xml
new file mode 100644
index 0000000..f042007
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/wifi.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/wifi_off.xml b/NetGuard/app/src/main/res/drawable/wifi_off.xml
new file mode 100644
index 0000000..27ffd67
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/wifi_off.xml
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/wifi_off_disabled.xml b/NetGuard/app/src/main/res/drawable/wifi_off_disabled.xml
new file mode 100644
index 0000000..f006648
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/wifi_off_disabled.xml
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/wifi_on.xml b/NetGuard/app/src/main/res/drawable/wifi_on.xml
new file mode 100644
index 0000000..8653752
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/wifi_on.xml
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/drawable/wifi_on_disabled.xml b/NetGuard/app/src/main/res/drawable/wifi_on_disabled.xml
new file mode 100644
index 0000000..d20f995
--- /dev/null
+++ b/NetGuard/app/src/main/res/drawable/wifi_on_disabled.xml
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/layout/about.xml b/NetGuard/app/src/main/res/layout/about.xml
new file mode 100644
index 0000000..34ca746
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/about.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/layout/access.xml b/NetGuard/app/src/main/res/layout/access.xml
new file mode 100644
index 0000000..c71cc24
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/access.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/layout/actionlog.xml b/NetGuard/app/src/main/res/layout/actionlog.xml
new file mode 100644
index 0000000..95340ba
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/actionlog.xml
@@ -0,0 +1,15 @@
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/layout/actionmain.xml b/NetGuard/app/src/main/res/layout/actionmain.xml
new file mode 100644
index 0000000..c174dc4
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/actionmain.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/layout/android.xml b/NetGuard/app/src/main/res/layout/android.xml
new file mode 100644
index 0000000..951ecc7
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/android.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/layout/challenge.xml b/NetGuard/app/src/main/res/layout/challenge.xml
new file mode 100644
index 0000000..adce740
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/challenge.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/layout/datasaving.xml b/NetGuard/app/src/main/res/layout/datasaving.xml
new file mode 100644
index 0000000..d8af2b9
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/datasaving.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/layout/dns.xml b/NetGuard/app/src/main/res/layout/dns.xml
new file mode 100644
index 0000000..643cfa3
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/dns.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/layout/doze.xml b/NetGuard/app/src/main/res/layout/doze.xml
new file mode 100644
index 0000000..caaccca
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/doze.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/layout/enable.xml b/NetGuard/app/src/main/res/layout/enable.xml
new file mode 100644
index 0000000..9d2d2c1
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/enable.xml
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/layout/filter.xml b/NetGuard/app/src/main/res/layout/filter.xml
new file mode 100644
index 0000000..b952430
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/filter.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/layout/first.xml b/NetGuard/app/src/main/res/layout/first.xml
new file mode 100644
index 0000000..92bd049
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/first.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/layout/forward.xml b/NetGuard/app/src/main/res/layout/forward.xml
new file mode 100644
index 0000000..76bf63e
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/forward.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/layout/forwardadd.xml b/NetGuard/app/src/main/res/layout/forwardadd.xml
new file mode 100644
index 0000000..263a894
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/forwardadd.xml
@@ -0,0 +1,143 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/layout/forwardapproval.xml b/NetGuard/app/src/main/res/layout/forwardapproval.xml
new file mode 100644
index 0000000..3094c8f
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/forwardapproval.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/layout/forwarding.xml b/NetGuard/app/src/main/res/layout/forwarding.xml
new file mode 100644
index 0000000..bf287d7
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/forwarding.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/layout/legend.xml b/NetGuard/app/src/main/res/layout/legend.xml
new file mode 100644
index 0000000..334ffec
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/legend.xml
@@ -0,0 +1,374 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/layout/log.xml b/NetGuard/app/src/main/res/layout/log.xml
new file mode 100644
index 0000000..366111b
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/log.xml
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/layout/logging.xml b/NetGuard/app/src/main/res/layout/logging.xml
new file mode 100644
index 0000000..bab9f6d
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/logging.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/layout/main.xml b/NetGuard/app/src/main/res/layout/main.xml
new file mode 100644
index 0000000..c968037
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/main.xml
@@ -0,0 +1,226 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/layout/pro.xml b/NetGuard/app/src/main/res/layout/pro.xml
new file mode 100644
index 0000000..ccb1736
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/pro.xml
@@ -0,0 +1,427 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/layout/resolving.xml b/NetGuard/app/src/main/res/layout/resolving.xml
new file mode 100644
index 0000000..109a4ae
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/resolving.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/layout/rule.xml b/NetGuard/app/src/main/res/layout/rule.xml
new file mode 100644
index 0000000..d9ae125
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/rule.xml
@@ -0,0 +1,488 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/layout/sure.xml b/NetGuard/app/src/main/res/layout/sure.xml
new file mode 100644
index 0000000..c1e9b6f
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/sure.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/layout/traffic.xml b/NetGuard/app/src/main/res/layout/traffic.xml
new file mode 100644
index 0000000..43c758c
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/traffic.xml
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/layout/vpn.xml b/NetGuard/app/src/main/res/layout/vpn.xml
new file mode 100644
index 0000000..7455b50
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/vpn.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/layout/widgetlockdown.xml b/NetGuard/app/src/main/res/layout/widgetlockdown.xml
new file mode 100644
index 0000000..9987edf
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/widgetlockdown.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/layout/widgetmain.xml b/NetGuard/app/src/main/res/layout/widgetmain.xml
new file mode 100644
index 0000000..9987edf
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/widgetmain.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/layout/xposed.xml b/NetGuard/app/src/main/res/layout/xposed.xml
new file mode 100644
index 0000000..5319fb3
--- /dev/null
+++ b/NetGuard/app/src/main/res/layout/xposed.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/menu/access.xml b/NetGuard/app/src/main/res/menu/access.xml
new file mode 100644
index 0000000..68aed2b
--- /dev/null
+++ b/NetGuard/app/src/main/res/menu/access.xml
@@ -0,0 +1,31 @@
+
+
+ -
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/menu/dns.xml b/NetGuard/app/src/main/res/menu/dns.xml
new file mode 100644
index 0000000..c97002a
--- /dev/null
+++ b/NetGuard/app/src/main/res/menu/dns.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/menu/forward.xml b/NetGuard/app/src/main/res/menu/forward.xml
new file mode 100644
index 0000000..1efc480
--- /dev/null
+++ b/NetGuard/app/src/main/res/menu/forward.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/menu/forwarding.xml b/NetGuard/app/src/main/res/menu/forwarding.xml
new file mode 100644
index 0000000..60606dd
--- /dev/null
+++ b/NetGuard/app/src/main/res/menu/forwarding.xml
@@ -0,0 +1,9 @@
+
+
+
+
diff --git a/NetGuard/app/src/main/res/menu/log.xml b/NetGuard/app/src/main/res/menu/log.xml
new file mode 100644
index 0000000..c9fefee
--- /dev/null
+++ b/NetGuard/app/src/main/res/menu/log.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/menu/logging.xml b/NetGuard/app/src/main/res/menu/logging.xml
new file mode 100644
index 0000000..a17bda4
--- /dev/null
+++ b/NetGuard/app/src/main/res/menu/logging.xml
@@ -0,0 +1,72 @@
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/menu/main.xml b/NetGuard/app/src/main/res/menu/main.xml
new file mode 100644
index 0000000..e9766c3
--- /dev/null
+++ b/NetGuard/app/src/main/res/menu/main.xml
@@ -0,0 +1,78 @@
+
+
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/menu/pro.xml b/NetGuard/app/src/main/res/menu/pro.xml
new file mode 100644
index 0000000..339c97f
--- /dev/null
+++ b/NetGuard/app/src/main/res/menu/pro.xml
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/NetGuard/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/NetGuard/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..c9ad5f9
--- /dev/null
+++ b/NetGuard/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/NetGuard/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..c9ad5f9
--- /dev/null
+++ b/NetGuard/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/mipmap-hdpi/ic_launcher.png b/NetGuard/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..73e31c1
Binary files /dev/null and b/NetGuard/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/NetGuard/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/NetGuard/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..e2c44a0
Binary files /dev/null and b/NetGuard/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/NetGuard/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/NetGuard/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..2647ef5
Binary files /dev/null and b/NetGuard/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/NetGuard/app/src/main/res/mipmap-mdpi/ic_launcher.png b/NetGuard/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..d023f2f
Binary files /dev/null and b/NetGuard/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/NetGuard/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/NetGuard/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..8f0d17d
Binary files /dev/null and b/NetGuard/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/NetGuard/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/NetGuard/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..cd01641
Binary files /dev/null and b/NetGuard/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/NetGuard/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/NetGuard/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..6f25407
Binary files /dev/null and b/NetGuard/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/NetGuard/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/NetGuard/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..22f4cf9
Binary files /dev/null and b/NetGuard/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/NetGuard/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/NetGuard/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..af87885
Binary files /dev/null and b/NetGuard/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/NetGuard/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/NetGuard/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..c0950f3
Binary files /dev/null and b/NetGuard/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/NetGuard/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/NetGuard/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..c5404cc
Binary files /dev/null and b/NetGuard/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/NetGuard/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/NetGuard/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..6b94c44
Binary files /dev/null and b/NetGuard/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/NetGuard/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/NetGuard/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..194e70a
Binary files /dev/null and b/NetGuard/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/NetGuard/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/NetGuard/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..1dcfd28
Binary files /dev/null and b/NetGuard/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/NetGuard/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/NetGuard/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..0980d40
Binary files /dev/null and b/NetGuard/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/NetGuard/app/src/main/res/values-af-rZA/strings.xml b/NetGuard/app/src/main/res/values-af-rZA/strings.xml
new file mode 100644
index 0000000..3ea04e7
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-af-rZA/strings.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/NetGuard/app/src/main/res/values-ar-rSA/strings.xml b/NetGuard/app/src/main/res/values-ar-rSA/strings.xml
new file mode 100644
index 0000000..5ab712f
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-ar-rSA/strings.xml
@@ -0,0 +1,288 @@
+
+
+ NetGuard يوفر طرق بسيطة ومتقدمة لمنع الوصول إلى شبكة الإنترنت - لا يلزم الجذر. يمكن السماح أو الرفض بشكل فردي للتطبيقات والعناوين النفاذ إلى الواي فاي أو الإتصال عبر الجوال.
+ NetGuard requires Android 5.1 or later
+ يسبب Xposed الكثير من الأعطال ، مما قد يؤدي إلى إزالة NetGuard من متجر Google Play ، لذلك لا يتم دعم NetGuard إن تم تثبيت Xposed
+ سياسة الخصوصية
+ تم تطوير وتجربة NetGuard بعناية فائقة ولكن من الممكن ألّا يعمل NetGuard بشكل جيد في بعض الاجهزة.
+ أنا أوافق
+ لا أوافق
+ NetGuard يحتاج لدعمكم. اضغط لشراء الخصائص المتقدمة ودعم استمرارية المشروع.
+ الخدمات قيد التشغيل
+ الإشعارات العامة
+ إشعارات النفاذ
+ البحث عن تطبيقات
+ تصفية التطبيقات
+ إظهار تطبيقات المستخدم
+ إظهار تطبيقات النظام
+ إظهار التطبيقات غير المتصلة بالإنترنت
+ إظهار التطبيقات المعطلة
+ تصنيف التطبيقات
+ فرز حسب الاسم
+ فرز حسب رمز المستخدم
+ فرز حسب استخدام البيانات
+ إظهار السجل
+ الإعدادات
+ دعوة
+ Legend
+ الدعم
+ عن التطبيق
+ تطبيقات أخرى
+ أخرى
+ مسموح
+ محظور
+ تحديثات حية
+ تحديث
+ إظهار الأسماء
+ إظهار المنظمة
+ تمكين PCAP
+ تصدير PCAP
+ محو
+ تصدير
+ إعادة تعيين
+ إضافة
+ حذف
+ تنظيف
+ البروتوكول
+ منفذ المصدر
+ عنوان الوجهة
+ منفذ الوجهة
+ تطبيق الوجهة
+ لخادم خارجي اختر \"لا أحد\"
+ الافتراضي (القائمة البيضاء/السوداء)
+ حظر الواي فاي
+ حظر شبكة الهاتف
+ السماح بشبكة Wi-Fi عندما تكون الشاشة نشطة
+ السماح لشبكة الهاتف عندما تكون الشاشة نشطة
+ حظر التجوال
+ الخيارات
+ المظهر: %1$s
+ استخدم المظهر الداكن
+ اخطار عند التثبيت الجديد
+ تطبيق القواعد \'عندما تكون الشاشة مفتوحة\'
+ تمكين تلقائي بعد %1$s دقيقة/دقائق
+ تأخير تعتيم الشاشة %1$s دقيقة/دقائق
+ فحص توفر التحديثات
+ خيارات الشبكة
+ توجيه الشبكة الفرعية
+ السماح بالربط ومشاركة الاتصال
+ السماح بالوصول إلى شبكة المنطقة المحلية
+ تمكين حركة مرور IPv6
+ شبكات الواي فاي المنزلية: %1$s
+ تعامل مع شبكات Wi-Fi المقاسة
+ إعتبر الجيل الثاني غير مقاس
+ إعتبر الجيل الثالث غير مقاس
+ إعتبر شبكات LTE غير مقاسة
+ تجاهل خدمة التجوال المحلية
+ تجاهل تجوال الاتحاد الأوروبي
+ تعطيل أثناء المكالمة
+ أقفل الواي فاي
+ اقفل شبكة الهاتف
+ إعادة التحميل عند كل تغيير في الاتصال
+ الخيارات المتقدمة
+ إدارة تطبيقات النظام
+ تسجيل النفاذ إلى الإنترنت
+ إخطار عند الوصول إلى الإنترنت
+ تصفية حركة البيانات
+ تصفية حركة البيانات UDP
+ تسليم VPN سلس عند إعادة التحميل
+ إغلاق الاتصالات عند التحديث
+ اقفل حركة مرور البيانات
+ متابعة استخدام الشبكة
+ إعادة تعيين استخدام الشبكة
+ عرض أسماء النطاقات التي تم حلها
+ حظر أسماء نطاقات
+ رمز استجابة نظام أسماء النطاقات: %s
+ توجيه المنفذ
+ الشبكة الافتراضية الخاصة IPv4: %s
+ الشبكة الإفتراضية الخاصة IPv6: %s
+ DNS للشبكة الافتراضية الخاصة: %s
+ تم التحقق منه في: %s
+ مدة الحياة الدنيا لـ DNS: %s ثا
+ استخدام وكيل SOCKS5
+ عنوان SOCKS5: %s
+ منفذ SOCKS5: %s
+ اسم المستخدم SOCKS5: %s
+ كلمة المرور SOCKS5: %s
+ سجل PCAP حجمه: %s ب
+ حجم ملف PCAP الأعلى: %s م ب
+ توقيت Watchdog: كل %s دقائق
+ اشعار السرعة
+ إظهار إشعار السرعة
+ إظهار التطبيقات الأعلى
+ الفاصل الزمني للعينة: %s مللي ثانية
+ عدد العينات: %s ثا
+ النسخ الاحتياطي
+ تصدير الإعدادات
+ استيراد الإعدادات
+ استيراد ملف hosts
+ استيراد ملف hosts (إلحاق)
+ رابط تنزيل ملف hosts
+ تنزيل ملف المضيفين hosts
+ المعلومات التقنية
+ الإعدادات العامة
+ الشبكات
+ الإشتراكات
+ إظهار إعلام في شريط المعلومات للتطبيقات المثبتة حديثا (ميزة برو)
+ بعد تعطيل NetGuard باستخدام الويدجت، فعل NetGuard تلقائيا مرة أخرى بعد عدد محدد من الدقائق (ادخل صفر لتعطيل هذا الخيار)
+ بعد إغلاق الشاشة، إبقاء الشاشة على القواعد نشطة لعدد محدد من الدقائق (ادخل صفر لتعطيل هذا الخيار)
+ التحقق من وجود إصدارات جديدة في GitHub مرتين يوميا
+ وفقا لاصدار الأندرويد، ربط الانترنت قد يعمل وقد لا يعمل، الانترنت المربوط(المشارك) لا يمكن تصفيتة.
+ يُمكّن توجيه الشبكة الفرعية؛ و قد يُمكّن اتصال Wi-Fi ، ولكن قد يؤدي أيضًا إلى ظهور أخطاء في Android وزيادة استخدام البطارية
+ السماح للتطبيقات بالاتصال بعناوين شبكة الاتصال المحلية ، مثل 10.0.0.0/8، 172.16.0.0/12 و 192.168.0.0/16
+ توجيه حركة مرور IP الإصدار 6 إلى NetGuard حيث يمكن بشكل انتقائي السماح بها أو المنع
+ تطبيق قواعد الشبكة اللاسلكية للشبكة المحددة فقط (تطبيق قواعد شبكة الجوال لباقي الشبكات اللاسلكية)
+ تطبيق قواعد شبكة الهاتف النقال للشبكات اللاسلكية المقاسة (مدفوعة الأجر، المربوطة)
+ تطبيق قواعد الشبكة اللاسلكية لاتصالات شبكات 2G
+ تطبيق قواعد الشبكة اللاسلكية لاتصالات شبكات 3G
+ تطبيق قواعد الشبكة اللاسلكية لاتصالات شبكات LTE
+ لا تطبق قواعد التجوال عندما تكون الشريحة ودولة شبكـة المحمول هي نفسها
+ لا تـفعل الـتـجـوال عـنـدمـا تـكـون الشريحة من نفس دولة شـبـكـة الـمـحـمـول
+ تعطيل NetGuard على المكالمات الهاتفية الواردة أو الصادرة. يمكن استخدام هذا حل مشاكل الاتصال حول IP/Wi-Fi.
+ تحديد القواعد لتطبيقات النظام (للخبراء)
+ تسجل محاولات وصول التطبيقات إلى الإنترنت. قد ينتج عن هذا استخدام إضافي للبطارية.
+ إظهار إعلام شريط المعلومات عندما يحاول تطبيق الوصول إلى عنوان إنترنت جديد (عند التصفية معطل، إلا محاولات الوصول إلى الإنترنت المحظورة فسيتم الإخطار)
+ تصفية حزم IP الخارجة من نفق VPN. قد ينتج عن هذا استخدام إضافي للبطارية.
+ تتبع عدد وحدات البايت المرسلة والمتلقاة لكل تطبيق وعنوان. قد ينتج عن هذا استخدام إضافي للبطارية.
+ الاستجابة ب \'اسم خاطئ\' (NXDOMAIN) لأسماء النطاقات المحظورة. يعطل هذا الخيار عند عدم وجود ملف المضيفين.
+ الـقيمة الافتراضية هي 3 (NXDOMAIN)، وهذا يعني \'أنّ اسم النطاق غير موجود\'.
+ اسم النطاق المستخدم للتحقق من صحة اتصال الإنترنت عن طريق منفذ 443 (https).
+ يـــتـــم إرســال حــركـــة مـــرور TCP فـــقـــط إلـــى الـــمـــلـــقـــم الـــوكــيـــل
+ الــفـــحـــص الــدوري إذا كــان قـــيـــد تـــشـــغـــيـــل NetGuard (فــأدخـــل صـــفـــر لـــتـــعـــطـــيـــل هـــذا الــخـــيـــار). قـــد يـــســـتـــلـــزم هـــذا إســـتـــخـــدام أكـــثـــر لـلـــبـــطــاريـــة.
+ إظهار الرسم البياني لسرعة الشبكة على شريط حالة الإشعارات
+ هل أنت متأكد؟
+ فرض الـقـواعد
+ %1$d مسموح، %2$d محظور
+ %1$d مسموحة ، %2$d محظورة ، %3$d مضيفين
+ في انتظار حدث
+ التطبيق غير مُفعّل، قم بتنشيط نات غارد بالضغط على الزر في الأعلى
+ تم تعطيل NetGuard، يُحتمل أنّ السبب راجع إلى استخدام تطبيق VPN آخر في آن واحد
+ \'%1$s\' مثبت
+ تم تثبيته
+ لقد حاول %1$s الوصول إلى الإنترنت
+ حاوَلَ الوصول إلى الإنترنت
+ اكتمل الإجراء
+ يستخدم NetGuard شبكة VPN محلية لتصفية حركة الانترنت. لهذا، يرجى السماح لاتصال VPN في مربع الحوار القادم. حركة الانترنت الخاصة بك لا يتم ارسالها الى خادم VPN بعيد.
+ لا يمكن بدء NetGuard بشكل تلقائي عند التشغيل بسبب وجود خلل في إصدار الاندرويد الخاص بك
+ حدث خطأ غير متوقع: \'%s\'
+ أنـــدرويـــت رفـــض أن تـــبـــدأ خـــدمـــة VPN فـــي هـــذه اللـــحـــظـــة. مـــن الـــمـــحـــتـــمـــل بـــســـبـــب عـــطـــل فـــي نـــســـخـــة أنـــدرويــت الـــخـــاص بـــك.
+ جـرّب NetGuard
+ عند تبرعك فهذا يعني انك مواقق على الشروط والاحكام. احكام & شروط
+ إن لم تستطع الضغط على زر الموافقة في مربع الحوار القادم فهذا معناه أنه يوجد برنامج آخر يتحكم في الشاشة.
+ ± %1$.3f▲ %2$.3f▼ ميغابيت/يوم
+ %1$7.3f▲ %2$7.3f▼ كيلو بايت
+ %1$7.3f▲ %2$7.3f▼ ميجا بايت
+ %1$7.3f▲ %2$7.3f▼ جيجابايت
+ %dس
+ للحصول على نتائج متناسقة، يجب تعطيل تحسينات البطارية للاندرويد لـ NetGuard. عن طريق \n\n ، حدد \"جميع التطبيقات\" في الجزء العلوي، انقر على NetGuard في القائمة وتحديد وتأكيد \"تعطيل تحسينات البطارية\".
+ للحصول على نتائج متسقة، يجب تعطيل البيانات الروبوت توفير خيارات ل NetGuard \n\nIn مربع الحوار التالي، تمكين خيارات \"بيانات أساسية\" و \"استخدام البيانات غير المقيد\"
+ استخدام التصفية سيتسبب بأن ينسب الأندرويد استخدام البيانات والطاقة الى NetGuard - يفترض الأندرويد أن البيانات والطاقة تستخدمان من قبل NetGuard بدلاً من التطبيقات الأصلية
+ أنـــدرويـــد 4 يـــتـــطـــلــَّــب إجــراء تـــصـــفـــيـــة لـلـتـــمـــكـــيـــن
+ تسجيل الحركة معطل، استخدم رمز التبديل أعلاه لتمكين التسجيل. قد يؤدي تسجيل الحركة الى استخدام إضافي للبطارية.
+ هذا سوف يعيد تعيين القواعد والشروط إلى قيمها الافتراضية
+ هذا سيؤدي إلى حذف خطوط سجل محاولة الوصول دون قواعد السماح/الحظر
+ آخر استيراد: %s
+ جارٍ تنزيل\n%1s
+ تم تنزيل ملف المضيفين
+ آخر تنزيل: %s
+ ابدأ إعادة التوجيه من %1$s منفذ %2$d الى %3$s:%4$d من %5$s؟
+ إيقاف إعادة توجيه %1$s منفذ %2$d؟
+ الشبكة مقاسة
+ لا يوجد اتصال إنترنت نشط
+ NetGuard مشغول
+ هناك تحديث متوفر، اضغط لتنزيله
+ يــمــكــنــك الــســمــاح (مــخــضــر) أو الــرفــض (الــمــحــمــر) واي فاي أو دخــول شــبــكــة الــمــحــمــول بــواســطــة الـــضـــغـــط عــلــى الــرمــوز الــمــوجــودة بــجــانــب الــتــطــبــيــق
+ إذا قمت بتثبيت NetGuard لحماية خصوصيتك، فقد تكون مهتمًا بFairEmail ، تطبيق بريد إلكتروني مفتوح المصدر ومناسب للخصوصية أيضًا
+ الدخول للإنترنت مسموح بشكل إفتراضي، وهذا يمكن تغييرة في الإعدادات
+ معظم الرسائل يتم معالجتها بواسطة خدمات النظام المتاحة، وهي التى مسموحة بدخول الإنترنت بشكل إفتراضي
+ يمكنك تمكين إدارة تطبيقات النظام في الخيارات المتقدمة
+ الرجاء أوصف المشكلة وبيّن وقت المشكلة
+ لــقــد ألـغــي الإتــصــال عــن طــريــق n/ VPN هــل تــريــد تــكــويــن VPN آخــر حــتــى تــكــون عـلـى إتــصــال دائــم عــن طــريــق VPN ؟
+ إيقاف جهازك مع تشغيل NetGuard، سؤدي لعمل NetGuard تلقائياً عند تشغيل الجهاز
+ هذه الوظيفة غير متوفرة في هذا الاصدار
+ يتم تعيين VPN آخر دوماً على VPN
+ اوقف \"حجب الاتصلات التي لا تستخدم VPN\" في اعدادات VPN الخاص باندرويد لتتمكن من استخدام NetGuard في وضع التصفية
+ اوقف \"DNS شخصي\" في اعدادات الشبكة الخاصة باندرويد لتتمكن من استخدام NetGuard في وضع التصفية
+ تم تأمين مرور المعلومات
+ الحركة الغير مقاسة مسموحة
+ الحركة الغير مقاسة محظورة
+ لا يتم تطبيق قواعد unmetered
+ الحركة المقاسة مسموحة
+ الحركة المقاسة محظورة
+ لا يتم تطبيق قواعد metered
+ العنوان مسموح
+ العنوان محظور
+ السماح عند تكون الشاشة فعالة
+ حظر أثناء التجوال
+ بشكل افتراضي، تعتبر شبكات الاتصال اللاسلكي غير مقاسة وشبكات اتصال الهاتف مقاسة
+ ليس لديه اذن انترنت
+ معطل
+ يتم تلقي الرسائل الواردة بواسطة خدمات Google Play وليس عن طريق هذا التطبيق، وبالتالي لا يمكن حظرها عن طريق حظر هذا التطبيق
+ يتم التحميل بواسطة مدير التحميلات وليس بواسطة هذا التطبيق ، وبالتالي لا يمكن حظرها عن طريق حظر هذا التطبيق
+ تطبيق القواعد والشروط
+ الشروط
+ السماح للشبكات اللاسلكية عندما تكون الشاشة فعالة
+ السماح لشبكة الهاتف عندما تكون الشاشة فعالة
+ تجوال
+ حظر أثناء التجوال
+ السماح في وضع التأمين
+ تصفية ذي الصلة
+ محاولات الوصول
+ قواعد الوصول لها الأسبقية على غيرها من القواعد
+ الخيارات
+ تنبيه عن محاولات الوصول إلى إنترنت
+ لم يتم تمكين التسجيل أو التصفية
+ تم تمكين التسجيل والتصفية
+ ضبط
+ تمكين تسجيل العناوين المحظورة فقط
+ تمكين التصفية لسجل العناوين المسموح بها
+ تفعيل إشعارات الدخول لأحدث العناوين المسجلة
+ مساعدة تفعيل العنوان
+ تالصفية مطلوبة أيضا للسماح أو حظر العناوين الفردية
+ تمكين تسجيل الدخول (أقل) أو التصفية (أكثر) قد يؤدي إلى زيادة استخدام البطارية وقد تؤثر على سرعة الشبكة
+ قيّم التطبيق
+ سماح
+ حظر
+ السماح ل Wi-Fi
+ حظر Wi-Fi
+ السماح للجوال
+ حظر المحمول
+ الجذر
+ خادم الوسائط
+ لا أحد
+ لا تسأل مرة أخرى
+ بيانات تسجيل اسم النطاق %1$s
+ منفذ %1$d
+ نسخ
+ ميزات النسخة الكاملة
+ الميزات التالية للنسخة الكاملة متوفرة:
+ عرض سجل الحركة المحظورة
+ تصفية حركة الشبكة
+ تنبيهات تطبيق جديد
+ تنبيه رسم بياني لسرعة الشبكة
+ المظهر (المظهر، ألوان)
+ كل ميزات النسخة الكاملة أعلاه
+ دعــم الــتـــطـــويـــر
+ شراء
+ مفعل
+ غير متاح
+ اضغط على العنوان لمزيد مِن المعلومات
+ تحدّي
+ الاستجابة
+ هذه ميزة الإصدار المهنية
+ اشتراكات شهرية بقيمة ١ أو ٢ يورو (باستثناء الضرائب المحلية) ستفعل كافة الميزات المحترفة.
+ يمكنك إلغاء أو إدارة اشتراك عبر لسان الاشتراكات في تطبيق Play store.
+
+
+ - أزرق مخضر/برتقالي
+ - أزرق/برتقالي
+ - بنفسجي/أحمر
+ - عنبر/ أزرق
+ - برتقالي/ رمادي
+ - أخضر
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-az-rAZ/strings.xml b/NetGuard/app/src/main/res/values-az-rAZ/strings.xml
new file mode 100644
index 0000000..40729af
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-az-rAZ/strings.xml
@@ -0,0 +1,292 @@
+
+
+ NetGuard, root-a ehtiyac olmadan internetə müraciəti əngəlləmək üçün sadə və qabaqcıl yolları təqdim edir. Wi-Fi və/və ya mobil bağlantı üzərindən tətbiqlər və ünvanlar üçün internetə müraciəti tək-tək ləğv edə bilərsiniz.
+ NetGuard, Android 5.1 və daha yuxarı versiyanı tələb edir
+ Xposed, NetGuard-ın Google Play Store-dan çıxarılmasına səbəb ola biləcək bir çox çökməyə səbəb ola bilər. Buna görə də, NetGuard, Xposed quraşdırılarkən dəstəklənmir
+ Gizlilik siyasəti
+ NetGuard-ı tərtib etmək və sınaqdan keçirmək üçün böyük diqqət göstərilmişdir, ancaq NetGuard-ın hər cihazda düzgün işləməyinə zəmanət vermək mümkünsüzdür.
+ Razıyam
+ Razı deyiləm
+ NetGuard-ın köməyinizə ehtiyacı var. Pro xüsusiyyətləri satın alaraq layihəni davam etdirmək üçün toxunun.
+ İşləyən xidmətlər
+ Ümumi bildirişlər
+ Bildirişlərə müraciət
+ Tətbiq axtar
+ Tətbiqləri filtrlə
+ İstfdçi tətbiqlərini göstər
+ Sistem tətbiqlərini göstər
+ İnternetsiz tətbiqləri göstər
+ Ləğv edilmiş tətbiqləri göstər
+ Tətbiqləri sırala
+ Ada görə
+ İstfdçi kimliyinə görə
+ Verilənlər istfdsnə görə
+ Jurnalını göstər
+ Tənzimləmələr
+ Dəvət et
+ Mənalar
+ Dəstək
+ Haqqında
+ Digər tətbiqlər
+ Digər
+ İcazə verildi
+ Əngəlləndi
+ Canlı yeniləmələr
+ Təzələ
+ Adları göstər
+ Təşkilatı göstər
+ PCAP fəallaşdırıldı
+ PCAP ixrac etmə
+ Təmizlə
+ İxrac et
+ Sıfırla
+ Əlavə et
+ Sil
+ Təmizlik
+ Protokol
+ Mənbə portu
+ Təyinat ünvanı
+ Təyinat portu
+ Təyinat tətbiqi
+ Xarici bir server üçün \'heç kim\' seç
+ İlkin (ağ/qara siyahı)
+ \"Wi-Fi\"ı əngəllə
+ Mobil verlnləri əngəllə
+ Wi-Fi-a ekran açıq olanda icazə ver
+ Mobil verlnlrə ekran açıq olanda icazə ver
+ Roaminqi əngəllə
+ Seçimlər
+ Tema: %1$s
+ Tünd tema
+ Yeni tətbiqləri bildir
+ \'Ekran açıq olanda\' qaydalarını tətbiq et
+ %1$s dəqiqə sonra avto-fəallaşdır
+ Ekran sönməsini %1$s dəqiqə gecikdir
+ Yeniləmələri yoxla
+ Şəbəkə seçimləri
+ Subnet marşrutu
+ İnternet paylaşımına icazə ver
+ LAN müraciətinə icazə ver
+ IPv6 trafikini fəallaşdır
+ Wi-Fi ev şəbəkələri: %1$s
+ Wi-Fi şəbəkəsinə limit qoyun
+ 2G istifadəsini nəzərə al
+ 3G istifadəsini nəzərə al
+ LTE istifadəsini nəzərə al
+ Milli roaminqə məhəl qoyma
+ AB roaminqinə məhəl qoyma
+ Zəngdə ləğv et
+ Wi-Fi-ı kilidlə
+ Mobil verlnləri kilidlə
+ Bağlantı hər dəyişəndə yenidən yüklə
+ Qabaqcıl seçimlər
+ Sistem tətbiqlərini idarə et
+ İnternetə müraciəti jurnala yaz
+ İnternet müraciətində bildir
+ Trafiki filtrlə
+ UDP trafikini filtrlə
+ Yükləmədə kəsintisiz VPN çatdırılması
+ Yenidən yükləmədə bağlantını kəs
+ Trafiki kilidlə
+ Şəbəkə istifadəsini izlə
+ Şəbəkə istifadəsini sıfırla
+ Həll edilmiş domen adlarını göstər
+ Domen adlarını əngəllə
+ DNS cavab kodu: %s
+ Port yönləndirmə
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Təsdiqləmə ünvanı: %s
+ Minimum DNS TTL: %s s
+ SOCKS5 proksi istifadə et
+ SOCKS5 ünvanı: %s
+ SOCKS5 portu: %s
+ SOCKS5 istifadəçi adı: %s
+ SOCKS5 parolu: %s
+ PCAP qeyd həcmi: %s B
+ PCAP maks. fayl həcmi: %s MB
+ Gözətçi: hər %s dəqiqə
+ Sürət bildirişi
+ Sürət bildirişini göstər
+ Başlıca tətbiqləri göstər
+ Nümunə aralığı: %s ms
+ Nümunə sayı: %s s
+ Nüsxələmə
+ Tənzimləmələri ixrac et
+ Tənzimləmələri idxal et
+ Hosts fayllarını idxal et
+ Hosts faylını idxal et (əlavə)
+ Hosts faylını endirmə bağlantısı
+ Hosts faylını endir
+ Texniki məlumat
+ Ümumi
+ Şəbəkələr
+ Abunəliklər
+ Yeni quraşdırılmış tətbiqləri birbaşa konfiqurasiya etmək üçün vəziyyət sətrində bildiriş göstər (pro xüsusiyyət)
+ Vicetin istifadəsini ləğv etdikdən sonra, seçilmiş dəqiqə sayından sonra NetGuard-ı təkrar avtomatik fəallaşdır (bu seçimi ləğv etmək üçün 0 yazın)
+ Ekran sönəndə, seçilmiş dəqiqə üçün aktiv qaydalarla ekranı açıq saxla (bu seçimi ləğv etmək üçün sıfır daxil edin)
+ Yeni versiyaları GitHub-da gün ərzində iki dəfə yoxla
+ Android versiyasından asılı olaraq, internet paylaşımı işləyə və ya işləməyə bilər. Paylaşılan trafik filtrlənə bilməz.
+ Subnet marşrutunu fəallaşdır; Wi-Fi zəngi fəallaşdırıla bilər, ancaq Android-də xətaları işə sala və batareya istifadəsini artıra bilər
+ Tətbiqlərin 10.0.0.0/8, 172.16.0.0/12 və 192.168.0.0/16 kimi lokal şəbəkə ünvanları ilə bağlantı qurmasına icazə verər
+ IPv6 trafikini, icazə verilən və ya əngəllənən olaraq seçilə bilməsi üçün NetGuard-a yönləndir
+ Yalnız seçilmiş şəbəkə üçün Wi-Fi şəbəkə qaydalarını tətbiq et (digər Wi-Fi şəbəkələri üçün mobil şəbəkə qaydalarını tətbiq et)
+ Mobil şəbəkə qaydalarını kvotalı Wi-Fi şəbəkələrinə (ödənişli, paylaşılan) tətbiq et
+ 2G bağlantıları üçün Wi-Fi şəbəkə qaydalarını tətbiq et
+ 3G bağlantıları üçün Wi-Fi şəbəkə qaydalarını tətbiq et
+ LTE bağlantıları üçün Wi-Fi şəbəkə qaydalarını tətbiq et
+ SIM kart və mobil şəbəkə ölkəsi eyni olanda roaminq qaydalarını tətbiq etmə
+ SIM kart və mobil şəbəkə ölkəsi Avropa Birliyində olanda roaminq qaydalarını tətbiq etmə
+ Gələn və ya gedən telefon zənglərində NetGuard-ı ləğv et. Bu, IP/Wi-Fi zəng problemlərini həll etmək üçün istifadə edilə bilər.
+ Sistem tətbiqləri üçün qaydalar təyin edin (mütəxəssislər üçün)
+ Jurnal, tətbiqlər üçün internetə müraciətət cəhd edir. Bu, batareya istifadəsini artıra bilər.
+ Bir tətbiq yeni bir ünvana müraciət etməyə cəhd edəndə vəziyyət sətrində bir bildiriş göstər (filtrləmə ləğv ediləndə, yalnız əngəllənən cəhdlərin bildirişi göstəriləcək)
+ VPN tunelindən çıxan IP paketləri filtrlə. Bu, batareya istifadəsini artıra bilər.
+ Hər bir tətbiq və ünvan üçün göndərilən və alınan bayt sayını izləyin. Bu, batareya istifadəsini artıra bilər.
+ Əngəllənən domen adları üçün konfiqurasiya edilmiş DNS cavab kodu ilə cavablayın. Hosts faylı mövcud olmayanda bu seçim ləğv edilir.
+ İlkin dəyər 3 (NXDOMAIN), yəni \'mövcud olmayan domen\'.
+ 443 (https) portundakı internet bağlantısını təsdiqləmək üçün istifadə olunan domen adı.
+ Yalnız TCP trafiki proksi serverə göndəriləcək
+ NetGuard-ın işlədiyini müntəzəm olaraq yoxla (bu seçimi ləğv etmək üçün sıfır yazın). Batareya istifadəsini artıra bilər.
+ Vəziyyət sətrində şəbəkə sürətinin qrafik bildirişini göstər
+ Əminsiniz?
+ Qaydaları məcbur et
+ %1$d icazə verildi, %2$d əngəlləndi
+ %1$d icazə verildi, %2$d əngəlləndi, %3$d hosts
+ Tədbir gözlənilir
+ NetGuard ləğv edildi, yuxarıdan fəallaşdırın
+ NetGuard ləğv edildi, yəqin ki, başqa bir VPN əsaslı tətbiq istifadə edilir
+ \'%1$s\' quraşdırıldı
+ Quraşdırıldı
+ %1$s internetə müraciət etməyə cəhd etdi
+ Internetə müraciətə cəhd etdi
+ Əməliyyat tamamlandı
+ NetGuard, internet trafikini filtrləmək üçün lokal bir VPN istifadə edir.
+Buna görə də, zəhmət olmasa növbəti dialoqda VPN bağlantısına icazə verin.
+İnternet trafikiniz heç bir VPN serverinə göndərilmir.
+ NetGuard avtomatik olaraq başladıla bilmədi. Yəqin ki, Android versiyanızda bir xəta buna səbəb olur.
+ Gözlənilməz bir xəta baş verdi: \'%s\'
+ Android, hal-hazırda VPN xidmətini başlatmağı rədd etdi. Yəqin ki, Android versiyanızda bir xəta buna səbəb olur.
+ NetGuard-ı sınayın
+ İanə verərək şərtlər və qaydalarla razılaşırsınız
+ Əgər növbəti dialoqda \"Oldu\"ya basa bilmirsinizsə, başqa bir tətbiq (ekran qaraltma) ekranı idarə etmiş ola bilər.
+ ± %1$.3f▲ %2$.3f▼ MB/gün
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Qərarlı nəticələr əldə etmək üçün, NetGuard üçün Android batareya optimallaşdırmaları ləğv edilməlidir.
+\n\nNövbəti dialoqda, yuxarıdan \"Bütün tətbiqlər\"i seçin, NetGuard-ı seçin və \"Optimallaşdırma\"nı təsdiqləyin.
+ Qərarlı nəticələr əldə etmək üçün, NetGuard üçün Android verilənlərə qənaət seçimi ləğv edilməlidir.
+\n\nNövbəti dialoqda, \"Arxaplan verilənləri\" və \"Məhdudiyyətsiz verilənlər istifadəsi\" seçimlərini fəallaşdırın.
+ Filtrləməni istifadə etmək, Android-in verilənlər və enerji istifadəsini NetGuard-a aid etməsinə səbəb olacaq - Android, verilənlər və enerjinin orijinal tətbiqlər əvəzinə NetGuard tərəfindən istifadə edildiyini nəzərə alacaq
+ Android 4 filtrləmənin fəallaşdırılmasını tələb edir
+ Trafikin jurnala yazılması ləğv edildi, fəallaşdırmaq üçün yuxarıdakı açarı istifadə edin. Trafikin jurnala yazılmasını fəallaşdırmaq batereya istifadəsini artıra bilər.
+ Bu, qaydaların və şərtlərin dəyərlərini ilkin vəziyyətə qaytarar
+ Bu, icazə verilən/əngəllənən qaydalar istisna olmaqla müraciət cəhdi qeyd sətirlərini siləcək
+ Son idxal: %s
+ Endirilir\n%1s
+ Hosts fayl endirildi
+ Son endirmə: %s
+ \'%5$s\' üçün %1$s:%2$d -> %3$s:%4$d yönləndirmə başladılsın?
+ %1$s:%2$d yönləndirilməsi dayandırılsın?
+ Şəbəkə ölçüldü
+ Aktiv internet bağlantısı yoxdur
+ NetGuard məşğuldur
+ Yeniləmə var, endirmək üçün toxunun
+ Tətbiqin yanındakı nişanlara toxunaraq Wi-Fi və ya mobil internet müraciətinə icazə verə (yaşılımtıl) və ya rədd edə (qırmızımtıl) bilərsiniz
+ Gizliliyinizi qorumaq üçün NetGuard-ı quraşdırmısınızsa, açıq mənbəli, gizlilik dostu e-poçt tətbiqi olan FairEmail ilə maraqlana bilərsiniz
+ İlkin olaraq (qara siyahı rejimi) internetə müraciətə icazə verildi, bu, tənzimləmələrdə dəyişdirilə bilər
+ Gələn (ani) mesajlar əsasən sistem komponenti olan Play xidmətləri tərəfindən idarə olunur və bu xidmətlərin ilkin olaraq internetə müraciətinə icazə verilir
+ Bütün (sistem) tətbiqlərinin idarə edilməsi tənzimləmələrdə fəallaşdırıla bilər
+ Zəhmət olmasa probleminizi təsvir edin və problemin vaxtını göstərin:
+ VPN bağlantısı ləğv edildi\nBaşqa bir VPN-i həmişə açıq qalacaq formada konfiqurasiya etmisiniz?
+ NetGuard fəal ikən cihazınızı söndürsəniz, cihazınız açılanda NetGuard avtomatik olaraq başlayacaq
+ Bu xüsusiyyət bu Android versiyasında əlçatmazdır
+ Başqa VPN, Həmişə açıq VPN kimi tənzimləndi
+ NetGuard-ı filtrləmə rejimində istifadə etmək üçün Android VPN tənzimləmələrində \"VPN-siz bağlantıları əngəllə\" seçimini söndürün
+ NetGuard-ı filtrləmə rejimində istifadə etmək üçün Android şəbəkə tənzimləmələrində \"Özəl DNS\" seçimini söndürün
+ Trafik kilidləndi
+ Ölçülməmiş trafikə icazə verildi
+ Ölçülməmiş trafik əngəlləndi
+ Ölçülməmiş qaydalar tətbiq edilməyib
+ Ölçülmüş trafikə icazə verildi
+ Ölçülmüş trafik əngəlləndi
+ Ölçmə qaydaları tətbiq edilməyib
+ Ünvana icazə verildi
+ Ünvan əngəlləndi
+ Ekran açıq olanda icazə verilən
+ Roaminqdə əngəllənən
+ İlkin olaraq Wi-Fi bağlantısı ölçülməmiş hesab edilir və mobil bağlantı ölçülür
+ internet icazəsi yoxdur
+ ləğv edildi
+ Gələn mesajlar bu tətbiq tərəfindən yox, Google Play xidmətləri tərəfindən alınır və buna görə də bu tətbiqi əngəlləmək işə yaramaz
+ Endirmələr bu tətbiq tərəfindən yox, endirmə meneceri tərəfindən icra olunur və buna görə də bu tətbiqi əngəlləmək işə yaramaz
+ Qaydaları və şərtləri tətbiq et
+ Şərtlər
+ Wi-Fi-a ekran açıq olanda icazə ver
+ Mobil ver.lərə ekran açıq olanda icazə ver
+ R
+ Roaminqdə əngəllə
+ Kilid rejimində icazə ver
+ Əlaqəliləri filtrlə
+ Müraciət cəhdləri
+ Digər qaydalara nisbətən müraciət qaydalarına üstünlük verilir
+ Seçimlər
+ İnternet müraciət cəhdlərini bildir
+ Jurnala yazma və ya filtrləmə fəal deyil
+ Jurnala yazma və ya filtrləmə fəaldır
+ Konfiqurasiya et
+ Yalnız əngəllənən ünvanlar jurnala yazılsın
+ İcazə verilən ünvanların jurnala yazılması üçün filtrləmə fəallaşdırılsın
+ Yeni jurnala yazılmış ünvanlar üçün müraciət bildirişlərini fəallaşdır
+ Bu tənzimləmələr bütün tətbiqlərə tətbiq edilən qlobal tənzimləmələrdir
+ Ünvanları ayrı-ayrı idarə etmək üçün filtrləmə lazımdır
+ Jurnala yazma (az) və ya filtrləmə (çox), batareya istifadəsini artıra və şəbəkə sürətinə təsir edə bilər
+ Qiymətləndir
+ İcazə ver
+ Əngəllə
+ Wi-Fi-a icazə ver
+ Wi-Fi-ı əngəllə
+ Mobil ver.lərə icazə ver
+ Mobil ver.ləri əngəllə
+ root
+ mediaserver
+ heç kim
+ Təkrar soruşma
+ Whois %1$s
+ Port %1$d
+ Kopyala
+ Pro xüsusiyyətlər
+ Pro versiyada aşağıdakı xüsusiyyətlər var:
+ Əngəllənən trafikə bax
+ Şəbəkə trafikini filtrlə
+ Yeni tətbiq bildirişləri
+ Şəbəkə sürəti qrafik bildirişi
+ Görünüş (tema, rənglər)
+ Bütün pro xüsusiyyətlər
+ Tərtibatçını dəstəklə
+ Satın al
+ Fəallaşdırıldı
+ Əlçatmazdır
+ Daha çox məlumat üçün başlığa toxunun
+ Çağırış
+ Cavab
+ Bu bir Pro xüsusiyyətdir
+ Vergilər xaric aylıq 1 və ya 2 avroluq abunəlik bütün pro xüsusiyyətləri aktivləşdirir.
+ Play store tətbiqindəki abunəliklər vərəqi vasitəsilə abunəliyinizi ləğv edə və ya idarə edə bilərsiniz.
+
+
+ - tünd yaşıl/narıncı
+ - mavi/narıncı
+ - bənövşəyi/qırmızı
+ - kəhrəba/mavi
+ - narıncı/boz
+ - yaşıl
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-bg-rBG/strings.xml b/NetGuard/app/src/main/res/values-bg-rBG/strings.xml
new file mode 100644
index 0000000..e5cf4e0
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-bg-rBG/strings.xml
@@ -0,0 +1,281 @@
+
+
+ NetGuard предоставя прост, а също така и по-задълбочен начини за блокиране достъпа до интернет - без нужда от ROOT права. Достъпът на приложенията и адресите чрез Wi-Fi или мобилни данни, могат да се разрешават и забраняват по отделно.
+ NetGuard изисква Android 5.1 или по-нова версия
+ Политика за личните данни
+ NetGuard се разраборва и изпитва с голямо внимание, но е невъзможно да бъде дадена гаранция, че ще функционира правилно на всяко устройство.
+ Приемам
+ Не съм съгласен
+ FairEmail се нуждае от вашата подкрепа. Докоснете, за да закупите допълнителните възможности така проектът ще продължи да се развива.
+ Работещи услуги
+ Общи известия
+ Известия за достъп
+ Търсене на приложение
+ Филтър по приложения
+ Потребителски приложения
+ Системни приложения
+ Приложения без достъп до интернет
+ Деактивирани приложения
+ Сортиране на приложения
+ Сортиране по име
+ Сортиране по ID на приложението
+ Сортиране по използван трафик
+ Показване на дневник
+ Настройки
+ Поканете
+ Легенда
+ Поддръжка
+ За приложението
+ Други приложения
+ Други
+ Разрешен
+ Блокиран
+ Обновяване в реално време
+ Опресняване
+ Показване на имената
+ Организация
+ PCAP разрешено
+ PCAP експортиране
+ Изчистване
+ Изнасяне
+ Нулиране
+ Добавяне
+ Изтриване
+ Почистване
+ Протокол
+ Изходящ порт
+ Отдалечен адрес
+ Отдалечен порт
+ Текущо приложение
+ За външен сървър изберете \'nobody\'
+ По подразбиране
+ Блокиране на Wi-Fi
+ Блокиране на мобилни данни
+ Позволяване на Wi-Fi, когато екранът е включен
+ Позволяване на мобилни данни, когато екранът е включен
+ Блокиране при роуминг
+ Настройки
+ Тема: %1$s
+ Използване на тъмна тема
+ Известие при инсталиране на приложение
+ Прилагане на правилата „при включен екран“
+ Автоматично включване след %1$s минути
+ Отлагане изключването на екрана с %1$s минути
+ Проверка за обновяване
+ Мрежови настройки
+ Маршрутизиране на подмрежи
+ Позволяване на привързване
+ Позволяване на LAN достъп
+ Включване на IPv6 трафик
+ Домашни мрежи на Wi-Fi: %1$s
+ Управление на достъпа до мрежи на Wi-Fi с ограничен трафик
+ Приемане на 2G за неограничен трафик
+ Приемане на 3G за неограничен трафик
+ Приемане на LTE за неограничен трафик
+ Пренебрегване на национален роуминг
+ Пренебрегване на роуминга в ЕС
+ Изключване при обаждане
+ Заключване на Wi-Fi
+ Заключване на мобилни данни
+ Презареждане при всяка промяна на връзката
+ Разширени настройки
+ Управление на системни приложения
+ Регистриране на достъпа до интернет във файл
+ Известие при достъп до интернет
+ Филтриране на трафика
+ Филтриране на трафика по UDP
+ Прекъсване на връзката при презареждане
+ Заключване на трафика
+ Следене на достъпа до мрежа
+ Нулиране на данните за достъп до мрежа
+ Показване на заявените домейни
+ Блокиране на домейни
+ Код на отговора на DNS: %s
+ Пренасочване на порт
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Проверка: %s
+ Минимален TTL за DNS: %s с
+ Използване на SOCKS5 прокси
+ SOCKS5 адрес: %s
+ SOCKS5 порт: %s
+ SOCKS5 потребителско име: %s
+ SOCKS5 парола: %s
+ PCAP записване на размер: %s B
+ PCAP максимален размер на файла: %s MB
+ Пазител: всеки %s минути
+ Известие с текущите скорости
+ Показване на известия за скоростта
+ Показване на най-използваните приложения
+ Интервал на измерване: %s мс
+ Брой измервания: %s бр.
+ Архивиране
+ Изнасяне на настройки
+ Внасяне на настройки
+ Внасяне на файл „hosts“
+ Внасяне на файл „hosts“ (добавя)
+ Адрес за изтегляне на файл „hosts“
+ Изтегляне на файл „hosts“
+ Техническа информация
+ Общи
+ Мрежи
+ Абонаменти
+ Показва се известие за настройка на новто инсталирано приложение (платена функция)
+ След изключване на активна притурка, автоматично активиране на NetGuard отново след избрания брой минути (въведете 0 за деактивиране на опцията)
+ След изключване на екрана, влизат в сила правилата при включен екран за избрания брой минути (въведете 0 за деактивиране на опцията)
+ Проверка за нови версии в GitHub два пъти дневно
+ Според версията на Android, привързването може да работи или не. Трафикът от привързване не може да се филтрира.
+ Разрешаване на подмрежово маршрутизиране; може да активира Wi-Fi обаждане, но може да предизвика грешки в Android и да увеличи използването на батерията
+ Разрешаване на приложенията да се свързват към адреси в локалната мрежа, като 10.0.0.0/8, 172.16.0.0/12 и 192.168.0.0/16
+ Маршрутизиране на IP V6 трафикa към NetGuard, дава възможност избирателно да бъде разрешаван или блокиран
+ Прилагане на правилата за Wi-Fi мрежа само за избраната мрежа (прилагане на правилата за мобилни данни за други Wi-Fi мрежи)
+ Прилагане на правилата за мобилни данни при мрежи на Wi-Fi с ограничен трафик (платен, привързан)
+ Прилагане на правилата за Wi-Fi при връзка за мобилни данни на 2G
+ Прилагане на правилата за Wi-Fi при връзка за мобилни данни на 3G
+ Прилагане на правилата за Wi-Fi при връзка за мобилни данни на LTE
+ Да не се прилагат правилата при роуминг, когато СИМ картата и операторът са от една и съща държава
+ Да не се прилагат правилата при роуминг, когато СИМ картата и операторът са в ЕС
+ Задаване на правила за системни приложения (за напреднали потребители)
+ Регистриране на опитите за достъп до интернет на приложенията. Това може да доведе до допълнително използване на батерията.
+ Показва се известие при опит на приложение за достъп до нов интернет адрес (при изключено филтриране, ще се показват само блокираните опити)
+ Филтриране на IP пакетите излязащи от VPN тунела. Това може да доведе до допълнително използване на батарията.
+ Проследяване на броя байтове, изпратени и получени за всяко приложение и адрес. Това може да доведе до допълнителено използване на батерията.
+ Отговаря с настроената грешка на DNS за блокиран домейн. Тази възможност е изключена, когато няма файл „hosts“.
+ Подразбираната стойност е 3 (NXDOMAIN), което означава „несъществуващ домейн“.
+ Домейн, използван за проверка на връзката с интернет на порт 443 (https).
+ Само TCP трафикът ще бъде изпратен към прокси сървъра
+ Периодично проверява дали NetGuard е активен (въведете 0 за деазктивиране на опцията). Това може да доведе до допълнителен разход на батерията.
+ Показва се графика със скоростите на пренос в лентата за известия
+ Сигурни ли сте?
+ Строги правила
+ %1$d, разрешени, %2$d блокирани
+ %1$d разрешени, %2$d забранени, %3$d хостове
+ Изчакване за събитие
+ NetGuard е изключен, използвайте превключвателя горе, за да включите NetGuard
+ NetGuard се изключи, най-вероятно използвате друго VPN базирано приложение
+ \"%1$s\" инсталирани
+ Е инсталиран
+ %1$s опита за достъп до интернет
+ Опитвал достъп до интернет
+ Действието е завършено
+ NetGuard използва местен VPN за филтриране на трафика.
+Поради тази причина в следващия диалогов прозорец разрешете връзката през VPN.
+Трафик към интернет не се изпраща към отдалечен сървър на VPN.
+ NetGuard не може да се стартира автоматично при стартиране на системата поради грешка в Android версията
+ Възникна неочаквана грешка: \"%s\"
+ Андроид отказва за момента да стартира услугата за ВЧМ. Най-вероятно се дължи на дефект в изданието на Андроид.
+ Опитайте NetGuard
+ Чрез даряването, вие се съгласявате с общите условия
+ Ако не можете да натиснете OK в следващия диалогов прозорец, то вероятно друго приложение манипулира екрана (затъмняване на екрана).
+ ± %1$.3f▲ %2$.3f▼ Мб/ден
+ %1$7.3f▲ %2$7.3f▼ Кб
+ %1$7.3f▲ %2$7.3f▼ Мб
+ %1$7.3f▲ %2$7.3f▼ Гб
+ %dx
+ За правилната работа на приложението моля, не активирайте оптимизация на батерията за NetGuard. \n\nв следващия диалогов прозорец, изберете \"Всички приложения\" в горната част, докоснете върху NetGuard в списъка. Изберете и потвърдете \"Не оптимизирай\".
+ За постоянни резултати трябва да изключите \"Android data saving\" за NetGuard \n\nВ следващия диалогов прозорец, разрешете \"Background data\" и \"Unrestricted data usage\"
+ Филтрирането на трафика ще накара Android да причисли използвания трафик и консумация на батерия към NetGuard, а не към приложенията, които реално са извършили консумацията им
+ Андроид 4 изисква филтрирането да бъде включено
+ Rегистрирането на трафика е изключено, използвайте опцията по-горе за да разрешите регистрирането. Регистрирането на трафика може да доведе до допълнителна употреба на батерията.
+ Това ще се нулира правилата и условията към стойностите им по подразбиране
+ Така ще бъдат премахнати редовете от дневника с опитите за достъп, без правила за разрешаване/забраняване
+ Последно вмъкване: %s
+ Сваляне\n%1s
+ Файлът „hosts“ е изтеглен
+ Последно сваляне: %s
+ Започнете пренасочване от %1$s порт %2$d към %3$s:%4$d на \"%5$s\"?
+ Спиране пренасочването на %1$s порт %2$d?
+ Мрежа с ограничен трафик
+ Няма връзка с интернет
+ NetGuard е зает
+ Налична е актуализация, докоснете за сваляне
+ Можете да разрешите (зеленикаво) или забраните (червеникаво) достъп през безжични мрежи или мобилни данни, като докосвате иконите до приложението
+ Ако сте инсталирали NetGuard, за да подобрите неприкосновеността на личните си данни, вероятно също ще бъдете заинтересовани от FairEmail , приложение за електронна поща с отворен код, съобразено с поверителността
+ Достъпът до интернет е разрешен по подразбиране (като черен списък), това може да се промени в настройките
+ \"Push\" съобщенията се обработват предимно от системния комонент \"Play services\", който по подразбиране е с разрешен достъп до интернет
+ Управляване на всички (системни) приложения може да бъде включено в настройките
+ Моля, опишете проблема и отбележете часа на възникването му:
+ Ако изключите устройството докато NetGuard е включен, когато го включите NetGuard автоматично ще стартира
+ Тази възможност не се поддържа от това издание на Андроид
+ Трафикът е заключен
+ Неограниченият трафик е разрешен
+ Неограниченият трафик е блокиран
+ Правилата за неограничен трафик не са приложени
+ Ограниченият трафик е разрешен
+ Ограниченият трафик е забранен
+ Правилата за ограничен трафик не са приложени
+ Адресът е разрешен
+ Адресът е блокиран
+ Позволи, когато екранът е включен
+ Блокиране при роуминг
+ По подразбиране, връзката по Wi-Fi се счита за неограничен трафик, а мобилна връзка за ограничен
+ няма разрешение за интернет достъп
+ е изключен
+ Прилагане на павилата и условията
+ Условия
+ Позволяване на Wi-Fi, когато екранът е включен
+ Позволяване на мобилни данни, когато екранът е включен
+ Р
+ Блокиране при роуминг
+ Разрешаване по време на заключен трафик
+ Поради текущ филтър
+ Опити за достъп
+ Правилата за достъп имат предимство пред други правила
+ Настройки
+ Известяване при опити за достъп до интернет
+ Дневникът или филтрирането не са включени
+ Дневникът и филтрирането са включени
+ Настройки
+ Запис в дневника само на забранените адреси
+ Включване на филтрирането, за да се записват и разрешените
+ Известяване при нов записан адрес
+ Това са общи настройки за всички приложения
+ Филтрирането е необходимо и за разрешаване или забраняване на отделни адреси
+ Включване на дневника (по-малко) или филтрирането (повече) може да има отражение върху разхода на батерия, а също и върху скоростта на мрежата
+ Оценяване
+ Разрешаване
+ Забраняване
+ Разрешаване на Wi-Fi
+ Забраняване на Wi-Fi
+ Разрешаване на мобилни данни
+ Забраняване на мобилни данни
+ права на суперпотрбител
+ сървър за медиа
+ никой
+ Без ново питане
+ Whois %1$s
+ Порт %1$d
+ Копиране
+ Платени възможности
+ Налични са следните платени възможности:
+ Преглед на дневника с блокиран трафик
+ Филтриране на мрежовия трафик
+ Известие при ново инсталирано приложение
+ Графика в известието за скорост на трафика
+ Изглед (тема, цветове)
+ Всички платени възможности по-горе
+ Подкрепете разработката
+ Купуване
+ Включено
+ Недостъпно
+ Докоснете заглавията за повече информация
+ Предизвикателство
+ Отговор
+ Това е платена възможност
+ Месечен абонамент от 1 или 2 евро (без такси и данъци) ще включи всички платени възможности.
+ Можете да спрете или управлявате абонамента от раздела за абонаменти в приложението на Play Store.
+
+
+ - синьо-зелено/оранжево
+ - синьо/оранжево
+ - лилаво/червено
+ - кехлибарено/синьо
+ - оранжево/сиво
+ - зелено
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-bn-rBD/strings.xml b/NetGuard/app/src/main/res/values-bn-rBD/strings.xml
new file mode 100644
index 0000000..35eacab
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-bn-rBD/strings.xml
@@ -0,0 +1,25 @@
+
+
+ নেটগার্ড ইন্টারনেটে অ্যাক্সেস ব্লক করার সহজ এবং উন্নত উপায় প্রোভাইড করে - কোনও রুট করার প্রয়োজন হয় না। প্রতিটি অ্যাপ্লিকেশন এবং ওয়েব এড্রেসগুলোকে পৃথকভাবে আপনার ওয়াইফাই এবং / অথবা মোবাইল সংযোগ অ্যাক্সেসের অনুমতি দেয় বা বিরত রাখে।
+ নেটগার্ডের জন্য অ্যান্ড্রয়েড 5.1 বা তার পরের কোনো ভার্সন প্রয়োজন পরে।
+ আমি সম্মতি দিচ্ছি
+ আমি সম্মতি দিচ্ছি না
+ চলমান পরিষেবা
+ সাধারণ বিজ্ঞপ্তি
+ অ্যাপ খুঁজো
+ অ্যাপ ফিল্টার করো
+ সিস্টেম অ্যাপ্স প্রদর্শন করুন
+ ইন্টারনেট ছাড়া অ্যাপ্স প্রদর্শন করুন
+ অ্যাপ সাজাও
+ নাম অনুযায়ী সাজাও
+ সেটিংস
+ সমর্থন
+ পরিচিতি
+ অন্যান্য
+ অবরুদ্ধ
+ পুনঃনির্মাণ
+ মুছে ফেলুন
+ গন্তব্যস্থানের ঠিকানা
+ গন্তব্যস্থানের পোর্ট
+ গন্তব্য অ্যাপ
+
diff --git a/NetGuard/app/src/main/res/values-ca-rES/strings.xml b/NetGuard/app/src/main/res/values-ca-rES/strings.xml
new file mode 100644
index 0000000..c3e5002
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-ca-rES/strings.xml
@@ -0,0 +1,127 @@
+
+
+ NetGuard proveeix una forma simple i avançada per blocar l\'accés a internet sense requerir privilegis d\'administració. Es pot denegar o permetre l\'accés al vostre Wi-Fi i/o connexió mòbil a les aplicacions i adreces individualment.
+ NetGuard requerix d\'Android 5.1 o posterior
+ Xposed provoca massa errors que podria portar l\'eliminació de NetGuard a la botiga del Google Play, per tant, NetGuard no està suportat mentre Xposed estiga instal·lat
+ Política de privacitat
+ S\'ha pres bona cura al desenvolupar i provar NetGuard, tot i així no és possible garantir un correcte funcionament en tots els aparells.
+ Accepte
+ Rebutge
+ NetGuard us necessita. Polseu a comprar característiques pro per mantindre el projecte en marxa.
+ Serveis en execució
+ Notificacions generals
+ Accés a notificacions
+ Cercar app
+ Filtrar apps
+ Mostra apps de l\'usuari
+ Mostra apps del sistema
+ Mostra apps sense internet
+ Mostrar apps deshabilitades
+ Organitzar apps
+ Organitzar per nom
+ Organitzar per uid
+ Organitzar per ús de dades
+ Mostrar log
+ Preferències
+ Convida
+ Llegenda
+ Assistència
+ Quant a
+ Altres aplicacions
+ Altres
+ Permès
+ Bloquejat
+ Actualitzacions
+ Actualitzar
+ Mostrar noms
+ Mostrar organitzacions
+ PCAP habilitat
+ Exportar PCAP
+ Elimina
+ Exportar
+ Restablir
+ Afegir
+ Eliminar
+ Neteja
+ Protocol
+ Port d\'origen
+ Adreça de destí
+ Port de destinació
+ Aplicació de destí
+ Per a servidor extern seleccioneu \'cap\'
+ Defecte (llistat blanc/negre)
+ Blocar Wi-Fi
+ Blocar mòbil
+ Permetre Wi-Fi amb pantalla encesa
+ Permetre mòbil amb pantalla encesa
+ Blocar itinerància
+ Opcions
+ Tema: %1$s
+ Utilitza un tema fosc
+ Notificar noves instal·lacions
+ Aplica regles \'quan pantalla encesa\'
+ Auto activació després de %1$s minuts
+ Retard de pantalla apagada en %1$s minuts
+ Comprova si hi ha actualitzacions
+ Preferències de xarxa
+ Ruta de subxarxa
+ Permet ancoratge
+ Permet accessos LAN
+ Habilita tràfic IPv6
+ Xarxes de Wi-Fi pròpies: %1$s
+ Gestionar mètrica de xarxes Wi-Fi
+ No tractes mètriques en 2G
+ No tractes mètriques en 3G
+ No tractes mètriques en LTE
+ Ignora la itinerància al país
+ Ignora la itinerància dins la UE
+ Deshabilita en telefonades
+ Bloca Wi-Fi
+ Bloca dades mòbils
+ Recarrega en canviar connectivitat
+ Opcions avançades
+ Gestiona les apps del sistema
+ Registre d\'accés a internet
+ Avisa en accedir a internet
+ Filtra el tràfic
+ Filtra el tràfic UDP
+ Transferència suau de VPN en recarregar
+ Tanca les connexions en recarregar
+ Bloca el tràfic
+ Monitora l\'ús de la xarxa
+ Reinicialitza l\'ús de xarxa
+ Mostra els noms de domini resolts
+ Bloca noms de dominis
+ Codi de resposta DNS: %s
+ Desviació de ports
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Valida en: %s
+ DNS TTL mínim: %s s
+ Empra intermediari SOCKS5
+ Adreça SOCKS5: %s
+ Port SOCKS5: %s
+ Nom d\'usuari SOCKS5: %s
+ Mot de pas SOCKS5: %s
+ Pes del registre PCAP: %s B
+ Pes màxim del fitxer PCAP: %s MB
+ Guaita cada %s minuts
+ Avís de velocitat
+ Mostra l\'avís de velocitat
+ Mostra les apps destacades
+ Interval de mostreig: %s ms
+ Nombre de mostreig: %s s
+ Còpies
+ Exporta preferències
+ Importa preferències
+ Importa fitxer hosts
+ Importa fitxer host (adjunt)
+ URL de descarrega del fitxer Hosts
+ Descarregar fitxer hosts
+ Informació tècnica
+ General
+ Xarxes
+ Subscripcions
+ Mostra la notificació a la barra d\'estat per a configurar noves apps instal·lades (característica pro)
+
diff --git a/NetGuard/app/src/main/res/values-cs-rCZ/strings.xml b/NetGuard/app/src/main/res/values-cs-rCZ/strings.xml
new file mode 100644
index 0000000..f3106bc
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-cs-rCZ/strings.xml
@@ -0,0 +1,292 @@
+
+
+ NetGuard nabízí jednoduché i pokročilé způsoby pro blokování přístupu k Internetu - vše bez potřeby rootu. Aplikacím a adresám lze individuálně povolit či zakázat přístup k Vašemu Wi-Fi a/nebo datovému připojení.
+ NetGuard vyžaduje Android 5.1 nebo novější
+ Xposed způsobuje příliš mnoho pádů, což by mohlo vést k odstranění NetGuard z Obchodu Google Play. NetGuard proto není podporován, pokud je nainstalován Xposed
+ Zásady soukromí
+ Vývoji a testování NetGuardu byla věnována velká péče. Není však možné garantovat bezchybné fungování na všech zařízeních.
+ Souhlasím
+ Nesouhlasím
+ NetGuard potřebuje vaši pomoc. Stiskněte pro zakoupení Pro-funkcí a zajistěte tak pokračování projektu.
+ Spuštěné služby
+ Obecná oznámení
+ Oznámení o přístupu
+ Hledat aplikaci
+ Filtrovat aplikace
+ Zobrazit uživatelské aplikace
+ Zobrazit systémové aplikace
+ Zobrazit aplikace bez internetu
+ Zobrazit zakázané aplikace
+ Řadit aplikace
+ Řadit podle názvu
+ Řadit podle uid
+ Řadit podle využití dat
+ Zobrazit protokol
+ Nastavení
+ Pozvat
+ Legenda
+ Podpora
+ O programu
+ Další aplikace
+ Další
+ Povoleno
+ Blokováno
+ Přímá aktualizace
+ Načíst znovu
+ Zobrazit názvy
+ Zobrazit organizaci
+ PCAP povolen
+ PCAP export
+ Vymazat
+ Export
+ Obnovit
+ Přidat
+ Odstranit
+ Vyčištit
+ Protokol
+ Zdrojový port
+ Cílová adresa
+ Cílový port
+ Cílová aplikace
+ Pro externí server zvolte \'nikdo\'
+ Výchozí nastavení (bílá/černá listina)
+ Blokovat Wi-Fi
+ Blokovat mobilní data
+ Povolit Wi-Fi při zapnuté obrazovce
+ Povolit mobilní data při zapnuté obrazovce
+ Blokovat roaming
+ Možnosti
+ Vzhled: %1$s
+ Použít tmavý motiv
+ Upozornit na novou instalaci
+ Aplikovat pravidla \'při zapnuté obrazovce\'
+ Automaticky povolit po %1$s minutách
+ Odložit pravidla vypnuté obrazovky o %1$s minut
+ Zkontrolovat aktualizace
+ Možnosti sítě
+ Směrování podsítě
+ Povolit sdílení Internetu
+ Povolit přístup do LAN
+ Povolit IPv6 přenosy
+ Domácí sítě Wi-Fi: %1$s
+ Obsluhovat účtované sítě Wi-Fi
+ Považovat 2G za neomezené
+ Považovat 3G za neomezené
+ Považovat LTE za neomezené
+ Ignorovat vnitrostátní roaming
+ Ignorovat EU roaming
+ Vypnout během hovoru
+ Blokovat provoz Wi-Fi
+ Blokovat provoz přes mobilni data
+ Načíst znovu při každé změně připojení
+ Pokročilé možnosti
+ Spravovat systémové aplikace
+ Protokolovat přístup k Internetu
+ Upozornit na připojení k Internetu
+ Filtrovat přenosy
+ Filtrovat UDP přenosy
+ Plynulé předání VPN při znovunačtení
+ Ukončit spojení při znovunačtení
+ Blokovat veškeré přenosy
+ Sledovat využití sítě
+ Resetovat využití sítě
+ Zobrazit přeložené názvy domén
+ Blokovat názvy domén
+ Kód odpovědi DNS: %s
+ Přesměrování portů
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Ověřit na: %s
+ Minimální DNS TTL: %s s
+ Použít SOCKS5 proxy
+ SOCKS5 adresa: %s
+ SOCKS5 port: %s
+ SOCKS5 uživatelské jméno: %s
+ SOCKS5 heslo: %s
+ Velikost záznamu PCAP: %s B
+ Max. velikost souboru PCAP: %s MB
+ Hlídač: každých %s minut
+ Oznámení o rychlosti
+ Zobrazit oznámení o rychlosti
+ Zobrazit top aplikace
+ Interval vzorkování: %s ms
+ Počet vzorků: %s
+ Záloha
+ Exportovat nastavení
+ Importovat nastavení
+ Importovat soubor hosts
+ Importovat soubor hosts (připojit)
+ Adresa URL souboru hosts
+ Stáhnout soubor hosts
+ Technické informace
+ Obecné
+ Sítě
+ Předplatné
+ Zobrazit upozornění ve stavovém řádku pro přímé nastavení nově instalovaných aplikací (verze Pro)
+ Po zakázání skrze widget automaticky povolit NetGuard po zvoleném počtu minut (zadejte nulu pro vypnutí této volby)
+ Po vypnutí obrazovky ponechat v platnosti pravidla pro zapnutou obrazovku po zvolený počet minut (zadejte nulu pro vypnutí této volby)
+ Kontrolovat nové verze v GitHub dvakrát denně
+ V závislosti na verzi systému Android, sdílení internetu (tethering) může nebo nemusí fungovat. Sdílenou síťovou komunikaci nelze filtrovat.
+ Povolit směrování podsítě; může umožnit volání skrze Wi-Fi, ale také může vyvolat chyby v systému Android a zvýšit využití baterie
+ Povolit aplikacím připojení k adresám místní sítě, např. 10.0.0.0/8, 172.16.0.0/12 a 192.168.0.0/16
+ Přesměrovat IPv6 přenosy do NetGuardu, aby je bylo možné selektivně zakázat nebo povolit
+ Použít pravidla Wi-Fi pouze pro zvolené sítě (ostatní Wi-Fi sítě budou používat pravidla pro mobilní sítě)
+ Použít pravidla mobilní sítě pro účtované (placené, sdílené) sítě Wi-Fi
+ Použít pravidla Wi-Fi pro 2G datová připojení
+ Použít pravidla Wi-Fi pro 3G datová připojení
+ Použít pravidla Wi-Fi pro LTE datová připojení
+ Nepoužívat pravidla pro roaming, pokud je SIM a země mobilní sítě totožná
+ Nepoužívat pravidla pro roaming, pokud je SIM a mobilní síť v zemích EU (ceny jako doma)
+ Zakázat NetGuard při příchozím nebo odchozím telefonním hovoru. Může vyřešit problémy s IP/Wi-Fi voláním.
+ Definovat pravidla pro systémové aplikace (pro odborníky)
+ Zaznamenávat do protokolu pokusy aplikací o přístup k internetu. Může mít vliv na spotřebu baterie.
+ Zobrazit upozornění ve stavovém řádku při pokusu aplikace o přístup k nové internetové adrese (při zakázaném filtrování budete upozorněni pouze na zablokované přístupy)
+ Filtrovat IP pakety procházející VPN tunelem směrem ven. Může mít vliv na spotřebu baterie.
+ Sledovat počet odeslaných a přijatých bytů pro každou aplikaci a adresu. Může mít vliv na spotřebu baterie.
+ Blokovaným doménám odpovídat přednastaveným kódem DNS odpovědi. Tato možnost je zakázána pokud není k dispozici soubor hosts.
+ Výchozí hodnota je 3 (NXDOMAIN), což znamená \'neexistující doména\'.
+ Název domény použitý pro validaci internetového spojení na portu 443 (https).
+ Pouze TCP přenosy budou přenášeny skrze proxy server
+ Pravidelně kontrolovat, zda NetGuard stále běží (zadejte nulu pro vypnutí). Toto nastavení může mít vliv na spotřebu.
+ Zobrazit graf rychlosti sítě v notifikační liště
+ Jste si jistý?
+ Vynucení pravidel
+ povoleno: %1$d | blokováno: %2$d
+ povoleno: %1$d | blokováno: %2$d | hosts: %3$d
+ Čekání na událost
+ NetGuard je deaktivován, použijte přepínač výše pro jeho aktivaci
+ NetGuard byl deaktivován, pravděpodobně jinou aplikací používající VPN rozhraní
+ \'%1$s\' nainstalováno
+ Instalace dokončena
+ %1$s se pokusil o přístup k internetu
+ Pokus o přístup do Internetu
+ Akce byla dokončena
+ NetGuard používá lokální VPN pro filtrování internetového provozu.
+Z tohoto důvodu prosím povolte VPN připojení v následujícím dialogu.
+Váš internetový provoz není odesílán žádnému vzdálenému VPN serveru.
+ NetGuard nemůže být spuštěn automaticky při startu zařízení kvůli chybě ve Vaší verzi Androidu.
+ Došlo k neočekávané chybě: \'%s\'
+ Android odmítl spustit službu VPN. Může to být způsobeno chybou ve vaší verzi Androidu.
+ Vyzkoušet NetGuard
+ Darováním souhlasíte s podmínkami& služby
+ Pokud v následujícím dialogu nelze potvrdit OK, jiná aplikace (např. barevný filtr) pravděpodobně překrývá obrazovku.
+ ± %1$.3f▲ %2$.3f▼ MB/den
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Pro optimální výsledky by pro NetGuard měla být vypnuta optimalizace spotřeby baterie.
+\n\nV následujícím dialogu nahoře se přepněte na \"Všechny aplikace\", v seznamu vyberte NetGuard a označte a potvrďte volbu \"Neoptimalizovat\".
+ Pro optimální výsledky by pro NetGuard měly být vypnuty funkce úspory dat systému Android
+\n\nV následujícím dialogu povolte možnosti \"Data na pozadí\" a \"Neomezené využití dat\"
+ Použití filtrování způsobí, že systém Android přiřadí využití dat a baterie aplikaci NetGuard, namísto původním aplikacím
+ Android 4 vyžaduje zapnuté filtrování
+ Záznam síťových přenosů do protokolu je vypnutý, použijte přepínač výše pro jeho zapnutí. Může mít vliv na spotřebu baterie.
+ Resetuje pravidla a podmínky do výchozího nastavení
+ Smaže protokol pokusů o přístup, pravidla povolení/blokování zůstanou nedotčena
+ Poslední import: %s
+ Stahuji\n%1s
+ Soubor hosts úspěšně stažen
+ Poslední stažení: %s
+ Začít přesměrovávat z %1$s port %2$d na %3$s:%4$d z \'%5$s\'?
+ Přestat přesměrovávat %1$s port %2$d?
+ Síť je účtovaná
+ Žádné aktivní připojení k Internetu
+ NetGuard je zaneprázdněn
+ Aktualizace k dispozici, stiskněte pro stažení
+ Můžete povolit (zelená) nebo zakázat (červená) přístup k internetu pro Wi-Fi či mobilní připojení stisknutím ikon vedle aplikace
+ Pokud jste si NetGuard nainstalovali aby chránil vaše soukromí, mohl by vás zaujmout i FairEmail , e-mailový klient s otevřeným kódem zaměřený na soukromí
+ Přístup k internetu je ve výchozím stavu povolený (režim černé listiny), může být změněno v nastavení
+ Příchozí (push) zprávy jsou většinou zpracovány systémovou součástí služeb Play, která má ve výchozím stavu internetový přístup povolený
+ Správu všech (systémových) aplikací lze povolit v nastavení
+ Prosím, popište problém a uveďte čas kdy k němu došlo:
+ VPN spojení ukončeno\nNenastavili jste jinou VPN jako trvalou síť VPN?
+ Při vypnutí zařízení s povoleným NetGuardem bude NetGuard při zapnutí automaticky spuštěn
+ Tato funkce není na této verzi Androidu k dispozici
+ Jiná VPN je nastavena jako Trvalá síť VPN
+ Vypněte \"Blokovat připojení bez VPN\" v Android VPN nastavení pro použití NetGuard filtrovacího režimu
+ Vypněte \"Soukromé DNS\" v nastavení sítě androidu pro použití NetGuardu v režimu filtrování
+ Veškeré přenosy jsou blokovány
+ Neomezené přenosy jsou povoleny
+ Neomezené přenosy jsou blokovány
+ Pravidla pro neomezená připojení nejsou aplikována
+ Účtované přenosy jsou povoleny
+ Účtované přenosy jsou blokovány
+ Pravidla pro účtovaná připojení nejsou aplikována
+ Adresa je povolena
+ Adresa je blokována
+ Povolit při zapnuté obrazovce
+ Blokovat při roamingu
+ Ve výchozím stavu je připojení Wi-Fi považováno za neomezené a mobilní připojení za účtované
+ nemá oprávnění pro přístup k internetu
+ je zakázáno
+ Příchozí zprávy jsou přijímány službami Google Play a ne touto aplikací a nemohou být proto blokovány zablokováním této aplikace
+ Stahování jsou prováděna správcem stahování a nikoliv touto aplikací a nelze je proto zablokovat blokováním této aplikace
+ Nastavit pravidla a podmínky
+ Podmínky
+ Povolit Wi-Fi při zapnuté obrazovce
+ Povolit mobilní data při zapnuté obrazovce
+ R
+ Blokovat při roamingu
+ Povolit v režimu blokování všech přenosů
+ Filtrovat související
+ Pokusy o přístup
+ Pravidla přístupu mají přednost před ostatními pravidly
+ Možnosti
+ Upozorňovat na pokusy o přístup k internetu
+ Záznam nebo filtrování síťových přenosů není zapnuto
+ Záznam a filtrování síťových přenosů je zapnuto
+ Nastavit
+ Povolit záznamenávání pouze blokovaných adres
+ Zapnout také filtrování pro záznam povolených adres
+ Povolit oznámení o přístupu pro nově zaznamenané adresy
+ Tato nastavení jsou globální nastavení, která se aplikují na všechny aplikace
+ Filtrování je také vyžadováno, aby bylo možné povolit nebo blokovat jednotlivé adresy
+ Povolení záznamu (méně) nebo filtrování (více) může zvýšit využití baterie a ovlivnit rychlost sítě
+ Ohodnotit
+ Povolit
+ Blokovat
+ Povolit Wi-Fi
+ Blokovat Wi-Fi
+ Povolit mobilní data
+ Blokovat mobilní data
+ root
+ mediaserver
+ nikdo
+ Znovu se neptat
+ Whois %1$s
+ Port %1$d
+ Kopírovat
+ Pro funkce
+ K dispozici jsou následující Pro funkce:
+ Zobrazit protokol zablokovaného provozu
+ Filtrovat síťové přenosy
+ Upozornění na nové aplikace
+ Oznámení s grafem rychlosti sítě
+ Vzhled (téma, barvy)
+ Všechny výše uvedené Pro funkce
+ Podpořit vývoj
+ Zakoupit
+ Povoleno
+ Nedostupné
+ Stiskněte název pro více informací
+ Výzva
+ Odpověď
+ Toto je Pro funkce
+ Měsíční předplatné ve výši 1 nebo 2 EUR (bez DPH) aktivuje všechny Pro funkce.
+ Předplatné můžete zrušit nebo spravovat skrze záložku předplatné v aplikaci Obchod Play.
+
+
+ - modro-zelená/oranžová
+ - modrá/oranžová
+ - fialová/červená
+ - jantarová/modrá
+ - oranžová/šedá
+ - zelená
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-da-rDK/strings.xml b/NetGuard/app/src/main/res/values-da-rDK/strings.xml
new file mode 100644
index 0000000..358e5bf
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-da-rDK/strings.xml
@@ -0,0 +1,292 @@
+
+
+ NetGuard tilbyder enkle og avancerede metoder til blokering af Internetadgang - ingen Root-rettighed krævet. Apps og adresser kan individuelt tillades eller nægtes adgang til din Wi-Fi- og/eller mobilforbindelse.
+ NetGuard kræver Android 5.1 eller senere
+ Xposed forårsager for mange nedbrud, som kan medføre, at NetGuard fjernes fra Google Play Butik. Derfor understøttes NetGuard er ikke, så længe Xposed er installeret
+ Fortrolighedspolitik
+ Stor omhu er lagt i at udvikle og teste NetGuard, men det er umuligt at garanterer, at NetGuard vil fungere korrekt på alle eksisterende enheder.
+ Jeg accepterer
+ Jeg accepterer ikke
+ NetGuard behøver din hjælp. Tryk for at købe pro funktioner for at holde projektet igang.
+ Aktive tjenester
+ Generelle notifikationer
+ Adgangsnotifikationer
+ Søg efter app
+ Filtrér apps
+ Vis bruger-apps
+ Vis systemapps
+ Vis apps uden Internet
+ Vis deaktiverede apps
+ Sortér apps
+ Sortér efter navn
+ Sortér efter UID
+ Sortér efter dataforbrug
+ Vis log
+ Indstillinger
+ Invitér
+ Forklaring
+ Support
+ Om
+ Andre apps
+ Øvrigt
+ Tilladt
+ Blokeret
+ Live-opdatering
+ Opfrisk
+ Vis navne
+ Vis organisation
+ PCAP aktiveret
+ PCAP-eksport
+ Ryd
+ Eksportér
+ Nulstil
+ Tilføj
+ Slet
+ Oprydning
+ Protokol
+ Kildeport
+ Destinationsadresse
+ Destinationsport
+ Destinations-app
+ For ekstern server, vælg \'ingen\'
+ Standarder (Hvid-/Sortlister)
+ Blokér Wi-Fi
+ Blokér mobildata
+ Tillad Wi-Fi når skærmen er tændt
+ Tillad mobildata når skærmen er tændt
+ Blokér roaming
+ Indstillinger
+ Tema: %1$s
+ Benyt mørkt tema
+ Notificér ved ny installation
+ Anvend \'når skærm er tændt\'-regler
+ Auto-aktivér efter %1$s minutter
+ Forsink skærmslukning %1$s minutter
+ Søg efter opdateringer
+ Netværksindstillinger
+ Subnet routing
+ Tillad kabling
+ Tillad LAN-adgang
+ Aktivér IPv6-trafik
+ Wi-Fi-hjemmenetværk: %1$s
+ Håndtér forbrugsafregnede Wi-Fi-netværk
+ Betragt 2G som ikke-forbrugsafregnet
+ Betragt 3G som ikke-forbrugsafregnet
+ Betragt LTE som ikke-forbrugsafregnet
+ Ignorér national roaming
+ Ignorér EU-roaming
+ Deaktivér ved opkald
+ Aflås Wi-Fi
+ Afslås mobil
+ Genindlæs ved hver forbindelsesændring
+ Avancerede indstillinger
+ Håndtér systemapps
+ Log Internetadgang
+ Notificér ved Internetadgang
+ Filtrér trafik
+ Filtrér UDP-trafik
+ Problemfri VPN-overdragelse ved genindlæsning
+ Luk forbindelse ved genindlæsning
+ Aflås trafik
+ Spor netværksforbrug
+ Nulstil netværksforbrug
+ Vis opløste domænenavne
+ Blokér domænenavne
+ DNS-svarkode: %s
+ Port-viderestilling
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Validér på: %s
+ Minimum DNS TTL: %s s
+ Benyt SOCKS5-proxy
+ SOCKS5-adresse: %s
+ SOCKS5-port: %s
+ SOCKS5-brugernavn: %s
+ SOCKS5-adgangskode: %s
+ PCAP-logstørrelse: %s B
+ PCAP maks. filstørrelse: %s MB
+ Vagthund: Hvert %s. minut
+ Hastigheds-notifikation
+ Vis hastigheds-notifikation
+ Vis top apps
+ Samplingsinterval: %s ms
+ Samplingsfrekvens: %s s
+ Sikkerhedskopiering
+ Eksportér indstillinger
+ Importér indstillinger
+ Importér hosts-fil
+ Importér værtsfil (tilføj)
+ Hosts-fil download-URL
+ Download hosts-fil
+ Tekniske oplysninger
+ Generelt
+ Netværk
+ Abonnementer
+ Vis statusbjælkenotifikation for direkte opsætning af nyligt installerede apps (Pro-funktion)
+ Efter deaktivering vha. widget\'en, genaktivér automatisk NetGuard efter det valgte antal minutter (angiv 0 for at deaktivere denne funktion)
+ Efter slukning af skærm, bevar skærmen aktiv i det valgte antal minutter (angiv 0 for at deaktivere denne funktion)
+ Søg to gange dagligt efter nye udgivelser på GitHub
+ Afhængig af Android-version, vil kabling muligvis, eller muligvis ikke, fungere. Kablet trafik kan ikke filtreres.
+ Aktivering af subnet routing aktiverer muligvis også Wi-Fi-opkald, men kan ligeledes fremprovokere fejl i Android og forøge batteriforbruget
+ Tillad apps at oprette forbindelse til lokale netværksadresser såsom 10.0.0.0/8, 172.16.0.0/12 og 192.168.0.0/16
+ Route IP V6-trafik til NetGuard, så denne selektivt kan blive tilladt eller blokeret
+ Anvend kun Wi-Fi-netværksregler på udvalgte netværk (anvend mobilnetværksregler på andre Wi-Fi-netværk)
+ Anvend mobilenetværksregler på forbrugsafregnede (betalte, kablede) Wi-Fi-netværk
+ Anvend Wi-Fi-netværksregler på 2G-dataforbindelser
+ Anvend Wi-Fi-netværksregler på 3G-dataforbindelser
+ Anvend Wi-Fi-netværksregler på LTE-dataforbindelser
+ Anvend ikke roaming-regler, når SIM-korts- og mobilnetværksland er det samme
+ Anvend ikke roaming-regler, når SIM- og mobilnetværksland er indenfor EU (roam som i hjemlandet)
+ Deaktivér NetGuard ved ind- eller udgående telefonopkald. Dette kan benyttes som en løsning ved IP/Wi-Fi-opkaldsproblemer.
+ Definér regler for system-apps (avanceret)
+ Log forsøg på Internetadgang for apps. Dette kan medføre forøget strømforbrug.
+ Vis en statusbjælkenotifikation, når en app forsøger at tilgå en ny Internetadresse (er filtrering inaktiv, vil kun blokerede Internetadgangsforsøg generere notifikationer)
+ Filtrér udgående IP-pakker i VPN-tunnelen. Dette kan medføre forøget strømforbrug.
+ Spor antal afsendte og modtagne bytes for hver app og adresse. Dette kan medføre forøget strømforbrug.
+ Besvar med opsat DNS-svarkode til blokerede domænenavne. Denne omskifter er inaktiv, såfremt ingen hosts-filer er tilgængelige.
+ Standardværdien er 3 (NXDOMAIN), som betyder \'ikke-eksisterende domæne\'.
+ Domænenavn benyttet til validering af Internetforbindelsen på port 443 (HTTPS).
+ Kun TCP-trafik sendes til proxy-serveren
+ Kontrollér periodisk at NetGuard stadig kører (angiv 0 for at deaktivere denne funktion). Dette kan medføre forøget strømforbrug.
+ Vis netværkshastighedsgraf i statusbjælkenotifikation
+ Er du sikker?
+ Håndhæver regler
+ %1$d tilladt, %2$d blokeret
+ %1$d tilladt, %2$d blokeret, %3$d hosts
+ Afventer begivenhed
+ NetGuard er inaktiv. Benyt kontakten ovenfor for at aktivere NetGuard
+ NetGuard er blevet deaktiveret formentlig grundet brug af anden VPN-baseret app
+ \'%1$s\' installeret
+ Er blevet installeret
+ %1$s internetadgangsforsøg
+ Internetadgangsforsøg
+ Handling fuldført
+ NetGuard benytter et lokalt VPN for at filtrere Internettrafik.
+Af samme årsag bedes VPN-forbindelsen tillades i næste dialog.
+Din Internettrafik sendes ikke til en ekstern VPN-server.
+ NetGuard kunne ikke starte automatisk. Dette beror sandsynligvis på en fejl i din Android-version.
+ En uventet fejl er opstået: %s
+ Android nægter i øjeblikket at starte VPN-tjenesten. Dette beror sandsynligvis på en fejl i din Android-version.
+ Prøv NetGuard
+ Ved at donere, accepterer du vilkårene og betingelserne
+ Kan du ikke trykke OK i næste dialog, så håndteres skærmen sandsynligvis af en anden (skærmnedtonings-) app.
+ ± %1$.3f▲ %2$.3f▼ MB/dag
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Med henblik på ensartethed i resultaterne, bør Androids batterioptimering ikke inkludere NetGuard.\n\n
+Vælg \"Alle apps\" øverst i den næste dialog, tryk på NetGuard på listen og vælg - og bekræft - \"Optimér ikke\".
+ Med henblik på ensartethed i resultaterne, bør Androids datasparefunktion ikke inkludere NetGuard.\n\n
+Aktivér venligst indstillingerne \"Baggrundsdata\" og \"Ubegrænset dataforbrug\" i næste dialog
+ Anvendelse af filtrering vil foranledige Android til at antage, at data- og strømforbrug hidrører fra NetGuard og ikke fra de oprindelige apps
+ Android 4 kræver, at filtrering er aktiv
+ Trafik-logning er inaktiv. Benyt kontakten ovenfor for at aktivere logning. Trafik-logning kan medføre forøget strømforbrug.
+ Dette vil nulstille regler og betingelser til deres standardværdier
+ Dette vil slette loglinjerne for adgangsforsøg uden tillad/blokér regler
+ Seneste import: %s
+ Downloader\n%1s
+ Værtsfil downloadet
+ Seneste download: %s
+ Start viderestilling af \'%5$s\' fra %1$s port %2$d til %3$s:%4$d?
+ Stop viderestilling af %1$s port %2$d?
+ Netværk er forbrugsafregnet
+ Ingen aktiv Internetforbindelse
+ NetGuard er optaget
+ Opdatering tilgængelig, tryk for at downloade
+ Du kan tillade (grønlig) eller nægte (rødlig) Wi-Fi eller mobil Internetadgang ved at trykke på ikonet ved siden af en app
+ Installerede du NetGuard for at beskytte dit privatliv, kan FairEmail , en open source, privatlivsorienteret e-mail app, måske også have din interesse
+ Internetadgang er som standard tilladt (sortlistetilstand), hvilket dog kan ændres i indstillingerne
+ Push-beskeder håndteres primært af systemkomponenten Play-tjenester, der som standard tillader Internetadgang
+ Håndtering af alle (system-)apps kan aktiveres i indstillingerne
+ Beskriv venligst problemet og angiv tidspunkt for problemet:
+ VPN-forbindelse annulleret\nHar du opsat en anden VPN til at være en \'altid aktiv VPN\'?
+ Nedlukning af din enhed med NetGuard aktiv vil automatisk starte NetGuard ved genopstart af din enhed
+ Funktionen er utilgængelig i denne Android-version
+ En anden VPN er opsat som Altid Aktiv-VPN
+ Slå \"Blokér forbindelser uden VPN\" fra i Android VPN-indstillinger for at benytte NetGuard i filtreringstilstand
+ Slå \"Private DNS\" fra i networksindstillinger for at benytte NetGuard i filtreringstilstand
+ Trafik er aflåst
+ Ikke-forbrugsafregnet trafik er tilladt
+ Ikke-forbrugsafregnet trafik er blokeret
+ Fastprisadgangsregler anvendes ikke
+ Forbrugsafregnet trafik er tilladt
+ Forbrugsafregnet trafik er blokeret
+ Forbrugsafregningsregler anvendes ikke
+ Adresse er tilladt
+ Adresse er blokeret
+ Tillad, når skærm er tændt
+ Blokér under roaming
+ Som standard betragtes en Wi-Fi-forbindelse som ikke-forbrugsafregnet og en mobilforbindelse som forbrugsafregnet
+ har ingen Internettilladelse
+ er deaktiveret
+ Indgående beskeder modtages af Google Play-tjenester og ikke af denne app. De kan derfor ikke blokeres ved at blokere denne app
+ Downloads udføres af download-håndteringren og ikke af denne app, og de kan derfor ikke blokeres ved at blokere denne app
+ Anvend regler og betingelser
+ Betingelser
+ Tillad Wi-Fi, når skærmen er tændt
+ Tillad mobildata, når skærmen er tændt
+ R
+ Blokér under roaming
+ Tillad i aflåst tilstand
+ Filtér relaterede
+ Adgangsforsøg
+ Adgangsregler har forrang over andre regler
+ Indstillinger
+ Notificér ved Internetadgangsforsøg
+ Logning eller filtrering er ikke aktiv
+ Logning og filtrering er aktiv
+ Opsæt
+ Aktivér kun logring af blokerede adresser
+ Aktivér filtrering for også at logge tilladte adresser
+ Aktivér adgangsnotifikationer for nyligt registrerede adresser
+ Disse indstillinger er globale og gælder for alle apps
+ Filtrering kræves også for at tillade eller blokere individuelle adresser
+ Strømforbrug og netværksbelastning forøges muligvis ved aktivering af logning (i mindre omfang) eller filtrering (i større omfang)
+ Bedøm
+ Tillad
+ Blokér
+ Tillad Wi-Fi
+ Blokér Wi-Fi
+ Tillad mobildata
+ Blokér mobildata
+ Root
+ medieserver
+ ingen
+ Spørg ikke igen
+ WHOIS %1$s
+ Port %1$d
+ Kopiér
+ Pro-funktioner
+ Følgende Pro-funktioner er tilgængelige:
+ Se blokeret trafik-log
+ Filtrér netværkstrafik
+ Ny app notifikation
+ Netværkshastighedsgraf-notifikation
+ Udseende (tema, farver)
+ Alle ovenstående Pro-funktioner
+ Støt udviklingen
+ Køb
+ Aktiveret
+ Utilgængelig
+ Tryk på en titel for yderligere oplysninger
+ Udfordring
+ Svar
+ Dette er en Pro-funktion
+ Et månedligt abonnement på 1 eller 2 euro (ekskl. lokal moms) vil aktivere alle Pro-funktioner.
+ Du kan afmelde eller håndtere et abonnement via fanen Abonnementer i Play Butik-appen.
+
+
+ - blågrøn/orange
+ - blå/orange
+ - lilla/rød
+ - rav/blå
+ - orange/grå
+ - grøn
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-de-rDE/strings.xml b/NetGuard/app/src/main/res/values-de-rDE/strings.xml
new file mode 100644
index 0000000..58e53de
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-de-rDE/strings.xml
@@ -0,0 +1,288 @@
+
+
+ NetGuard bietet einfache und erweiterte Möglichkeiten, um Zugriffe auf das Internet zu blockieren - keine Root-Rechte erforderlich! Anwendungen und Adressen kann der Zugriff auf die WLAN- und/oder mobile Datenverbindung einzeln erlaubt oder verweigert werden.
+ NetGuard erfordert Android 5.1 oder höher
+ Xposed verursacht sehr viele Abstürze, was dazu führen kann, dass NetGuard aus dem Google Play Store entfernt werden könnte. Deshalb wird NetGuard nicht unterstützt, solange Xposed installiert ist
+ Datenschutzerklärung
+ Die Entwicklung und das Testen von NetGuard wurden mit großer Sorgfalt durchgeführt, jedoch kann nicht garantiert werden, dass NetGuard auf jedem Gerät korrekt funktioniert.
+ Zustimmen
+ Ablehnen
+ NetGuard braucht Ihre Hilfe. Tippen Sie auf Pro-Funktion kaufen, um das Projekt weiterentwickeln zu können.
+ Aktive Dienste
+ Allgemeine Benachrichtigungen
+ Auf Benachrichtigungen zugreifen
+ Nach App suchen
+ Anwendungen filtern
+ Benutzeranwendungen anzeigen
+ Systemanwendungen anzeigen
+ Anwendungen ohne Internet anzeigen
+ Deaktivierte Anwendungen anzeigen
+ Anwendungen sortieren
+ Nach Namen sortieren
+ Nach UID sortieren
+ Nach Datennutzung sortieren
+ Protokoll anzeigen
+ Einstellungen
+ Einladung
+ Legende
+ Hilfe
+ Über
+ Andere Apps
+ Andere
+ Erlaubt
+ Blockiert
+ Live-Updates
+ Aktualisieren
+ Namen anzeigen
+ Organisation zeigen
+ PCAP aktiviert
+ PCAP exportieren
+ Löschen
+ Export
+ Zurücksetzen
+ Hinzufügen
+ Löschen
+ Bereinigen
+ Protokoll
+ Quellport
+ Zieladresse
+ Zielport
+ Zielanwendung
+ Für einen externen Server wählen Sie \'Keiner\' aus
+ Standardeinstellungen
+ WLAN blockieren
+ Mobilfunk blockieren
+ WLAN erlauben, wenn Bildschirm eingeschaltet ist
+ Mobilfunk erlauben, wenn Bildschirm eingeschaltet ist
+ Roaming blockieren
+ Optionen
+ Design: %1$s
+ Dunkles Design verwenden
+ Benachrichtigung bei neuer Installation
+ \'Wenn Bildschirm an\' Regeln anwenden
+ Automatisch nach %1$s-Minuten aktivieren
+ Bildschirmabschaltung um %1$s Minuten verzögern
+ Nach Aktualisierungen suchen
+ Netzwerkoptionen
+ Subnet-Routing
+ Tethering erlauben
+ LAN-Zugriff erlauben
+ IPv6-Datenverkehr aktivieren
+ WLAN-Heimnetzwerk: %1$s
+ Volumenbeschränktes WLAN-Netzwerk handhaben
+ 2G als “nicht volumenbeschränkt“ betrachten
+ 3G als “nicht volumenbeschränkt“ betrachten
+ LTE als “nicht volumenbeschränkt“ betrachten
+ Nationales Roaming ignorieren
+ EU-Roaming ignorieren
+ Bei Anruf deaktivieren
+ WLAN-Zugriffsbeschränkung
+ Mobile Daten-Zugriffsbeschränkung
+ Erneut laden bei jeder Verbindungsänderung
+ Erweiterte Optionen
+ System-Apps anzeigen
+ Internetzugriff protokollieren
+ Bei Internetzugriff benachrichtigen
+ Datenverkehr filtern
+ UDP-Datenverkehr filtern
+ Nahtlose VPN-Übergabe beim Neuladen
+ Die Verbindungen beim Neuladen trennen
+ Datenverkehr-Zugriffsbeschränkung
+ Netzwerknutzung verfolgen
+ Netzwerknutzung zurücksetzen
+ Aufgelöste Domainnamen anzeigen
+ Domainnamen blockieren
+ DNS-Rückantwortcode: %s
+ Portweiterleitung
+ VPN-IPv4: %s
+ VPN-IPv6: %s
+ VPN-DNS: %s
+ Validieren unter: %s
+ Minimum DNS-TTL: %s s
+ SOCKS5-Proxy verwenden
+ SOCKS5-Adresse: %s
+ SOCKS5-Port: %s
+ SOCKS5-Benutzername: %s
+ SOCKS5-Passwort: %s
+ PCAP-Datensatzgröße: %s B
+ PCAP-Dateigröße (max): %s MB
+ Watchdog: alle %s Minuten
+ Geschwindigkeitsbenachrichtigung
+ Netzwerkgeschwindigkeit anzeigen
+ Top-Anwendungen anzeigen
+ Abtastfrequenz: %s ms
+ Abtastanzahl: %s s
+ Sicherung
+ Einstellungen exportieren
+ Einstellungen importieren
+ Hosts-Datei importieren
+ Hosts-Datei importieren (anhängen)
+ Download-URL der Hosts-Datei
+ Hosts-Datei herunterladen
+ Technische Information
+ Allgemein
+ Netzwerke
+ Abos
+ Statusleisten-Benachrichtigung anzeigen, um neu installierte Anwendungen direkt zu konfigurieren (Pro-Funktion)
+ Nach dem Deaktivieren über das Widget wird NetGuard nach einer festgelegten Anzahl von Minuten automatisch wieder aktiviert (Null eingeben zum Deaktivieren dieser Option)
+ Nach Ausschalten des Bildschirms diesen während der festgelegten Minuten aktiviert lassen (Null eingeben zum Deaktivieren dieser Option)
+ Es wird auf GitHub zweimal täglich nach neuen Versionen gesucht
+ Abhängig von der Android Version kann Tethering funktionieren. Dieser Verkehr kann nicht gefiltert werden.
+ Subnet-Routing aktivieren ermöglicht möglicherweise das Telefonieren über WLAN, triggert aber auch das Auftreten von Fehler in Android und lässt den Batterieverbrauch steigen
+ Apps den Zugriff auf lokale Netzwerkadressen wie 10.0.0.0/8, 172.16.0.0/12 und 192.168.0.0/16 erlauben.
+ IP6-Datenverkehr an NetGuard weiterleiten, so dass es selektiv zugelassen oder blockiert werden kann
+ WLAN-Regeln nur für ausgewähltes Netzwerk anwenden (Mobilfunknetz-Regeln für andere WLAN-Netzwerke anwenden)
+ Mobilfunk-Regeln auf volumenbeschränkte (kostenpflichtige, Tethering-) WLAN-Netzwerke anwenden
+ WLAN-Regeln für 2G-Datenverbindungen anwenden
+ WLAN-Regeln für 3G-Datenverbindungen anwenden
+ WLAN-Regeln für LTE-Datenverbindungen anwenden
+ Roaming-Regeln nicht anwenden, wenn die Nationalität für SIM und mobiles Netzwerk identisch sind
+ Roaming-Regeln nicht anwenden, wenn sich die Nationalitäten für SIM und mobiles Netzwerk innerhalb der EU befinden (Roaming wie Zuhause)
+ NetGuard bei ein- oder ausgehenden Anrufen deaktivieren. Dadurch können Probleme bei IP-/WLAN-Telefonie gelöst werden.
+ Regeln für System-Apps definieren (für Experten)
+ Protokoll zeichnet den Internetzugriff von Anwendungen auf (Dadurch kann ein zusätzlicher Batterieverbrauch entstehen)
+ Benachrichtigungsleiste anzeigen, wenn eine Anwendung versucht, auf eine neue Internetadresse zuzugreifen (bei deaktivierter Filterung werden nur blockierte Internet-Zugriffsversuche angezeigt)
+ IP-Pakete filtern, die den VPN-Tunnel verlassen. (Dadurch kann ein zusätzlicher Batterieverbrauch entstehen)
+ Anzahl der gesendeten und empfangenen Bytes für jede Anwendung und Adresse verfolgen. (Dadurch kann ein zusätzlicher Batterieverbrauch entstehen)
+ Mit dem festgelegten DNS-Rückantwortcode auf blockierte Domainnamen antworten. Diese Option ist deaktiviert, wenn keine Hosts-Datei zur Verfügung steht.
+ Der Standardwert ist 3 (NXDOMAIN) und bedeutet \'Nicht vorhandene Domain\'.
+ Domainname, der verwendet wird, um die Internetverbindung unter Port 443 (HTTPS) zu validieren.
+ Nur TCP-Datenverkehr wird an den Proxyserver gesendet
+ In regelmäßigen Abständen überprüfen, ob NetGuard noch läuft (Null, um diese Option zu deaktivieren). Das kann den Akkuverbrauch erhöhen!
+ Netzwerkgeschwindigkeitskurve in Statusleiste anzeigen
+ Sind Sie sicher?
+ Regeln werden angewendet
+ %1$d erlaubt, %2$d blockiert
+ %1$d erlaubt, %2$d blockiert, %3$d Hosts
+ Auf Ereignis warten
+ NetGuard ist deaktiviert. Verwenden Sie den Schalter, um NetGuard zu aktivieren.
+ NetGuard wurde deaktiviert. Wahrscheinlich durch Verwendung einer anderen VPN-Anwendung
+ \'%1$s\' installiert
+ Wurde installiert
+ %1$s versucht Internetzugriff
+ Versucht Internetzugriff
+ Aktion abgeschlossen
+ NetGuard verwendet ein lokales VPN, um den Internetverkehr zu filtern. Gestatten Sie aus diesem Grund im nächsten Dialog eine VPN-Verbindung. Ihr Internetverkehr wird nicht an einen VPN-Server gesendet!
+ NetGuard konnte aufgrund eines Fehlers Ihrer aktuellen Android-Version beim Booten nicht automatisch starten
+ Unerwarteter Fehler ist aufgetreten: \'%s\'
+ Android verhinderte den Start des VPN-Dienstes. Der Grund ist wahrscheinlich ein Fehler in der aktuellen Android-Version.
+ NetGuard ausprobieren
+ Durch eine Spende stimmen Sie den AGB zu.
+ Falls Sie nicht auf OK im nächsten Fenster tippen können, manipuliert eine andere Anwendung Ihren Bildschirm.
+ ± %1$.3f▲ %2$.3f▼ MB/Tag
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Für konsistente Ergebnisse sollten für NetGuard die Android-Batterie-Optimierungen deaktiviert werden.\n\nIm nächsten Dialogfenster wählen Sie ganz oben \"Alle Apps\", tippen auf NetGuard in der Liste und wählen und bestätigen \"Nicht optimieren\".
+ Für konsistente Ergebnisse sollten die Android-Datenspeicheroptionen für NetGuard deaktiviert werden.\n\nIm nächsten Fenster aktivieren Sie die Optionen \"Hintergrunddaten\" und \"Uneingeschränkte Datennutzung\".
+ Bei Verwendung von Filtern werden Daten- und Energiewerte erfasst und Android nimmt an, dass Daten und Energie von NetGuard statt von den ursprünglichen Anwendungen verbraucht werden
+ Android 4 erfordert die Aktivierung der Filterung.
+ Datenverkehrprotokollierung ist deaktiviert. Zum Aktivieren den Schalter oben verwenden. Die Protokollierung kann zu höherem Batterieverbrauch führen.
+ Dadurch werden die Regeln und Bedingungen auf ihre Standardwerte zurückgesetzt
+ Dadurch werden die Zugriffsversuche im Protokoll ohne Erlaubt-/Blockier-Regeln gelöscht
+ Letzter Import: %s
+ Herunterladen\n%1s
+ Hosts-Datei heruntergeladen
+ Letztes Herunterladen: %s
+ Weiterleitung von %2$d Port %1$s nach %3$s:%4$d von \'%5$s\' starten?
+ Weiterleitung von %1$s Port %2$d stoppen?
+ Volumenbeschränktes Netzwerk
+ Keine aktive Internetverbindung
+ NetGuard ist beschäftigt
+ Neue Version verfügbar, zum Herunterladen tippen
+ Sie können den Wi-Fi- oder mobilen Internet-Zugang zulassen (grünlich) oder verweigern (rötlich), indem Sie auf die Symbole neben einer Anwendung tippen
+ Falls Sie NetGuard installiert haben, um Ihre Privatsphäre zu schützen, könnten Sie auch an FairEmail , einer Open-Source- und privatsphärenfreundlichen E-Mail-App, interessiert sein
+ Internet-Zugang ist standardmäßig erlaubt. Das kann in den Einstellungen geändert werden
+ Push-Nachrichten werden normalerweise durch die Systemkomponente Play-Dienste gesteuert, dieser ist standardmäßig der Internetzugang erlaubt
+ Verwalten von Systemanwendungen kann in den erweiterten Optionen aktiviert werden
+ Bitte beschreiben Sie Ihr Problem und geben Sie den Zeitpunkt an:
+ VPN-Verbindung abgebrochen\nHaben Sie eine anderes VPN für die Funktion \'VPN immer eingeschaltet\' konfiguriert?
+ Wenn NetGuard beim Ausschalten aktiv war, dann startet NetGuard beim Einschalten automatisch wieder.
+ Diese Funktion ist in dieser Android-Version nicht verfügbar
+ Ein anderes VPN ist als \'VPN immer eingeschaltet\' festgelegt
+ Um NetGuard im Filtermodus benutzen zu können, deaktivieren Sie in den Android-VPN-Einstellungen \"Verbindungen ohne VPN blockieren\"
+ \"Private DNS\" unter Android-Netzwerkeinstellungen deaktivieren, um NetGuard im Filtermodus zu verwenden
+ Datenverkehr ist eingeschränkt
+ Netzwerkverkehr ohne Volumenbeschränkung ist erlaubt
+ Nicht volumenbeschränkter Verkehr ist blockiert
+ Unbeschränkte Regeln wurden nicht angewendet
+ Volumenbeschränkter Verkehr ist erlaubt
+ Volumenbeschränkter Verkehr ist blockiert
+ Beschränkte Regeln wurden nicht angewendet
+ Adresse ist erlaubt
+ Adresse ist blockiert
+ Erlauben, wenn Bildschirm an
+ Bei Roaming blockieren
+ Standardmäßig wird eine WLAN-Verbindung als nicht volumenbeschränkt und eine mobile Verbindung als volumenbeschränkt betrachtet.
+ hat keine Internet-Berechtigung
+ ist deaktiviert
+ Eingehende Nachrichten werden von den Google Play-Diensten empfangen und nicht von dieser App und können daher nicht durch Blockieren dieser App blockiert werden
+ Downloads werden vom Download-Manager durchgeführt und nicht von dieser App und können daher nicht durch Blockieren dieser App verhindert werden
+ Regeln und Bedingungen anwenden
+ Bedingungen
+ WLAN erlauben, wenn Bildschirm eingeschaltet ist
+ Mobilfunk erlauben, wenn Bildschirm eingeschaltet ist
+ R
+ Bei Roaming blockieren
+ Im Zugriffsbeschränkungsmodus erlauben
+ Filterabhängig
+ Zugriffsversuche
+ Zugriffsregeln haben vor anderen Regeln Vorrang
+ Optionen
+ Bei Internetzugriffsversuchen benachrichtigen
+ Protokollierung oder Filterung ist nicht aktiviert
+ Protokollierung und Filterung sind aktiviert
+ Konfigurieren
+ Nur die Protokollierung für blockierte Adressen aktivieren
+ Auch die Filterung für die Protokollierung erlaubter Adressen aktivieren
+ Zugriffsbenachrichtigungen für kürzlich protokollierte Adressen aktivieren
+ Diese Einstellungen sind globale Einstellungen, die für alle Apps gelten.
+ Die Filterung ist auch für das Zulassen oder Blockieren einzelner Adressen erforderlich.
+ Die Protokollierung (weniger) oder Filterung (mehr) kann den Batterieverbrauch erhöhen und die Netzwerkgeschwindigkeit beeinflussen.
+ Bewerten
+ Erlauben
+ Sperren
+ WLAN erlauben
+ WLAN blockieren
+ Mobile Daten erlauben
+ Mobile Daten blockieren
+ root
+ Medienserver
+ Keiner
+ Nicht erneut fragen
+ Wer ist %1$s
+ Port %1$d
+ Kopieren
+ Pro-Funktionen
+ Die folgenden Pro-Funktionen sind verfügbar:
+ Protokoll des blockierten Verkehrs anzeigen
+ Netzwerkverkehr filtern
+ Benachrichtigung über neue App
+ Benachrichtigung mit Netzwerkgeschwindigkeitsgrafik
+ Aussehen (Design, Farben)
+ Alle oben stehenden Pro-Funktionen
+ Entwicklung unterstützen
+ Kaufen
+ Aktiviert
+ Nicht verfügbar
+ Auf einen Titel für weitere Informationen tippen
+ Puzzle
+ Antwort
+ Dies ist eine Pro-Funktion
+ Ein monatliches Abonnement von 1 oder 2 Euro (ohne lokale Steuern) aktiviert alle Pro-Funktionen.
+ Sie können ein Abonnement über die Registerkarte Abonnements in der Play Store-App kündigen oder verwalten.
+
+
+ - Blaugrün/Orange
+ - Blau/Orange
+ - Lila/Rot
+ - Gelb/Blau
+ - Orange/Grau
+ - Grün
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-el-rGR/strings.xml b/NetGuard/app/src/main/res/values-el-rGR/strings.xml
new file mode 100644
index 0000000..f8d34c4
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-el-rGR/strings.xml
@@ -0,0 +1,278 @@
+
+
+ Το NetGuard παρέχει απλούς αλλά και σύνθετους τρόπους να εμποδίσετε την πρόσβαση στο διαδίκτυο χωρίς να απαιτείται root. Μπορείτε να εμποδίσετε ή να επιτρέψετε ξεχωριστά την πρόσβαση στο WiFI ή/και στη σύνδεση δεδομένων για εφαρμογές και διευθύνσεις που εσείς επιλέγετε.
+ Το NetGuard απαιτεί Android 5.1 ή κάποια νεότερη έκδοση
+ Το Xposed προκαλεί πάρα πολλές συντριβές, γεγονός που μπορεί να οδηγήσει στην απομάκρυνση του NetGuard από το Google Play Store, επομένως το NetGuard δεν υποστηρίζεται όταν είναι εγκατεστημένο το Xposed
+ Πολιτική απορρήτου
+ Έχει δοθεί μεγάλη προσοχή στην ανάπτυξη και δοκιμή του NetGuard, ωστόσο είναι αδύνατο να διασφαλιστεί ότι το NetGuard θα λειτουργήσει σωστά σε κάθε συσκευή.
+ Συμφωνώ
+ Διαφωνώ
+ Το NetGuard χρειάζεται την βοήθεια σας. Πατήστε για να αγοράσετε λειτουργίες pro ώστε να διατηρήσετε το project.
+ Υπηρεσίες που εκτελούνται
+ Γενικές ειδοποιήσεις
+ Πρόσβαση στις ειδοποιήσεις
+ Αναζήτηση εφαρμογής
+ Φιλτράρισμα των εφαρμογών
+ Προβολή εφαρμογών του χρήστη
+ Προβολή εφαρμογών συστήματος
+ Εμφάνιση εφαρμογών χωρίς internet
+ Εμφάνιση απενεργοποιημένων εφαρμογών
+ Ταξινόμηση Εφαρμογών
+ Ταξινόμηση κατά όνομα
+ Ταξινόμηση κατά ταυτότητα εφαρμογής
+ Ταξινόμηση βάση χρήσης δεδομένων
+ Προβολή αρχείου καταγραφής
+ Ρυθμίσεις
+ Προσκάλεσε
+ Υπόμνημα
+ Υποστήριξη
+ Σχετικά με την εφαρμογή
+ Άλλες εφαρμογές
+ Άλλες
+ Επιτρέπεται
+ Αποκλεισμένο
+ Ζωντανές ενημερώσεις
+ Ανανέωση
+ Εμφάνιση ονομάτων
+ Εμφάνιση οργανισμού
+ PCAP ενεργοποιημένο
+ Εξαγωγή PCAP
+ Καθαρισμός
+ Εξαγωγή
+ Μηδενισμός
+ Προσθήκη
+ Διαγραφή
+ Καθαρισμός
+ Πρωτόκολλο
+ Θύρα προέλευσης
+ Διεύθυνση προορισμού
+ Θύρα προορισμού
+ Εφαρμογή προορισμού
+ Για έναν εξωτερικό διακομιστή, επιλέξτε \'nobody\'
+ Προεπιλογές (λευκή/μαύρη λίστα)
+ Αποκλεισμός Wi-Fi
+ Αποκλεισμός δεδομένων
+ Να επιτρέπεται το Wi-Fi όταν η οθόνη είναι ενεργοποιημένη
+ Να επιτρέπονται τα δεδομένα όταν η οθόνη είναι ενεργοποιημένη
+ Αποκλεισμός περιαγωγής
+ Επιλογές
+ Θέμα: %1$s
+ Χρήση σκοτεινού θέματος
+ Ειδοποίηση για νέα εγκατάσταση
+ Εφαρμογή κανόνων «ενεργή οθόνη»
+ Αυτόματη ενεργοποίηση μετά από %1$s λεπτά
+ Καθυστέρηση μετά το σβήσιμο της οθόνης για %1$s λεπτά
+ Έλεγχος Ενημερώσεων
+ Επιλογές δικτύου
+ Δρομολόγηση υποδικτύου
+ Να επιτρέπεται το tethering
+ Να επιτρέπεται η πρόσβαση LAN
+ Ενεργοποιήστε IPv6 κυκλοφορία
+ Ασύρματα οικιακά δίκτυα: %1$s
+ Διαχείριση ασυρμάτων δικτύων με όγκο-χρέωση
+ Θεώρησε απεριόριστη τη σύνδεση 2G
+ Θεώρησε απεριόριστη τη σύνδεση 3G
+ Θεώρησε απεριόριστη τη σύνδεση LTE
+ Παράβλεψε την εθνική περιαγωγή
+ Παράβλεψη της περιαγωγής εντος ΕΕ
+ Απενεργοποίηση κατά τη διάρκεια κλήσης
+ Φραγή Wi-Fi
+ Φραγή κινητής
+ Φορτώστε ξανά σε κάθε αλλαγή συνδεσιμότητας
+ Επιλογές για προχωρημένους
+ Διαχείριση εφαρμογών του συστήματος
+ Καταγραφή πρόσβασης στο διαδίκτυο
+ Ειδοποίηση για πρόσβαση στο διαδίκτυο
+ Φιλτράρισμα κίνησης
+ Κλείσιμο συνδέσεων κατά την επαναφόρτωση
+ Κλείδωμα της κυκλοφορίας
+ Παρακολούθησε τη χρήση δικτύου
+ Επαναφορά μετρητή χρήσης δικτύου
+ Εμφάνιση επιλυμένων ονομάτων τομέα
+ Φραγή ονομάτων τομέα
+ Κωδικός απόκρισης DNS: %s
+ Προώθηση θυρών
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Ελάχιστη DNS TTL: %s s
+ Χρήση διαμεσολαβητή SOCKS5
+ SOCKS5 διεύθυνση: %s
+ SOCKS5 θύρα: %s
+ SOCKS5 όνομα χρήστη: %s
+ SOCKS5 κωδικός πρόσβασης: %s
+ PCAP μέγεθος εγγραφής: %s B
+ PCAP μέγιστο μέγεθος αρχείου: %s MB
+ Παρακολούθηση: κάθε %s λεπτά
+ Ταχύτητα ειδοποιήσεων
+ Εμφάνιση ειδοποίησης ταχύτητα
+ Κορυφαίες εφαρμογές
+ Δείγμα διαστήματος: %s ms
+ Αριθμός δειγμάτων: %s s
+ Αντίγραφο Ασφαλείας
+ Εξαγωγή ρυθμίσεων
+ Εισαγωγή ρυθμίσεων
+ Εισαγωγή αρχείου hosts
+ Εισαγωγή αρχείου hosts (προσάρτηση)
+ Διεύθυνση κατεβάσματος αρχείου Hosts
+ Κατεβάστε το αρχείο hosts
+ Τεχνικές πληροφορίες
+ Γενικές ρυθμίσεις
+ Δίκτυα
+ Συνδρομή
+ Εμφάνιση ειδοποίησης στη γραμμή καταγραφής για απευθείας ρύθμιση παραμέτρων πρόσφατα εγκατεστημένων εφαρμογών (pro έκδοση)
+ Μετά την απενεργοποίηση χρησιμοποιώντας το widget, αυτόματα ενεργοποιήσετε το NetGuard ξανά μετά τον επιλεγμένο αριθμό λεπτών (εισάγετε το μηδέν για να απενεργοποιήσετε αυτή την επιλογή)
+ Μετά την απενεργοποίηση της οθόνης, κρατήστε τους κανόνες για ενεργή οθόνη για τον επιλεγμένο αριθμό λεπτών (εισάγετε το μηδέν για να απενεργοποιήσετε αυτή την επιλογή)
+ Έλεγχος για νέες κυκλοφορίες στο GitHub, δύο φορές την ημέρα
+ Ανάλογα με την έκδοση του Android, το tethering ενδέχεται να λειτουργεί ή οχι. Η κίνηση δεδομένων μέσω tethering δεν είναι δυνατό να φιλτραριστεί.
+ Ενεργοποίηση της δρομολόγησης υποδικτύου; μπορεί να ενεργοποιήσει την κλήση Wi-Fi, αλλά μπορεί επίσης να προκαλέσει σφάλματα στο Android και αύξηση της κατανάλωσης της μπαταρίας
+ Επιτρέπει στις εφαρμογές να συνδεθούν σε διευθύνσεις του τοπικό δίκτυο, όπως 10.0.0.0/8, 172.16.0.0/12 και 192.168.0.0/16
+ Δρομολόγηση της κυκλοφορίας IP έκδοση 6 μέσω του NetGuard έτσι ώστε να μπορούν επιλεκτικά να επιτρέπονται ή να αποκλείονται
+ Εφαρμογή κανόνων Wi-Fi μόνο για τα επιλεγμένα δίκτυα (για τα υπόλοιπα δίκτυα Wi-Fi θα εφαρμοστούν οι κανόνες δεδομένων)
+ Εφαρμογή κανόνων δεδομένων για δίκτυα Wi-Fi με ογκοχρέωση (επί πληρωμή, με tethering)
+ Εφαρμογή κανόνων δικτύων Wi-Fi για συνδέσεις δεδομένων 2G
+ Εφαρμογή κανόνων δικτύων Wi-Fi για συνδέσεις δεδομένων 3G
+ Εφαρμογή κανόνων δικτύων Wi-Fi για συνδέσεις δεδομένων LTE
+ Να μην εφαρμοστούν κανόνες περιαγωγής όταν ταυτίζεται η χώρα της SIM και του δικτύου κινητής τηλεφωνίας
+ Να μην εφαρμοστούν κανόνες περιαγωγής όταν η χώρα της SIM και του δικτύου κινητής τηλεφωνίας είναι εντός της ΕΕ (περιαγωγή σαν εθνικό δίκτυο)
+ Απενεργοποιήστε το NetGuard για εισερχόμενη ή εξερχόμενη τηλεφωνική κλήση. Αυτό μπορεί να χρησιμοποιηθεί για την επίλυση προβλημάτων σε IP/Wi-Fi κλήσεις.
+ Ορισμός κανόνων για εφαρμογές του συστήματος (για προχωρημένους)
+ Καταγραφή των προσπαθειών που κάνουν οι εφαρμογές για πρόσβαση στο διαδίκτυο. Μπορεί να οδηγήσει σε πρόσθετη χρήση μπαταρίας.
+ Εμφάνισε μια ειδοποίηση στη γραμμή κατάστασης, όταν μια εφαρμογή προσπαθεί να αποκτήσει πρόσβαση σε μια νέα διεύθυνση στο διαδίκτυο (όταν είναι απενεργοποιημένο το φιλτράρισμα, θα εμφανίζονται μόνο οι αποκλεισμένες προσπάθειες πρόσβασης στο διαδίκτυο)
+ Φιλτράρισμα IP πακέτων που κινούνται εκτός της VPN δρομολόγησης. Αυτό μπορεί να οδηγήσει σε πρόσθετη κατανάλωση μπαταρίας.
+ Παρακολουθείστε τον αριθμό των bytes που αποστέλλονται και λαμβάνονται για κάθε εφαρμογή και κάθε διεύθυνση. Αυτό μπορεί να οδηγήσει σε πρόσθετη κατανάλωση μπαταρίας.
+ Ανταπόκριση με το ρυθμισμένο κωδικό απόκρισης DNS για αποκλεισμένους τομείς. Αυτός ο διακόπτης είναι απενεργοποιημένος όταν δεν υπάρχει διαθέσιμο αρχείο hosts.
+ Η προεπιλεγμένη τιμή είναι 3 (NXDOMAIN), που σημαίνει «ανύπαρκτος τομέας».
+ Μόνο η κυκλοφορία TCP θα αποστέλλεται στο διακομιστή μεσολάβησης
+ Ελέγχετε περιοδικά αν εκτελείται ακόμα το NetGuard (εισάγετε το μηδέν για να απενεργοποιήσετε αυτή την επιλογή). Αυτό μπορεί να οδηγήσει σε πρόσθετη κατανάλωση μπαταρίας.
+ Εμφάνιση γραφήματος ταχύτητας δικτύου στη γραμμή κατάστασης
+ Είστε βέβαιος/η;
+ Επιβολή των κανόνων
+ %1$d επιτρέπονται, %2$d έχουν μπλοκαριστεί
+ %1$d επιτρέπονται, %2$d έχουν μπλοκαριστεί, %3$d hosts
+ Αναμονή για συμβάν
+ Το NetGuard είναι απενεργοποιημένο, χρησιμοποιήστε τον παραπάνω διακόπτη για να ενεργοποιήσετε το NetGuard
+ Το NetGuard έχει απενεργοποιηθεί, πιθανόν χρησιμοποιώντας μια άλλη εφαρμογή που βασίζεται σε VPN
+ \'%1$s\' έχει εγκατασταθεί
+ Έχει εγκατασταθεί
+ %1$s απόπειρα πρόσβασης στο διαδίκτυο
+ Απόπειρα πρόσβασης στο διαδίκτυο
+ Η ενεργεία ολοκληρώθηκε
+ Το NetGuard χρησιμοποιεί ένα τοπικό VPN για να φιλτράρει την κίνηση στο διαδίκτυο. Για το λόγο αυτό παρακαλώ επιτρέψτε μια σύνδεση VPN στο επόμενο παράθυρο διαλόγου. Η Κυκλοφορία του διαδικτύου σας δεν αποστέλλεται σε έναν απομακρυσμένο διακομιστή VPN.
+ Το NetGuard δεν μπόρεσε να ξεκινήσει αυτόματα. Αυτό είναι πιθανό να συνέβη εξαιτίας ενός σφάλματος στην έκδοση του Android σας.
+ Παρουσιάστηκε ένα μη αναμενόμενο σφάλμα: «%s»
+ Το Android αρνήθηκε να ξεκινήσει την υπηρεσία VPN αυτή τη στιγμή. Αυτό είναι πιθανό εξαιτίας ενός σφάλματος στην έκδοση του Android σας.
+ Δοκιμάστε το NetGuard
+ Δωρίζοντας συμφωνείτε με τους Όρους & προϋποθέσεις
+ Εάν δεν μπορείτε να πατήστε το κουμπί OK στο επόμενο παράθυρο διαλόγου, μια άλλη εφαρμογή (σκοτείνιασματος οθόνης) είναι πιθανό να έχει το χειρισμό της οθόνης.
+ ± %1$.3f▲ %2$.3f▼ MB ανά ημέρα
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Για συνεπή αποτελέσματα, η βελτιστοποίηση μπαταρίας του Android πρέπει να είναι απενεργοποιημένη για το NetGuard. \n\nΣτο επόμενο παράθυρο διαλόγου, επιλέξτε «Όλες οι εφαρμογές» στο πάνω μέρος, πατήστε NetGuard στη λίστα και επιλέξτε και επιβεβαιώστε να «Μην βελτιστοποιείται».
+ Για συνεπή αποτελέσματα, η επιλογή εξοικονόμησης δεδομένων του Android θα πρέπει να απενεργοποιηθεί για το NetGuard \n\nΣτο επόμενο παράθυρο διαλόγου, ενεργοποιήστε τις επιλογές «δεδομένα παρασκηνίου » και «απεριόριστη δεδομένων χρήσης»
+ Η χρήση φιλτραρίσματος θα κάνει το Android να αποδώσει τη χρήση δεδομένων και κατανάλωσης στο NetGuard, υποθέτοντας ότι τα δεδομένα και η κατανάλωση χρησιμοποιούνται από το NetGuard, αντί για τις πραγματικές εφαρμογές
+ Το Android 4 απαιτεί φιλτράρισμα για να ενεργοποιηθεί
+ Η καταγραφή κυκλοφορίας είναι απενεργοποιημένη, χρησιμοποιήστε το διακόπτη παραπάνω για να ενεργοποιήσετε την καταγραφή. Η καταγραφή κυκλοφορίας μπορεί να οδηγήσει σε πρόσθετη κατανάλωση μπαταρίας.
+ Αυτό θα επαναφέρει τους κανόνες και τους όρους στις προεπιλεγμένες τιμές τους
+ Αυτό θα διαγράψει τις γραμμές καταγραφής της προσπάθειας πρόσβασης των εκτός κανόνων αποδοχής/αποκλεισμού
+ Τελευταία εισαγωγή: %s
+ Ταχύτητα κατεβάσματος\n%1s
+ Ολοκλήρωση κατεβάσματος αρχείου Hosts
+ Τελευταία λήψη: %s
+ Ξεκίνησε προώθηση από %1$s θύρα %2$d εως %3$s:%4$d απο %5$s\';
+ Σταμάτημα προώθησης της %1$s θύρας %2$d;
+ Το δίκτυο μετριέται
+ Δεν υπάρχει ενεργή σύνδεση στο διαδίκτυο
+ NetGuard είναι απασχολημένο
+ Διαθέσιμη ενημέρωση, πατήστε για να κατεβάσετε
+ Μπορείτε να επιτρέψετε (πράσινο) ή να αρνηθείτε (κόκκινο) την ασύρματη η μέσω δεδομένων, πρόσβαση στο διαδίκτυο, πατώντας πάνω στα εικονίδια δίπλα σε μια εφαρμογή
+ Εάν εγκαταστήσατε το NetGuard για να προστατεύσετε το απόρρητό σας, μπορεί να σας ενδιαφέρει το FairEmail , μια ανοιχτού κώδικα εφαρμογή ηλεκτρονικού ταχυδρομείου, φιλική προς το ιδιωτικό απόρρητο
+ Η πρόσβαση στο Διαδίκτυο επιτρέπεται από προεπιλογή ( λειτουργία μαύρης λίστας), αυτό μπορεί να αλλάξει στις ρυθμίσεις
+ Τα εισερχόμενα μηνύματα (push) αντιμετωπίζονται ως επί το πλείστον από το σύστημα ως μέρη των υπηρεσιών του Play, στις οποίες επιτρέπεται πρόσβαση στο διαδίκτυο από προεπιλογή
+ Η διαχείριση όλων των εφαρμογών (του συστήματος) μπορεί να ενεργοποιηθεί στις ρυθμίσεις
+ Παρακαλούμε περιγράψτε το πρόβλημα και υποδείξετε το σημείο εμφάνισης του προβλήματος:
+ Η VPN σύνδεση ακυρώθηκε\n Έχετε ρυθμίσει μια άλλη VPN σύνδεση να είναι πάντα ενεργή;
+ Η απενεργοποίηση τη συσκευή σας με το NetGuard ενεργοποιημένο, θα ξεκινήσει αυτόματα το NetGuard με την επόμενη ενεργοποίηση τη συσκευή σας
+ Αυτή η δυνατότητα δεν είναι διαθέσιμη σε αυτήν την έκδοση του Android
+ Ένα άλλο VPN έχει οριστεί ως μόνιμα ενεργοποιημένο VPN
+ Απενεργοποιήστε την επιλογή \"Αποκλεισμός συνδέσεων χωρίς VPN\" στις ρυθμίσεις του VPN Android για να χρησιμοποιήσετε το NetGuard σε λειτουργία φιλτραρίσματος
+ Απενεργοποιήστε το \"Ιδιωτικό DNS\" στις ρυθμίσεις δικτύου του Android για να χρησιμοποιήσετε το NetGuard σε λειτουργία φιλτραρίσματος
+ Η κυκλοφορία είναι κλειδωμένη
+ Επιτρέπεται η χρονικά απεριόριστη κίνηση
+ Αποκλείεται η χρονικά απεριόριστη κυκλοφορία
+ Οι κανόνες της χρονικά απεριόριστης κυκλοφορίας δεν εφαρμόζονται
+ Επιτρέπεται η χρόνο-χρεουμενη κυκλοφορία
+ Η χρόνο-χρεουμενη κυκλοφορία έχει αποκλειστεί
+ Οι κανόνες της χρόνο-χρεουμενης κυκλοφορίας δεν εφαρμόζονται
+ Η διεύθυνση επιτρέπεται
+ Η διεύθυνση είναι αποκλεισμένη
+ Επιτρέπεται όταν η οθόνη είναι ενεργοποιημένη
+ Φραγή κατά την περιαγωγή
+ Από προεπιλογή, μια σύνδεση Wi-Fi θεωρείται να είναι χρονικά απεριόριστη και μια σύνδεση κινητού χρονοχρέωση
+ δεν έχει άδεια χρήσης Διαδικτύου
+ είναι απενεργοποιημένη
+ Εφαρμογή κανόνων και προϋποθέσεων
+ Προϋποθέσεις
+ Επέτρεψε Wi-Fi, όταν η οθόνη είναι ενεργοποιημένη
+ Να επιτρέπονται τα δεδομένα όταν η οθόνη είναι ενεργοποιημένη
+ R
+ Φραγή κατά την περιαγωγή
+ Επέτρεψε σε κατάσταση κλειδώματος
+ Σχετικές με τα φίλτρα
+ Προσπάθειες πρόσβασης
+ Οι κανόνες πρόσβασης έχουν προτεραιότητα έναντι άλλων κανόνων
+ Επιλογές
+ Ειδοποίησε για προσπάθειες πρόσβασης στο διαδίκτυο
+ Δεν είναι ενεργοποιημένη η καταγραφή ή το φιλτράρισμα
+ Η καταγραφή και το φιλτράρισμα είναι ενεργοποιημένα
+ Ρύθμιση
+ Ενεργοποίηση της καταγραφής των φραγμένων διευθύνσεων μόνο
+ Ενεργοποίηση φιλτραρίσματος στην καταγραφή και των επιτρεπόμενων διευθύνσεων επίσης
+ Ενεργοποιήσετε τις ειδοποιήσεις για πρόσβαση σε πρόσφατα συνδεδεμένες διευθύνσεις
+ Οι ρυθμίσεις αυτές είναι καθολικές ρυθμίσεις που ισχύουν για όλες τις εφαρμογές
+ Το φιλτράρισμα απαιτείται επίσης στην αποδοχή ή τον αποκλεισμό σε μεμονωμένες διευθύνσεις
+ Ενεργοποίηση καταγραφής (λιγότερο) ή φιλτραρίσματος (περισσότερα) μπορεί να αυξήσει την κατανάλωση της μπαταρίας και ενδέχεται να επηρεάσει την ταχύτητα του δικτύου
+ Αξιολόγηση
+ Να επιτραπεί
+ Αποκλεισμός
+ Επέτρεψε την χρήση Wi-Fi
+ Αποκλεισμός Wi-Fi
+ Επέτρεψε την χρήση δεδομένων
+ Αποκλεισμός δεδομένων
+ root
+ mediaserver
+ κανείς
+ Να μην ερωτηθώ ξανά
+ Ποιος είναι %1$s
+ Θύρα %1$d
+ Αντιγραφή
+ Δυνατότητες έκδοσης Pro
+ Διατίθενται οι ακόλουθες δυνατότητες pro:
+ Προβολή αρχείου καταγραφής μπλοκαρισμένης κυκλοφορίας
+ Φιλτράρισμα κίνησης δικτύου
+ Ειδοποίησεις νέας εφαρμογής
+ Ειδοποίηση γραφήματος ταχύτητας δικτύου
+ Εμφάνιση (θέμα, χρώματα)
+ Όλα τα παραπάνω χαρακτηριστικά pro
+ Υποστήριξη της ανάπτυξης
+ Αγοράστε
+ Ενεργοποιημένο
+ Μη διαθέσιμος/η
+ Πατήστε στον τίτλο για περισσότερες πληροφορίες
+ Πρόκληση
+ Ανταπόκριση
+
+ - κυπαρισσί/πορτοκαλί
+ - μπλε/πορτοκαλί
+ - μωβ/κόκκινο
+ - πορτοκαλί-μπλε
+ - πορτοκαλί/γκρι
+ - πρασινο
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-en-rUS/strings.xml b/NetGuard/app/src/main/res/values-en-rUS/strings.xml
new file mode 100644
index 0000000..2bcc29b
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-en-rUS/strings.xml
@@ -0,0 +1,13 @@
+
+
+ NetGuard provides simple and advanced ways to block access to the internet - no root required. Apps and addresses can individually be allowed or denied access to your Wi-Fi and/or mobile connection.
+ NetGuard requires Android 5.1 or later
+ Xposed causes too many crashes, which might result in NetGuard being removed from the Google Play Store, therefore NetGuard isn\'t supported while Xposed is installed
+ Privacy policy
+ Great care has been taken to develop and test NetGuard, however it is impossible to guarantee NetGuard will work correctly on every device.
+ I agree
+ I disagree
+ NetGuard needs your help. Tap to purchase pro features to keep the project going.
+ Running services
+ General notifications
+
diff --git a/NetGuard/app/src/main/res/values-es-rES/strings.xml b/NetGuard/app/src/main/res/values-es-rES/strings.xml
new file mode 100644
index 0000000..9507094
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-es-rES/strings.xml
@@ -0,0 +1,288 @@
+
+
+ NetGuard proporciona formas sencillas y avanzadas de bloquear el acceso a Internet - sin necesidad de acceso root. Se puede permitir o denegar individualmente el acceso a su conexión Wi-Fi o móvil a aplicaciones y direcciones.
+ NetGuard requiere Android 5.1 o superior
+ Xposed causa demasiados errores que podrían llevar a eliminar NetGuard de Google Play Store, por lo tanto, NetGuard no es soportado mientras Xposed esté instalado
+ Política de privacidad
+ Se ha tenido gran cuidado para desarrollar y probar NetGuard, sin embargo, es imposible garantizar que NetGuard funcione correctamente en todos los dispositivos.
+ Aceptar
+ Rechazar
+ NetGuard necesita su ayuda. Pulse para comprar características de pago y así seguir ayudando al desarrollo del proyecto.
+ Servicios en ejecución
+ Notificaciones generales
+ Notificaciones de acceso
+ Buscar aplicación
+ Filtrar aplicaciones
+ Mostrar aplicaciones del usuario
+ Mostrar aplicaciones del sistema
+ Mostrar aplicaciones sin Internet
+ Mostrar aplicaciones desactivadas
+ Ordenar aplicaciones
+ Ordenar por nombre
+ Ordenar por uid
+ Ordenar por uso de datos
+ Mostrar registro
+ Ajustes
+ Invitar
+ Símbolos
+ Soporte
+ Acerca de
+ Otras aplicaciones
+ Otros
+ Permitido
+ Bloqueado
+ Actualizaciones en tiempo real
+ Actualizar
+ Mostrar nombres
+ Mostrar organización
+ PCAP activado
+ Exportar PCAP
+ Vaciar
+ Exportar
+ Restablecer
+ Añadir
+ Eliminar
+ Limpieza
+ Protocolo
+ Puerto de origen
+ Dirección de destino
+ Puerto de destino
+ Aplicación de destino
+ Para un servidor externo, seleccione \'nadie\'
+ Valores predeterminados (lista blanca/negra)
+ Bloquear Wi-Fi por defecto
+ Bloquear red móvil por defecto
+ Permitir Wi-Fi con la pantalla encendida
+ Permitir red móvil con la pantalla encendida
+ Bloquear roaming
+ Opciones
+ Tema: %1$s
+ Usar tema oscuro
+ Notificar nuevas instalaciones
+ Aplicar reglas \'cuando pantalla encendida\'
+ Activar automáticamente después de %1$s minutos
+ Retardar apagado de pantalla en %1$s minutos
+ Buscar actualizaciones
+ Opciones de red
+ Enrutamiento de subred
+ Permitir anclaje a red
+ Permitir acceso a LAN
+ Permitir tráfico IPv6
+ Redes Wi-Fi domésticas: %1$s
+ Gestionar redes Wi-Fi medidas
+ Considerar 2G ilimitado
+ Considerar 3G ilimitado
+ Considerar LTE ilimitado
+ Ignorar roaming nacional
+ Ignorar roaming en UE
+ Desactivar ante llamada
+ Bloquear Wi-Fi
+ Bloquear red móvil
+ Recargar en cada cambio de conectividad
+ Opciones avanzadas
+ Administrar aplicaciones de sistema
+ Registrar acceso a Internet
+ Notificar accesos a Internet
+ Filtrar tráfico
+ Filtrar tráfico UDP
+ Transferencia de VPN sin interrupción al recargar
+ Cerrar conexiones al recargar
+ Bloquear tráfico
+ Registrar uso de red
+ Restablecer uso de red
+ Mostrar nombres de dominio resueltos
+ Bloquear nombres de dominio
+ Código de respuesta DNS: %s
+ Redirección de puertos
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Validar en: %s
+ TTL mínimo para DNS: %s s
+ Usar proxy SOCKS5
+ Dirección de SOCKS5: %s
+ Puerto de SOCKS5: %s
+ Usuario de SOCKS5: %s
+ Contraseña de SOCKS5: %s
+ Tamaño de registro PCAP: %s B
+ Máximo tamaño del archivo PCAP: %s MB
+ Watchdog: cada %s minutos
+ Notificación de velocidad
+ Mostrar notificación de velocidad
+ Mostrar aplicaciones principales
+ Intervalo de muestreo: %s ms
+ Número de muestras: %s s
+ Copia de seguridad
+ Exportar ajustes
+ Importar ajustes
+ Importar archivo hosts
+ Importar archivo hosts (añadir)
+ URL de descarga del archivo hosts
+ Descargar archivo hosts
+ Información técnica
+ General
+ Redes
+ Suscripciones
+ Mostrar notificación en la barra de estado para configurar directamente las aplicaciones recién instaladas (característica de pago)
+ Después de desactivar desde el widget, activar NetGuard automáticamente después del número de minutos seleccionados (introduzca cero para desactivar esta opción)
+ Después de apagar la pantalla, mantener las reglas activas de pantalla encendida durante el número seleccionado de minutos (introduzca cero para desactivar esta opción)
+ Buscar nuevas versiones en GitHub dos veces al día
+ Dependiendo de la versión de Android, el anclaje a red puede funcionar o no. El tráfico por anclaje no puede filtrarse.
+ Activar el enrutamiento de subred podría permitir llamadas Wi-Fi pero podría también provocar errores en Android y consumir más batería
+ Permitir a las aplicaciones conectarse a direcciones de la red local, como 10.0.0.0/8, 172.16.0.0/12 y 192.168.0.0/16
+ Dirigir tráfico IPv6 a NetGuard para permitir o bloquearlo selectivamente
+ Aplicar sólo reglas de red Wi-Fi en la red seleccionada (aplicar reglas de red móvil para otras redes Wi-Fi)
+ Aplicar reglas de red móvil a redes Wi-Fi medidas (de pago, por anclaje)
+ Aplicar reglas de red Wi-Fi para conexiones de datos 2G
+ Aplicar reglas de red Wi-Fi para conexiones de datos 3G
+ Aplicar reglas de red Wi-Fi para conexiones de datos LTE
+ No aplicar reglas de roaming cuando la SIM y la red móvil son del mismo país
+ No aplicar reglas de roaming cuando la SIM y la red móvil son de la UE (roaming como red nacional)
+ Desactivar NetGuard ante llamada entrante o saliente. Esto puede utilizarse para solucionar problemas en llamadas IP/Wi-Fi.
+ Definir reglas para aplicaciones de sistema (para expertos)
+ Registrar intentos de acceso a Internet para aplicaciones. Esto podría consumir más batería.
+ Mostrar una notificación en la barra de estado cuando una aplicación intente acceder a una nueva dirección de Internet (cuando se desactiva el filtrado, solo se notificarán los intentos de acceso a Internet bloqueados)
+ Filtrar paquetes IP salientes del túnel VPN. Esto podría consumir más batería.
+ Registrar número de bytes enviados y recibidos para cada aplicación y dirección. Esto podría consumir más batería.
+ Responder con el código de respuesta DNS configurado para nombres de dominio bloqueados. Esta opción está desactivada cuando no hay ningún archivo hosts disponible.
+ El valor predeterminado es 3 (NXDOMAIN), que significa \'dominio inexistente\'.
+ Nombre de dominio usado para validar la conexión a internet en el puerto 443 (https).
+ Sólo se enviará el tráfico TCP al servidor proxy
+ Comprobar periódicamente si NetGuard está ejecutándose (introduzca cero para desactivar esta opción). Esto podría consumir más batería.
+ Mostrar gráfico de velocidad de red en notificaciones de la barra de estado
+ ¿Estás seguro?
+ Reglas aplicadas
+ Permitidas: %1$d | Bloqueadas: %2$d
+ Permitidas: %1$d | Bloqueadas: %2$d | Hosts: %3$d
+ Esperando evento
+ NetGuard está desactivado. Utilice el interruptor de arriba para activarlo.
+ NetGuard ha sido desactivado, probablemente por usar otra aplicación de VPN
+ \'%1$s\' instalado
+ Se ha instalado
+ %1$s intentó acceder a Internet
+ Intento de acceso a Internet
+ Acción completada
+ NetGuard utiliza una VPN local para filtrar el tráfico de Internet. Por esta razón, permita la conexión VPN en el siguiente cuadro de diálogo. El tráfico de Internet no será enviado a un servidor VPN remoto.
+ NetGuard podría no iniciarse automáticamente en el arranque debido a un error en su versión de Android
+ Se ha producido un error inesperado: \'%s\'
+ Android ha impedido iniciar el servicio VPN en este momento debido probablemente a un error en la versión de Android.
+ Prueba NetGuard
+ Al donar, acepta los términos y condiciones
+ Si no puede pulsar \'Aceptar\' en el próximo diálogo, otra aplicación (de atenuación de pantalla) esté probablemente manipulando la pantalla.
+ ± %1$.3f▲ %2$.3f▼ MB/día
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Para obtener resultados consistentes, las optimizaciones de batería de Android deberían desactivarse para NetGuard. \n\nEn el siguiente diálogo, seleccione \'Todas las aplicaciones\' en la parte superior, pulse en NetGuard en la lista y seleccione y confirme \'No optimizar\'.
+ Para obtener resultados consistentes, las opciones de ahorro de datos de Android deben estar desactivadas para NetGuard.\n\nEn el siguiente cuadro de diálogo, active las opciones \'Datos en segundo plano\' y \'Uso de datos ilimitado\'.
+ Al utilizar el filtrado, Android atribuirá el uso de datos y batería a Netguard en lugar de las aplicaciones originales
+ Android 4 requiere que el filtrado esté activado
+ El registro de tráfico está desactivado. Utilice el interruptor de arriba para activarlo. El registro de tráfico podría consumir más batería.
+ Esto restablecerá las reglas y condiciones a sus valores originales
+ Esto eliminará líneas de registro de intento de acceso sin reglas de permitir/bloquear
+ Última importación: %s
+ Descargando\n%1s
+ Archivo hosts descargado
+ Última descarga: %s
+ ¿Iniciar redirección desde el puerto %1$s, %2$d hacia %3$s:%4$d de \'%5$s\'?
+ ¿Detener redirección de %1$s puerto %2$d?
+ La red está medida
+ No hay conexión a Internet
+ NetGuard está ocupado
+ Actualización disponible, pulse para descargar
+ Puede permitir (verde) o denegar (rojo) el acceso a Internet Wi-Fi o móvil pulsando en los iconos al lado de cada aplicación
+ Si ha instalado NetGuard para proteger su privacidad, podría estar interesado en FairEmail , una aplicación de correo electrónico de código abierto que respeta también la privacidad
+ El acceso a Internet está permitido de forma predeterminada (modo de lista negra), esto puede cambiarse en los ajustes
+ Las notificaciones (push) son gestionadas principalmente por el componente del sistema \"Play Services\", que está autorizado para acceder a Internet de forma predeterminada
+ La gestión de las aplicaciones del sistema puede activarse en los ajustes
+ Por favor, describa el problema e indique el tiempo del mismo:
+ Conexión VPN cancelada\n¿Ha configurado otra VPN para estar conectada permanentemente?
+ Al apagar el dispositivo con NetGuard activado, este se iniciará automáticamente al encender el dispositivo
+ Esta característica no está disponible para esta versión de Android
+ Otra VPN está configurada como \'Siempre activa\'
+ Desactivar \"Bloquear conexiones sin VPN\" en ajustes de VPN de Android para usar NetGuard en modo de filtrado
+ Desactivar \"DNS privada\" en ajustes de red de Android para usar NetGuard en modo de filtrado
+ El tráfico está bloqueado
+ Tráfico ilimitado permitido
+ Tráfico ilimitado bloqueado
+ Las reglas ilimitadas no son aplicadas
+ Tráfico medido permitido
+ Tráfico medido bloqueado
+ Las reglas limitadas no son aplicadas
+ Dirección permitida
+ Dirección bloqueada
+ Permitir con la pantalla encendida
+ Bloquear en roaming
+ Por defecto, una conexión Wi-Fi se considera ilimitada y una conexión móvil medida
+ sin permiso de acceso a Internet
+ está desactivado
+ Los mensajes entrantes son recibidos por los servicios de Google Play y no por esta aplicación y por lo tanto no se puede bloquear bloqueando esta aplicación
+ Las descargas las realiza el gestor de descargas y no esta aplicación y por tanto no pueden ser bloqueadas bloqueando esta aplicación
+ Aplicar reglas y condiciones
+ Condiciones
+ Permitir Wi-Fi con la pantalla encendida
+ Permitir red móvil con la pantalla encendida
+ R
+ Bloquear en roaming
+ Permitir en modo de bloqueo
+ Filtro relacionado
+ Intentos de acceso
+ Las reglas de acceso prevalecen sobre otras reglas
+ Opciones
+ Notificar intentos de acceso a Internet
+ El registro y filtrado están desactivados
+ El registro y filtrado están activados
+ Configurar
+ Activar registro solo de direcciones bloqueadas
+ Activar filtrado para registrar también las direcciones permitidas
+ Activar notificaciones de acceso para direcciones recién registradas
+ Esta configuración es global y se aplica a todas las aplicaciones
+ El filtrado es necesario también para permitir o bloquear direcciones individuales
+ Activar el registro (menos) o filtrado (más) podría aumentar el uso de la batería y afectar a la velocidad de la red
+ Calificar
+ Permitir
+ Bloquear
+ Permitir Wi-Fi
+ Bloquear Wi-Fi
+ Permitir red móvil
+ Bloquear red móvil
+ raíz
+ mediaserver
+ nadie
+ No volver a preguntar
+ Quién es %1$s
+ Puerto %1$d
+ Copiar
+ Características de pago
+ Las siguientes características de pago están disponibles:
+ Ver registro de tráfico bloqueado
+ Filtrar tráfico de red
+ Notificaciones de aplicación nueva
+ Notificación gráfica de velocidad de red
+ Apariencia (tema, colores)
+ Todas las características de pago anteriores
+ Apoyar al desarrollador
+ Comprar
+ Activado
+ No disponible
+ Pulse en un título para más información
+ Desafío
+ Respuesta
+ Esta es una característica Pro
+ Una suscripción mensual de 1 o 2 euros (excluyendo impuestos locales) activará todas las características profesionales.
+ Puedes cancelar o administrar una suscripción a través de la pestaña de suscripciones en la aplicación Play Store.
+
+
+ - turquesa/anaranjado
+ - azul/anaranjado
+ - púrpura/rojo
+ - ámbar/azul
+ - anaranjado/gris
+ - verde
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-et-rEE/strings.xml b/NetGuard/app/src/main/res/values-et-rEE/strings.xml
new file mode 100644
index 0000000..bf6b7ff
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-et-rEE/strings.xml
@@ -0,0 +1,126 @@
+
+
+ Nõustun
+ Ei nõustu
+ Rakenduse otsimine
+ Rakenduse filtreerimine
+ Näita kasutajarakendusi
+ Näita süsteemirakendusi
+ Näita ilma internetita rakendusi
+ Näita keelatud rakendusi
+ Sorteeri rakendusi
+ Sorteeri nime järgi
+ Sorteeri uid alusel
+ Sorteeri andmekasutuse järgi
+ Näita logi
+ Seaded
+ Kutsu
+ Legend
+ Kasutajatugi
+ Info
+ Muu
+ Lubatud
+ Blokeeritud
+ Uuendused
+ Värskenda
+ Näita nimesid
+ Näita organisatsiooni
+ PCAP lubatud
+ PCAP eksport
+ Tühjenda
+ Lähtesta
+ Lisa
+ Kustuta
+ Puhasta
+ Protokoll
+ Lähteport
+ Sihtkoha aadress
+ Sihtkoha port
+ Sihtrakendus
+ Vaikeväärtused (valge/must nimekiri)
+ Blokeeri wifi
+ Blokeeri andmeside
+ Luba WiFi, kui ekraan on sisse lülitatud
+ Luba andmeside, kui ekraan on sisse lülitatud
+ Blokeeri rändluse ajal
+ Valikud
+ Teema: %1$s
+ Kasuta tumedat teemat
+ Võrgu valikud
+ Alamvõrgu marsuutimine
+ Luba edasijagamine
+ Luba LAN ligipääs
+ Ära mõõda 2G mühendust
+ Ära mõõda 3G mühendust
+ Ära mõõda LTE mühendust
+ Jälgi võrgu kasutamist
+ Nulli võrgu kasutamine
+ Näita lahendatud domeeninimesid
+ Blokeeri domeenid
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Minimaalne DNS TTL: %s s
+ Kasuta SOCKS5 puhverserverit
+ SOCKS5 aadress: %s
+ Kiirus teavitus
+ Varunda
+ Ekspordi seaded
+ Impordi seaded
+ Tehniline info
+ Üldine
+ Võrgud
+ Tellimused
+ Oled sa kindel?
+ Reeglite jõustamine
+ %1$d lubatud, %2$d blokeeritud
+ %1$d lubatud %2$d blokeeritud, %3$d hosti
+ Sündmuse ootel
+ \'%1$s\' paigaldatud
+ On paigaldatud
+ Proovi NetGuardi
+ ± %1$.3f▲ %2$.3f▼ MB/päevas
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Viimane import: %s
+ Liiklus on lukus
+ Tingimused
+ Luba WiFi, kui ekraan on sisse lülitatud
+ Luba andmeside, kui ekraan on sisse lülitatud
+ R
+ Blokeeri rändluse ajal
+ Valikud
+ Seadista
+ Hinda
+ Luba
+ Blokeeri
+ Luba wifi
+ Blokeeri wifi
+ Luba mobiilandmeside
+ Blokeeri andmeside
+ meediaserver
+ mitte keegi
+ Ära enam küsi
+ Whois %1$s
+ Port %1$d
+ Pro funktsioonid
+ Osta
+ Lubatud
+ Pole saadaval
+ Väljakutse
+ Vastus
+
+ - rohekas-sinine/oranž
+ - sinine/oranž
+ - lilla/punane
+ - merevaik/sinine
+ - oranž/hall
+ - roheline
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-eu-rES/strings.xml b/NetGuard/app/src/main/res/values-eu-rES/strings.xml
new file mode 100644
index 0000000..7b7097d
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-eu-rES/strings.xml
@@ -0,0 +1,289 @@
+
+
+ NetGuard-ek internet sarbidea blokeatzeko modu sinple eta aurreratuak ematen dizkizu - ez da root behar. Aplikazio eta helbideko banaka baimendu edo ukatu daiteke Wi-Fi edo sare mugikorraren bitarteko konexioa.
+ NetGuardek Android 5.1 edo berriagoa behar du
+ Xposed kraskatze gehiegi eragiten ditu, eta horregatik NetGuard kendu zezaketen Google Play Store-tik, beraz NetGuard-ek ez du euskarririk Xposed instalatuta badago
+ Pribatutasun politika
+ Kontu handiz garatu eta probatu da NetGuard, baina ezin dugu bermatu gailu guztietan ibiliko dela.
+ Ados nago
+ Ez nago ados
+ NetGuard proiektuak zure laguntza behar du. Sakatu ordainpeko ezaugarriak erosi eta proiektua babesteko.
+ Zerbitzuak abian
+ Jakinarazpen orokorrak
+ Sarbide-jakinarazpenak
+ Bilatu aplikazioa
+ Iragazi aplikazioak
+ Erakutsi erabiltzailearen aplikazioak
+ Erakutsi sistemako aplikazioak
+ Erakutsi internet gabeko aplikazioak
+ Erakutsi desgaitutako aplikazioak
+ Ordenatu aplikazioak
+ Ordenatu izenaren arabera
+ Ordenatu uid arabera
+ Ordenatu datu erabileraren arabera
+ Erakutsi egunkaria
+ Ezarpenak
+ Gonbidatu
+ Legenda
+ Laguntza
+ Honi buruz
+ Beste aplikazioak
+ Bestea
+ Baimenduta
+ Blokeatua
+ Eguneraketa jarraiak
+ Berritu
+ Erakutsi izenak
+ Erakutsi erakundea
+ PCAP gaituta
+ PCAP exportazioa
+ Garbitu
+ Esportatu
+ Berrezarri
+ Gehitu
+ Ezabatu
+ Garbiketa
+ Protokoloa
+ Jatorriaren ataka
+ Helburuaren helbidea
+ Helburuaren ataka
+ Helburuaren aplikazioa
+ Kanpo zerbitzari baterako aukeratu \'inor ez\'
+ Lehenetsitakoak (zerrenda zuri/beltza)
+ Blokeatu Wi-Fia
+ Blokeatu mugikorra
+ Baimendu Wi-Fia pantaila piztuta dagoenean
+ Baimendu mugikorra pantaila piztuta dagoenean
+ Blokeatu ibiltaritza
+ Aukerak
+ Azala: %1$s
+ Erabili azal iluna
+ Jakinarazi instalazio berria
+ Aplikatu \'pantaila piztuta dagoenean\' arauak
+ Automatikoki gaitu %1$s minutura
+ Atzeratu pantaila itzaltzea %1$s minutu
+ Egiaztatu eguneraketarik dagoen
+ Sare-aukerak
+ Azpisarea bideratzea
+ Baimendu tethering
+ Baimendu LAN sarbidea
+ Gaitu IPv6 trafikoa
+ Etxeko Wi-Fi sareak: %1$s
+ Kudeatu neurtutako Wi-Fi sareak
+ Hartu 2G neurtutzat
+ Hartu 3G neurtutzat
+ Hartu LTE neurtutzat
+ Ezikusi ibiltaritza nazionala
+ Ezikusi Europar Batasuneko ibiltaritza
+ Desgaitu deietan
+ Blokeatu Wi-Fia
+ Blokeatu mugikorra
+ Birkargatu konektibitate aldaketa bakoitzean
+ Aukera aurreratuak
+ Kudeatu sistemako aplikazioak
+ Gorde Internet sarbideen egunkaria
+ Jakinarazi internet atzitzen denean
+ Iragazi trafikoa
+ Iragazi UDP trafikoa
+ Pasatu VPNra etenik gabe birkargatzean
+ Itxi konexioak birkargatzean
+ Blokeatu trafikoa
+ Monitorizatu sare-erabilera
+ Berrezarri sare-erabilera
+ Erakutsi ebatzitako domeinu izenak
+ Blokeatu domeinu izenak
+ DNS erantzun kodea: %s
+ Atakak birbidaltzea
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Balioztatu hemen: %s
+ Gutxieneko DNS TTL: %s s
+ Erabili SOCKS5 proxya
+ SOCKS5 helbidea: %s
+ SOCKS5 ataka: %s
+ SOCKS5 erabiltzaile-izena: %s
+ SOCKS5 pasahitza: %s
+ PCAP grabazioaren tamaina: %s B
+ PCAP gehieneko fitxategi-tamaina: %s MB
+ Watchdog: %s minutuero
+ Abiadura-jakinarazpena
+ Erakutsi abiadura-jakinarazpena
+ Erakutsi aplikazio gorenak
+ Laginaren tartea: %s ms
+ Lagin kopurua: %s s
+ Babes-kopia
+ Esportatu ezarpenak
+ Inportatu ezarpenak
+ Inportatu ostalarien fitxategia
+ Inportatu ostalarien fitxategia (gehitu)
+ Ostalarien fitxategia deskargatzeko URL-a
+ Deskargatu ostalarien fitxategia
+ Informazio teknikoa
+ Orokorra
+ Sareak
+ Harpidetzak
+ Erakutsi egoera barrako jakinarazpena berriki instalatutako aplikazioak zuzenean konfiguratzeko (ordainpeko ezaugarria)
+ Trepeta erabiltzea desgaitu eta gero, automatikoki gaitu NetGuard berriro esandako minutu kopurua igarotzean (idatzi 0 ezaugarri hau desgaitzeko)
+ Pantaila itzali eta gero, mantendu pantaila piztuta dagoeneko arauak aktibo esandako minutu kopuru batez (idatzi zero aukera hau desgaitzeko)
+ Egiaztatu bertsio berririk dagoen GitHub-en egunean birritan
+ Android bertsioaren arabera, tethering ibili daiteke ala ez. Tethering bidezko trafikoa ezin da iragazi.
+ Azpisare bideratzeak Wi-Fi deiak ahalbidetu ditzake, baina bestelako Android akats batzuk azalarazi ditzake eta bateria kontsumoa areagotu
+ Baimendu aplikazioei sare lokaleko helbideetara konektatzea, adibidez 10.0.0.0/8, 172.16.0.0/12 eta 192.168.0.0/16
+ Bideratu IPv6 trafikoa NetGurd-era, selektiboki baimendu edo blokeatzeko
+ Aplikatu Wi-Fi sareko arauak hautatutako sareetan besterik ez (aplikatu sare mugikorraren arauak beste Wi-Fi sareetan)
+ Aplikatu sare mugikorraren arauak neurtutako (ordainpeko, tethering) Wi-Fi sareetan ere
+ Aplikatu Wi-Fi sare arauak 2G datu konexioetan ere
+ Aplikatu Wi-Fi sare arauak 3G datu konexioetan ere
+ Aplikatu Wi-Fi sare arauak LTE datu konexioetan ere
+ Ez aplikatu ibiltaritza arauak SIM eta sarearen herrialdea bera direnean
+ Ez aplikatu ibiltaritza arauak SIM eta sarearen herrialdeak biak Europar Batasunean badaude (ibiltaritza nazionala bezala)
+ Desgaitu NetGuard telefono deiak jaso edo egitean. Hau IP/Wi-Fi deiekin arazoak daudenean erabili daiteke.
+ Zehaztu sistemako aplikazioen arauak (adituentzat)
+ Gorde aplikazioek Internet atzitzeko egindako saiakeren egunkaria. Honek bateria kontsumoa areagotu dezake.
+ Erakutsi egoera barrako jakinarazpena aplikazioak Internet helbide berri bat atzitzen saiatzean (Iragaztea desgaituta dagoenean, bakarrik blokeatutako Internet sarbide saiakerak gordeko dira)
+ Iragazi VPN tuneletik ateratako IP paketeak. Honek bateria kontsumoa areagotu dezake.
+ Monitorizatu aplikazio eta helbide bakoitzak bidali eta jasotako byte kopurua. Honek bateria kontsumoa areagotzea ekar lezake.
+ Erantzun blokeatutako domeinuentzat konfiguratutako DNS erantzun kodearekin. Etengailu hau desgaituta dago hosts fitxategirik ez badago.
+ Lehenetsitako balioa 3 (NXDOMAIN) da, eta \'domeinua ez da existitzen\' esan nahi du.
+ Internet konexioa 443 atakan (https) balioztatzeko erabilitako domeinuaren izena.
+ TCP trafikoa besterik ez da bidaliko proxy zerbitzarira
+ Egiaztatu aldiro NetGuarg oraindik martxan dagoen (idatzi 0 ezaugarri hau desgaitzeko). Honek bateria gehiago erabiltzea ekar lezake.
+ Erakutsi sare-abiaduraren grafikoak egoera-barrako jakinarazpenetan
+ Ziur zaude?
+ Arauak betearazten
+ %1$d baimenduta, %2$d blokeatuta
+ %1$d baimenduta, %2$d blokeatuta, %3$d ostalari
+ Gertaeraren zain
+ NetGuard desgaituta dago, erabili goiko etengailua NetGuard gaitzeko
+ NetGuard desgaitua izan da, litekeena beste VPN motako aplikazio bat erabiltzeagatik
+ \'%1$s\' instalatuta
+ Instalatu da
+ %1$s internet atzitzen saiatu da
+ Internet atzitzen saiatu da
+ Ekintza burututa
+ NetGuard-ek VPN lokal bat darabil internet trafikoa iragazteko.
+Horregatik, baimendu VPN konexioa hurrengo elkarrizketa koadroan mesedez.
+Zure internet trafikoa ez da kanpo VPN zerbitzari batera bidaltzen.
+ NetGuard ezin izan da automatikoki abiatu. Litekeena zure Android bertsioaren akats baten erruz.
+ Ustekabeko errorea gertatu da: \'%s\'
+ Androidek uko egin dio VPN zerbitzua orain abiatzeari. Litekeena zure Android bertsioak akats bat duelako.
+ Probatu NetGuard
+ Dohaintza eginez termino eta baldintzak onartzen dituzu
+ Ezin baduzu \'Ados\' zapaldu hurrengo elkarrizketa-koadroan, beste aplikazio bat pantaila manipulatzen dago.
+ ± %1$.3f▲ %2$.3f▼ MB/egunean
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Emaitza egokiak izateko, Android sistemako bateria optimizazioak desgaitu behar dira NetGuard aplikazioarentzat.
+\n\nHurrengo elkarrizketa-koadroan, hautatu \"Aplikazio guztiak\" goian, sakatu NetGuard zerrendan eta berretsi \"Ez optimizatu\".
+ Emaitza egokiak izateko, Android sistemako datuak aurrezteko optimizazioak desgaitu behar dira NetGuard aplikazioarentzat.
+\n\nHurrengo elkarrizketa-koadroan, gaitu \"bigarren planoko datuak\" eta \"mugagabeko datu erabilera\"
+ Iragaztea erabiltzean Androiden NetGuard-i egotziko dio datu eta bateria erabilera - Androidek uste du NetGuard-ek erabiltzen duela datuak eta bateria, ez jatorrizko aplikazioek
+ Android 4-k iragaztea gaitzera behartzen du
+ Trafifoaren egunkaria desgaituta dago, erabili goiko etengailua egunkaria gaitzeko. Trafikoaren egunkariak bateria kontsumoa areagotu dezake.
+ Honek arauak eta baldintzak lehenetsitako balioetara berrezarriko ditu
+ Honek baimendu/ukatu araurik gabeko sarbide saiakeren egunkaria ezabatuko du
+ Azken inportazioa: %s
+ Deskargatzen\n%1s
+ Ostalarien fitxategia deskargatuta
+ Azken deskarga: %s
+ Hasi birbidalketa, hemendik %1$s ataka %2$d hona %3$s:%4$d - \'%5$s\'?
+ Utzi %1$s ataka %2$d birbidaltzeari?
+ Sarea neurtutakoa da
+ Internet konexio aktiborik ez
+ NetGuard lanpetuta dago
+ Eguneraketa eskuragarri, sakatu deskargatzeko
+ Wi-Fi edo mugikor bidez Internetera sarbidea baimendu (berde) edo ukatu (gorri) aplikazioaren ondoan dauden ikonoak sakatuz
+ NetGuard zure pribatutasuna babesteko instalatu baduzu, agian FairEmail interesatuko zaizu, e-mail bezero librea eta pribatutasuna aintzat duena
+ Internet sarbidea lehenetsita baimenduta dago (zerrenda beltza modua), hau ezarpenetan aldatu daiteke
+ Jasotako (push) mezuak gehienbat Play Services osagaiak kudeatzen ditu, eta Internet sarbidea baimentzen zaio lehenetsita
+ Aplikazio guztiak (sistemakoak) kudeatzea ezarpenetan gaitu daiteke
+ Azaldu arazoa eta aipatu arazoaren data eta ordua mesedez:
+ VPN konexioa ezeztatuta\nBeste VPN bat ezarri duzu beti gaituta dagoen VPN gisa?
+ NetGuard gaituta dagoela gailua itzaltzen baduzu, NetGuard automatikoki abiatuko da gailua berriro piztean
+ Ezaugarri hau ez dago eskuragarri Android bertsio honetan
+ Beste VPN bat ezarri da beti gaituta dagoen VPN gisa
+ Itzali \'Blokeatu VPN gabeko konexioak\' Android VPN ezarpenetan NetGuard iragazte moduan erabiltzeko
+ Itzali \'DNS pribatua\' Android sare ezarpenetan NetGuard iragazte moduan erabiltzeko
+ Trafikoa blokeatuta dago
+ Neurtu gabeko trafikoa onartzen da
+ Neurtu gabeko trafikoa blokeatzen da
+ Neurtu gabeko sareen arauak ez dira aplikatzen
+ Neurtutako trafikoa onartzen da
+ Neurtutako trafikoa blokeatzen da
+ Neurtutako sareen arauak ez dira aplikatzen
+ Helbidea baimenduta dago
+ Helbidea blokeatuta dago
+ Baimendu pantaila piztuta dagoenean
+ Blokeatu ibiltaritzan
+ Lehenetsita Wi-Fi konexio bat neurtu gabekotzat hartzen da eta sare mugikorra neurtutzat
+ ez du Interneterako baimena
+ desgaituta dago
+ Mezuak Google Play services bidez jasotzen dira, ez ditu aplikazio honek zuzenean jasotzen, beraz ezin dira blokeatu aplikazio hau blokeatuz
+ Deskargak deskarga kudeatzaileak egiten ditu eta ez aplikazio honek, ondorioz ezin dira blokeatu aplikazio hau blokeatuz
+ Aplikatu arau eta baldintzak
+ Baldintzak
+ Baimendu Wi-Fia pantaila piztuta dagoenean
+ Baimendu mugikorra pantaila piztuta dagoenean
+ R
+ Blokeatu ibiltaritzan
+ Baimendu blokeo moduan
+ Iragazi erlazionatutakoak
+ Sarbide saiakaerak
+ Sarbide arauek beste arauekiko lehentasuna dute
+ Aukerak
+ Jakinarazi internet atzitzeko saiakerak
+ Egunkaria eta iragazkia desaktibatuta
+ Egunkaria eta iragazkia aktibatuta
+ Konfiguratu
+ Gaitu egunkarian blokeatutako helbideak gordetzea besterik ez
+ Gaitu egunkarian baimendutako helbideak ere gordetzea
+ Gaitu sarbide jakinarazpenak berriki gordetako helbideentzat
+ Ezarpen hauek orokorrak dira eta aplikazio guztiei eragiten diete
+ Iragaztea helbideak banaka gaitu edo blokeatzeko behar da ere
+ Egunkari (gutxiago) edo iragazkia (gehiago) akbibatzeak bateria erabilera areagotu dezake eta trafikoaren abiaduran eragin
+ Baloratu
+ Baimendu
+ Blokeatu
+ Baimendu Wi-Fia
+ Blokeatu Wi-Fia
+ Baimendu mugikorra
+ Blokeatu mugikorra
+ root
+ media zerbitzaria
+ inor ez
+ Ez galdetu berriro
+ Whois %1$s
+ %1$d ataka
+ Kopiatu
+ Ordainpeko ezaugarriak
+ Hurrengo ordainpeko ezaugarriak eskuragarri daude:
+ Ikusi blokeatutako trafikoaren egunkaria
+ Iragazi sareko trafikoa
+ Aplikazio berrien jakinarazpenak
+ Sare-abiaduraren grafikoen jakinarazpenak
+ Itxura (azala, koloreak)
+ Goiko ordainpeko ezaugarri guztiak
+ Babestu garapena
+ Erosi
+ Gaituta
+ Eskuraezina
+ Sakatu lauza bat informazio gehiagorako
+ Erronka
+ Erantzuna
+ Hau ordainpeko ezaugarri bat da
+
+ - berdexka/laranja
+ - urdina/laranja
+ - morea/gorria
+ - orixka/urdina
+ - laranja/grisa
+ - berdea
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-fa-rIR/strings.xml b/NetGuard/app/src/main/res/values-fa-rIR/strings.xml
new file mode 100644
index 0000000..aab38fd
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-fa-rIR/strings.xml
@@ -0,0 +1,271 @@
+
+
+ NetGuard راهکارهای ساده و پیشرفتهای برای مسدود کردن دسترسی به اینترنت فراهم میکند - بدون نیاز به روت بودن گوشی. هرکدام از برنامهها و سایتها میتوانند جداگانه به وایفای/داده موبایل دسترسی مجاز یا غیر مجاز داشته باشند.
+ NetGuard نیاز به اندروید 5.1 یا بالاتر دارد
+ Xposed موجب خطاهای زیاد میشود، که شاید موجب حذف شدن NetGuard از گوگل پلی استور شود، برای همین NetGuard هنگامی که Xposed نصب شده است ، پشتیبانی نمیشود
+ سیاست حفظ حریم خصوصی
+ مراقبتی عالی برای توسعه و آزمایش NetGuard بکار برده شده است، با این حال تضمین اینکه NetGuard بر روی هر دستگاهی به درستی کار خواد کرد غیرممکن است.
+ میپذیرم
+ نمیپذیرم
+ NetGuard به کمک شما نیاز دارد. برای خرید ویژگیهای حرفهای بهخاطر یاری پروژه ضربه بزنید.
+ خدمات درحال اجرا
+ اعلانهای عمومی
+ اعلانهای دسترسی
+ جستجو برای برنامه
+ پالودن برنامهها
+ نمایش برنامههای کاربر
+ نمایش برنامههای سیستمی
+ نمایش برنامهها بدون اینترنت
+ نمایش برنامههای غیرفعال
+ مرتبسازی برنامهها
+ مرتبسازی براساس نام
+ مرتبسازی براساس uid
+ مرتبسازی براساس مصرف داده
+ نمایش گزارش رویداد
+ تنظیمات
+ دعوت کردن
+ راهنما و علائم
+ پشتیبانی
+ درباره
+ سایر برنامهها
+ ساير
+ مجاز
+ مسدود شده
+ بهروزرسانیهای زنده
+ نوسازی
+ نمایش اسامی
+ نمایش سازمان
+ PCAP فعال شد
+ اکسپورت کردن PCAP
+ پاکسازی
+ اکسپورت
+ بازنشانی
+ افزودن
+ حذف
+ پاکسازی
+ پروتکل
+ درگاه منبع
+ آدرس مقصد
+ درگاه مقصد
+ برنامه مقصد
+ برای سرور خارجی گزینۀ nobody را انتخاب کنید
+ پیشفرضها (لیست سیاه / سفید)
+ مسدود کردن وایفای
+ مسدود کردن داده
+ هنگام روشن بودن صفحه به وایفای اجازه استفاده بده
+ هنگام روشن بودن صفحه به داده اجازۀ استفاده بده
+ مسدود کردن رومینگ
+ تنظیمات
+ پوسته: %1$s
+ استفاده از پوسته تیره
+ آگاهسازی هنگام نصب جدید
+ اعمال قوانین هنگام روشن بودن صفحه
+ فعالسازی خودکار بعد از %1$s دقیقه
+ تأخیر در خاموش کردن صفحه %1$s دقیقه
+ بررسی برای بروزرسانیها
+ گزینههای شبکه
+ مسیریابی زیرشبکه
+ اجازه به tethering
+ اجازه دسترسی به شبکه محلی
+ فعال کردن ترافیک IPv6
+ شبکه خانگی Wi-Fi:%1$s
+ به شبکههای وایفای اندازهگیری شده رسیدگی کن
+ 2G را اندازهگیری نشده در نظر بگیر
+ 3G را اندازهگیری نشده در نظر بگیر
+ LTE را اندازهگیری نشده در نظر بگیر
+ رومینگ ملی را نادیده بگیر
+ نادیده گرفتن رومینگ اروپا
+ غیر فعالشدن در طول تماس
+ قفل کردن وای فای
+ قفل کردن تلفن همراه
+ بارگذاری مجدد در هر نوعی از تغییرات اتصال
+ تنظیمات پیشرفته
+ مدیریت برنامه های سیستم
+ ثبت دسترسی ها به اینترنت
+ آگاه سازی هنگام دسترسی به اینترنت
+ فیلتر کردن ترافیک
+ فیلتر ترافیک UDP
+ بستن اتصالها هنگام بارگذاری مجدد
+ قفل کردن ترافیک
+ مصرف شبکه را ردیابی کن
+ بازنشانی مصرف شبکه
+ نمایش نامهای دامنه پیدا شده
+ نامهای دامنه را مسدود کن
+ کد واکنش DNS: %s
+ هدایت درگاه
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ تایید اعتبار در: %s
+ استفاده از پروکسی SOCKS5
+ نشانی SOCKS5: %s
+ درگاه SOCKS5: %s
+ نامکاربری SOCKS5: %s
+ گذرواژه SOCKS5: %s
+ Watchdog: هر %s دقیقه
+ اعلان سرعت
+ نمایش اعلان سرعت
+ نمایش برنامههای برتر
+ وقفه نمونه: %s ms
+ شمار نمونهها: %s s
+ پشتیبانگیری
+ خارجکردن تنظیمات
+ واردکردن تنظیمات
+ واردکردن پرونده hosts
+ واردکردن پرونده hosts (پیوست)
+ پیوند بارگیری پرونده hosts
+ بارگیری پرونده hosts
+ اطلاعات فنی
+ کلی
+ شبکهها
+ اشتراکها
+ بررسی برای نگارشهای جدید دوبار در روز
+ بسته به نگارش tethering ، Android ممکن است کار کند یا ممکن است کار نکند. ترافیک tethering نمیتواند پالایش شود.
+ قوانین شبکهی وایفای را فقط برای شبکهی انتخاب شده اِعمال کن (قوانین شبکهی همراه را برای دیگر شبکههای وایفای اِعمال کن)
+ قوانین شبکههای همراه را برای شبکههای وایفای اندازهگیری شده (پولی،متصل به نقطه) اعمال کن
+ قوانین شبکه وایفای را برای اتصالهای داده 2G اعمال کن
+ قوانین شبکه وایفای را برای اتصالهای داده 3G اعمال کن
+ قوانین شبکه وایفای را برای اتصالهای داده LTE اعمال کن
+ قوانین رومینگ را زمانیکه شبکهی کشور سیمکارت و همراه مشابهاند اِعمال نکن
+ قوانین رومینگ را زمانیکه شبکهی کشور سیمکارت و همراه درون اروپا هستند اِعمال نکن (رومینگ شبیه داخلی)
+ غیرفعال کردن NetGuard برای تماسهای تلفنی ورودی یا خروجی. این تنظیم میتواند برای استفاده از مشکلات تماسهای آیپی/وایفای استفاده شود.
+ تعیین قوانین برای برنامههای سیستم (برای کارشناسان)
+ تلاشهای دسترسی به اینترنت برای برنامهها را ثبت کن. این ممکن است منجر به مصرف باتری اضافی شود.
+ هنگام تلاش برای دستیابی به یک آدرس اینترنتی جدید ، اعلان نوار وضعیت را نشان بده (وقتی فیلتر غیرفعال است ، فقط به تلاشهای دسترسی به اینترنت مسدود شده اطلاع داده میشود)
+ بسته های IP را که از تونل VPN خارج می شوند فیلتر کن. این ممکن است منجر به مصرف باتری اضافی شود.
+ تعداد بایت های ارسال شده و دریافت شده برای هر برنامه و آدرس را دنبال کن. این ممکن است منجر به مصرف باتری اضافی شود.
+ با کد پاسخ DNS تنظیم شده برای نامهای دامنه مسدود شده پاسخ دهد. این سوئیچ هنگامی که فایل میزبان در دسترس نیست غیرفعال می شود.
+ مقدار پیش فرض ۳ (NXDOMAIN) است که به معنی \"دامنه غیر وجود\" است.
+ نام دامنه استفاده شده برای تایید اعتبار اتصال اینترنت برای درگاه ۴۴۳ (https).
+ تنها ترافیک TCP به سرور پروکسی فرستاده خواهد شد
+ نمودار سرعت شبکه را در اعلان نوار وضعیت نشان بده
+ آیا مطمئن هستید؟
+ در حال اجرای قوانین
+ %1$d مجازشد، %2$d مسدود شد
+ %1$d مجازشد، %2$d مسدود شد، %3$d هاست
+ در حال انتظار برای رویداد
+ NetGuard غیرفعال است، از کلید بالا برای فعالسازی NetGuard استفاده کنید
+ NetGuard غیرفعال شده است، به احتمال زیاد به خاطر استفاده از یک برنامه مبتنی بر VPN
+ \'%1$s\' نصب شد
+ نصب شده است
+ %1$s تلاش برای دسترسی به اینترنت
+ تلاش برای دسترسی به اینترنت
+ کنش کامل شد
+ NetGuard از یک VPN محلی برای فیلتر کردن ترافیک اینترنت استفاده می کند.
+ به همین دلیل ، لطفاً در گفتگوی بعدی اتصال VPN را مجاز کنید.
+ ترافیک اینترنت شما به یک سرور VPN از راه دور ارسال نمیشود.
+ NetGuard نمیتواند خودکار اجرا شود. این شاید بهخاطر یک باگ در نگارش اندروید شماست.
+ یک خطای غیر منتظره رخ داده است: \'%s\'
+ اندروید در این لحظه از شروع سرویس VPN خودداری کرد. این به احتمال زیاد به دلیل اشکال در نسخه اندروید شما است.
+ NetGuard را بیازمایید
+ با اهداء شما با شرایط و مقررات & موافقت میکنید
+ اگر در گفتگوی بعدی نمیتوانید OK را فشار دهید ، احتمالاً برنامه دیگری (کم رنگ کننده صفحه) صفحه را دستکاری میکند.
+ ± %1$.3f▲ %2$.3f▼مگابایت/روز
+ %1$7.3f▲ %2$7.3f▼کیلوبایت
+ %1$7.3f▲ %2$7.3f▼مگابایت
+ %1$7.3f▲ %2$7.3f▼ گیگابایت
+ %dx
+ برای عملکرد درست ، بهینه سازی باتری اندروید باید برای NetGuard غیرفعال شود.
+\n\n در گفتگوی بعدی ، \"همه برنامه ها\" را در بالا انتخاب کنید ، روی NetGuard در لیست ضربه بزنید و \"بهینه سازی نکنید\" را انتخاب و تأیید کنید.
+ برای نتایج مداوم ، گزینه های ذخیره داده اندرویدی باید برای NetGuard غیرفعال شود
+\n\n در گفتگوی بعدی گزینه های \"داده پس زمینه\" و \"استفاده از داده های بدون محدودیت\" را فعال کنید
+ استفاده از فیلتر باعث میشود انتقال داده اندروید و مصرف برق را به NetGuard نسبت دهد - اندروید فرض میکند که دادهها و قدرت توسط NetGuard استفاده میشود ، نه برنامه های اصلی
+ در اندروید ۴ فیلتر باید فعال باشد
+ آخرین واردکردن: %s
+ درحال بارگیری\n%1s
+ پرونده Hosts بارگیری شد
+ آخرین بارگیری: %s
+ شبکه اندازهگیری میشود
+ اتصال فعال اینترنت موجود نیست
+ NetGuard مشغول است
+ بهروزرسانی موجود است، برای بارگیری لمس کنید
+ اگر شما NetGuard را برای حفاظت از حریم خصوصی خود نصب کردهاید شاید به FairEmail نیز علاقه مند باشید، یک برنامه ایمیل، منبع باز و نیز دوستدار حریم خصوصی
+ لطفاً مشکل را شرح داده و به زمان مشکل نیز اشاره کنید:
+ اتصال VPN لغو شد\n آیا شما یک VPN دیگر را به عنوان همیشه-روشن پیکربندی کردهاید؟
+ این ویژگی در این نسخه اندروید در دسترس نیست
+ VPN دیگری به عنوان VPN همیشه-فعال تنظیم شده است
+ \"اتصال اتصالات بدون VPN\" را در تنظیمات VPN اندروید خاموش کنید تا از NetGuard در حالت فیلتر استفاده کنید
+ \"DNS خصوصی\" را در تنظیمات شبکه اندروید خاموش کنید تا از NetGuard در حالت فیلتر استفاده کنید
+ ترافیک قفل شد
+ ترافیکِ اندازهگیری نشده مجاز شد
+ ترافیک اندازهگیری نشده مسدود شد
+ قوانین اندازهگیری نشده اعمال نمیشوند
+ ترافیک اندازهگیری شده مجاز است
+ ترافیک اندازهگیری شده مسدود است
+ قوانین اندازهگیری شده اعمال نمیشوند
+ نشانی مجاز است
+ نشانی مسدود است
+ هنگام روشن بودن صفحه اجازه بده
+ هنگام رومینگ مسدود کن
+ اتصال وایفای به طور پیشفرض اندازه گیری نشده و داده همراه اندازهگیری شده در نظر گرفته میشود
+ هیچ اجازه اینترنتی ندارد
+ غیرفعال است
+ پیام های دریافتی توسط خدمات گوگلپِلی و نه توسط این برنامه دریافت میشوند و بنابراین نمیتوان با مسدود کردن این برنامه آنرا مسدود کرد
+ دانلودها توسط مدیرِ دانلود انجام میشود و نه توسط این برنامه و بنابراین نمیتوان با مسدود کردن این برنامه آنها را مسدود کرد
+ اعمال قوانین و وضعیتها
+ وضعیتها
+ هنگام روشن بودن صفحه به وایفای اجازه استفاده بده
+ هنگام روشن بودن صفحه به داده اجازۀ استفاده بده
+ رومینگ
+ هنگام رومینگ مسدود کن
+ اجازه در حالت قفل
+ وابسته به پالایش
+ تلاشهای دسترسی
+ قوانین دسترسی بر سایر قوانین مقدماند
+ تنظیمات
+ اعلان برای تلاش های دسترسی به اینترنت
+ گزارشگیری یا پالایش فعال نمیباشد
+ گزارشگیری و پالایش فعال میباشند
+ پیکربندی
+ فعال شدن ورود به سیستم فقط برای آدرسهای مسدود شده
+ فعال کردن فیلتر همچنین برای ورود به آدرسهای مجاز
+ فعال شدن اعلانهای دسترسی برای آدرسهای تازه
+ این تنظیمات، تنظیمات جهانی است که برای همه برنامه ها اعمال می شود
+ فیلتر کردن همچنین برای مجاز یا مسدود کردن آدرسهای فردی لازم است
+ فعال کردن ورود به سیستم با فیلترینگ (کمتر) یا (بیشتر) ممکن است باعث افزایش مصرف باتری شود و بر سرعت شبکه تأثیر بگذارد
+ امتیازدهی
+ اجازه دادن
+ مسدود کردن
+ اجازه به وایفای
+ مسدود کردن وایفای
+ اجازه به داده همراه
+ مسدود کردن داده
+ روت
+ سرور رسانه
+ هیچکس
+ دوباره نپرس
+ Whois %1$s
+ درگاه %1$d
+ روگرفت
+ ویژگیهای حرفهای
+ ویژگیهای حرفهای زیر موجود است:
+ نمایش گزارش ترافیک مسدود شده
+ ترافیک شبکه را فیلتر کن
+ اعلانهای جدید برنامه
+ اعلان نمودار سرعت شبکه
+ ظاهر (پوسته، رنگها)
+ تمام ویژگیهای حرفهای فوق
+ حمایت از توسعه
+ خرید
+ فعال شده
+ ناموجود
+ برای آگاهی بیشتر روی عنوان بزنید
+ چالش
+ واکنش
+ این یک ویژگی نسخه حرفهای است
+ اشتراک ماهانه 1 یا 2 یورو (به استثنای مالیات محلی) تمام ویژگیهای حرفهای را فعال میکند.
+ می توانید اشتراک را از طریق برگه اشتراک در برنامه فروشگاه Play لغو یا مدیریت کنید.
+
+
+ - آبی دریایی/نارنجی
+ - آبی/نارنجی
+ - بنفش/قرمز
+ - کهربایی/آبی
+ - نارنجی/خاکستری
+ - سبز
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-fi-rFI/strings.xml b/NetGuard/app/src/main/res/values-fi-rFI/strings.xml
new file mode 100644
index 0000000..a757bc4
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-fi-rFI/strings.xml
@@ -0,0 +1,290 @@
+
+
+ NetGuard tarjoaa yksinkertaisia ja edistyneitä keinoja estää yhteydet internettiin - ilman tarvetta root-oikeuksille. Sovelluksille ja osoitteille voi yksilöllisesti sallia tai estää pääsyn Wi-Fi- ja/tai mobiiliyhteyteesi.
+ NetGuard edellyttää vähintään Android versiota 5.1
+ Xposed aiheuttaa liikaa kaatumisia, minkä takia NetGuard saatetaan poistaa Google Play Kaupasta, joten NetGuard ei ole tuettu, kun Xposed on asennettuna
+ Tietosuojakäytäntö
+ NetGuardia kehitettäessä ja testatessa on noudatettu suurta huolellisuutta, mutta on mahdotonta taata, että se toimii oikein kaikissa laitteissa.
+ Hyväksyn
+ En hyväksy
+ NetGuard tarvitsee apuasi. Napauttamalla voit ostaa pro-ominaisuudet pitääksesi projektin käynnissä.
+ Käynnissä olevat palvelut
+ Yleiset ilmoitukset
+ Yhteysilmoitukset
+ Etsi sovellusta
+ Suodata sovelluksia
+ Näytä käyttäjän sovellukset
+ Näytä järjestelmäsovellukset
+ Näytä sovellukset ilman internetiä
+ Näytä käytöstä poistetut sovellukset
+ Järjestä sovellukset
+ Järjestä nimen mukaan
+ Järjestä uid:n mukaan
+ Järjestä datan käytön mukaan
+ Näytä loki
+ Asetukset
+ Kutsu
+ Selite
+ Tuki
+ Tietoja
+ Muut sovellukset
+ Muu
+ Sallittu
+ Estetty
+ Automaattipäivitykset
+ Päivitä
+ Näytä nimet
+ Näytä organisaatio
+ PCAP käytössä
+ PCAP vienti
+ Tyhjennä
+ Vie
+ Palauta oletukset
+ Lisää
+ Poista
+ Siistiminen
+ Protokolla
+ Lähdeportti
+ Kohdeosoite
+ Kohdeportti
+ Kohdesovellus
+ Valitse \"ei kukaan\" halutessasi ulkoisen palvelimen
+ Oletusarvot (valkoinen/musta lista)
+ Estä Wi-Fi
+ Estä mobiili
+ Salli Wi-Fi näytön ollessa päällä
+ Salli mobiili näytön ollessa päällä
+ Estä verkkovierailu
+ Asetukset
+ Teema: %1$s
+ Käytä tummaa teemaa
+ Ilmoita uusista asennuksista
+ Käytä \'näyttö päällä\'-sääntöjä
+ Automaattinen käyttöönotto %1$s minuutin jälkeen
+ Näyttö pois päältä viive %1$s minuuttia
+ Tarkasta päivitykset
+ Verkkoasetukset
+ Aliverkon reititys
+ Salli internetin jako
+ Salli pääsy LAN verkkoon
+ Ota käyttöön IPv6 liikenne
+ Wi-Fi kotiverkot: %1$s
+ Hallitse käytön mukaan laskutettavia yhteyksiä
+ Älä huomioi 2G:tä käytön mukaan laskutettavana
+ Älä huomioi 3G:tä käytön mukaan laskutettavana
+ Älä huomioi LTE:tä käytön mukaan laskutettavana
+ Älä huomioi kotimaan verkkovierailua
+ Älä huomioi EU-verkkovierailua
+ Poista käytöstä puhelun aikana
+ Lukitse Wi-Fi
+ Lukitse mobiili
+ Lataa uudelleen aina yhteyden vaihtuessa
+ Lisäasetukset
+ Hallitse järjestelmäsovelluksia
+ Tallenna internet yhteydet lokiin
+ Ilmoita internetyhteydestä
+ Suodata liikennettä
+ Suodata UDP-liikennettä
+ Saumaton VPN-yhteyden siirto uudelleen ladattaessa
+ Sulje yhteydet uudelleen ladattaessa
+ Lukitse liikenne
+ Seuraa verkon käyttöä
+ Nollaa verkon käyttö
+ Näytä selvitetyt verkkotunnukset
+ Estä verkkotunnuksia
+ DNS-vastauskoodi: %s
+ Porttien uudelleenohjaus
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Yhteyden validoinnin kohde: %s
+ DNS TTL-vähimmäisarvo: %s s
+ Käytä SOCKS5-välityspalvelinta
+ SOCKS5-osoite: %s
+ SOCKS5-portti: %s
+ SOCKS5-käyttäjätunnus: %s
+ SOCKS5-salasana: %s
+ PCAP-tallenteen koko: %s B
+ PCAP:n suurin tiedostokoko: %s MB
+ Watchdog: joka %s minuutti
+ Nopeusilmoitus
+ Näytä nopeusilmoitus
+ Näytä yleisimmät ohjelmat
+ Näytteistysväli: %s ms
+ Näytteiden määrä: %s s
+ Varmuuskopiointi
+ Vie asetukset
+ Tuo asetukset
+ Tuo hosts-tiedosto
+ Tuo hosts-tiedosto (lisää olemassa olevaan)
+ Hosts-tiedoston URL-osoite
+ Lataa hosts-tiedosto
+ Tekniset tiedot
+ Yleiset
+ Verkkoyhteydet
+ Tilaukset
+ Näytä tilapalkki-ilmoitus muokataksesi suoraan asetuksia uusille asennetuille ohjelmille (pro-ominaisuus)
+ Ota NetGuard automaattisesti käyttöön kytkettyäsi sen pois widgetillä (näin monen minuutin kuluttua, 0 kytkee toiminnon pois)
+ Pidä näyttö päällä -asetuksia aktiivisina näytön sammuttua (näin monta minuuttia, 0 kytkee toiminnon pois)
+ Tarkasta päivitykset kahdesti päivässä GitHubista
+ Internetin jakaminen saattaa toimia Android-versiosta riippuen. Jaettua liikennettä ei voi suodattaa.
+ Ota käyttöön aliverkon reititys; saattaa ottaa käyttöön Wi-Fi-puhelut, mutta saattaa myös aktivoida Androidissa olevia bugeja ja lisätä akun käyttöä
+ Salli ohjelmien yhdistää lähiverkon osoitteisiin, kuten 10.0.0.0/8, 172.16.0.0/12 ja 198.168.0.0/16
+ Reititä IPv6-liikenne NetGuardiin, jotta se voidaan valikoiden sallia tai estää
+ Käytä Wi-Fi-verkkojen sääntöjä vain valitulle verkolle (käytä mobiiliverkon sääntöjä muille Wi-Fi verkoille)
+ Käytä mobiiliverkkojen sääntöjä käytön mukaan laskutettaville (maksulliset, mobiilijako) Wi-Fi-verkoille
+ Käytä Wi-Fi-verkon sääntöjä 2G-yhteyksille
+ Käytä Wi-Fi-verkon sääntöjä 3G-yhteyksille
+ Käytä Wi-Fi-verkon sääntöjä LTE-yhteyksille
+ Älä käytä verkkovierailun sääntöjä, kun SIM-kortti ja mobiiliverkko ovat samasta maasta
+ Älä käytä verkkovierailun sääntöjä, kun SIM-kortti ja mobiiliverkko ovat molemmat EU-maasta (kotimaanhintaiset verkkovierailut)
+ Laita NetGuard pois käytöstä puheluiden aikana. Tämä kiertää mahdollisia IP-/Wi-Fi-puheluongelmia.
+ Määritä sääntöjä järjestelmäsovelluksille (kokeneille käyttäjille)
+ Kirjaa lokiin yritykset yhdistää internetiin. Tämä saattaa lisätä akun käyttöä.
+ Näytä tilapalkin ilmoitus, kun sovellukset yrittävät yhdistää uuteen internetosoitteeseen (vain estetyt yritykset näytetään, jos suodatus ei ole käytössä)
+ Suodata VPN-tunnelista ulospäin kulkevat IP-paketit. Tämä saattaa lisätä akun käyttöä.
+ Seuraa jokaisen sovelluksen ja osoitteen lähettämien ja vastaanottamien tavuja lukumäärää. Tämä saattaa lisätä akun käyttöä.
+ Vastaa asetetulla DNS-vastauskoodilla estettyihin verkkotunnuksiin kohdistuviin pyyntöihin. Tämä valinta on kytketty pois päältä, jos hosts-tiedostoa ei ole saatavilla.
+ Oletusarvo on 3 (NXDOMAIN), joka tarkoittaa \'verkkotunnusta ei ole olemassa\'.
+ Verkkotunnus, jonka porttiin 443 (https) yhdistämällä validoidaan internetyhteys.
+ Vain TCP-liikenne lähetetään välityspalvelimelle
+ Tarkasta väliajoin NetGuardin päälläolo (aseta 0 kytkeäksesi tämä pois käytöstä). Tämä saattaa lisätä akun käyttöä.
+ Näytä verkkoyhteyden nopeuskuvaaja tilapalkin ilmoituksessa
+ Oletko varma?
+ Toimeenpanee sääntöjä
+ %1$d sallittu, %2$d estetty
+ %1$d sallittu, %2$d estetty, %3$d osoitetta
+ Odottaa tapahtumaa
+ NetGuard ei ole käytössä, ota se käyttöön
+ NetGuard on poistettu käytöstä luultavasti käyttämällä toista VPN-sovellusta
+ \'%1$s\' asennettu
+ On asennettu
+ %1$s yritti ottaa yhteyttä internetiin
+ Yritetty internetyhteyttä
+ Toiminto suoritettu
+ NetGuard käyttää paikallista VPN-yhteyttä internetyhteyksien suodattamiseen. Tämän takia tulee sallia VPN-yhteys seuraavassa valikossa. Verkkoliikennettäsi ei ohjata ulkoiselle VPN-palvelimelle.
+ NetGuard ei voinut käynnistyä automaattisesti. Tämä johtunee ohjelmistovirheestä Android-versiossasi.
+ Tapahtui odottamaton virhe: \'%s\'
+ Android esti VPN-yhteyden käynnistymisen. Tämä johtunee ohjelmistovirheestä Android-versiossasi.
+ Kokeile NetGuardia
+ Lahjoittamalla hyväksyt terms & ehdot
+ Jos et voi valita OK seuraavassa kohdassa, jokin näyttöä hallinnoiva (himmentävä) sovellus luultavasti estää sen.
+ ± %1$.3f▲ %2$.3f▼ MB/päivä
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Androidin akun käytön optimointi tulisi sulkea NetGuardin osalta luotettavan toiminnan takaamiseksi.
+\n\nValitse seuraavassa valikossa ylhäältä \"Kaikki ohjelmat\", NetGuard ja valitse sekä hyväksy \"Älä optimoi\".
+ Androidin dataa säästävät asetukset tulisi laittaa pois päältä NetGuardin osalta luotettavan toiminnan takaamiseksi.
+\n\nOta käyttöön seuraavassa valikossa vaihtoehdot \"Taustatiedonsiirto\" ja \"Rajoittamaton datan käyttö\"
+ Verkkoliikenteen suodatus saa Androidin kohdistamaan datan ja akun käytön NetGuard-sovellukselle, eikä dataa ja akkua todellisuudessa käyttäville sovelluksille
+ Android 4 edellyttää suodatuksen kytkemistä päälle
+ Verkkoliikenteen lokiin kirjaaminen ei ole käytössä. Kirjaamisen käyttäminen saattaa lisätä akun käyttöä.
+ Tämä palauttaa säännöt ja ehdot oletusarvoihinsa
+ Tämä poistaa yritettyjen yhteyksien lokimerkinnät ilman salli/estä sääntöjä
+ Edellinen tuonti: %s
+ Ladataan\n%1s
+ Hosts-tiedosto ladattu
+ Edellinen lataus: %s
+ Aloita uudelleenohjaus osoitteen %1$s portista %2$d osoitteeseen %3$s:%4$d sovelluksille \'%5$s\'?
+ Lopeta uudelleenohjaus osoitteen %1$s portista %2$d?
+ Verkko on käytön mukaan laskutettava
+ Ei aktiivista internetyhteyttä
+ NetGuard on varattu
+ Päivitys saatavilla, valitse ladataksesi
+ Voit sallia (vihertävä) tai estää (punertava) sovelluksen pääsyn internetiin Wi-Fi- tai mobiiliverkon kautta sovelluksen vieressä olevista kuvakkeista
+ Jos asensit NetGuardin suojellaksesi yksityisyyttäsi, voit olla kiinnostunut myös FairEmailista , avoimen lähdekoodin, yksityisyysystävällisestä sähköpostisovelluksesta
+ Internetyhteys on sallittu oletuksena (musta lista -tila), tämän voi muuttaa asetuksista
+ Järjestelmäsovellus Play Palvelut käsittelee pääsääntöisesti saapuvat (push) viestit ja sen pääsy internetiin on sallittu oletuksena
+ Kaikkien sovellusten (myös järjestelmäsovellusten) hallinnoinnin voi ottaa käyttöön asetuksista
+ Kuvaile ongelmatilanne ja ilmoita milloin ongelma ilmenee:
+ VPN-yhteys on peruttu\n Oletko asettanut toisen VPN-yhteyden aina käytössä olevaksi?
+ Laitteen sammuttaminen, kun NetGuard on käytössä, käynnistää NetGuardin automaattisesti laitteen käynnistyksen yhteydessä
+ Tämä ominaisuus ei ole saatavilla tässä Android-versiossa
+ Toinen VPN on asetettu aina käytössä olevaksi
+ Kytke Androidin VPN-asetuksissa pois \"Estä yhteydet, jotka eivät käytä VPN:ää\" käyttääksesi NetGuardin suodatustilaa
+ Kytke pois \"Yksityinen DNS\" Androidin verkkoasetuksissa käyttääksesi NetGuardin suodatustilaa
+ Liikenne on lukittu
+ Liikenne, joka ei ole käytön mukaan laskutettava, on sallittu
+ Liikenne, joka ei ole käytön mukaan laskutettava, on estetty
+ Sääntöjä liikenteelle, joka ei ole käytön mukaan laskutettava, ei käytetä
+ Käytön mukaan laskutettava liikenne on sallittu
+ Käytön mukaan laskutettava liikenne on estetty
+ Käytön mukaan laskutettavalle liikenteelle olevia sääntöjä ei käytetä
+ Osoite on sallittu
+ Osoite on estetty
+ Salli näytön ollessa päällä
+ Estä verkkovierailun aikana
+ Oletuksena mobiiliyhteyttä pidetään käytön mukaan laskutettavana mutta Wi-Fi-yhteyttä ei
+ ei ole internetoikeuksia
+ on poistettu käytöstä
+ Google Play Palvelut ottaa vastaan tulevat viestit, joten tämän sovelluksen estäminen ei estä viestejä
+ Latauksista vastaa latausten hallinta, eikä tämän sovelluksen estäminen estä niitä
+ Käytä sääntöjä ja ehtoja
+ Ehdot
+ Salli Wi-Fi näytön ollessa päällä
+ Salli mobiili näytön ollessa päällä
+ R
+ Estä verkkovierailun aikana
+ Salli lukitustilassa
+ Suodata liittyvät
+ Yhteysyritykset
+ Yhteyksien säännöt ovat etusijalla ennen muita sääntöjä
+ Asetukset
+ Ilmoita internetyhteysyrityksistä
+ Lokiin kirjaaminen tai suodatus eivät ole käytössä
+ Lokiin kirjaaminen ja suodatus ovat käytössä
+ Määritä
+ Ota käyttöön vain estettyjen osoitteiden lokiin kirjaaminen
+ Ota käyttöön myös sallittujen osoitteiden lokiin kirjaaminen
+ Ota käyttöön yhteysilmoitukset uusille lokiin kirjatuille osoitteille
+ Nämä asetukset ovat globaaleja ja vaikuttavat kaikkiin sovelluksiin
+ Suodatus vaaditaan yksittäisten osoitteiden sallimiseksi tai estämiseksi
+ Akun käyttö saattaa lisääntyä ja verkkoliikeenteen nopeus saattaa hidastua lokiin kirjaamisesta (vähän) ja suodatuksesta (enemmän)
+ Arvostele
+ Salli
+ Estä
+ Salli Wi-Fi
+ Estä Wi-Fi
+ Salli mobiili
+ Estä mobiili
+ root
+ mediapalvelin
+ ei kukaan
+ Älä kysy uudelleen
+ Whois %1$s
+ Portti %1$d
+ Kopioi
+ Pro-ominaisuudet
+ Seuraavat pro-ominaisuudet ovat saatavilla:
+ Näytä estetyn liikenteen loki
+ Suodata verkkoliikennettä
+ Ilmoitukset uusista sovelluksista
+ Verkkoyhteyden nopeuskuvaaja ilmoituksessa
+ Ulkonäkö (teema, värit)
+ Kaikki ylläolevat pro-ominaisuudet
+ Tue kehitystä
+ Osta
+ Käytössä
+ Ei saatavilla
+ Valitse otsikko saadaksesi lisätietoja
+ Haaste
+ Vastaus
+ Tämä on pro-ominaisuus
+ 1 tai 2 euron kuukausitilaus (paikallisia veroja lukuun ottamatta) aktivoi kaikki pro-ominaisuudet.
+ Voit peruuttaa tilauksen tai hallita sitä Play-kauppa sovelluksen tilausvälilehdeltä.
+
+
+ - sinivihreä/oranssi
+ - sininen/oranssi
+ - purppura/oranssi
+ - ruskeankeltainen/sininen
+ - oranssi/harmaa
+ - vihreä
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-fil-rPH/strings.xml b/NetGuard/app/src/main/res/values-fil-rPH/strings.xml
new file mode 100644
index 0000000..16a09bf
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-fil-rPH/strings.xml
@@ -0,0 +1,272 @@
+
+
+ Ang NetGuard ang nagbibigay ng simple at pinahusay na mga paraan para harangan ang akses sa internet - ang root ay hindi kinakailangan. Ang mga App at mga adres ay isa-isang pinapayagan o tinatanggihan ang akses sa iyong Wi-Fi at/o sa iyong mobile koneksyon.
+ NetGuard requires Android 5.1 or later
+ Ang Xposed ang nagiging dahilan kung bakit masyadong maraming salpukan, kung saan ay nagiging resulta na ang NetGuard ay tinatanggal mula sa Google Play Store, kaya ang NetGuard at hindi suportado habang ang Xposed ay naka-install
+ Ang patakaran sa pagiging pribado
+ Ako ay sumasang-ayon
+ Ako ay hindi sumasang-ayon
+ Pinapatakbo ang mga serbisyo
+ Ang pangkalahatang mga notipikasyon
+ Ang akses sa mga notipikasyon
+ Ang paghahanap para sa mga aplikasyon
+ Ang pagsasala sa mga aplikasyon
+ Ipakita ang gumagamit ng mga aplikasyon
+ Ipakita ang sistema ng mga aplikasyon
+ Ipakita ang mga aplikasyon kahit na walang internet
+ Ipakita ang naka-disable na mga aplikasyo
+ Ayos ng mga aplikasyon
+ Ayosin ayon sa pangalan
+ Ayosin ayun sa uid
+ Ayosin ayon sa gamit ng datus
+ Ipakita ang log
+ Ang mga setting
+ Imbitado
+ Alamat
+ Suporta
+ Tungkol sa
+ Iba pa
+ Pinayagan
+ Naka-block
+ Ang layb na mga updeyt
+ I-refresh
+ Ang mga pangalan ay ipakita
+ Ang orginisasyon ay ipakita
+ Naka-enable ang PCAP
+ I-eksport ang PCAP
+ Malinaw
+ I-reset
+ Idagdag
+ Alisin
+ Paglilinis
+ Protokol
+ Ang pinagmulan ng port
+ Ang destinasyon ng adres
+ Ang destinasyon ng port
+ Ang destinasyon ng aplikasyon
+ Para sa panlabas na serber piliin ang \'wala\'
+ Ang mga default na (white/blacklist)
+ I-block ang Wi-Fi
+ I-block ang mobile
+ Payagan ang Wi-Fi kapag ang nakabukas na ang iskrin
+ Payagan ang mobile kapag ang nakabukas na ang iskrin
+ I-block ang roaming
+ Ang mga opsyon
+ Tema: %1$s
+ Gamitin ang maitim na tema
+ Ang notipikasyon sa bagong install
+ Gamitin ang mga alituntunin \'kapag nakabukas na ang iskrin\'
+ Awtomatikong naka-enable pagkatapos ng %1$s isang minuto
+ Huli ng isang minuto kapag pinatay ang iskrin %1$s
+ I-tsek para sa mga updeyt
+ Ang mga opsiyon ng Network
+ Ang pagrorota sa subnet
+ Payagan ang pagti-tether
+ Payagan ang pag-akses sa LAN
+ Naka-enble ang daloy ng IPv6
+ Ang mga network ng Wi-Fi sa tahanan: %1$s
+ Hawakan ang panukat sa mga network Wi-Fi
+ Isaalang-alang na ang 2G ay hindi nasukat
+ Isaalang-alang na ang 3G ay hindi nasukat
+ Isaalang-alang na ang LTE ay hindi nasukat
+ Balewalain ang roaming na pangnasyonal
+ Balewalain ang EU roaming
+ Naka-disable ang pagtawag
+ I-lockdown ang Wi-Fi
+ I-lockdown ang mobile
+ I-reload sa kada may pagbabago sa pagkokonekta
+ Ang mga opsyon na pinahusay
+ Pamahalaan ang sistema ng mga aplikasyon
+ Ang akses sa internet ay log
+ Ang notipikasyon sa akses para sa internet
+ Pagsasala sa daloy
+ Isarado ang mga koneksyon sa kapag ni-reload
+ I-lockdown ang daloy
+ Subaybayan ang gamit ng network
+ I-rest ang paggamit ng network
+ Ipakita na naresolba ang mga pangalan ng domain
+ I-block ang mga pangalan ng domain
+ Ang sagot ng DNS para sa kowd: %s
+ Pagpapasa ng Port
+ Ang VPN IPv4: %s
+ Ang VPN IPv6: %s
+ Ang VPN ng DNS: %s
+ Ang pinakamababang DNS sa TTL: %s s
+ Gamitin ang proksi na SOCKS5
+ Ang SOCKS5 address: %s
+ Ang SOCKS5 port: %s
+ Ang username ng SOCKS5: %s
+ Ang password ng SOCKS5: %s
+ Ang sukat ng tala sa PCAP: %s B
+ Ang pinakamataas na sukat na payl ng PCAP ay: %s MB
+ Guwardiyahan: kada %s minuto
+ Ang bilis ng notipikasyon
+ Ipakita ang bilis ng notipikasyon
+ Ipakita ang nasa itaas na mga aplikasyon
+ Ang hilambawa ng agwat: %s ms
+ Ang bilang ng mga halimbawa: %s s
+ Mag-backup
+ Ang mga setting ay I-eksport
+ Ang mga setting ay i-import
+ Ang mga host na payl ay i-import
+ I-download ang URL ng mga host payl
+ I-download ang mga host payl
+ Ang impormasyong teknikal
+ Pangkalahatan
+ Ang mag network
+ Ang mga subskripsyon
+ Ipakita ang notipikasyon ng estado ng bar para direktang kumpigurahin ang mga bagong na-install na mga aplikasyon (tampok ang mahuhusay)
+ Pagkatapos na i-disable gamit ang widget, awtomatikong ma-enable uli ang NetGuard pagkatapos piliin ang numero ng mga minuto (ilagay ang bokya para i-disable ang opsyong ito)
+ Pagkatapos patayin ang iskrin, panatilihing nakabukas ang mga alituntunin ng iskrin para sa mga napiling bilang ng mga minuto (ilagay ang bokya para i-disable ang opsyong ito)
+ Tignan ng dalawang beses sa isang araw ang mga bagong nilalabas sa Github
+ Depende sa beryon ng Android, kung ang pagte-tether ay gagana o hindi gagana. Ang daloy ng tether ay hindi pwedeng salain.
+ Ang subnet routing ay naka-enable; baka mapagana ang Wi-Fi sa pagtawag, pero maaari din itong pagmulan ng mga bug sa pagdagdag ng gamit ng baterya ng Android
+ Payagan ang mga aplikasyon para makakonekta sa lokal na area network na mga address, gaya ng 0.0.0.0/8, 172.16.0.0/12 at 192.168.0.0/16
+ Ang bersyon IP 6 sa Rota ng dalot para sa NetGuard ito ay maaaring payagan o i-block
+ I-aplay ang mga alituntunin ang Wi-Fi network para sa napiling network lamang (i-aplay ang mga alituntunin ng mobile network sa ibang Wi-Fi na mga network)
+ I-aplay ang alituntunin ng mobile network para makwenta ang (bayad na, tethered) at Wi-Fi networks
+ I-aplay ang mga alituntunin ng Wi-Fi network para sa datus ng mga koneksyong 2G
+ I-aplay ang mga alituntunin ng Wi-Fi network para sa datus ng mga koneksyong 3G
+ I-aplay ang mga alituntunin ng Wi-Fi network para sa datus ng mga koneksyong LTE
+ Huwag i-aplay ang alituntunin ang roaming kapag ang SIM at network ng mobile ay pareha ng bansa
+ Huwag i-aplay ang alituntunin ang roaming kapag ang SIM at network ng mobile network kapag ang bansa ay malapit sa EU (ang roam katulad sa bahay)
+ I-disable ang NetGuard sa papasok o kaya ay papalabas na tawag sa telepeno. Pwede itong magamit para mapagana sa palibot ng IP/Wi-Fi na mga problema sa pagtawag.
+ Bigyan ng kahulugan ang mga alituntunin para sa sistema ng mga aplikasyon (para sa mga eksperto)
+ Tinangkang mag log para ma-akses ang internet para sa mga aplikasyon. Ito ay maaaring magkaresulta ng dagdag gamit sa baterya.
+ Ipakita ang notipikasyon ng estado na bar kapag ang aplikasyon ay sinusubukang ma-akses ang baging adres ng internet (naka-disable kapag sinasala, yung mga nablock na internet lamang ang subukan at i-akses at mag-nonotipikasyon)
+ Ang pagsasala sa pakete ng IP ay lalabas sa lagusan ng VPN. Ito ay maaaring magkaresulta ng dagdag gamit sa baterya.
+ Subaybayan ang bilang ng mga byte na napadala at natanggap para sa bawat aplikasyon at adres. Ito ay maaaring magkaresulta ng dagdag gamit sa baterya.
+ Romesponde sa pagkukumpigura sa DNS tumugod sa kowd para i-block ang mga pangalan ng domain. Ang pindutang ito ay naka-disable kapag walang mga payl na host ang pwede.
+ Ang default na mga halaga ay 3 (NXDOMAIN), ang ibig sabihin \'walang-sumobrang domain\'.
+ Ang daloy ng TCP lamang ang ipapadala sa serber ng proksi
+ Pana-panahon ang pagtsi-tsek kung ang NetGuard ay nanatiling tumatakbo parin (ilagay ang bokya para i-disable ang opsyong ito). ito ay maaaring magkaresulta ng dagdag gamit sa baterya.
+ Ipakita ang bilis ng network sa talangguhitan at sa notipikasyon ng bar na estado
+ Ikaw ba ay sigurado?
+ Ang pagpapatupad ng mga patakaran
+ %1$d payagan, %2$d i-block
+ %1$d payagan, %2$d i-block, %3$d ang mga host
+ Naghahantay para sa kaganapan
+ Ang NetGuard ay naka-disable, gamitin ang pindutan sa itaas para i-enable ang NetGuard
+ Ang NetGuard ay dinisable, kagaya ng paggamit sa ibang VPN base sa aplikasyon
+ \'%1$s\' naka-install
+ Ay naka-install
+ %1$s tinangka ang akses para sa internet
+ Tinangka ang akses para sa internet
+ Kumpleto na ang aksyon
+ Ginamit ang NetGuard ang lokal na VPN para salain ang daloy ng internet.
+Para sa dahilang ito, pakiusap payagan ang VPN na koneksyon sa susunod na diyalogo.
+Ang iyong daloy ng internet ay hindi naipadala sa malayong serber ng VPN.
+ Ang NetGuard ay hindi awtomatikong magbubukas. Dahil ito ay malamang na bug sa iyong bersyon ng Android.
+ May hindi inaasahang mali na naganap: \'%s\'
+ Ang android ay tinanggihan na magsimula ang serbisyo ng VPN sa mga sandaling ito. Ito ay dahil sa malamang sa bug sa iyong bersyon ng Android.
+ Subukan ang NetGuard
+ Kapag mag-aambag ay sang-ayon kaba sa mga alituntunin at & mga kondisyon
+ Kung hindi mo pipindutin ang OK sa susunod na diyalogo, may bago na namang (iskrin dimming) na aplikasyon na magninipula sa iskrin.
+ ± %1$.3f▲ %2$.3f▼ ang MB/kada-araw
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Para sa tuloy-tuloy na mga resulta, ang pag-ooptimize sa baterya ng Android ay idi-disable para sa NetGuard. \n\nSa susunod na diyalogo, piliin \"Ang lahat ng aplikasyon\" duon sa itaas, Tapikin ang NetGuard sa listahan at piliin at kumpirmahin at \"Huwag i-optimize\".
+ Para sa tuloy-tuloy na mga resulta, ang mga opsyon para sa pagsi-seyb ng datus sa Android ay idi-disable para sa NetGuard \n\nSa susunod na diyalogo, i-enable ang mga opsyon ng \"Datus ng background\" ay \"Huwag higpitan ang gamit ng datus\"
+ Ang paggamit ng pagsasala ay magiging dahilan sa Android para katangian ng datus at ang gamit ng kapangayarihan ng NetGuard - Ang Android ay pinapalagay na ang datus ay kapangyarihan ay ginagamit ayon sa NetGuard, kumpara sa orihinal na mga aplikasyon
+ Ang Android 4 ay nangangailangn ang pagsasala para mapagana
+ Naka-disable ang daloy para sa paglo-log, gamitin ang pindutan sa itaas upang ma-enable ang paglo-log. Ang daloy sa paglo-log ay maaaring magka resulta sa ekstrang paggamit sa baterya.
+ Ito ay ang pag rerest sa mga alintuntunin at ang mga kondisyon sa mga hala ng default
+ Ito ay kaloobang alisin ang akses sa pagtatangka sa pag-log in kahit na walang pinapayagan/i-block ang mga alintuntunin
+ Ang huling pag-import: %s
+ Dina-download\n%1s
+ Dinadownload ang mga host payl
+ Ang huling pag-download: %s
+ Simulan ang pagpapasa mula sa %1$s port %2$d at sa %3$s:%4$d ng \'%5$s\'?
+ Ihinto ang pagpapasa ng %1$s port %2$d?
+ Sinusukat ang network
+ Walang aktibong koneksyon para sa internet
+ Ang NetGuar ay maraming ginagawa
+ Ang pag-updeyt ay pwede, tapikin para sa pagdownload
+ Pwede mong payagan ang (ma-berde) o tanggihan ang (mapula) na Wi-Fi o kaya ang pag-akses sa mobile interernet sa pamamagitan ng pagtapik sa mga imahe na susunod sa aplikasyon
+ Pinapayagan ang na i-akses ang internet sa pamamagitan ng default (blacklist mode), pwede nitong baguhin ang mga seting
+ Ang paparating na mga mensahe ay ang mga madalas hawakan ayon sa nilalaman ng Play na mga serbisyo (itulak), kung saan ay pinapayagan na i-akses ang default na internet
+ Pamahalaan ang lahat na (sistema) ng mga aplikasyon para ma-enable ang mga seting
+ Pakiusap ipaliwanag ang problema at isaan ang oras ng mga problema:
+ Kinansela ang koneksyon ng VPN\nKinumpigara mo ba ang ibang VPN para maging laging-bukas ang VPN?
+ Ang kapangyarahin ay ibaba ang iyong gamit kasama ang NetGuard ay naka-enable, gagawin nameng awtomato ang pagbukas ng NetGuard para sa pagpapataas ng kapangyarahin sa iyong gamit
+ Ang katangiang ito ay hindi pwede sa iyong beryon ng Android
+ Ang panibagong VPN ay nakatakda para maging laging-bukas ang VPN
+ Ang daloy ay naka-lock down
+ Ang hindi sinukat na daloy ay pinapayagan
+ Ang hindi sinukat na dalot ay naka-block
+ Ang hindi nasaukat na mga alintuntunin ay hindi inaplay
+ Ang pagsusukat sa daloy ay pinapayagan
+ Ang pagsusukat sa daloy ay naka-block
+ Ang pagsusukat na mga alituntunin ay hindi inaplay
+ Pinapayagan ang adres
+ Naka-block ang adres
+ Payagan kung ang iskrin ay bukas
+ I-block ang roaming kapag
+ Sa pamamagitan ng default ang koneksyon ng Wi-Fi ay itinuturing na hindi na kwenta at ang koneksyon ng mobile ay nakwenta
+ ay walang pahintulot sa internet
+ ito ay naka-disable
+ I-aplay ang mga alituntunin at mga kondisyon
+ Ang mga kondisyon
+ Payagan ang Wi-Fi kapag ang iskrin ay bukas
+ Payagan ang mobile kapag ang iskrin ay bukas
+ R
+ I-block kapag ang roaming
+ Payagan sa mode na lockdown
+ May kaugnayan sa pagsasala
+ Ang mga pagtatangka sa akses
+ Ang mga alituntunin ay alinsunod bago ang ibang mga alituntunin
+ Ang mga opsyon
+ Ang Notipikasyon sa mga pagtataka na ma-akses ang internet
+ Ang paglo-log o pagsasala ay hindi naka-enable
+ Ang paglo-log o pagsasala ay naka-enable
+ Kumpigura
+ Naka-enable ang paglo-log sa blinock na adres lamang
+ Naka-enable ang pagsasala para sa log na payagan ang mga adres din
+ Naka-enable ang akses sa mga notipikasyon para sa mga bagong adres na nag log
+ Ang mga setting na ito ay pang daigdigan na mga setting na dapat ay i-aplay sa lahat ng mga aplikasyon
+ Ang pagsasala ay kailangan din para payagan o i-block isa-isa ang mga adres
+ Pinagana ang paglo-log (mas konti) o kaya sa pagsasala ng (mas marami) ay pagtaas ang gamit ng baterya at makakaapekto sa bilis ng network
+ I-rate
+ Payagan
+ I-block
+ Pinayagan ang Wi-Fi
+ I-block ang Wi-Fi
+ Pinayagan ang mobile
+ I-block ang mobile
+ i-root
+ ang serber ng medya
+ walang kahit sinuman
+ Huwag ka nang magtatanong uli
+ Sino sya %1$s
+ Port %1$d
+ Kopyahin
+ Ang mga tampok na mahuhusay
+ Ang mga sumusuno na tampok na mahuhusay ay pwedeng magamit:
+ Tignan ang mga na-block na dalog ng log
+ Salain ang dalot ng network
+ Ang mga notipikasyon sa bagong app
+ Ang notipikasyon sa talangguhitan sa bilis ng network
+ Ang anyo (tema, at mga kulay)
+ Ang lahat ng mahuhusay na tampok ay nasa itaas
+ Suportahan ang pag-unlad
+ Bumili
+ Naka-enable
+ Hindi pwede
+ Para sa maraming impormasyon tapikin ang titulo
+ Pagsubok
+ Tugon
+
+ - tial/kahel
+ - kulay asul/kahel
+ - kulay lila/pula
+ - kulay marilaw/asul
+ - kulay kahil/abo
+ - berde
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-fr-rFR/strings.xml b/NetGuard/app/src/main/res/values-fr-rFR/strings.xml
new file mode 100644
index 0000000..c9a882e
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-fr-rFR/strings.xml
@@ -0,0 +1,290 @@
+
+
+ NetGuard offre des moyens simples et avancés pour bloquer l\'accès à internet - root non requis. L\'accès à votre connexion Wi-Fi et/ou mobile peut être individuellement autorisé ou refusé à des applications et à des adresses.
+ NetGuard nécessite Android 5.1 ou supérieur
+ Xposed provoque de trop nombreux plantages, qui pourraient faire en sorte que NetGuard soit retiré du Google Play Store, donc NetGuard n’est pas pris en charge tant que Xposed est installé
+ Politique de confidentialité
+ Une grande attention a été apportée pour développer et tester NetGuard, cependant il est impossible de garantir un bon fonctionnement sur tous les appareils.
+ J\'accepte
+ Je refuse
+ NetGuard a besoin de votre aide. Appuyez pour acheter des fonctionnalités Pro pour continuer à faire avancer le projet.
+ Services en cours d\'exécution
+ Notifications générales
+ Accéder aux notifications
+ Rechercher une application
+ Filtrer les applications
+ Afficher les applications utilisateur
+ Afficher les applications système
+ Afficher les applications sans internet
+ Afficher les applications désactivées
+ Trier les applications
+ Trier par nom
+ Trier par uid
+ Trier par utilisation des données
+ Afficher le journal
+ Paramètres
+ Inviter
+ Légende
+ Assistance
+ À propos
+ Autres applications
+ Autre
+ Autorisé
+ Bloqué
+ Mises à jour en temps réel
+ Actualiser
+ Afficher les noms
+ Afficher l\'organisation
+ PCAP activé
+ Exporter PCAP
+ Effacer
+ Exporter
+ Réinitialiser
+ Ajouter
+ Supprimer
+ Nettoyer
+ Protocole
+ Port source
+ Adresse de destination
+ Port de destination
+ Application de destination
+ Pour un serveur externe, sélectionnez \"personne\"
+ Valeurs par défaut (liste blanche/noire)
+ Bloquer le Wi-Fi
+ Bloquer les données
+ Autoriser le Wi-Fi quand l\'écran est allumé
+ Autoriser les données mobiles quand l\'écran est allumé
+ Bloquer l\'itinérance
+ Options
+ Thème : %1$s
+ Utiliser le thème sombre
+ Notifier lors d\'une nouvelle installation
+ Appliquer les règles « quand l’écran est allumé »
+ Activer automatiquement après %1$s minutes
+ Retarder l\'extinction de l\'écran de %1$s minutes
+ Vérifier les mises à jour
+ Options de réseau
+ Routage de sous-réseau
+ Autoriser le partage
+ Autoriser l\'accès au réseau local
+ Activer le trafic IPv6
+ Réseaux Wi-Fi domicile : %1$s
+ Gérer les réseaux Wi-Fi limités
+ Considérer 2G illimité
+ Considérer 3G illimité
+ Considérer LTE illimité
+ Ignorer l\'itinérance nationale
+ Ignorer l’itinérance en Europe
+ Désactiver lors d\'un appel
+ Verrouiller les données Wi-Fi
+ Verrouiller les données mobiles
+ Recharger à chaque changement de connectivité
+ Options avancées
+ Gérer les applications système
+ Journaliser l\'accès internet
+ Notifier lors de l\'accès à internet
+ Filtrer le trafic
+ Filtrer le trafic UDP
+ Transmission au VPN sans interruption lors du rechargement
+ Fermer les connexions lors du rechargement
+ Verrouiller le trafic
+ Surveiller l\'utilisation du réseau
+ Réinitialiser l\'utilisation du réseau
+ Afficher les noms de domaine résolus
+ Bloquer les noms de domaine
+ Code retour DNS : %s
+ Redirection de port
+ VPN IPv4 : %s
+ VPN IPv6 : %s
+ VPN DNS : %s
+ Valider à : %s
+ DNS TTL minimum : %s s
+ Utiliser un proxy SOCKS5
+ Adresse SOCKS5 : %s
+ Port SOCKS5 : %s
+ Nom d\'utilisateur SOCKS5 : %s
+ Mot de passe SOCKS5 : %s
+ Taille d’enregistrement PCAP : %s o
+ Taille max. du fichier PCAP : %s Mo
+ Gardien : toutes les %s minutes
+ Notification de débit
+ Afficher la notification de vitesse
+ Afficher les meilleures applications
+ Intervalle d\'échantillonnage : %s ms
+ Nombre d\'échantillons : %s s
+ Sauvegarde
+ Exporter les paramètres
+ Importer les paramètres
+ Importer un fichier hosts
+ Importer un fichier hosts (ajout)
+ URL de téléchargement du fichier hosts
+ Télécharger le fichier hosts
+ Informations techniques
+ Général
+ Réseaux
+ Abonnements
+ Afficher une notification dans la barre d\'état pour configurer directement les applications nouvellement installées (fonctionnalité Pro)
+ Après désactivation via le widget, activer automatiquement de nouveau NetGuard après le nombre de minutes indiqué (entrez zéro pour désactiver cette option)
+ Après avoir éteint l\'écran, garder les règles d\'écran allumé actives pendant le nombre de minutes indiqué (entrez zéro pour désactiver cette option)
+ Vérifier les nouvelles versions sur GitHub deux fois par jour
+ Selon la version d\'Android, le partage de connexion peut fonctionner ou non. Le trafic partagé ne peut pas être filtré.
+ Activer le routage de sous-réseau ; pourrait permettre les appels Wi-Fi, mais pourrait aussi déclencher des bogues dans Android et augmenter l’utilisation de la batterie
+ Autoriser les applications à se connecter à des adresses de réseau local, comme 10.0.0.0/8, 172.16.0.0/12 et 192.168.0.0/16
+ Diriger le trafic IP version 6 vers NetGuard de sorte qu\'il peut être sélectivement autorisé ou bloqué
+ Appliquer les règles de réseau Wi-Fi pour le réseau sélectionné uniquement (appliquer les règles de réseau mobile pour les autres réseaux Wi-Fi)
+ Appliquer les règles de réseaux mobiles aux réseaux Wi-Fi limités (payants, partagés)
+ Appliquer les règles de réseau Wi-Fi pour les connexions de données 2G
+ Appliquer les règles de réseau Wi-Fi pour les connexions de données 3G
+ Appliquer les règles de réseau Wi-Fi pour les connexions de données LTE
+ Ne pas appliquer les règles d\'itinérance lorsque le pays de la SIM et celui du réseau mobile sont les mêmes
+ Ne pas appliquer les règles d\'itinérance lorsque le pays de la SIM et celui du réseau mobile font partie de l\'Union Européenne (roam like at home)
+ Désactiver NetGuard lors d\'un appel téléphonique entrant ou sortant. Ceci peut être utilisé pour contourner les problèmes d\'appels IP/Wi-Fi.
+ Définir les règles pour les applications système (pour experts)
+ Journaliser les tentatives d\'accès à internet des applications. Cela peut entraîner une surconsommation de la batterie.
+ Afficher une notification dans la barre d\'état quand une application tente d\'accéder à une nouvelle adresse internet (lorsque le filtrage est désactivé, seules les tentatives d\'accès internet bloquées seront notifiées)
+ Filtrer les paquets IP sortant du tunnel VPN. Cela peut entraîner une surconsommation de la batterie.
+ Surveiller le nombre d\'octets envoyés et reçus pour chaque application et adresse. Cela peut entraîner une surconsommation de la batterie.
+ Répondre avec le code retour DNS configuré pour les noms de domaine bloqués. Cette option est désactivée lorsqu\'aucun fichier hosts n’est disponible.
+ La valeur par défaut est 3 (NXDOMAIN), ce qui signifie « domaine inexistant ».
+ Nom de domaine utilisé pour valider la connexion internet sur le port 443 (https).
+ Seul le trafic TCP sera envoyé au serveur proxy
+ Vérifier périodiquement si NetGuard est toujours en fonctionnement (entrez zéro pour désactiver cette option). Cela peut entraîner une surconsommation de la batterie.
+ Afficher le graphe de débit du réseau dans la barre d\'état
+ Êtes-vous sûr ?
+ Application des règles
+ %1$d autorisée(s), %2$d bloquée(s)
+ %1$d autorisée(s), %2$d bloquée(s), %3$d hôte(s)
+ En attente d\'évènement
+ NetGuard est désactivé, utilisez le bouton ci-dessus pour activer NetGuard
+ NetGuard a été désactivé, probablement en utilisant une autre application VPN
+ %1$s installé
+ A été installé
+ %1$s a tenté d\'accéder à internet
+ A tenté d\'accéder à internet
+ Action terminée
+ NetGuard utilise un VPN local pour filtrer le trafic Internet.
+Pour cette raison, veuillez autoriser la connexion VPN lors du prochain message.
+Votre trafic Internet n\'est pas envoyé vers un serveur VPN distant.
+ NetGuard n\'a pas pu démarrer automatiquement. Ceci est probablement dû à un bug dans votre version d\'Android.
+ Une erreur inattendue s’est produite : \'%s\'
+ Android a refusé de démarrer le VPN maintenant. Ceci est probablement dû à un bug dans votre version d\'Android.
+ Essayer NetGuard
+ En faisant un don vous acceptez les termes et conditions
+ Si vous ne pouvez pas appuyer sur OK dans la fenêtre suivante, une autre application (filtre de luminosité) manipule probablement l\'écran.
+ ± %1$.3f▲ %2$.3f▼ Mo/jour
+ %1$7.3f▲ %2$7.3f▼ Ko
+ %1$7.3f▲ %2$7.3f▼ Mo
+ %1$7.3f▲ %2$7.3f▼ Go
+ %dx
+ Pour des résultats cohérents, les optimisations Android de la batterie doivent être désactivées pour NetGuard.\n\nDans la fenêtre suivante, sélectionnez « Toutes les applications » en haut, appuyez sur NetGuard dans la liste, puis sélectionnez et confirmez « Ne pas optimiser ».
+ Pour des résultats cohérents, les options de limitation de données de d\'Android doivent être désactivées pour NetGuard \n\nDans la boîte de dialogue suivante, activez les options « Données en arrière-plan » et « Utilisation de données sans restriction »
+ L\'utilisation du filtrage fera qu\'Android attribuera l\'utilisation de données et de batterie à NetGuard - Android suppose que les données et la batterie sont utilisées par NetGuard, plutôt que par les applications d\'origine
+ Android 4 nécessite que le filtrage soit activé
+ La journalisation du trafic est désactivée, utilisez le bouton ci-dessus pour activer la journalisation. La journalisation du trafic peut entraîner une surconsommation de la batterie.
+ Cela réinitialisera les règles et conditions à leurs valeurs par défaut
+ Cela supprimera les lignes du journal de tentatives d\'accès sans autoriser/bloquer les règles
+ Dernier import : %s
+ Téléchargement\n%1s
+ Fichier hosts téléchargé
+ Dernier téléchargement : %s
+ Lancer la redirection du %1$s port %2$d au %3$s:%4$d de \'%5$s\' ?
+ Arrêter la redirection du %1$s port %2$d ?
+ Le réseau est limité
+ Pas de connexion Internet
+ NetGuard est occupé
+ Mise à jour disponible, appuyez pour télécharger
+ Vous pouvez autoriser (vert) ou refuser (rouge) l\'accès à internet Wi-Fi ou mobile en cliquant sur les icônes à coté d’une application
+ Si vous avez installé NetGuard pour protéger votre vie privée, vous pourriez être intéressé par FairEmail , une application de messagerie open source, respectueuse de la vie privée également
+ L’accès Internet est autorisé par défaut (mode liste noire), ceci peut être modifié dans les paramètres
+ Les messages Push sont principalement gérés par le composant système Play services, qui est autorisé à accéder à internet par défaut
+ La gestion des applications système peut être activée dans les options avancées
+ Veuillez décrire le problème et indiquer l\'heure à laquelle il est survenu :
+ La connexion VPN a été arrêtée\nAvez-vous configuré un autre VPN destiné à être un VPN toujours actif ?
+ Si vous éteignez votre appareil avec NetGuard activé, celui ci démarrera automatiquement lorsque vous rallumerez votre appareil
+ Cette fonctionnalité n’est pas disponible sur cette version d’Android
+ Un autre VPN est défini comme VPN permanent
+ Désactiver \"Bloquer les connexions sans VPN\" dans les paramètres VPN d\'Android pour utiliser le filtrage de NetGuard
+ Désactivez l’option « DNS privé » dans les paramètres réseau Android pour utiliser NetGuard en mode filtrage
+ Le trafic est verrouillé
+ Le trafic illimité est autorisé
+ Le trafic illimité est bloqué
+ Les règles illimitées ne sont pas appliquées
+ Le trafic limité est autorisé
+ Le trafic limité est bloqué
+ Les règles limitées ne sont pas appliquées
+ L\'adresse est autorisée
+ L\'adresse est bloquée
+ Autoriser lorsque l\'écran est allumé
+ Bloquer en itinérance
+ Par défaut, une connexion Wi-Fi est considérée comme illimitée et une connexion mobile limitée
+ n\'a aucune autorisation internet
+ est désactivé
+ Les messages entrants sont reçus par les services Google Play et non par cette application et ne peuvent donc pas être bloqués en bloquant cette application
+ Les téléchargements sont effectués par le gestionnaire de téléchargement et non par cette application et ne peuvent donc pas être bloqués en bloquant cette application
+ Appliquer les règles et conditions
+ Conditions
+ Autoriser le Wi-Fi quand l\'écran est allumé
+ Autoriser les données mobiles quand l\'écran est allumé
+ R
+ Bloquer en itinérance
+ Autoriser en mode verrouillage
+ Filtre lié
+ Tentatives d\'accès
+ Les règles d\'accès ont la priorité sur les autres
+ Options
+ Notifier les tentatives d\'accès à internet
+ La journalisation ou le filtrage n\'est pas activé
+ La journalisation et le filtrage sont activés
+ Configurer
+ Activer la journalisation d’adresses bloquées seulement
+ Activer le filtrage pour enregistrer aussi les adresses autorisées
+ Activer les notifications d’accès pour les adresses nouvellement enregistrées
+ Ces paramètres sont des paramètres globaux qui s’appliquent à toutes les applications
+ Le filtrage est également nécessaire pour autoriser ou bloquer des adresses individuelles
+ Activer la journalisation (moins) ou le filtrage (plus) peut augmenter l’utilisation de la batterie et peut affecter la vitesse du réseau
+ Évaluer
+ Autoriser
+ Bloquer
+ Autoriser Wi-Fi
+ Bloquer le Wi-Fi
+ Autoriser les données mobiles
+ Bloquer les données mobiles
+ root
+ mediaserver
+ personne
+ Ne plus demander
+ Whois %1$s
+ Port %1$d
+ Copier
+ Fonctionnalités Pro
+ Les fonctionnalités Pro suivantes sont disponibles :
+ Voir le journal du trafic bloqué
+ Filtrer le trafic réseau
+ Notifications de nouvelles applications
+ Notification avec graphe de débit réseau
+ Apparence (thème, couleurs)
+ Toutes les fonctionnalités Pro ci-dessus
+ Soutenir le développement
+ Acheter
+ Activé
+ Non disponible
+ Tapez sur un titre pour plus d’information
+ Code
+ Réponse
+ Ceci est une fonctionnalité Pro
+ Un abonnement mensuel de 1 à 2 euros (hors taxes locales) activera toutes les fonctionnalités Pro.
+ Vous pouvez annuler ou gérer un abonnement via l\'onglet Abonnements dans l\'application Play Store.
+
+
+ - bleu sarcelle/orange
+ - bleu/orange
+ - violet/rouge
+ - ambre/bleu
+ - orange/gris
+ - vert
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-hi-rIN/strings.xml b/NetGuard/app/src/main/res/values-hi-rIN/strings.xml
new file mode 100644
index 0000000..9b75376
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-hi-rIN/strings.xml
@@ -0,0 +1,288 @@
+
+
+ NetGuard इंटरनेट तक पहुंच को अवरुद्ध करने के लिए सरल और उन्नत तरीके प्रदान करता है - कोई रूट आवश्यक नहीं है। ऐप्स और पते व्यक्तिगत रूप से आपके वाई-फाई और/या मोबाइल कनेक्शन तक पहुंच की अनुमति या अस्वीकार किए जा सकते हैं।
+ NetGuard को Android 5.1 या बाद के संस्करण की आवश्यकता है
+ Xposed बहुत से दुर्घटनाओं का कारण बनता है, जिसके परिणामस्वरूप Google Play Store से NetGuard को हटाया जा सकता है, इसलिए NetGuard समर्थित नहीं है, जब तक Xposed स्थापित है
+ गोपनीयता नीति
+ नेटगार्ड को विकसित करने और परीक्षण करने के लिए बहुत सावधानी बरती गई है, हालांकि यह गारंटी देना असंभव है कि नेटगार्ड हर डिवाइस पर सही ढंग से काम करेगा।
+ मैं सहमत हूँ
+ मैं असहमत हूं
+ नेटगार्ड को आपकी मदद की जरूरत है। प्रोजेक्ट को चालू रखने के लिए प्रो फीचर्स खरीदने के लिए टैप करें।
+ गतिशील सेवाएं
+ सामांय सूचनाएं
+ अधिसूचनाओं में जाएँ
+ आवेदन के लिए खोजें
+ फ़िल्टर अनुप्रयोगों
+ उपयोगकर्ता को दिखाने के अनुप्रयोगों
+ सिस्टम ऐप्स दिखाएँ।
+ बिना इंटरनेट के ऐप दिखाएं
+ अक्षम ऐप्स दिखाएं
+ क्रमबद्ध अनुप्रयोगों
+ नाम पर क्रमबद्ध
+ यूआईडी पर क्रमबद्ध
+ डेटा के उपयोग पर क्रमबद्ध
+ लॉग दिखाएँ
+ सेटिंग्स
+ आमंत्रण
+ किंवदंती
+ सहायता
+ के बारे में
+ अन्य ऐप्स
+ अन्य
+ अनुमति है
+ अवरोधित
+ लाइव अपडेट
+ नवीकरण
+ नाम दिखाएँ
+ संगठन दिखाएँ
+ PCAP सक्षम
+ PCAP निर्यात
+ खाली करें
+ निर्यात
+ रीसेट
+ जोड़ें
+ मिटाए
+ Depending on the Android version, tethering may work or may not work. Tethered traffic cannot be filtered.
+ प्रोटोकॉल
+ स्रोत पोर्ट
+ गंतव्य पता
+ गंतव्य पोर्ट
+ गंतव्य ऐप
+ बाहरी सर्वर के लिए \'कोई नहीं\' का चयन करें
+ चूक
+ वाईफ़ाई अवरोधित करें
+ मोबाइल अवरोधित करें
+ जब स्क्रीन चालू हो तब वाईफ़ाई की अनुमति दें
+ जब स्क्रीन चालू हो तब मोबाइल की अनुमति दें
+ ब्लॉक रोमिंग
+ विकल्प
+ दिखावट: %1$s
+ डार्क थीम का इस्तेमाल करें
+ नई स्थापना पर सूचित करें
+ लागू करें \'जब स्क्रीन चालू हो\' नियम
+ %1$s मिनट के बाद स्वतः सक्षम
+ देरी स्क्रीन बंद %1$s मिनट
+ नवीनतम के लिए जाँच करें
+ नेटवर्क विकल्प
+ सबनेट रूटिंग
+ टेदरिंग की अनुमति दें
+ LAN पहुँच की अनुमति दें
+ IPv6 यातायात सक्षम करें
+ Wi-Fi घर नेटवर्क: %1$s
+ मीटर्ड Wi-Fi नेटवर्क संभालें
+ 2G unmetered चुनें
+ 3G unmetered चुनें
+ LTE unmetered चुनें
+ राष्ट्रीय रोमिंग पर ध्यान न दें
+ EU roaming को अनदेखा करें
+ कॉल पर अक्षम करें
+ लॉकडाउन Wi-Fi
+ लॉकडाउन मोबाइल
+ प्रत्येक कनेक्टिविटी परिवर्तन पर पुनः लोड करें
+ उन्नत विकल्प
+ सिस्टम अनुप्रयोग प्रबंधित करें
+ इंटरनेट उपयोग लॉग करें
+ इंटरनेट का उपयोग होने पर सूचित करें
+ इंटरनेट यातायात छाटें
+ फ़िल्टर UDP ट्रैफ़िक
+ Seamless VPN handover on reload
+ पुनः लोड पर कनेक्शन बंद करें
+ लॉकडाउन आवागमन
+ नेटवर्क के उपयोग को ट्रैक करें
+ नेटवर्क उपयोग रीसेट करें
+ Show resolved domain names
+ ब्लॉक डोमेन नाम
+ DNS प्रतिक्रिया कोड: %s
+ पोर्ट अग्रेषण
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ %s पर मान्य
+ न्यूनतम DNS TTL: %s s
+ SOCKS5 प्रॉक्सी का उपयोग करें
+ SOCKS5 पता: %s
+ SOCKS5 पोर्ट: %s
+ SOCKS5 उपयोगकर्ता नाम: %s
+ SOCKS5 पासवर्ड: %s
+ PCAP रिकॉर्ड आकार: %s B
+ PCAP मैक्स। फ़ाइल का आकार: %s MB
+ प्रहरी: प्रत्येक %s मिनट
+ गति अधिसूचना
+ गति अधिसूचना दिखाएं
+ शीर्ष अनुप्रयोगों दिखाएँ
+ नमूना अंतराल: %s ms
+ नमूनों की संख्या: %s s
+ Backup
+ सेटिंग्स निर्यात
+ सेटिंग्स आयात करें
+ होस्ट्स फ़ाइल आयात करें
+ होस्ट फ़ाइल आयात करें (परिशिष्ट)
+ होस्ट्स फ़ाइल डाउनलोड URL
+ होस्ट्स फ़ाइल डाउनलोड करें
+ तकनीकी जानकारी
+ सामान्य
+ नेटवर्क
+ सदस्यता
+ नया अनुप्रयोग स्थापित होने पर तत्काल व्यवस्थित करने के लिये सूचना दखाएँ (प्रो सुविधा)
+ विजेट के उपयोग से अक्षम करने के बाद, स्वचालित रूप से चयनित मिनटों के बाद नेटगार्ड को फिर से सक्षम करें (इस विकल्प को निष्क्रिय करने के लिए शून्य दर्ज करें)
+ स्क्रीन बंद करने के बाद, स्क्रीन पर नियम मिनट की चयनित संख्या के लिए सक्रिय रखें (इस विकल्प को अक्षम करने के लिए शून्य दर्ज करें)
+ दिन में दो बार GitHub पर नए रिलीज के लिए जाँच करें
+ Android संस्करण के आधार पर, टेदरिंग काम कर सकती है और नहीं भी। टेथर्ड ट्रैफ़िक को फ़िल्टर नहीं किया जा सकता है।
+ सबनेट रूटिंग सक्षम; और हो सकता है Wi-Fi कॉलिंग, सक्षम करें लेकिन हो सकता है एंड्रॉयड में कीड़े भी ट्रिगर बैटरी उपयोग बढ़ाएँ
+ स्थानीय क्षेत्र नेटवर्क पते, 10.0.0.0/8, 172.16.0.0/12 और 192.168.0.0/16 की तरह करने के लिए कनेक्ट करने के लिए अनुप्रयोग की अनुमति दें
+ IP संस्करण 6 यातायात रूट करने के लिए NetGuard तो यह चुनिंदा की अनुमति प्रतिबंधित कर सकते हो या
+ केवल चयनित नेटवर्क के लिए Wi-Fi नेटवर्क नियम लागू होते हैं (अन्य Wi-Fi नेटवर्क के लिए मोबाइल नेटवर्क नियम लागू)
+ मीटर्ड (भुगतान किया है, सीमित) करने के लिए Wi-Fi नेटवर्क मोबाइल नेटवर्क नियम लागू करें
+ 2 जी डेटा कनेक्शन के लिए वाई-फाई नेटवर्क नियम लागू करें
+ 2 जी डेटा कनेक्शन के लिए वाई-फाई नेटवर्क नियम लागू करें
+ 2 जी डेटा कनेक्शन के लिए वाई-फाई नेटवर्क नियम लागू करें
+ रोमिंग नियम लागू नहीं होते हैं, जब सिम और मोबाइल नेटवर्क देश ही हैं
+ जब सिम और मोबाइल नेटवर्क देश यूरोपीय संघ के भीतर हैं रोमिंग नियम लागू न करें (घर पर तरह घूमते रहें)
+ आने वाले या जावक टेलीफोन कॉल पर NetGuard अक्षम करें। इसका उपयोग IP/ Wi-Fi कॉलिंग समस्याओं के काम करने के लिए किया जा सकता है।
+ (विशेषज्ञों) के लिए सिस्टम अनुप्रयोगों के लिए नियमों को परिभाषित
+ ऐप्स के लिए इंटरनेट एक्सेस करने के प्रयास लॉग करें। इसके परिणामस्वरूप अतिरिक्त बैटरी का उपयोग हो सकता है।
+ एक नए इंटरनेट पते तक पहुँचने के लिए कोई अनुप्रयोग का प्रयास करता है, जब एक स्थिति बार सूचना दिखाएँ (फ़िल्टरिंग अक्षम किया गया है, जब केवल अवरुद्ध इंटरनेट का उपयोग प्रयास को सूचित किया जाएगा)
+ VPN टनल से बाहर जा रहा IP पैकेट फ़िल्टर। यह अतिरिक्त बैटरी उपयोग में परिणाम हो सकता है।
+ भेजा है और प्रत्येक अनुप्रयोग और पते के लिए प्राप्त बाइट्स की संख्या ट्रैक। यह अतिरिक्त बैटरी उपयोग में परिणाम हो सकता है।
+ ब्लॉक किए गए डोमेन नाम के लिए कॉन्फ़िगर किया गया DNS प्रतिसाद कोड के साथ प्रतिसाद दें । यह स्विच अक्षम है जब कोई होस्ट्स फ़ाइल उपलब्ध नहीं है ।
+ डिफ़ॉल्ट मान 3 (NXDOMAIN) है, जिसका अर्थ है \'गैर-मौजूद डोमेन\'।
+ डोमेन नेम का उपयोग पोर्ट 443 (https) पर इंटरनेट कनेक्शन को मान्य करने के लिए किया जाता है।
+ केवल TCP यातायात प्रॉक्सी सर्वर से भेजा जाएगा
+ समय-समय पर NetGuard अभी भी चल रहा है या नहीं की जाँच करें (इस विकल्प को अक्षम करने के लिए शून्य दर्ज करें)। यह अतिरिक्त बैटरी उपयोग में परिणाम हो सकता है।
+ स्थिति पट्टी में सूचना नेटवर्क गति ग्राफ़ दिखाएँ
+ क्या आपको यकीन है?
+ नियमों को लागू करने के
+ अनुमति, %2$d अवरुद्ध %1$d
+ %1$d की अनुमति दी, %2$d ब्लॉक, %3$d होस्ट्स
+ घटना के लिए प्रतीक्षा कर रहा है
+ NetGuard अक्षम है, NetGuard को सक्षम करने के लिए ऊपर दिए गए स्विच का उपयोग करें
+ NetGuard, होने की संभावना द्वारा किसी अन्य VPN आधारित अनुप्रयोग का उपयोग करके अक्षम कर दिया गया है
+ \'%1$s\' स्थापित
+ स्थापित किया गया है
+ %1$s इंटरनेट का उपयोग करने का प्रयास किया
+ इंटरनेट का उपयोग करने का प्रयास किया
+ क्रिया पूर्ण
+ NetGuard इंटरनेट ट्रैफ़िक को फ़िल्टर करने के लिए एक स्थानीय वीपीएन का उपयोग करता है। इस कारण के लिए, कृपया अगले संवाद में एक VPN कनेक्शन की अनुमति दें। अपने इंटरनेट यातायात एक दूरस्थ VPN सर्वर को नहीं भेजा जा रहा है।
+ NetGuard स्वचालित रूप से प्रारंभ नहीं हो सका। यह आपके Android संस्करण में बग के कारण होने की संभावना है।
+ कोई अनपेक्षित त्रुटि उत्पन्न हुई: \'%s\'
+ एंड्रायड ने इस समय वीपीएन सेवा शुरू करने से इनकार कर दिया । यह आपके एंड्रॉयड संस्करण में एक बग के कारण होने की संभावना है.
+ NetGuard को आज़माएं
+ दान करने से आप & नियम और शर्तों के लिए सहमत हैं
+ यदि आप अगले संवाद में ओके नहीं दबा सकते हैं, तो एक किसी (स्क्रीन डिमिंग) ऐप से स्क्रीन के हेरफेर होने की संभावना है।
+ ± %1$.3f▲ %2$.3f▼ MB/दिन
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ KB
+ %dx
+ एकरूप परिणाम के लिए, के लिए NetGuard Android बैटरी ऑप्टिमाइजेशन अक्षम किया जाना चाहिए। \n\nIn अगले संवाद, \"सभी apps\" शीर्ष पर का चयन करें, का चयन करें और सूची में NetGuard पर टैप करें और \"ऑप्टिमाइज़ नहीं\" की पुष्टि करें।
+ NetGuard \n\nIn अगले संवाद, सक्षम करें के लिए विकल्प \"पृष्ठभूमि डेटा\" और \"अप्रतिबंधित डेटा उपयोग\" संगत परिणामों के लिए, Android डेटा बचत विकल्प निष्क्रिय किया जाना चाहिए
+ फ़िल्टरिंग का उपयोग कर Android विशेषता डेटा और पावर NetGuard करने के लिए उपयोग करने के लिए कारण होगा - डेटा और पावर NetGuard, बजाय द्वारा मूल अनुप्रयोग उपयोग किया जा रहा हैं Android मानता है
+ एंड्रॉयड 4 सक्षम होने के लिए फ़िल्टरिंग की आवश्यकता है
+ ट्रैफ़िक लॉगिंग अक्षम है, लॉगिंग सक्षम करने के लिए ऊपर दिए गए स्विच का उपयोग करें। ट्रैफ़िक लॉगिंग के परिणामस्वरूप अतिरिक्त बैटरी उपयोग हो सकता है।
+ यह नियमों और शर्तों को उनके डिफ़ॉल्ट मानों के लिए रीसेट करेगा
+ यह पहुँच की अनुमति दें/ब्लॉक नियम बिना प्रयास लॉग लाइनों को हटा देगा
+ अंतिम आयात: %s
+ Downloading\n%1s
+ होस्ट्स फ़ाइल डाउनलोड
+ पिछले डाउनलोड: %s
+ अग्रेषण %1$s पोर्ट %2$d से प्रारंभ करने के लिए \'%5$s\' का %3$s:%4$d?
+ %1$s पोर्ट %2$d का अग्रेषण रोकना?
+ नेटवर्क मीटर है
+ कोई इंटरनेट कनेक्शन नहीं
+ NetGuard व्यस्त है
+ उपलब्ध अद्यतन के लिए, डाउनलोड करने के लिए टैप करें
+ आप कर सकते हैं या (हरा) की अनुमति दें (लाल) Wi-Fi या मोबाइल इंटरनेट का उपयोग करने के लिए किसी अनुप्रयोग के आगे चिह्न पर दोहन द्वारा इनकार
+ यदि आपने अपनी निजता की रक्षा के लिए NetGuard स्थापित किया है, तो आप एक ओपन सोर्स, प्राइवेसी के अनुकूल ईमेल ऐप, FairEmail में भी रुचि रख सकते हैं,
+ इंटरनेट का उपयोग की अनुमति दी है डिफ़ॉल्ट रूप से, यह सेटिंग में परिवर्तित किया जा सकता
+ पुश संदेश ज्यादातर सिस्टम घटक प्ले सेवाओं द्वारा, जो डिफ़ॉल्ट रूप से इंटरनेट तक पहुँच की अनुमति दी है नियंत्रित किया जाता है
+ सिस्टम अनुप्रयोगों के प्रबंधन सेटिंग्स में सक्षम कर सकते हैं
+ कृपया समस्या का वर्णन करें और समस्या के समय से संकेत मिलता है:
+ VPN कनेक्शन रद्द\nक्या आपने किसी अन्य VPN को हमेशा चलने पर कॉन्फ़िगर किया है?
+ NetGuard के साथ अपने डिवाइस को बंद करने पर, आपके डिवाइस के शुरू होने के साथ NetGuard स्वचालित रूप से शुरू होगा।
+ यह सुविधा इस एंड्रॉइड संस्करण पर उपलब्ध नहीं है
+ अन्य VPN हमेशा चालू रहने लिए निर्धारित हैं
+ फ़िल्टरिंग मोड में NetGuard का उपयोग करने के लिए Android VPN सेटिंग्स में \"VPN के बिना ब्लॉक कनेक्शन\" को बंद करें
+ फ़िल्टरिंग मोड में नेटगार्ड का उपयोग करने के लिए Android नेटवर्क सेटिंग्स में \"प्राइवेट DNS\" बंद करें
+ आवागमन बंद है
+ Unmetered यातायात की अनुमति है
+ Unmetered यातायात अवरुद्ध है
+ अनमित किए गए नियम लागू नहीं हैं
+ मीटर के जरिए यातायात की अनुमति है
+ मीटर के जरिए यातायात अवरुद्ध है
+ मीटर लगाए गए नियम लागू नहीं होते
+ पते की अनुमति है
+ पता ब्लॉक किया गया है
+ स्क्रीन चालू होने पर अनुमति दें
+ रोमिंग पर ब्लॉक
+ द्वारा डिफ़ॉल्ट एक Wi-Fi कनेक्शन unmetered माना जाता है और मीटर के जरिए किया जा करने के लिए एक मोबाइल कनेक्शन
+ इंटरनेट की अनुमति नहीं है
+ अक्षम है
+ आने वाले संदेश Google Play सेवाओं द्वारा प्राप्त किए जाते हैं और इस एप्लिकेशन द्वारा नहीं और इसलिए इस एप्लिकेशन को अवरुद्ध करके नहीं रोका जा सकता है
+ डाउनलोड प्रबंधक द्वारा डाउनलोड किए जाते हैं और इस एप्लिकेशन द्वारा नहीं किए जाते हैं और इसलिए इस एप्लिकेशन को अवरुद्ध करके नहीं किया जा सकता है
+ नियम और शर्तें लागू
+ शर्तें
+ जब स्क्रीन चालू हो तब वाईफ़ाई की अनुमति दें
+ जब स्क्रीन चालू हो तब मोबाइल की अनुमति दें
+ R
+ रोमिंग पर ब्लॉक
+ लॉकडाउन मोड में अनुमति दें
+ संबंधित फ़िल्टर करें
+ का उपयोग प्रयास
+ पहुँच नियम अन्य नियमों पर पूर्वता ले
+ विकल्प
+ इंटरनेट का उपयोग प्रयास को सूचित करें
+ लॉगिंग और फ़िल्टरिंग सक्षम नहीं हैं
+ लॉगिंग और फ़िल्टरिंग सक्षम हैं
+ विन्यस्त करें
+ केवल अवरोधित पतों का लॉगिंग सक्षम करें
+ लॉग करने के लिए फ़िल्टरिंग अनुमति पते भी सक्षम करें
+ नए लॉग किए गए पते के लिए पहुंच सूचनाएं सक्षम करें
+ ये सेटिंग सभी ऐप्लिकेशन पर लागू होने वाली वैश्विक सेटिंग होती हैं
+ व्यक्तिगत पते को अनुमति देने या ब्लॉक करने के लिए फ़िल्टरिंग की भी आवश्यकता है
+ लॉगिंग (कम) या फ़िल्टरिंग (अधिक) को सक्षम करने से बैटरी उपयोग बढ़ सकता है और यह नेटवर्क की गति को प्रभावित कर सकता है
+ रेट करें
+ अनुमति
+ ब्लॉक
+ वाई-फ़ाई की अनुमति दें
+ वाईफ़ाई अवरोधित करें
+ मोबाइल की अनुमति दें
+ मोबाइल अवरोधित करें
+ रूट
+ mediaserver
+ कोई भी नहीं
+ पुन: न पूछें
+ Whois %1$s
+ पोर्ट %1$d
+ कॉपी करें
+ प्रो सुविधाएँ
+ निम्न प्रो सुविधाएँ उपलब्ध हैं:
+ अवरुद्ध ट्रैफ़िक लॉग देखें
+ नेटवर्क ट्रैफ़िक फ़िल्टर करें
+ नए आवेदन सूचना
+ नेटवर्क गति ग्राफ अधिसूचना
+ दिखावट (थीम, रंग)
+ उपरोक्त सभी प्रो सुविधाएं
+ विकासकर्ता को आर्थिक समर्थन दीजिए
+ ख़रीदें
+ सक्षम
+ अनुपलब्ध
+ अधिक जानकारी के लिए एक शीर्षक पर टैप करें
+ चुनौती
+ प्रतिक्रिया
+ यह एक प्रो फीचर है
+ 1 या 2 यूरो (स्थानीय कर को छोड़कर) की मासिक सदस्यता सभी प्रो सुविधाओं को सक्रिय करेगी।
+ आप प्ले स्टोर ऐप में सदस्यता टैब के माध्यम से सदस्यता को रद्द या प्रबंधित कर सकते हैं।
+
+
+ - चैती / नारंगी
+ - नीला/ नारंगी
+ - बैंगनी/लाल
+ - एम्बर/ब्लू
+ - ऑरेंज/ग्रे
+ - हरा
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-hr-rHR/strings.xml b/NetGuard/app/src/main/res/values-hr-rHR/strings.xml
new file mode 100644
index 0000000..dcc7212
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-hr-rHR/strings.xml
@@ -0,0 +1,288 @@
+
+
+ NetGuard nudi jednostavne i napredne načine blokiranja pristupa internetu - root pristup nije potreban. Pristup Wi-Fi i/ili mobilnoj vezi može se individualno dopustiti ili odbiti aplikacijama i adresama.
+ NetGuard zahtijeva Android 5.1 ili noviji
+ Xposed uzrokuje previše rušenja aplikacije, što može uzrokovati uklanjanje NetGuarda iz Trgovine Google Play, tako da NetGuard nije podržan sve dok je Xposed instaliran
+ Pravilnik o privatnosti
+ Velika pažnja je posvećena razvijanju i testiranju NetGuard aplikacije, no nemoguće je jamčiti da će NetGuard ispravno raditi na svim uređajima.
+ Slažem se
+ Ne slažem se
+ NetGuard treba Vašu pomoć. Dodirnite za kupnju pro-značajki za pomoć projektu.
+ Pokrenuti servisi
+ Opće obavijesti
+ Pristup obavijestima
+ Potraži aplikaciju
+ Filtriraj aplikacije
+ Prikaži korisničke aplikacije
+ Prikaži aplikacije sustava
+ Prikaži aplikacija bez Interneta
+ Prikaži onemogućene aplikacije
+ Sortiraj aplikacije
+ Sortiranje po nazivu
+ Sortiranje po UID-u
+ Sortiranje po korištenju podataka
+ Prikaži zapisnik
+ Postavke
+ Pozovi
+ Legenda
+ Podrška
+ O aplikaciji
+ Ostale aplikacije
+ Ostalo
+ Dopušteno
+ Blokirano
+ Ažuriranja u stvarnom vremenu
+ Osvježi
+ Prikaži nazive
+ Prikaži organizaciju
+ PCAP je omogućen
+ PCAP izvoz
+ Očisti
+ Izvoz
+ Resetiraj
+ Dodaj
+ Izbriši
+ Čišćenje
+ Protokol
+ Izvorni port
+ Adresa odredišta
+ Odredišni port
+ Odredišna aplikacija
+ Za vanjskog poslužitelja odaberite \'nitko\'
+ Zadane postavke (bijela/crna lista)
+ Blokiraj Wi-Fi
+ Blokiraj mobilne podatke
+ Dopusti Wi-Fi kada je zaslon uključen
+ Dopusti mobilne podatke kada je zaslon uključen
+ Blokiraj roaming
+ Opcije
+ Tema: %1$s
+ Koristi tamnu temu
+ Obavijesti o novoj instalaciji
+ Primjeni \'kada je zaslon uključen\' pravila
+ Automatski omogući nakon %1$s minuta
+ Odgodi isključivanje zaslona za %1$s minuta
+ Provjeri ažuriranja
+ Mrežne postavke
+ Podmrežno usmjeravanje
+ Dopustiti tethering
+ Dopusti LAN pristup
+ Omogući IPv6 promet
+ Wi-Fi kućne mreže: %1$s
+ Rukuj ograničenim Wi-Fi mrežama
+ Smatraj 2G neograničenim
+ Smatraj 3G neograničenim
+ Smatraj LTE neograničenim
+ Ignoriraj nacionalni roaming
+ Ignoriraj EU roaming
+ Onemogući kod poziva
+ Zaključaj Wi-Fi
+ Zaključaj mobilne podatke
+ Ponovno učitaj pri svakoj promjeni povezivosti
+ Napredne opcije
+ Upravljaj aplikacijama sustava
+ Zapisuj pristup internetu
+ Obavijesti pri pristupu internetu
+ Filtriraj promet
+ Filtriraj UDP promet
+ Prebacite se na VPN bez prekida za ponovno učitavanje
+ Zatvorite vezu prilikom ponovnog učitavanja
+ Zaključaj promet
+ Prati korištenje mreže
+ Resetiraj korištenje mreže
+ Prikaži riješena imena domena
+ Blokiraj nazive domena
+ Kod odgovora DNS-a: %s
+ Prosljeđivanje porta
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Potvrdi u: %s
+ Minimum DNS TTL: %s s
+ Koristi SOCKS5 proxy
+ SOCKS5 adresa: %s
+ SOCKS5 port: %s
+ SOCKS5 korisničko ime: %s
+ SOCKS5 lozinka: %s
+ PCAP veličina zapisa: %s B
+ PCAP max. veličina datoteke: %s MB
+ Watchdog: svakih %s minuta
+ Obavijest o brzini
+ Prikaži obavijest o brzini
+ Prikaži najčešće aplikacije
+ Uzorak intervala: %s ms
+ Broj uzoraka: %s s
+ Sigurnosno kopiranje
+ Izvezi postavke
+ Uvezi postavke
+ Uvezi datoteku hostova
+ Uvezi datoteku hostova (nadopuni)
+ URL za preuzimanje datoteke hostova
+ Preuzmi datoteku hostova
+ Tehničke informacije
+ Općenito
+ Mreže
+ Pretplate
+ Prikaz obavijesti trake stanja za izravno konfiguriranje novo instaliranih aplikacija (značajka pro)
+ Nakon što onemogućite upotrebu widgeta, automatski omogućite NetGuard ponovno nakon odabranog broja minuta (unesite nulu da biste onemogućili ovu opciju)
+ Nakon isključivanja zaslona, zadržite \'kada je zaslon uključen\' pravila aktivnim za odabrani broj minuta (unesite nulu da biste onemogućili ovu opciju)
+ Potražite nove verzije na GitHubu dva puta dnevno
+ Ovisno o verziji Androida, tethering može i ne mora raditi. Tethering promet nije moguće filtrirati.
+ Omogućavanje usmjeravanja podmreže može dopustiti Wi-Fi pozive, ali može također pokrenuti razne greške u Androidu i povećati potrošnju baterije
+ Dopustite aplikacijama povezivanje na adrese lokalne mreže, kao što su 10.0.0.0/8, 172.16.0.0/12 i 192.168.0.0/16
+ Prosljeđujte IP6 promet na NetGuard tako da se može selektivno dopustiti ili blokirati
+ Primjeni Wi-Fi pravila mreže samo za odabrane mreže (primjeni pravila mobilne mreže za ostale Wi-Fi mreže)
+ Primjeni pravila mobilne mreže na ograničene Wi-Fi mreže
+ Primjeni pravila Wi-Fi mreže za 2G podatkovne veze
+ Primjeni pravila Wi-Fi mreže za 3G podatkovne veze
+ Primjeni pravila Wi-Fi mreže za LTE podatkovne veze
+ Nemoj primjeniti pravila roaminga kada su SIM i mobilna mreža države isti
+ Nemoj primjeniti pravila roaminga kada su SIM i mobilna mreža države unutar EU
+ Onemogućite NetGuard kod dolaznog ili odlaznog telefonskog poziva. To se može koristiti za rješavanje IP/Wi-Fi problema kod pozivanja.
+ Definiraj pravila za aplikacije sustava (za stručnjake)
+ Zapisnik pokušaja pristupa aplikacija na Internet. To može dovesti do prekomjerne potrošnje baterije.
+ Prikažite obavijest na traci stanja kada aplikacija pokušava pristupiti novoj internetskoj adresi (kada je filtriranje onemogućeno, obavijestit će se samo blokirani pokušaji pristupa internetu)
+ Filtriranje IP paketa koji dolaze iz VPN-a. To može dovesti do prekomjerne potrošnje baterije.
+ Pratite broj poslanih i primljenih bajtova za svaku aplikaciju i adresu. To može dovesti do prekomjerne potrošnje baterije.
+ Odgovorite s DNS povratnim kodom konfiguriranim za blokirane nazive domena. Ova je opcija onemogućena kada nije dostupna nijedna datoteka hostova.
+ Zadana je vrijednost 3 (NXDOMAIN), što znači \"nepostojeća domena\".
+ Domena koja se koristi za potvrdu internet veze na portu 443 (https).
+ Samo TCP promet će biti poslan na proxy poslužitelj
+ Periodički provjeri da li je NetGuard još pokrenut (unesite nulu da biste onemogućili ovu opciju). To može dovesti do prekomjerne potrošnje baterije.
+ Prikaži grafikon mrežne propusnosti na traci statusa
+ Jeste li sigurni?
+ Primjenjivanje pravila
+ %1$d dopušteno, %2$d blokirano
+ %1$d dopušteno, %2$d blokirano, %3$d hostovi
+ Čekanje na događaj
+ NetGuard je onemogućen, koristitite gornji prekidač kako bi omogućili NetGuard
+ NetGuard je onemogućen, vjerojatno koristeći drugu VPN aplikaciju
+ \'%1$s\' je instalirano
+ Je instalirano
+ %1$s je pokušao pristupiti internetu
+ Pokušaj pristupa internetu
+ Radnja je završena
+ NetGuard koristi lokalni VPN za filtriranje internetskog prometa. Iz tog razloga, dopustite VPN vezu u sljedećem dijaloškom okviru. Vaš internetski promet se ne šalje udaljenom VPN poslužitelju.
+ NetGuard se nije mogao pokrenuti automatski. To je vjerojatno zbog greške u Vašoj verziji sustava Android.
+ Došlo je do neočekivane pogreške: \'%s\'
+ Android je odbio pokrenuti VPN uslugu u ovom trenutku. To je vjerojatno zbog greške u Vašoj verziji sustava Android.
+ Probaj NetGuard
+ Donacijom prihvaćate uvjete & odredbe
+ Ako ne možete kliknuti \"U redu\" u sljedećem dijaloškom okviru (zamračivanje zaslona), najvjerojatnije neka druga aplikacija koristi zaslon.
+ ± %1$.3f▲ %2$.3f▼ MB/dan
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Za dosljedne rezultate, optimizacija baterije za Android trebala bi biti isključena za NetGuard.\n\nU sljedećem dijaloškom okviru na vrhu odaberite \"Sve aplikacije\", dodirnite NetGuard na popisu i odaberite i potvrdite \"Ne optimiziraj\".
+ Za dosljedne rezultate, Androidove opcije za spremanje podataka trebale bi biti isključene za NetGuard\n\nU sljedećem dijaloškom okviru omogućite opcije \"Pozadinski podaci\" i \"Neograničeno korištenje podataka\"
+ Upotrebom filtriranja, Android će dodijeliti podatke i potrošnju baterije NetGuardu - Android pretpostavlja da NetGuard upotrebljava podatke i baterije, a ne izvorne aplikacije
+ Android 4 zahtijeva da je filtriranje omogućeno
+ Zapisivanje prometa je onemogućeno, pomoću gornjeg gumba omogućite zapisivanje. Zapisivanje prometa može dovesti do prekomjerne potrošnje baterije.
+ To će resetirati pravila i uvjete na njihove zadane vrijednosti
+ Time će se izbrisati linije zapisnika pokušaja pristupa bez pravila dopuštanja/blokiranja
+ Zadnji uvoz: %s
+ Preuzimanje\n%1s
+ Datoteka hostova je preuzeta
+ Zadnje preuzimanje: %s
+ Započeti prosljeđivanje iz %1$s porta %2$d %3$s:%4$d iz \'%5$s\'?
+ Zaustaviti prosljeđivanje %1$s porta %2$d?
+ Mreža je ograničena
+ Nema aktivne internetske veze
+ NetGuard je zauzet
+ Ažuriranje je dostupno, dodirnite za preuzimanje
+ Možete omogućiti (zeleno) ili odbiti (crveni) pristup Wi-Fi ili mobilnom internetu klikom na ikone pored aplikacije
+ Ako ste NetGuard instalirali radi zaštite svoje privatnosti, možda će Vas zanimati FairEmail , aplikacija e-pošte, otvorenog koda
+ Pristup internetu dopušten je prema zadanim postavkama (način rada crne liste), to se može promijeniti u postavkama
+ Push poruke primarno rješava komponenta sustava Play usluge, kojoj je dopušteno pristupanje internetu (zadana vrijednost)
+ Upravljanje svim (sustav) aplikacijama može biti omogućeno u postavkama
+ Opišite problem i navedite vrijeme problema:
+ VPN veza je prekinuta\nJeste li konfigurirali da je VPN uvijek aktivan VPN?
+ Ako isključite uređaj s omogućenom značajkom NetGuard, automatski će se pokrenuti kada ponovno uključite uređaj
+ Ova značajka nije dostupna na ovoj verziji Androida
+ Drugi VPN definiran je kao stalni VPN
+ Isključi \"Blokiraj veze bez VPN-a\" u postavkama VPN-a Android uređaja da biste koristili NetGuard u načinu filtriranja
+ Isključite \"Privatni DNS\" u mrežnim postavkama Android uređaja mreže da biste koristili NetGuard u načinu filtriranja
+ Promet je zaključan
+ Neograničeni promet je dopušten
+ Neograničeni promet je blokiran
+ Neograničena pravila nisu primjenjena
+ Ograničeni promet je dopušten
+ Ograničeni promet je blokiran
+ Ograničena pravila nisu primijenjena
+ Adresa je dopuštena
+ Adresa je blokirana
+ Dopustiti kada zaslon uključen
+ Blokiraj prilikom roaminga
+ Prema zadanim postavkama Wi-Fi veza se smatra neograničenom, a mobilna veza ograničenom
+ nema dopuštenje za internet
+ je onemogućen
+ Dolazne poruke ne šalje ova aplikacija već Google Play usluge stoga se ne mogu blokirati ovom aplikacijom
+ Preuzimanja se odvijaju kroz upravitelj preuzimanja, ne ovom aplikacijom stoga se ne mogu blokirati
+ Primijeni pravila i uvjete
+ Uvjeti
+ Dopusti Wi-Fi kada je zaslon uključen
+ Dopusti mobilne podatke kada je zaslon uključen
+ R
+ Blokiraj prilikom roaminga
+ Dopusti u zaključanom načinu
+ Filtriraj povezane
+ Pokušaji pristupa
+ Pravila pristupa imaju prednost ispred ostalih pravila
+ Opcije
+ Obavijesti pokušaje pristupa internetu
+ Zapisivanje i filtriranje nije omogućeno
+ Zapisivanje i filtriranje je omogućeno
+ Postavi
+ Omogući zapisivanje samo blokiranih adresa
+ Omogući filtriranje kako bi također zapisali dopuštene adrese
+ Omogući pristup obavijestima za nedavno prijavljene adrese
+ Ove postavke su globalne i primjenjuju se na sve aplikacije
+ Filtriranje je također dužno dopustiti ili blokirati pojedine adrese
+ Omogućavanje zapisivanja (manje) ili filtriranja (više) može povećati korištenje baterije i utjecati na brzinu mreže
+ Ocijeni
+ Dopusti
+ Blokiraj
+ Dopusti Wi-Fi
+ Blokiraj Wi-Fi
+ Dopusti mobilne podatke
+ Blokiraj mobilne podatke
+ root
+ mediaserver
+ nitko
+ Ne pitaj ponovno
+ Tko je %1$s
+ Port %1$d
+ Kopiraj
+ Pro značajke
+ Dostupne su sljedeće pro značajke:
+ Prikažite zapisnik blokiranog prometa
+ Filtrirajte promet mreže
+ Obavijesti o novim aplikacijama
+ Obavijest grafa brzine mreže
+ Izgled (teme, boje)
+ Sve gore navedene pro značajke
+ Podržite razvoj
+ Kupi
+ Omogućeno
+ Nije dostupno
+ Dodirnite naslov za više informacija
+ Izazov
+ Odgovor
+ Ovo je pro funkcija
+ Mjesečna poretplata od 1 ili 2 eura (bez pdv-a) će aktivirati pro značajke.
+ U svakom trenutku možete otkazati pretplatu kroz Play Store aplikaciju.
+
+
+ - tirkizna/narančasta
+ - plava/narančasta
+ - ljubičasta/crvena
+ - jantar/plava
+ - narančasta/siva
+ - zelena
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-hu-rHU/strings.xml b/NetGuard/app/src/main/res/values-hu-rHU/strings.xml
new file mode 100644
index 0000000..9a10196
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-hu-rHU/strings.xml
@@ -0,0 +1,290 @@
+
+
+ A NetGuard egyszerűen és speciálisan blokkolja az internet hozzáférést - nem szükséges root jogosultság hozzá. Az alkalmazásokat és a címeket külön-külön lehet engedélyezni vagy letiltani a Wi-Fi és/vagy a mobil kapcsolatokon.
+ A NetGuard használatához Android 5.1 vagy újabb szükséges
+ Az Xposed túl sokszor összeomlik, ami a NetGuard eltávolítását eredményezheti a Google Play Áruházból, ezért a NetGuard nem támogatott amikor az Xposed telepítve van
+ Adatvédelmi irányelvek
+ Nagy figyelmet fordítanak arra, hogy fejlesszék és teszteljék NetGuard-ot, de arra lehetetlen garanciát vállalni, hogy a NetGuard minden eszközön jól fog működni.
+ Elfogadom
+ Nem fogadom el
+ A NetGuard-nak szüksége van a segítségére. Koppintson a pro szolgáltatások megvásárlásához, hogy a projekt fennmaradhasson.
+ Futó szolgáltatások
+ Általános értesítések
+ Hozzáférés az értesítésekhez
+ Alkalmazás keresése
+ Alkalmazás szűrő
+ Felhasználói alkalmazások mutatása
+ Rendszer alkalmazások mutatása
+ Internet nélküli alkalmazások mutatása
+ Letiltott alkalmazások mutatása
+ Alkalmazások rendezése
+ Rendezés név szerint
+ Rendezés UID szerint
+ Rendezés adat használat szerint
+ Napló mutatása
+ Beállítások
+ Meghívás
+ Jelmagyarázat
+ Támogatás
+ Névjegy
+ Egyéb alkalmazások
+ Egyéb
+ Engedélyezve
+ Letiltva
+ Élő frissítés
+ Frissités
+ Név mutatása
+ Szervezet mutatása
+ PCAP engedélyezve
+ PCAP exportálás
+ Törlés
+ Exportálás
+ Visszaállitás
+ Hozzáadás
+ Tőrlés
+ Takarítás
+ Protokol
+ Forrás port
+ Cél cím
+ Cél port
+ Cél alkalmazás
+ Egy külső szerver választva \'senki\'
+ Alapértelmezések (fehér/fekete lista)
+ Wi-Fi letiltása
+ Mobil letiltása
+ Wi-Fi engedélyezése amikor a képernyő be van kapcsolva
+ Mobil engedélyezése amikor a képernyő be van kapcsolva
+ Roaming letiltása
+ Beállítások
+ Téma: %1$s
+ Sötét téma használata
+ Értesítés új alkalmazás telepítésekor
+ Az \'amikor a képernyő be van kapcsolva\' szabályok alkalmazása
+ Automatikus engedélyezés %1$s perc után
+ %1$s perc várakozás a képernyő kikapcsolása után
+ Frissítések ellenőrzése
+ Hálózati beállítások
+ Alhálózati útválasztó
+ Tethering engedélyezése
+ LAN hozzáférés engedélyezése
+ IPv6 forgalom engedélyezése
+ Otthoni Wi-Fi hálózat: %1$s
+ Mért Wi-Fi hálózatok kezelése
+ Méretlen 2G megfontolása
+ Méretlen 3G megfontolása
+ Méretlen LTE megfontolása
+ Belföldi roaming figyelmen kívül hagyása
+ Figyelmen kívül hagyja az EU roamingot
+ Letiltás hívás közben
+ Wi-Fi lezárás
+ Mobil lezárás
+ Újratöltés minden kapcsolat változáskor
+ Speciális beállítások
+ Rendszer alkalmazások kezelése
+ Internet hozzáférés naplózása
+ Értesítés internet hozzáféréskor
+ Forgalom szűrés
+ UDP forgalom szűrő
+ Zökkenőmentes VPN átadás újratöltéskor
+ Kapcsolatok lezárása újratöltéskor
+ Forgalom lezárás
+ Hálózat használat követés
+ Hálózat használat alaphelyzetbe
+ Mutassa a feloldott domain neveket
+ Domain nevek letiltása
+ DNS válasz kód: %s
+ Port forward
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Érvényesítés itt: %s
+ Minimális DNS TTL: %s s
+ SOCKS5 proxy használata
+ SOCKS5 cím: %s
+ SOCKS5 port: %s
+ SOCKS5 felhasználónév: %s
+ SOCKS5 jelszó: %s
+ PCAP rekord méret: %s B
+ PCAP max. fájl méret: %s MB
+ Watchdog: minden %s percben
+ Sebesség értesítés
+ Mutassa a sebesség értesítést
+ Csúcs alkalmazások mutatása
+ Mintavétel intervallum: %s ms
+ Minták száma: %s s
+ Biztonsági mentés
+ Beállítások exportálása
+ Beállítások importálása
+ Hosts fájl importálás
+ Hosts fájl importálása (append)
+ Hosts fájl letöltési URL
+ Hosts fájl letöltése
+ Technikai információk
+ Általános
+ Hálózatok
+ Előfizetések
+ Mutassa az értesítési sávon az újonan telepített alkalmazás közvetlen konfigurálási lehetőségét (Pro szolgáltatás)
+ A widget használat után automatikusan engedélyezze a NetGuard használatát a beírt perc eltelte után (a nulla beírása letiltja ezt az opciót)
+ A képernyő kikapcsolása után a szabályok a megadott perc időtartamig aktívak maradnak (a nulla beírása letiltja ezt az opciót)
+ Ellenőrizze naponta kétszer a GitHub-on az új kiadásokat
+ Az Android verziótól függően a Tethering vagy működik vagy nem. A Tethering forgalom nem szűrhető.
+ Engedélyezi a alhálózati útválasztót; lehet, hogy engedélyezi a Wi-Fi hívást, de lehet hogy hibát okoz az Androidban és növeli az akkumulátor használatot
+ Engedélyezi az alkalmazások kapcsolódását a LAN hálózati címekhez, mint pl. 10.0.0.0/8, 172.16.0.0/12 és 192.168.0.0/16
+ Az IP v6 forgalmat a NetGuard szelektíven tudja tiltani vagy engedélyezni
+ Wi-Fi hálózat szabályok alkalmazása csak a kiválasztott hálózatokra (a többi Wi-Fi hálózatra a Mobil hálózati szabályokat alkalmazza)
+ Mobil hálózati szabályok alkalmazása a mért (fizetős, kábeles) Wi-Fi hálózatokra
+ Wi-Fi hálózat szabályok alkalmazása a 2G adatátviteli kapcsolatokra
+ Wi-Fi hálózat szabályok alkalmazása a 3G adatátviteli kapcsolatokra
+ Wi-Fi hálózat szabályok alkalmazása az LTE adatátviteli kapcsolatokra
+ Ne alkalmazza roaming szabályokat, ha a SIM és a mobil hálózat országa azonos
+ Ne alkalmazza a roaming szabályokat, amikor a SIM-kártya és a mobilhálózat országa az EU-n belül van (roam like at home)
+ A NetGuard letiltása a bejövő vagy kimenő telefonhívás alatt. Ez használható IP / Wi-Fi hívási problémák megoldására.
+ Szabályok megállapítása a rendszer alkalmazásokra (szakértő)
+ Naplózza az alkalmazások internet elérési kísérleteit. Emiatt kicsit magasabb lehet az akkumulátor használat.
+ Mutassa az értesítés sávban, amikor egy alkalmazás megpróbál hozzáférni egy új internet címhez (amikor a szűrés le van tiltva, csak zárolt internet hozzáférési kísérletekről küld értesítést)
+ A szűrendő IP csomagok a VPN csatornán keresztül jutnak ki. Ez lehet, hogy egy kis többlet akkumulátor használattal járhat.
+ Nyomon követheti a küldött és fogadott bájtok számát minden egyes alkalmazáshoz és címhez. Ez egy kis extra akkumulátor használattal járhat.
+ A beállított DNS válasz kódot válaszolja a letiltott domain neveknek. Ez a kapcsoló le van tiltva, ha nincs elérhető hosts fájl.
+ Az alapértelmezett érték 3 (NXDOMAIN), ami azt jelenti: \'nem létező domain\'.
+ A használt domain név az internetkapcsolat ellenőrzéséhez a 443 (https) porton.
+ Csak a TCP forgalom küldése a proxy szerverre
+ Rendszeresen ellenőrzi ha a NetGuard fut (a 0 beírása letiltja azt az opciót). Ez extra akkumulátor használattal járhat.
+ Mutassa a hálózat sebesség grafikont az értesítés sávon
+ Biztos benne?
+ Szabályok érvényesítése
+ %1$d engedélyezve, %2$d letiltva
+ %1$d engedélyezve, %2$d letiltva, %3$d hosts
+ Várakozás eseményre
+ A NetGuard letiltva. Használja a kapcsolót a NetGuard engedélyezéshez
+ A NetGuard letiltva. Valószínűleg egy másik VPN alapú alkalmazással
+ \'%1$s\' telepítve
+ Telepítve van
+ %1$s internet hozzáférési kísérlet
+ Internet hozzáférési kísérlet
+ Művelet befejezve
+ A NetGuard helyi VPN-t használ az internetes forgalom szűréséhez.
+Ezért kérjük, hogy engedélyezze a VPN kapcsolatot a következő párbeszéd ablakban.
+Az internetes forgalom nem érkezik meg a távoli VPN kiszolgálóhoz.
+ A NetGuard nem indul el automatikusan a rendszer indításakor, mert egy hiba van ebben az Android verzióban
+ Váratlan hiba történt: \'%s\'
+ Jelenleg az Android nem kezeli a VPN szolgáltatást. Ennek az oka valószínűleg egy Android bug.
+ NetGuard kipróbálása
+ A támogató elfogadja a felhasználási feltételeket
+ Ha nem nyomja meg az OK gombot a következő párbeszédablakban, a másik (a képernyő fényerő) alkalmazás valószínűleg módosul a képernyőn.
+ ± %1$.3f▲ %2$.3f▼ MB/nap
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ A következetes eredményekhez az Androidos akkumulátor optimalizálásban a NetGuard-ot kivétellé kell tenni.\n\nA következő párbeszédablakban válassza felül az \"Összes alkalmazás\", érintse meg a NetGuard feliratot és válassza a \"Ne optimalizálja\" részt.
+ A következetes eredmény érdekében az Android adat mentés opciót le kell tiltani a NetGuard-ban\n\nA következő párbeszédablakban engedélyezni kell a \"Háttér adat\" és \"Korlátlan adat használat\" opciót.
+ A szűrés használatával az adat és az energia használat attributumait a NetGuard-hoz sorolja. Az Android azt feltételezi, hogy ezeket a NetGuard használta fel és nem az eredeti alkalmazás
+ A szűrés engedélyezéséhez legalább Android 4 szükséges
+ Forgalom naplózása le van tiltva, a fenti kapcsoló segítségével engedélyezheti a naplózást. A forgalom naplózása extra akkumulátor használattal jár.
+ Ez alaphelyzetbe állítja a szabályok és feltételek értékeit
+ Ez törli az elérési kísérletek sorait a naplóból az engedélyezés/tiltás szabályok nélkül
+ Utolsó importálás: %s
+ Letöltés\n%1s
+ Hosts fájl letöltve
+ Utolsó Letöltés: %s
+ Port forward indítás %1$s port %2$d to %3$s:%4$d \'%5$s\'?
+ Port forward leállítás %1$s port %2$d?
+ Ez mért hálózat
+ Nincs aktív internetkapcsolat
+ A NetGuard elfoglalt
+ Frissítés érhető el, érintse meg a letöltéshez
+ Engedélyezni (zöldes) vagy tiltani (vöröses) tudja a Wi-Fi vagy mobil internet hozzáférést, ha megérinti az alkalmazás melleti ikont
+ Ha a NetGuard-ot az adatvédelmed érdekében telepítetted, akkor érdekelhet a FairEmail , egy nyilt forráskódú, adatvédelem-barát alkalmazás is téged
+ Az internet hozzáférés alapértelmezésként engedélyezve van, ezt meg lehet változtatni a beállításokban
+ A Push üzeneteket többnyire a rendszer Play szolgáltatások komponense kezeli, aminek alapértelmezésben engedélyezve van az internet hozzáférés
+ A speciális beállítások engedélyezve a rendszer alkalmazások kezeléséhez
+ Kérjük, írja le a problémát, és a probléma időpontját:
+ VPN kapcsolat megszüntetve\nBeállít másik VPN kapcsolatot, hogy állandó legyen a VPN?
+ A készülék kikapcsolásakor a NetGuard engedélyezve van, akkor automatikusan elindul a NetGuard a készülék bekapcsolásakor
+ Ez a funkció nem érhető el ezen az Android verzión
+ Másik VPN beállítása állandóra
+ Kapcsold ki a \"A VPN nélküli kapcsolatok blokkolása\"-t az Android VPN beállításaiban hogy a NetGuard-ot használhasd szűrés módban
+ Kapcsold ki a \"Privát DNS\"-t az Android Hálózati beállításaiban hogy a NetGuard-ot használhasd szűrés módban
+ A forgalom lezárva
+ Méretlen forgalom engedélyezve
+ Méretlen forgalom letiltva
+ Méretlen hálózat szabályok nincsenek alkalmazva
+ Mért forgalom engedélyezve
+ Mért forgalom letiltva
+ Mért hálózat szabályok nincsenek alkalmazva
+ A cím engedélyezve
+ Cím letiltva
+ Engedélyezi amikor a képernyő be van kapcsolva
+ Letiltás roaming közben
+ Alapértelmezésben a Wi-Fi kapcsolat méretlennek a mobil kapcsolat pedig mértnek minősül
+ nincs internet elérés engedélye
+ letiltva
+ Az üzeneteket a Google Play szolgáltatások fogadják, nem pedig ezzel az alkalmazással, ezáltal az üzeneteket nem lehet blokkolni e alkalmazás blokkolásával
+ A letöltések a Letöltéskezelővel történnek meg, nem pedig ezzel az alkalmazással, ezáltal a letöltéseket nem lehet blokkolni e alkalmazás blokkolásával
+ Szabályok és feltételek alkalmazása
+ Feltételek
+ Wi-Fi engedélyezése amikor a képernyő be van kapcsolva
+ Mobil engedélyezése amikor a képernyő be van kapcsolva
+ R
+ Letiltás roaming közben
+ Engedélyezés lezárt módban
+ Kapcsolódás szűrő
+ Hozzáférési kísérletek
+ Hozzáférési szabályok elsőbbséget élveznek más szabályokkal szemben
+ Beállítások
+ Értesítés az internet hozzáférési kísérletekről
+ A naplózás vagy a szűrés nincs engedélyezve
+ A naplózás és a szűrés engedélyezve
+ Testreszabás
+ Csak a blokkolt címek naplózásának engedélyezése
+ A szűrés engedélyezése naplózza az engedélyezett címeket is
+ Engedélyezi a hozzáférést az értesítésekhez az újonnan naplózott címeknek
+ Ezek a beállítások az összes alkalmazásra érvényes globális beállítások
+ A szűrés engedélyezése szükséges az egyedi címek engedélyezéséhez vagy blokkolásához
+ A naplózás engedélyezése (kevésbé) vagy szűrés (jobban) növelheti az akkumulátor használatot és érintheti a hálózat sebességét
+ Értékelje
+ Engedélyezés
+ Letiltás
+ Wi-Fi engedélyezése
+ Wi-Fi letiltása
+ Mobil engedélyezése
+ Mobil letiltása
+ root
+ mediaserver
+ senki
+ Ne kérdezze újra
+ Whois %1$s
+ Port %1$d
+ Másolás
+ Pro funkciók
+ A következő pro funkciók állnak rendelkezésre:
+ Letiltott forgalom naplójának megnézése
+ Hálózati forgalom szűrés
+ Új alkalmazás értesítések
+ Hálózat sebesség grafikon értesítés
+ Megjelenés (téma, színek)
+ Az összes fenti pro funkció
+ A fejlesztés támogatása
+ Vásárlás
+ Engedélyezve
+ Nem érhető el
+ Érintse meg a címet további információért
+ Hívás
+ Válasz
+ Ez egy pro szolgáltatás
+ Egy havi 1 vagy 2 eurós előfizetéssel (hely adók levonásával) lehet aktiválni a pro funkciókat.
+ Az előfizetést a Play Áruház előfizetések oldalán tudja megszüntetni vagy kezelni.
+
+
+ - zöldeskék/narancssárga
+ - kék/narancssárga
+ - lila/piros
+ - borostyán/kék
+ - narancssárga/szürke
+ - zöld
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-in-rID/strings.xml b/NetGuard/app/src/main/res/values-in-rID/strings.xml
new file mode 100644
index 0000000..f86162a
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-in-rID/strings.xml
@@ -0,0 +1,292 @@
+
+
+ NetGuard menyediakan cara sederhana dan canggih untuk memblokir akses internet - tidak membutuhkan root. Izinkan atau tolak koneksi Wi-Fi dan/atau seluler untuk setiap apl dan alamat situs.
+ NetGuard membutuhkan Android 5.1 atau lebih baru
+ Xposed menyebabkan terlalu banyak crash, yang mungkin menyebabkan NetGuard dihapus dari Google Play Store, oleh karena itu NetGuard tidak didukung saat Xposed terpasang
+ Kebijakan privasi
+ NetGuard dikembangkan dan diuji coba dengan sangat hati-hati, meskipun demikian, tidak mungkin menjamin NetGuard akan bekerja dengan benar pada setiap perangkat.
+ Setuju
+ Tolak
+ NetGuard butuh bantuan anda. Sentuh untuk membeli fitur pro agar proyek bisa terus dikembangkan.
+ Layanan yang berjalan
+ Notifikasi umum
+ Notifikasi akses
+ Cari aplikasi
+ Filter apl
+ Tampilkan apl pengguna
+ Tampilkan apl sistem
+ Tampilkan apl tanpa akses internet
+ Tampilkan apl yang dinonaktifkan
+ Urutkan apl
+ Urutkan berdasarkan nama
+ Urutkan berdasarkan uid
+ Urutkan berdasarkan penggunaan data
+ Tampilkan log
+ Pengaturan
+ Undang
+ Legenda
+ Bantuan
+ Tentang
+ Apl lainnya
+ Lainnya
+ Diizinkan
+ Diblokir
+ Pembaruan langsung
+ Segarkan
+ Tampilkan nama
+ Tampilkan susunan
+ PCAP diaktifkan
+ Ekspor PCAP
+ Bersihkan
+ Ekspor
+ Set ulang
+ Tambah
+ Hapus
+ Bersihkan
+ Protokol
+ Port sumber
+ Alamat tujuan
+ Port tujuan
+ Apl tujuan
+ Untuk server eksternal pilih \'tidak ada\'
+ Bawaan (daftar putih/hitam)
+ Blokir Wi-Fi
+ Blok seluler
+ Izinkan Wi-Fi saat layar menyala
+ Izinkan seluler saat layar menyala
+ Blokir roaming
+ Opsi
+ Tema: %1$s
+ Gunakan tema gelap
+ Beritahu pada aplikasi baru
+ Terapkan aturan \'ketika layar menyala\'
+ Otomatis aktif setelah %1$s menit
+ Tundaan layar mati %1$s menit
+ Periksa pembaruan
+ Opsi jaringan
+ Routing subnet
+ Izinkan tethering
+ Izinkan akses LAN
+ Aktifkan lalu lintas IPv6
+ Wi-Fi jaringan rumah: %1$s
+ Tangani jaringan Wi-Fi terbatas
+ Mempertimbangkan 2G unmetered
+ Mempertimbangkan 3G unmetered
+ Pertimbangkan LTE unmetered
+ Abaikan roaming nasional
+ Abaikan roaming EU
+ Nonaktif selama panggilan
+ Kunci Wi-Fi
+ Kunci seluler
+ Muat ulang setiap perubahan konektivitas
+ Opsi lanjutan
+ Kelola apl sistem
+ Catat akses internet
+ Beritahu pada akses internet
+ Filter lalu lintas
+ Filter lalu lintas UDP
+ Seamless VPN handover on reload
+ Tutup koneksi saat memuat ulang
+ Kunci lalu lintas
+ Lacak penggunaan jaringan
+ Set ulang penggunaan jaringan
+ Tampilkan nama domain asli
+ Blokir nama domain
+ Kode respons DNS: %s
+ Port forwarding
+ IPv4 VPN: %s
+ IPv6 VPN: %s
+ DNS VPN: %s
+ Validasi pada:%s
+ Minimum DNS TTL: %s s
+ Gunakan proksi SOCKS5
+ Alamat SOCKS5: %s
+ Port SOCKS5: %s
+ Nama pengguna SOCKS5: %s
+ Sandi SOCKS5: %s
+ Ukuran rekam PCAP: %s B
+ Ukuran maks. berkas PCAP: %s MB
+ Watchdog: setiap %s menit
+ Notifikasi kecepatan
+ Tampilkan notifikasi kecepatan
+ Tampilkan apl teratas
+ Interval sampel: %s ms
+ Jumlah sampel: %s s
+ Cadangan
+ Pengaturan ekspor
+ Pengaturan impor
+ Impor berkas host
+ Impor berkas host (ditambahkan)
+ URL unduh berkas host
+ Unduh berkas host
+ Informasi teknis
+ Umum
+ Jaringan
+ Langganan
+ Tampilkan notifikasi bilah status untuk langsung mengkonfigurasi apl yang baru dipasang (fitur pro)
+ Setelah menonaktifkan menggunakan widget, otomatis aktifkan NetGuard lagi setelah jumlah menit yang dipilih (masukkan nol untuk menonaktifkan opsi ini)
+ Setelah mematikan layar, jaga aturan layar nyala aktif selama jumlah menit yang dipilih (masukkan nol untuk menonaktifkan opsi ini)
+ Periksa rilis baru di GitHub dua kali sehari
+ Tergantung pada versi Android, tethering mungkin bisa atau tidak bisa berfungsi. Lalu lintas tethering tidak bisa disaring.
+ Aktifkan routing subnet; mungkin mengaktifkan panggilan Wi-Fi, tetapi mungkin juga memicu bug di Android dan meningkatkan penggunaan baterai
+ Izinkan apl terhubung ke alamat jaringan area lokal, seperti 10.0.0.0/8, 172.16.0.0/12 dan 192.168.0.0/16
+ Arahkan lalu lintas IP versi 6 ke NetGuard sehingga bisa selektif diizinkan atau diblokir
+ Terapkan aturan jaringan Wi-Fi untuk jaringan yang dipilih saja (terapkan aturan jaringan seluler untuk jaringan Wi-Fi lainnya)
+ Terapkan aturan jaringan seluler ke jaringan Wi-Fi terbatas (berbayar, tether)
+ Terapkan aturan jaringan Wi-Fi untuk koneksi data 2G
+ Terapkan aturan jaringan Wi-Fi untuk koneksi data 3G
+ Terapkan aturan jaringan Wi-Fi untuk koneksi data LTE
+ Jangan terapkan aturan roaming saat negara jaringan SIM dan seluler sama
+ Jangan terapkan aturan roaming saat negara jaringan SIM dan seluler berada di dalam UE (roam seperti di rumah)
+ Nonaktifkan NetGuard pada panggilan telepon masuk atau keluar. Ini bisa digunakan untuk mengatasi masalah panggilan IP/Wi-Fi.
+ Tentukan aturan untuk apl sistem (untuk ahli)
+ Catat upaya akses internet untuk apl. Hal ini mungkin menyebabkan penggunaan baterai ekstra.
+ Tampilkan notifikasi bilah status saat apl mencoba mengakses alamat internet baru (saat penyaringan dinonaktifkan, hanya akses internet yang diblokir yang akan diberitahu)
+ Filter paket IP keluar dari tunnel VPN. Hal ini mungkin menyebabkan penggunaan baterai ekstra.
+ Lacak jumlah byte yang dikirim dan diterima untuk setiap apl dan alamat. Hal ini mungkin menyebabkan penggunaan baterai ekstra.
+ Tanggapi dengan kode respons DNS yang dikonfigurasi untuk nama domain yang diblokir. Opsi ini dinonaktifkan ketika tidak ada berkas hos yang tersedia.
+ Nilai bawaannya adalah 3 (NXDOMAIN), yang berarti \'tidak ada domain\'.
+ Nama domain digunakan untuk memvalidasi sambungan internet pada port 443 (https).
+ Hanya lalu lintas TCP yang akan dikirim ke server proksi
+ Periksa secara berkala apakah NetGuard masih berjalan (masukkan nol untuk menonaktifkan opsi ini). Hal ini mungkin menyebabkan penggunaan baterai ekstra.
+ Tampilkan grafik kecepatan jaringan di notifikasi bilah status
+ Apakah anda yakin?
+ Memaksa aturan
+ %1$d diizinkan, %2$d diblokir
+ %1$d diizinkan, %2$d diblokir, %3$d hos
+ Menunggu acara
+ NetGuard dinonaktifkan, gunakan opsi di atas untuk mengaktifkan NetGuard
+ NetGuard telah dinonaktifkan, kemungkinan karena menggunakan apl berbasis VPN lainnya
+ \'%1$s\' terpasang
+ Telah terpasang
+ %1$s mencoba akses internet
+ Mencoba akses internet
+ Tindakan selesai
+ NetGuard menggunakan VPN lokal untuk menyaring lalu lintas internet.
+Untuk alasan ini, silakan izinkan koneksi VPN di dialog berikutnya.
+Lalu lintas internet anda tidak akan dikirim ke server VPN eksternal.
+ NetGuard tidak bisa memulai secara otomatis. Hal ini mungkin karena adanya bug di versi Android anda.
+ Terjadi kesalahan tak terduga: \'%s\'
+ Android menolak untuk memulai layanan VPN saat ini. Hal ini mungkin karena adanya bug di versi Android anda.
+ Coba NetGuard
+ Dengan donasi anda setuju dengan syarat & kondisi
+ Jika anda tidak bisa menekan OKE pada dialog berikutnya, apl (peredup layar) mungkin sedang memanipulasi layar.
+ ± %1$.3f▲ %2$.3f▼ MB/hari
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Agar hasil konsisten, pengoptimalan baterai Android harus dinonaktifkan untuk NetGuard.
+\n\nPada dialog berikutnya, pilih \"Semua aplikasi\" dibagian atas, ketuk NetGuard dalam daftar dan pilih \"Jangan optimalkan\".
+ Agar hasil konsisten, opsi penghemat data Android harus dinonaktifkan untuk NetGuard
+\n\nPada dialog berikutnya, aktifkan opsi \"Data latar belakang\" dan \"Penggunaan data tak terbatas\"
+ Munggunakan penyaringan akan membuat Android mengaitkan penggunaan data dan daya ke NetGuard - Android berasumsi kalau data dan daya sedang digunakan oleh NetGuard, bukan apl aslinya
+ Android 4 membutuhkan penyaringan diaktifkan
+ Pencatatan lalu lintas dinonaktifkan, gunakan opsi di atas untuk mengaktifkan pencatatan. Pencatatan lalu lintas mungkin menyebabkan penggunaan baterai ekstra.
+ Ini akan mengatur ulang kondisi dan aturan ke nilai bawaannya
+ Ini akan menghapus baris catatan upaya akses tanpa aturan izinkan/blokir
+ Impor terakhir: %s
+ Mengunduh\n%1s
+ Berkas hos diunduh
+ Unduhan terakhir: %s
+ Mulai teruskan dari %1$s port %2$d ke %3$s:%4$d dari \'%5$s\'?
+ Hentikan penerusan %1$s port %2$d?
+ Jaringan terukur
+ Tidak ada koneksi internet aktif
+ NetGuard sedang sibuk
+ Pembaruan tersedia, ketuk untuk mengunduh
+ Anda bisa izinkan (kehijauan) atau tolak (kemerahan) akses internet Wi-Fi atau seluler dengan mengetuk ikon di sebelah apl
+ Jika anda memasang NetGuard untuk melindungi privasi anda, anda mungkin juga tertarik dengan FairEmail , aplikasi email sumber terbuka, ramah privasi
+ Akses internet diizinkan secara bawaan (mode daftar hitam), ini bisa diubah di pengaturan
+ Pesan masuk (push) umumnya ditangani oleh komponen sistem layanan Play, yang secara bawaan diizinkan mengakses internet
+ Mengelola semua apl (sistem) bisa diaktifkan di pengaturan
+ Silakan jelaskan masalahnya dan waktu terjadinya masalah:
+ Koneksi VPN dibatalkan\nApakah anda mengkonfigurasi VPN lain untuk tetap nyala?
+ Mematikan perangkat anda dengan NetGuard aktif, akan secara otomatis memulai NetGuard saat menyalakan perangkat anda
+ Fitur ini tidak tersedia pada versi Android ini
+ VPN lain diatur untuk tetap nyala
+ Nonaktifkan \"Blokir koneksi tanpa VPN\" di pengaturan VPN Android untuk menggunakan NetGuard dalam mode penyaringan
+ Nonaktifkan \"DNS Pribadi\" di pengaturan jaringan Android untuk menggunakan NetGuard dalam mode penyaringan
+ Lalu lintas dikunci
+ Lalu lintas tak terukur diizinkan
+ Lalu lintas tak terukur diblokir
+ Aturan tak terukur tidak diterapkan
+ Lalu lintas terukur diizinkan
+ Lalu lintas terukur diblokir
+ Aturan terukur tidak diterapkan
+ Alamat diizinkan
+ Alamat diblokir
+ Izinkan saat layar aktif
+ Blokir saat roaming
+ Secara bawaan koneksi Wi-Fi dianggap tak terukur dan koneksi seluler terukur
+ tidak memiliki izin internet
+ dinonaktifkan
+ Pesan masuk diterima oleh Google Play Service dan bukan aplikasi ini sehingga tidak akan diblokir dengan memblokir aplikasi ini
+ Unduhan dijalankan oleh pengelola unduhan dan bukan aplikasi ini sehingga tidak akan diblokir dengan memblokir aplikasi ini
+ Terapkan aturan dan kondisi
+ Kondisi
+ Izinkan Wi-Fi saat layar aktif
+ Izinkan seluler saat layar aktif
+ R
+ Blokir saat roaming
+ Izinkan dalam mode penguncian
+ Filter terkait
+ Upaya akses
+ Aturan akses lebih diutamakan daripada aturan lainnya
+ Opsi
+ Beritahu upaya akses internet
+ Pencatatan atau penyaringan tidak diaktifkan
+ Pencatatan atau penyaringan diaktifkan
+ Konfigurasikan
+ Aktifkan pencatatan hanya untuk alamat yang diblokir
+ Juga aktifkan penyaringan untuk mencatat alamat yang diizinkan
+ Aktifkan notifikasi akses untuk alamat yang baru dicatat
+ Pengaturan ini adalah pengaturan global yang diterapkan untuk semua apl
+ Penyaringan juga dibutuhkan untuk mengizinkan atau memblokir alamat individual
+ Mengaktifkan pencatatan (kurang) atau penyaringan (lebih) mungkin meningkatkan penggunaan baterai dan mungkin mempengaruhi kecepatan jaringan
+ Laju
+ Izinkan
+ Blokir
+ Izinkan Wi-Fi
+ Blokir Wi-Fi
+ Izinkan seluler
+ Blokir seluler
+ root
+ mediaserver
+ tidak ada
+ Jangan tanya lagi
+ Whois %1$s
+ Port %1$d
+ Salin
+ Fitur pro
+ Fitur pro berikut tersedia:
+ Lihat catatan lalu lintas yang diblokir
+ Filter lalu lintas jaringan
+ Notifikasi apl baru
+ Notifikasi grafik kecepatan jaringan
+ Penampilan (tema, warna)
+ Semua fitur pro di atas
+ Dukung pengembangan
+ Beli
+ Aktif
+ Tidak tersedia
+ Ketuk judul untuk informasi lebih lanjut
+ Tantangan
+ Respons
+ Ini adalah fitur Pro
+ Langganan bulanan dengan 1 atau 2 euro (tidak termasuk pajak lokal) akan mengaktifkan semua fitur pro.
+ Kamu dapat membatalkan atau mengelola langganan melalui tab langganan di aplikasi Play Store.
+
+
+ - teal/oranye
+ - biru/oranye
+ - ungu/merah
+ - kuning/biru
+ - oranye/abu-abu
+ - hijau
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-it-rIT/strings.xml b/NetGuard/app/src/main/res/values-it-rIT/strings.xml
new file mode 100644
index 0000000..ce0f6cd
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-it-rIT/strings.xml
@@ -0,0 +1,292 @@
+
+
+ NetGuard fornisce sia opzioni semplici che avanzate per bloccare l\'accesso a internet - non necessita di root. Alle applicazioni ed agli indirizzi può essere consentito o negato, singolarmente, l\'accesso alle connessioni Wi-Fi e/o mobile.
+ NetGuard richiede Android 5.1 o successiva
+ Xposed causa troppi arresti anomali, che potrebbero risultare nella rimozione di NetGuard da Google Play Store, dunque NetGuard non è supportato mentre Xposed è installata
+ Politica della privacy
+ Si è posta grande attenzione nello sviluppo e test di NetGuard, tuttavia è impossibile garantire che funzionerà correttamente su ogni dispositivo.
+ Acconsento
+ Nego il consenso
+ NetGuard ha bisogno del tuo aiuto. Tocca per acquistare le funzionalità pro per sostenere il progetto.
+ Servizi in esecuzione
+ Notifiche generali
+ Notifiche d\'accesso
+ Cerca applicazione
+ Filtra applicazioni
+ Mostra applicazioni utente
+ Mostra applicazioni di sistema
+ Mostra app senza internet
+ Mostra app disabilitate
+ Ordina applicazioni
+ Ordina per nome
+ Ordina per uid
+ Ordina per utilizzo dati
+ Mostra registro
+ Impostazioni
+ Invita
+ Legenda
+ Supporto
+ Info
+ Altre app
+ Altro
+ Permesse
+ Bloccate
+ Aggiornamenti in tempo reale
+ Aggiorna
+ Mostra nomi
+ Mostra organizzazione
+ PCAP abilitati
+ Esporta PCAP
+ Pulisci
+ Esporta
+ Ripristina
+ Aggiungi
+ Elimina
+ Pulisci
+ Protocollo
+ Porta di origine
+ Indirizzo di destinazione
+ Porta di destinazione
+ Applicazione di destinazione
+ Per un server esterno selezionare \'nessuno\'
+ Impostazioni predefinite
+ Blocca Wi-Fi
+ Blocca rete dati
+ Consenti la Wi-Fi a schermo acceso
+ Consenti la rete mobile a schermo acceso
+ Blocca roaming
+ Impostazioni opzionali
+ Tema: %1$s
+ Usa il tema scuro
+ Notifica l\'installazione di nuove applicazioni
+ Applica le regole \'a schermo acceso\'
+ Attiva automaticamente dopo %1$s minuti
+ Ritarda lo spegnimento dello schermo di %1$s minuti
+ Controlla gli aggiornamenti
+ Opzioni di rete
+ Routing della sottorete
+ Consenti tethering
+ Consenti l\'accesso LAN
+ Abilita il traffico IPv6
+ Reti Wi-Fi domestiche: %1$s
+ Gestisci le reti Wi-Fi a consumo
+ Considera 2G non a consumo
+ Considera 3G non a consumo
+ Considera LTE non a consumo
+ Ignora roaming nazionale
+ Ignora roaming UE
+ Disabilita su chiamata
+ Limita Wi-Fi
+ Limita rete dati
+ Ricarica a ogni modifica della connettività
+ Opzioni avanzate
+ Gestisci le app di sistema
+ Registra l\'accesso a internet
+ Notifica all\'accesso a internet
+ Filtra traffico
+ Filtra traffico UDP
+ Passaggio alla VPN senza soluzioni di continuità ricaricando
+ Chiudi le connessioni ricaricando
+ Limita il traffico
+ Monitora l\'uso di rete
+ Ripristina l\'uso di rete
+ Mostra i nomi di dominio risolti
+ Blocca i nomi di dominio
+ Codice di risposta DNS: %s
+ Port forwarding
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Convalida a: %s
+ TTL DNS minimo: %s s
+ Usa proxy SOCKS5
+ Indirizzo SOCKS5: %s
+ Porta SOCKS5: %s
+ Nome utente SOCKS5: %s
+ Password SOCKS5: %s
+ Dimensioni record PCAP: %s B
+ Dimensione massima PCAP del file: %s MB
+ Temporizzazione di supervisione: ogni %s minuti
+ Notifica di velocità
+ Mostra la notifica di velocità
+ Visualizza le app migliori
+ Intervallo campione: %s ms
+ Numero di campioni: s %s
+ Backup
+ Esporta le impostazioni
+ Importa le impostazioni
+ Importa file degli host
+ Importa file degli host (aggiungi)
+ URL di download del file degli host
+ Scarica i file degli host
+ Informazioni tecniche
+ Generale
+ Reti
+ Sottoscrizioni
+ Mostra la notifica della barra di stato per configurare direttamente le app appena installate (funzionalità pro)
+ Dopo aver disabilitato l\'uso del widget, riabilita automaticamente NetGuard dopo il numero di minuti selezionato (inserisci zero per disabilitare quest\'opzione)
+ Dopo aver spento lo schermo, mantieni attive le regole a schermo acceso per il numero selezionato di minuti (inserisci zero per disabilitare quest\'opzione)
+ Crea nuove versioni su GitHub due volte al giorno
+ In base alla versione di Android, il tethering potrebbe funzionare o no. Il traffico in tethering non è filtrabile.
+ Abilita il routing di sottorete; potrebbe abilitare le chiamate della Wi-Fi, ma potrebbe anche causare bug in Android e aumentare l\'uso della batteria
+ Consenti alle app di connettersi agli indirizzi di rete dell\'area locale, come 10.0.0.0/8, 172.16.0.0/12 e 192.168.0.0/16
+ Instrada il traffico dell\'IP versione 6 a NetGuard così che possa esser consentito o bloccato selettivamente
+ Applica le regole di rete della Wi-Fi solo per le reti selezionate (applica le regole di rete mobile per altre reti Wi-Fi)
+ Applica le regole di rete mobile alle reti Wi-Fi a consumo (pagate, in tethering)
+ Applica le regole di rete Wi-Fi per le connessioni dati a 2G
+ Applica le regole di rete Wi-Fi per le connessioni dati a 3G
+ Applica le regole di rete Wi-Fi per le connessioni dati a LTE
+ Non applicare le regole di roaming quando la SIM e il paese della rete mobile corrispondono
+ Non applicare le regole di roaming quando la SIM e il paese della rete mobile sono entro l\'UE (roam like at home)
+ Disabilita NetGuard alle chiamate telefoniche in entrata o uscita. Questo è utilizzabile per ovviare ai problemi di chiamata IP/Wi-Fi.
+ Definisci le regole per le app di sistema (per esperti)
+ Registra i tentativi d\'accesso a internet per le app. Questo potrebbe risultare in un uso aggiuntivo della batteria.
+ Mostra una notifica della barra di stato quando un\'app tenta di accedere a un nuovo indirizzo internet (quando il filtraggio è disabilitato, solo i tentativi d\'accesso a internet bloccati saranno notificati)
+ Filtra i pacchetti IP in uscita dal tunnel della VPN. Questo potrebbe risultare in un uso aggiuntivo della batteria.
+ Monitora quanti byte sono inviati e ricevuti per ogni app e indirizzi. Questo potrebbe risultare in un uso aggiuntivo della batteria.
+ Rispondi con il codice di risposta DNS configurato per i nomi di dominio bloccati. Quest\'opzione è disabilitata quando non è disponibile alcun file degli host.
+ Il valore predefinito è 3 (NXDOMAIN), il che significa \'dominio inesistente\'.
+ Il nome di dominio usato per convalidare la connessione internet alla porta 443 (https).
+ Solo il traffico TCP sarà inviato al server proxy
+ Controlla periodicamente se NetGuard è ancora in esecuzione (inserisci zero per disabilitare quest\'opzione). Questo potrebbe risultare in un uso extra della batteria.
+ Mostra il grafico della velocità di rete nella notifica della barra di stato
+ Sei sicuro?
+ Regole imposte
+ %1$d consentiti, %2$d bloccati
+ %1$d consentiti, %2$d bloccati, %3$d host
+ In attesa dell\'evento
+ NetGuard è disabilitato, usa l\'interruttore sopra per abilitare NetGuard
+ NetGuard è stata disabilitata, probabilmente usando un\'altra app basata sul VPN
+ \'%1$s\' installata
+ È stata installata
+ %1$s tentativi d\'accesso a internet
+ Tentativi d\'accesso a internet
+ Azione completata
+ NetGuard usa una VPN locale per filtrare il traffico internet.
+Per questo motivo, sei pregato di consentire una connessione VPN nella finestra successiva.
+Il tuo traffico internet non è inviato a un server VPN remoto.
+ Impossibile avviare automaticamente NetGuard. Questo potrebbe dipendere da un bug nella tua versione di Android.
+ Si è verificato un errore imprevisto: \'%s\'
+ Android si è rifiutato di avviare il servizio VPN al momento. Probabilmente a causa di un bug nella tua versione di Android.
+ Prova NetGuard
+ Donando acconsenti ai Termini e le Condizioni
+ Se non riesci a premere OK nella prossima finestra, un\'altra app (di oscuramento dello schermo) sta probabilmente manipolando lo schermo.
+ ± %1$.3f▲ %2$.3f▼ MB/giorno
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Per risultati attendibili, le ottimizzazioni della batteria di Android dovrebbero esser disabilitate per NetGuard.
+\n\nNella prossima finestra, seleziona \"Tutte le app\" in alto, tocca su NetGuard nell\'elenco e seleziona e conferma \"Non ottimizzare\".
+ Per risultati attendibili, le opzioni di salvataggio dei dati di Android dovrebbero esser disabilitate per NetGuard.
+\n\nNella prossima finestra, abilita le opzioni \"Dati in background\" e \"Uso illimitato dei dati\"
+ Usare il filtraggio causerà ad Android di attribuire i dati e l\'uso energetico a NetGuard; Android presume che i dati e l\'energia siano usati da NetGuard, piuttosto che dalle app originali
+ Android 4 richiede che il filtraggio sia abilitato
+ La registrazione del traffico è disabilitata, usa l\'interruttore sopra per abilitare la registrazione. La registrazione del traffico potrebbe risultare in un uso aggiuntivo della batteria.
+ Questo ripristinerà le regole e le condizioni ai loro valori predefiniti
+ Questo eliminerà le righe del registro dei tentativi d\'accesso senza le regole consenti/blocca
+ Ultima importazione: %s
+ Scaricando\n%1s
+ File degli host scaricati
+ Ultimo download: %s
+ Inizia ad inoltrare dalla porta %1$s %2$d a %3$s:%4$d di \'%5$s\'?
+ Interrompere l\'inoltro della porta %1$s %2$d?
+ La rete è a consumo
+ Nessuna connessione a internet attiva
+ NetGuard è occupato
+ Aggiornamento disponibile, tocca per scaricare
+ Puoi consentire (verdastro) o bloccare (rossastro) l\'accesso a internet mobile o Wi-Fi toccando sulle icone affianco a un\'app
+ Se hai installato NetGuard per proteggere la tua privacy, potresti essere anche interessato a FairEmail un app email rispettosa della privacy e open source
+ L\'accesso a internet è consentito di default (modalità blacklist), questo è modificabile nelle impostazioni
+ I messaggi (push) in arrivo sono prevalentemente gestiti dal componente di sistema Play Services, cui è consentito di default l\'accesso a internet
+ La gestione di tutte le app (di sistema) è abilitabile nelle impostazioni
+ Sei pregato di descrivere il problema e indicare quando si è verificato:
+ Connessione VPN annullata\nHai configurato un\'altra VPN affinché resti sempre attiva?
+ Spegnere il tuo dispositivo con NetGuard abilitato, lo avvierà automaticamente all\'avvio del tuo dispositivo
+ Questa funzionalità non è disponibile su questa versione di Android
+ Un\'altra VPN è impostata come Sempre Attiva
+ Disattiva \"Blocca le connessioni senza VPN\" nelle impostazioni della VPN di Android per usare NetGuard in modalità filtraggio
+ Disattiva \"DNS Privato\" nelle impostazioni di rete di Android per usare NetGuard in modalità filtraggio
+ Il traffico è limitato
+ Il traffico non a consumo è consentito
+ Il traffico non a consumo è bloccato
+ Le regole non a consumo non sono applicate
+ Il traffico a consumo è consentito
+ Il traffico a consumo è bloccato
+ Le regole a consumo non sono applicate
+ L\'indirizzo è consentito
+ L\'indirizzo è bloccato
+ Consenti quando lo schermo è acceso
+ Blocca in roaming
+ Di default, una connessione Wi-Fi è considerata non a consumo e una connessione mobile come a consumo
+ non ha autorizzazioni a internet
+ è disabilitata
+ I messaggi in arrivo sono ricevuti dai servizi di Google Play e non da quest\'app e possono dunque non esser bloccati da quest\'app
+ I download sono eseguiti dal gestore dei download e non da quest\'app e possono dunque non esser bloccati bloccando quest\'app
+ Applicare le regole e le condizioni
+ Condizioni
+ Consenti la Wi-Fi a schermo acceso
+ Consenti la rete mobile a schermo acceso
+ R
+ Blocca in roaming
+ Consenti in modalità limitata
+ Filtra correlati
+ Tentativi d\'accesso
+ Le regole d\'accesso hanno la precedenza sulle altre regole
+ Opzioni
+ Notifica i tentativi d\'accesso a internet
+ La registrazione o il filtraggio non sono abilitati
+ La registrazione o il filtraggio sono abilitati
+ Configura
+ Abilita la registrazione dei soli indirizzi bloccati
+ Abilita anche il filtraggio per registrare gli indirizzi consentiti
+ Abilita le notifiche d\'accesso per gli indirizzi appena registrati
+ Queste impostazioni sono globali e si applicano a tutte le app
+ Il filtraggio è necessario anche per consentire o bloccare i singoli indirizzi
+ Abilitare la registrazione (meno) o il filtraggio (più) potrebbe aumentare l\'uso della batteria e influenzare la velocità di rete
+ Valuta
+ Consenti
+ Blocca
+ Consenti Wi-Fi
+ Blocca Wi-Fi
+ Consenti rete mobile
+ Blocca rete mobile
+ root
+ mediaserver
+ nessuno
+ Non chiedere più
+ Whois %1$s
+ Porta %1$d
+ Copia
+ Funzionalità pro
+ Le seguenti funzionalità pro sono disponibili:
+ Visualizza il registro del traffico bloccato
+ Filtra il traffico di rete
+ Nuove notifiche dell\'app
+ Notifica del grafico della velocità di rete
+ Aspetto (tema, colori)
+ Tutte le suddette funzionalità pro
+ Sostieni lo sviluppo
+ Acquista
+ Abilitato
+ Non disponibile
+ Tocca su un titolo per ulteriori informazioni
+ Sfida
+ Risposta
+ Questa è una funzionalità pro
+ Un abbonamento mensile di 1 o 2 euro (escluse le tasse locali), attiverà tutte le funzionalità pro.
+ Puoi annullare o gestire un abbonamento tramite la scheda degli abbonamenti nell\'app del Play Store.
+
+
+ - foglia di tè/arancione
+ - blu/arancione
+ - viola/rosso
+ - ambra/blu
+ - arancione/grigio
+ - verde
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-iw-rIL/strings.xml b/NetGuard/app/src/main/res/values-iw-rIL/strings.xml
new file mode 100644
index 0000000..0a6fc09
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-iw-rIL/strings.xml
@@ -0,0 +1,289 @@
+
+
+ NetGuard מספקת דרכים פשוטות ומתקדמות לחסום גישה לאינטרנט - ללא צורך ברוט
+היא מאפשרת לחסום או לאפשר באופן פרטני גישת יישומים לרשתות Wi-Fi או אינטרנט סלולרי.
+ NetGuard זקוק לגירסת אנדרואיד 5 ומעלה
+ Xposed גורם ליותר מדי קריסות, אשר עלולות לגרום להסרת NetGuard מהPlay Google, ולכן NetGuard לא תפעל כל עוד Xposed מותקן
+ מדיניות פרטיות
+ תשומת לב רבה הושקעה בפיתוח ובדיקת NetGuard, אך לא ניתן לערוב שNetGuard תעבוד על כל סוגי המכשירים.
+ אני מסכים
+ אני לא מסכים
+ NetGuard זקוקה לעזרתך להמשיך בפיתוח הפרויקט, לחץ כאן לרכישת תכונות Pro.
+ שירותים פועלים
+ התראות כלליות
+ גישה להתראות
+ חפש יישום
+ סנן יישומים
+ הצג יישומי משתמש
+ הצג יישומי מערכת
+ הצג יישומים ללא אינטרנט
+ הצג יישומים מנוטרלים
+ מיין יישומים
+ מיון לפי שם
+ מיין לפי uid
+ מיון לפי השימוש בנתונים
+ הצג תיעוד
+ הגדרות
+ הזמן
+ מקרא
+ תמיכה
+ אודות
+ אפליקציות אחרות
+ אחר
+ מורשה
+ חסום
+ עדכונים חיים
+ רענון
+ הצג שמות
+ הצג ארגון
+ PCAP מופעל
+ ייצוא PCAP
+ נקה
+ יצוא
+ איתחול מחדש
+ הוסף
+ מחק
+ ניקוי
+ פרוטוקול
+ פורט מקור
+ כתובת היעד
+ פורט היעד
+ יישום היעד
+ עבור שרת חיצוני בחר \'ללא\'
+ ברירות מחדל
+ חסום Wi-Fi
+ חסום נייד
+ אפשר גישה לרשתות Wi-Fi כאשר המסך פועל
+ אפשר גישה לרשתות סלולריות כאשר המסך פועל
+ חסום נדידה
+ אפשרויות
+ ערכת נושא: %1$s
+ השתמש בערכת נושא כהה
+ הצג התראה על התקנה חדשה
+ החל כללי \'מסך דולק\'
+ אפשר אוטומטית לאחר %1$s דקות
+ השהה כיבוי מסך לאחרי %1$s דקות
+ בדוק האם קיימים עדכונים
+ אפשרויות רשת
+ ניתוב רשת משנה
+ אפשר שיתוף רשת סלולרית (tethering)
+ אפשר גישה ברשת LAN
+ אפשר תעבורת IPv6
+ רשתות Wi-Fi ביתיות: %1$s
+ טפל בתעבורת Wi-Fi מדודה
+ התייחס ל2G כתעבורה לא מדידה
+ התייחס ל3G כתעבורה לא מדידה
+ התייחס לLTE כתעבורה לא מדידה
+ התעלם מנדידה בתוך המדינה
+ התעלם ממצב נדידה EU
+ השבת במהלך שיחה
+ נעילת Wi-Fi
+ נעילת נתונים ניידים
+ רענן בכל שינוי מצב רשת
+ אפשרויות מתקדמות
+ נהל יישומי מערכת
+ יומן גישה לאינטרנט
+ התראה על גישה לאינטרנט
+ סנן תעבורה
+ סנן תעבורת UDP
+ העברה חלקה של ה-VPN בטעינה מחדש
+ סגור חיבורים ברענון
+ נעילת תעבורה
+ עקוב אחר השימוש ברשת
+ אפס את מונה השימוש ברשת
+ הצג שמות דומיין
+ חסום שמות מתחם (דומיין)
+ קוד תגובת DNS: %s
+ הפניית פורטים
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ אמת ב: %s
+ TTL DNS מינימלי: %s s
+ השתמש ב- SOCKS5 proxy
+ כתובת SOCKS5: %s
+ פורט SOCKS5: %s
+ שם משתמש SOCKS5: %s
+ סיסמת SOCKS5: %s
+ גודל רשומת PCAP: %s B
+ גודל מקסימלי של קובץ PCAP: %s MB
+ Watchdog טיימר: כל %s דקות
+ התראת מהירות
+ הצג התראת מהירות
+ הצג את היישומים העליונים
+ מרווח הדגימה: %s מ\"ש
+ מספר הדגימות: %s ש
+ גיבוי
+ ייצא הגדרות
+ יבא הגדרות
+ ייבוא קובץ hosts
+ יבא קובץ hosts (הוספה)
+ URL להורדת קובץ hosts
+ הורד קובץ hosts
+ מידע טכני
+ כללי
+ רשתות
+ מנויים
+ הצג הודעה בשורת המצב על מנת לאפשר גישה ישירה להגדרות היישום שהותקן (תכונה Pro)
+ לאחר ניטרול דרך הווידגט, אפשר לNetGuard להתחיל באופן אוטמטי לאחר מספר הדקות שנבחר (הזן אפס על מנת לבטל אופציה זאת)
+ לאחר כיבוי המסך, המשך להשתמש בחוקי מסך דולק למשך מספר הדקות שנבחר (הזן 0 כדי לבטל אפשרות זו)
+ בדוק עבור עדכונים חדשים דרך GitHub באופן יומי
+ בהתאם לגירסת אנדרואיד, ייתכן כי שיתוף רשת סלולרית (tethering) לא יפעל. לא ניתן לסנן תעבורת שיתוף רשת סלולרית (tethering).
+ אפשר ניתוב subnet: מאפשר קיום שיחות מעל רשת Wi-Fi, אך עלול לחשוף באגים במערכת ההפעלה אנדרואיד ולהגדיל את צריכת הסוללה
+ אפשר ליישומים להתחבר לכתובות רשת מקומית, כגון 10.0.0.0/8, 172.16.0.0/12 ו- 192.168.0.0/16
+ נתב תעבורת IPv6 אל NetGuard כך שניתן יהיה לאפשר או לחסום אותה באופן סלקטיבי
+ החל חוקי רשת Wi-Fi רק עבור הרשת שנבחרה (עבור רשתות Wi-Fi אחרות יחולו חוקי הרשת הסלולרית)
+ החל כללי רשת סלולרית על תעבורה נמדדת (בתשלום, שיתוף רשת סלולרית)
+ החל חוקי רשת Wi-Fi עבור חיבור נתונים 2G
+ החל חוקי רשת Wi-Fi עבור חיבור נתונים 3G
+ החל חוקי רשת Wi-Fi עבור חיבור נתונים LTE
+ אל תאפשר להחיל חוקי נדידת נתונים כאשר מדינת הסים והרשת זהים
+ אין להחיל כללי נדידה כאשר ה-SIM ומדינת הרשת הסלולרית נמצאים בתוך האיחוד האירופי
+ השבת NetGuard בשיחת טלפון נכנסת או יוצאת. זה יכול לעזור לעקוף בעיות התקשרות של IP/Wi-Fi.
+ הגדר חוקים עבור יישומי מערכת (למומחים)
+ תעד נסיונות גישה לאינטרנט ע”י יישומים. עלול להגביר צריכת סוללה.
+ הצג הודעה בשורת המצב כאשר יישום מנסה לגשת אל כתובת אינטרנט חדשה (כאשר תכונת הסינון אינה מאופשרת, יוצגו רק ניסיונות גישה שנחסמו)
+ סינון מנות IP ביציאה מערוץ VPN. עלול להגביר צריכת סוללה.
+ עקוב אחרי כמות המידע שנשלחה והתקבלה עבור כל יישום וכתובת. עלול להגביר צריכת סוללה.
+ הגב עם תגובת הDNS המוגדרת עבור דומיינים חסומים. אפשרות זו מושבתת כאשר קובץ hosts אינו זמין.
+ ערך ברירת המחדל הוא 3, שפירושו \'תחום לא קיים\'.
+ שם דומיין לביצוע אימות חיבור לאינטרנט בפורט 443 (https).
+ רק תעבורת TCP תועבר אל שרת ה-proxy
+ בדוק מדי פרק הזמן המוגדר האם NetGuard עדיין פועל (הזן 0 כדי לבטל אפשרות זו). עלול לגרום לצריכת סוללה מוגברת.
+ הצג גרף מהירות רשת בהתראת שורת המצב
+ האם אתה בטוח?
+ אוכף חוקים
+ %1$d אושרו, %2$d נחסמו
+ %1$d אושרו, %2$d נחסמו, %3$d שרתים
+ ממתין לאירוע
+ NetGuard מנוטרל, השתמש במתג שמעל כדי לאפשר את NetGuard
+ NetGuard מנוטרל, ככל הנראה בגלל שימוש ביישום מבוסס VPN אחר
+ \'%1$s\' מותקן
+ הותקן
+ %1$s ניסה לגשת לאינטרנט
+ ניסיון גישה לאינטרנט
+ הפעולה הסתיימה
+ NetGuard משתמש ב- VPN המקומי לסינון תעבורת האינטרנט. מסיבה זו, אנא אפשר חיבור VPN בתיבת הדו-שיח הבאה. תעבורת האינטרנט שלך אינה נשלחת לשרת VPN מרוחק.
+ לא היתה אפשרות להפעיל את NetGuard באופן אוטומטי באתחול עקב באג בגירסת האנדרואיד
+ אירעה שגיאה בלתי צפויה: \'%s\'
+ אנדרואיד סירב להפעיל את שירות ה-VPN ברגע זה. סביר שזה קרה עקב באג בגירסת האנדרואיד שלך.
+ נסה את NetGuard
+ בתרומתך אתה מסכים ל תנאים והגבלות
+ אם אין אפשרות ללחוץ על אישור בתיבת הדו-שיח הבאה, סביר להניח שיישום אחר (כגון עמעום מסך) משנה את המסך.
+ ± %1$.3f▲ %2$.3f▼ MB/יום
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ על מנת לקבל תוצאות עקביות, אופציית ייעול הסוללה של אנדרואיד צריכה להיות מכובה עבור NetGuard.
+\n\n בתיבת הדו שיח הבאה, בחר ב\"כל האפלקציות\" בחלק העליון, בחר ב-NetGuard מתוך הרשימה וסמן \"אל תייעל\".
+ על מנת לקבל תוצאות עקביות, הגבלות שמירת הנתונים באנדרואיד צריכות להיות מכובות עבור NetGuard.\n\n בתיבת הדו-שיח הבאה, אפשר את האפשרויות \"נתוני רקע\" ו- \"שימוש בלתי מוגבל בנתונים \"
+ שימוש בסינון יגרום לאנדרואיד לשייך לNetGuard את השימוש בתעבורת נתונים ובסוללה - אנדרואיד יניח שNetGuard משתמש בתעבורה ובסוללה, ולא היישומים המקוריים.
+ אנדרואיד 4 דורש כי תכונת הסינון תהיה מאופשרת
+ תיעוד תעבורת הנתונים מנוטרל, אנא השתמש במתג מעל כדי לאפשר תיעוד. תיעוד התעבורה עלול להגביר את צריכת הסוללה.
+ פעולה זו תאפס את הכללים והתנאים לערכי ברירת המחדל שלהם
+ פעולה זו תגרום למחיקת שורות תיעוד שבהן נרשמו ניסיונות גישה שעבורן לא הופעלו חוקי היתרים/חסימות
+ ייבוא אחרון: %s
+ מוריד\n%1s
+ קובץ hosts הורד
+ הורדה אחרונה: %s
+ התחל העברה מ %1$s פורט %2$d ל%3$s:%4$d של \'%5$s\'?
+ הפסק העברה של %1$s פורט %2$d?
+ הרשת מנוטרת
+ אין חיבור לאינטרנט
+ NetGuard עמוס
+ עדכון זמין, הקש כדי להוריד
+ באפשרותך לאשר (ירוק) או למנוע (אדום) מיישום גישה לרשתות Wi-Fi או לרשת האינטרנט הסלולרית באמצעות הקשה על הסמל שליד יישום
+ אם התקנת את NetGuard לשמירה על פרטיותך, אולי תהיה מעוניין גם ב FairEmail - אפליקציית email בקוד פתוח ששמה דגש על פרטיות
+ גישה לאינטרנט מותרת כברירת מחדל, ניתן לשנות זאת בתפריט ההגדרות
+ הודעות Push מטופלות בעיקר על ידי רכיב המערכת Play services, אשר עבורו מאופשרת גישה לאינטרנט כברירת מחדל
+ ניהול יישומי מערכת ניתן להפעלה מתוך תפריט הההגדרות
+ אנא תאר את הבעיה תוך ציון הזמן שבה קרתה:
+ חיבור VPN בוטל, האם הגדרת חיבור VPN נוסף אחר שיפעל תמיד?
+ כיבוי המכשיר שלך כאשר NetGuard פעיל, יפעיל את NetGuard אוטומטית בהדלקת המכשיר
+ תכונה זו אינו זמינה בגרסת האנדרואיד הנוכחית
+ חיבור VPN אחר מוגדר כ\'VPN מופעל תמיד\'
+ בכדי להשתמש בNetGuard במצב סינון אליך לבטל את ההגדרה, חסום חיבור ללא VPN הנמצא בהגדרות VPN של אנדרואיד
+ בכדי להשתמש בNetGuard במצב סינון אליך לבטל את ההגדרה, DNS פרטי בהגדרות הרשת של אנדרואיד
+ תעבורה נעולה
+ תעבורה חופשית מאופשרת
+ תעבורה חופשית חסומה
+ כללים לא מדודים אינם חלים
+ תעבורה נמדדת מאופשרת
+ תעבורה נמדדת חסומה
+ כללים מדודים אינם חלים
+ כתובת מותרת
+ כתובת חסומה
+ אפשר כאשר המסך פעיל
+ חסום בעת נדידה
+ כברירת מחדל, חיבור Wi-Fi נחשב כתעבורה לא נמדדת (חופשית), וחיבור סלולרי כתעבורה נמדדת
+ אין הרשאות אינטרנט
+ מושבת
+ הודעות מתקבלות ע\"י שירותי Google Play ולא ע\"י האפליקציה הזאת ולכן לא אפשרי לחסום אותן
+ הורדות מתבצעות ע\"י מנהל ההורדות ולא ע\"י האפליקציה הזאת ולכן לא אפשרי לחסום אותן
+ החל את הכללים והתנאים
+ תנאים
+ אפשר גישה ל-Wi-Fi כאשר המסך פעיל
+ אפשר גישה לרשת סלולרית כאשר המסך פעיל
+ R
+ חסום בעת נדידה
+ אפשר במצב נעילה
+ סנן דומים
+ נסיונות גישה
+ לכללי גישה יש קדימות על כללים אחרים
+ אפשרויות
+ התרע על נסיונות גישה לאינטרנט
+ תיעוד או סינון אינם מופעלים
+ תיעוד וסינון מופעלים
+ קבע תצורה
+ הפעל רישום של כתובות חסומות בלבד
+ אפשר תיעוד סינון גם כתובות מותרות
+ אפשר הודעות גישה עבור כתובות שנרשמו לאחרונה
+ הגדרות אלה הן הגדרות כלליות החלות על כל היישומים
+ נדרש סינון גם על מנת לאפשר או לחסום כתובות בודדות
+ הפעלת תיעוד (מופחת) או סינון (מוגבר) עלול להשפיע על צריכת סוללה, ועשוי גם להשפיע על מהירות הרשת
+ דרג
+ אפשר
+ חסום
+ אפשר Wi-Fi
+ חסום Wi-Fi
+ אפשר נתוני נייד
+ חסום נתוני נייד
+ root
+ שרת מדיה
+ nobody
+ אל תשאל שוב
+ Whois %1$s
+ פורט %1$d
+ העתק
+ מאפייני גירסת Pro
+ התכונות הבאות זמינות בגירסת Pro:
+ צפה בבתיעוד התעבורה החסומה
+ סנן תעבורת רשת
+ התראות על יישומים חדשים
+ התראת גרף מהירות הרשת
+ מראה (נושא, צבעים)
+ כל מאפייני גירסת Pro שהוזכרו
+ תמוך בפיתוח
+ קנה
+ מופעל
+ לא זמין
+ לחץ על הכותרת למידע נוסף
+ אתגר
+ תגובה
+ זוהי יכולת של גירסת ה-pro
+ מנוי חודשי של 1 או 2 יורו (לפני מיסים) יפעיל את כל יכולות גירסת ה-pro.
+יש באפשרותך לבטל את המנוי דרך טאב הממויים של ה-Play Store (חנות האפליקציות של גוגל).
+
+ - טורקיז/כתום
+ - כחול/כתום
+ - סגול/אדום
+ - עַנבָּר/כחול
+ - כתום/אפור
+ - ירוק
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-ja-rJP/strings.xml b/NetGuard/app/src/main/res/values-ja-rJP/strings.xml
new file mode 100644
index 0000000..a883758
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-ja-rJP/strings.xml
@@ -0,0 +1,287 @@
+
+
+ NetGuard は、インターネットへのアクセスをブロックするシンプルで高度な方法を提供します - root 権限は必要ありません。Wi-Fi および/またはモバイル接続へのアクセスを、アプリケーションとアドレスで個別に許可または拒否することができます。
+ NetGuard は Android 5.1 以降が必要です
+ Xposed があまりにクラッシュを引き起こしすぎるため、NetGuard が Google Play ストアから削除される可能性があります。したがって Xposed がインストールされていると、NetGuard はサポートされていません
+ プライバシーポリシー
+ NetGuard の開発およびテストには細心の注意を払いましたが、NetGuard がすべてのデバイスで正常に動作することを保証することはできません。
+ 同意する
+ 同意しない
+ NetGuard にはあなたの支援が必要です。プロジェクトを維持するため、タップしてプロ版を購入してください。
+ 実行中のサービス
+ 全般通知
+ アクセス通知
+ アプリを検索
+ アプリをフィルター
+ ユーザーアプリを表示
+ システムアプリを表示
+ インターネットを使用しないアプリを表示
+ 無効になっているアプリを表示
+ アプリの並び替え
+ 名前で並べ替え
+ UID で並べ替え
+ データ使用状況で並べ替え
+ ログを表示
+ 設定
+ 招待
+ 凡例
+ 支援
+ アプリについて
+ 他のアプリ
+ その他
+ 許可
+ ブロック
+ 自動更新
+ 更新
+ ホスト名で表示
+ 組織を表示
+ PCAP を有効
+ PCAP をエクスポート
+ 消去
+ エクスポート
+ リセット
+ 追加
+ 削除
+ クリーンアップ
+ プロトコル
+ 送信元ポート
+ 宛先アドレス
+ 宛先ポート
+ 送信先アプリ
+ 外部サーバーは \'nobody\' を選択してください
+ デフォルト
+ 既定で Wi-Fi をブロック
+ 既定でモバイルをブロック
+ 既定で画面点灯中 Wi-Fi を許可
+ 既定で画面点灯中モバイルを許可
+ 既定でローミングをブロック
+ オプション
+ テーマ: %1$s
+ ダークテーマを使用
+ アプリインストール時に通知
+ ‘“画面が点灯中” ルール’ を使用
+ %1$s 分後に自動的に有効にする
+ %1$s 分、画面消灯を遅延
+ アップデートの確認
+ ネットワークオプション
+ サブネットのルーティング
+ テザリングを許可
+ LAN アクセスを許可
+ IPv6 トラフィックを有効にする
+ Wi-Fi ホームネットワーク: %1$s
+ 従量制の Wi-Fi ネットワークを扱う
+ 定額制 2G を考慮する
+ 定額制 3G を考慮する
+ 定額制 LTE を考慮する
+ 国内ローミングを無視する
+ EU のローミングを無視
+ 呼び出し中は無効
+ Wi-Fi を封鎖対象にする
+ モバイルを封鎖対象にする
+ 接続が変更されるたびに再読み込み
+ 高度なオプション
+ システムアプリの管理
+ インターネットアクセスをログ
+ インターネットアクセス時に通知
+ トラフィックをフィルター
+ Netguard
+ 再読み込み時にシームレスVPNハンドオーバー
+ 再読み込み時に接続を閉じる
+ トラフィックを封鎖
+ ネットワークの使用状況を追跡
+ ネットワークの使用状況をリセット
+ 解決済みのドメイン名を表示
+ ドメイン名をブロック
+ DNS 応答コード: %s
+ ポート転送
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ 検証: %s
+ 最小 DNS TTL: %s 秒
+ SOCKS5 プロキシを使用
+ SOCKS5 アドレス: %s
+ SOCKS5 ポート: %s
+ SOCKS5 ユーザー名: %s
+ SOCKS5 パスワード: %s
+ PCAP レコードサイズ: %s B
+ PCAP 最大ファイルサイズ: %s MB
+ 監視タイマー: %s 分毎
+ 速度通知
+ 通信速度を通知で表示
+ 上位アプリを表示
+ サンプリング間隔: %s ミリ秒
+ サンプル数: %s s
+ バックアップ
+ 設定をエクスポート
+ 設定をインポート
+ hosts ファイルをインポート
+ hosts ファイルのインポート (追加)
+ hosts ファイルのダウンロード URL
+ hosts ファイルをダウンロード
+ 技術情報
+ 概要
+ ネットワーク
+ サブスクリプション
+ ステータスバーに通知を表示して、新しくインストールしたアプリの設定を直接行えます (プロ版の機能)
+ ウィジェットで NetGuard を無効にした後、指定時間(分)経過で自動的に有効にもどします\nこのオプションを無効にするには 0 を入力してください
+ 画面消灯後も、「画面が点灯中」ルールを指定時間(分)の間有効にします\nこのオプションを無効にするには 0 を入力してください
+ 新しいリリースを Github で毎日 2 回確認します
+ Android のバージョンによって、テザリングが動作する、または動作しない可能性があります。テザリングされたトラフィックはフィルターできません。
+ サブネットのルーティングを有効にします; Wi-Fi の通話を有効にすることができるかもしれませんが Android のバグを誘発したり、バッテリー使用量が増加する可能性があります。
+ 10.0.0.0/8、172.16.0.0/12、192.168.0.0/16 のような、ローカル エリア ネットワークのアドレスに接続するアプリケーションを許可します
+ NetGuard に IP バージョン 6 トラフィックをルーティングして、許可かブロックを選択することができます。
+ 選択したネットワークにのみ Wi-Fi ネットワークのルールを適用します (他の Wi-Fi ネットワークにはモバイルネットワークのルールを適用します)
+ 従量制 (有料、テザリング) Wi-Fi ネットワークにモバイル ネットワーク ルールを適用します
+ 2G データ接続の Wi-Fi ネットワーク ルールを適用します
+ 3G データ接続の Wi-Fi ネットワーク ルールを適用します
+ LTE データ接続の Wi-Fi ネットワーク ルールを適用します
+ SIM およびモバイル ネットワークの国が同じときは、ローミングのルールを適用しません
+ SIM およびモバイル ネットワークが EU 内の国ではローミングルールを適用しない (自国同様)
+ 電話の着信または発信時に NetGuard を無効にします。これは、IP/Wi-Fi の呼び出しの問題を回避するためにも使用できます。
+ システムアプリのルールを定義 (上級者向け)
+ アプリのインターネットへのアクセスをログ記録します。バッテリー使用量が増えることがあります。
+ アプリが初のインターネットアドレスにアクセスしようとするとき、ステータスバーに通知を表示します (フィルターが無効なときは、ブロックしたインターネットアクセスの試行のみ通知されます)
+ VPN トンネルを出る IP パケットをフィルターします。バッテリー使用量が増えることがあります。
+ 各アプリとアドレスごとの送受信バイト数を追跡します。バッテリー使用量が増えることがあります。
+ ブロックしたドメイン名に対して、設定した DNS 応答コードで応答します。hosts ファイルが使用できない場合、このスイッチは無効です。
+ デフォルト値は 3 (NXDOMAIN) です。\'ドメインが存在しない\' の意味です。
+ ポート 443 (https) でインターネット接続の検証に使用するドメイン名。
+ プロキシサーバーには TCP トラフィックのみが送信されます
+ NetGuard が実行されているかどうかを定期的にチェックします (0 を入力すると、このオプションを無効にします)。余分にバッテリーを使用することがあります。
+ 通知領域にネットワーク速度のグラフを表示します
+ よろしいですか?
+ ルールを執行します
+ 許可 %1$d、ブロック %2$d
+ 許可 %1$d、ブロック %2$d、ホスト %3$d
+ イベントの待機中
+ NetGuard は無効です。有効にするには上のスイッチを使用してください
+ NetGuard が無効にされました。別の VPN ベースのアプリケーションを使用した可能性があります
+ \'%1$s\' がインストールされました
+ インストールされています
+ %1$s がインターネット アクセスを試みました。
+ インターネットアクセスを試みました
+ 操作を完了しました
+ NetGuard は、ローカル VPN を使用してインターネット トラフィックをフィルターします。このため、次のダイアログ ボックスで VPN 接続を許可してください。インター ネット トラフィックはリモート VPN サーバーには送信されません。
+ お使いの Android のバージョンのバグのため、起動時に自動的に NetGuard を開始できませんでした
+ 予期しないエラーが発生しました: \'%s\'
+ 現時点では Android が VPN サービスを開始することを拒否しました。これはお使いの Android バージョンでのバグの可能性があります。
+ NetGuard を試してください
+ 寄付によって 利用規約 に同意します
+ 次のダイアログボックスで OK を押すことができない場合、別の (画面調光) アプリが画面を操作している可能性があります。
+ ± %1$.3f▲ %2$.3f▼ MB/日
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ 一貫性のある結果のため、NetGuard は Android のバッテリー最適化を無効にする必要があります。\n\nIn 次のダイアログで、上部の「すべてのアプリ」を選択し、リストで NetGuard をタップし、「最適化しない」を選択および確認してください。
+ 一貫性のある結果を得るために、NetGuard は Android のデータの保存オプションを無効にする必要があります\n\n次のダイアログで、オプション「バック グラウンド データ」と「無制限のデータ使用」を有効にしてください。
+ フィルターを使用すると、Android はデータと電力を、元のアプリではなく、NetGuard が使用しているものとみなします。
+ Android 4 は、フィルターを有効にする必要があります
+ トラフィックのログ記録は無効です。有効にするには上のスイッチを使用してください。トラフィックのログ記録は、余分にバッテリーを使用することがあります。
+ ルールと条件がデフォルト値にリセットされます
+ アクセス試行ログ中、許可/ブロックのルールがない行を削除します。
+ 最終インポート: %s
+ ダウンロード中\n%1s
+ Hosts ファイルをダウンロードしました
+ 最終ダウンロード: %s
+ %1$s ポート %2$d から \'%5$s\' の %3$s:%4$d に転送を開始しますか?
+ %1$s ポート %2$d の転送を停止しますか?
+ ネットワークは従量制です
+ アクティブなインターネット接続がありません
+ NetGuard はビジーです
+ アップデートが利用できます。タップするとダウンロードします
+ アプリの横にあるアイコンをタップして、Wi-Fi またはモバイルインターネットアクセスを、許可 (緑) または拒否 (赤) することができます
+ プライバシーを保護するために NetGuard をインストールした場合、オープンソースのプライバシーフレンドリーなメールアプリ FairEmail にもご興味ありませんか
+ デフォルトで、インターネットアクセスが許可されます。これは設定で変更することができます
+ プッシュメッセージは、システムコンポーネントの Play サービス (デフォルトでインターネットアクセスが許可されています) によって主に処理されます。
+ システムアプリの管理は、設定内で有効にできます
+ 問題と、問題のあった時刻を記述してください:
+ VPN 接続がキャンセルされました\n別の VPN を、常時使用 VPN として設定しましたか?
+ NetGuard を有効にしてデバイスの電源を切ると、デバイスの電源投入時に NetGuard が自動的に開始されます
+ この機能はこのAndroidのバージョンでは利用できません。
+ 別の VPN が、常時オン VPN として設定されます
+ フィルタリングモードで NetGuard を使用するには、Android VPN 設定で \"VPN でない接続をブロック\" をオフにしてください
+ フィルタ リングモードで NetGuard を使用するには Android のネットワーク設定で \"プライベート DNS\" をオフにしてください
+ トラフィックを封鎖
+ 定額制のトラフィックを許可
+ 定額制のトラフィックをブロック
+ 定額制ルールは適用されません
+ 従量制のトラフィックを許可
+ 従量制のトラフィックをブロック
+ 従量制は適用されません
+ アドレスを許可
+ アドレスをブロック
+ 画面が点灯中は許可
+ ローミング時にブロック
+ デフォルトで Wi-Fi 接続は定額制、モバイル接続は従量制と見なされます
+ インターネット アクセス許可がありません
+ 無効
+ このアプリをブロックしても、受信メッセージはこのアプリではなく Google Play サービスによって受信されるため、ブロックできません
+ このアプリではなくダウンロードマネージャーによってダウンロードが実行されるため、このアプリをブロックしてもダウンロードはブロックできません
+ ルールと条件を適用
+ 条件
+ 画面が点灯中は Wi-Fi 通信を許可
+ 画面が点灯中はモバイル通信を許可
+ R
+ ローミング時にブロック
+ 封鎖中でも通信を許可
+ フィルター関連
+ アクセス試行
+ アクセスルールは他のルールよりも優先します
+ オプション
+ インターネットアクセスの試みを通知
+ ログまたはフィルターが有効になっていません
+ ログとフィルターが有効です
+ 設定
+ ログを有効にする (ブロックされたアドレスのみ)
+ フィルターを有効にし、許可されたアドレスもログ記録する
+ 新しくログを記録したアドレスのアクセス通知を有効にする
+ これらの設定はすべてのアプリケーションに適用されるグローバル設定です
+ 個々のアドレスを許可またはブロックするためにフィルターも必要です
+ ログやフィルターを有効にすると、バッテリーの使用量が増えたり、ネットワーク速度に影響を与える可能性があります(ログ:少なめ、フィルター:多め)
+ 評価
+ 許可
+ ブロック
+ Wi-Fi 通信を許可
+ Wi-Fi 通信をブロック
+ モバイル通信を許可
+ モバイル通信をブロック
+ ルート
+ メディアサーバー
+ nobody
+ 次回から表示しない
+ Whois %1$s
+ ポート %1$d
+ コピー
+ プロ版の機能
+ 次のプロ版の機能が利用可能です:
+ ブロックされたトラフィックのログを表示
+ ネットワーク トラフィックのフィルター
+ 新しいアプリの通知
+ ネットワーク速度グラフ通知
+ 外観 (テーマ、色)
+ 上記すべてのプロ版の機能
+ 開発を支援する
+ 購入する
+ 有効
+ 利用不可
+ 詳細情報はタイトルをタップします
+ チャレンジ
+ 応答
+ これはプロ版の機能です
+ 1 または 2 ユーロ (地方税を除く) の月額サブスクリプションで、すべてのプロ版の機能を有効にします。
+Play ストアアプリの定期購入タブから、定期購入をキャンセルまたは管理できます。
+
+ - ティール/オレンジ
+ - ブルー/オレンジ
+ - パープル/レッド
+ - アンバー/ブルー
+ - オレンジ/グレー
+ - グリーン
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-ka-rGE/strings.xml b/NetGuard/app/src/main/res/values-ka-rGE/strings.xml
new file mode 100644
index 0000000..3ea04e7
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-ka-rGE/strings.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/NetGuard/app/src/main/res/values-ko-rKR/strings.xml b/NetGuard/app/src/main/res/values-ko-rKR/strings.xml
new file mode 100644
index 0000000..ded7efa
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-ko-rKR/strings.xml
@@ -0,0 +1,292 @@
+
+
+ NetGuard는 루트 없이 인터넷 접근을 막는 간단하면서도 발전된 방법을 제공합니다. 각각의 앱이나 주소가 Wi-Fi나 모바일 데이터에 접근하는 것을 허용할 지, 거부할 지 설정할 수 있습니다.
+ NetGuard 는 안드로이드 버전 5.1 이상에서 작동합니다
+ Xposed와 너무 많은 충돌을 일으켜서 NetGuard가 Google Play 스토어에서 내려갈 수 있기 때문에, Xposed가 설치되어 있는 동안에는 NetGuard를 사용할 수 없습니다
+ 개인정보 보호 정책
+ NetGuard의 제작과 테스트에 많은 시간을 쏟았지만, 모든 기기에서 완벽하게 돌아가는 걸 장담할 수는 없습니다.
+ 동의합니다
+ 동의하지 않습니다
+ NetGuard는 당신의 도움이 필요합니다. PRO 기능을 구매하여 프로젝트가 지속될 수 있게 해 주세요.
+ 실행 중인 서비스
+ 일반 알림
+ 알림 접근
+ 앱 검색
+ 앱 필터
+ 사용자 앱 표시
+ 시스템 앱 표시
+ 인터넷 미사용 앱 표시
+ 비활성화된 앱 표시
+ 앱 정렬
+ 이름순
+ UID순
+ 데이터 사용량 순
+ 로그 표시
+ 설정
+ 초대
+ 개요
+ 지원
+ 넷가드 정보
+ 다른 앱
+ 기타
+ 허용됨
+ 차단됨
+ 실시간 업데이트
+ 새로고침
+ 이름 표시
+ 조직 표시
+ PCAP 활성화됨
+ PCAP 내보내기
+ 비우기
+ 내보내기
+ 초기화
+ 추가
+ 제거
+ 비우기
+ 프로토콜
+ 소스 포트
+ 목적 주소
+ 목적 포트
+ 목적 앱
+ 외부 서버의 경우 \'미지정\'을 선택하십시오
+ 기본값 (차단/허용 목록)
+ Wi-Fi 차단을 기본 설정으로
+ 모바일 데이터 차단을 기본 설정으로
+ 화면이 켜져 있을 때 Wi-Fi 허용
+ 화면이 켜져 있을 때 모바일 데이터 허용
+ 로밍 차단
+ 설정
+ 테마: %1$s
+ 어두운 테마 사용
+ 새 앱을 설치할 때 알림
+ \'화면이 켜져 있을 때\' 규칙 적용
+ %1$s분 후 자동 활성화
+ %1$s분 간 화면 꺼짐 지연
+ 업데이트 확인
+ 네트워크 옵션
+ 서브넷 라우팅
+ 테터링 허용
+ LAN 접근 허용
+ IPv6 트래픽 사용
+ Wi-Fi 홈 네트워크: %1$s
+ 과금 Wi-Fi 네트워크 제어
+ 비과금 2G 고려
+ 비과금 3G 고려
+ 비과금 LTE 고려
+ 국제 로밍 무시
+ EU 로밍 무시
+ 통화 중 비활성화
+ Wi-Fi 차단
+ 모바일 데이터 차단
+ 연결 변경 시마다 다시 불러오기
+ 고급 설정
+ 시스템 앱 설정
+ 인터넷 접속 로그
+ 인터넷 접속 시 알림
+ 트래픽 필터
+ UDP 트래픽 필터
+ 재시작 시 끊김 없이 VPN 전환
+ 다시 불러올 때 연결 종료
+ 트래픽 차단
+ 네트워크 사용량 추적
+ 네트워크 사용량 초기화
+ 확인된 도메인 이름 표시
+ 도메인 이름 차단
+ DNS 응답 코드: %s
+ 포트 포워딩
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ 검증 주소: %s
+ 최소 DNS TTL: %s초
+ SOCKS5 프록시 사용
+ SOCKS5 주소: %s
+ SOCKS5 포트: %s
+ SOCKS5 사용자명: %s
+ SOCKS5 비밀번호: %s
+ PCAP 기록 크기: %sB
+ PCAP 최대. 파일 크기: %sMB
+ 워치독: %s분마다
+ 속도 알림
+ 속도 알림 표시
+ 상위 앱 표시
+ 샘플 간격: %sms
+ 샘플 수: %s s
+ 백업
+ 설정 내보내기
+ 설정 가져오기
+ Hosts 파일 가져오기
+ 호스트 파일 가져오기 (추가)
+ Hosts 파일 다운로드 URL
+ Hosts 파일 다운로드
+ 기술적 정보
+ 일반
+ 네트워크
+ 구독
+ 새로 설치된 앱을 곧바로 설정하기 위해 상태 표시줄 알림 표시 (PRO 기능)
+ 위젯 아용을 비활성화한 후, 설정한 시간(분) 후에 NetGuard를 자동으로 다시 활성화합니다(설정을 끄려면 0을 입력하세요).
+ 화면을 끈 후, 선택한 시간(분) 동안 화면이 켜졌을 때의 규칙을 유지합니다(이 설정을 끄려면 0을 입력).
+ 하루에 두 번 GitHub에 새 릴리즈가 있는지 확인합니다
+ 안드로이드 버전에 따라 테더링이 작동하거나 작동하지 않을 수 있습니다. 테더링 트래픽은 필터링할 수 없습니다.
+ 서브넷 라우팅을 활성화합니다. Wi-Fi 통화가 가능하게 될 수도 있지만, Android 내에서 버그가 발생하고 배터리 사용량이 증가할 수 있습니다.
+ 앱이 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16과 같은 근거리 통신망에 연결할 수 있도록 허용합니다.
+ IPv6을 NetGuard로 라우팅하여 선택적으로 허용 및 차단할 수 있도록 합니다.
+ 선택한 네트워크에만 Wi-Fi 네트워크 규칙 적용 (다른 Wi-Fi 네트워크에 대해서는 모바일 네트워크 규칙 적용)
+ 과금(요금 발생, 테더링) Wi-Fi 네트워크에 모바일 네트워크 규칙 적용
+ 2G 데이터 연결에 Wi-Fi 네트워크 규칙 적용
+ 3G 데이터 연결에 Wi-Fi 네트워크 규칙 적용
+ LTE 데이터 연결에 Wi-Fi 네트워크 규칙 적용
+ SIM과 모바일 네트워크의 국가가 같은 경우 로밍 규칙을 적용하지 않음
+ SIM과 모바일 네트워크의 국가가 EU 소속인 경우 로밍 규칙을 적용하지 않음 (roam like at home)
+ 전화를 수발신할 때 NetGuard를 비활성화합니다. IP/Wi-Fi 전화 이용 시 발생하는 문제를 해결할 때 사용할 수 있습니다.
+ 시스템 앱에 대한 규칙 정의 (숙련자용)
+ 앱의 인터넷 접속 시도를 기록합니다. 배터리 사용량이 증가할 수 있습니다.
+ 앱이 새 인터넷 주소로 접근하려 할 때 상태 표시줄에 알림을 표시합니다 (필터링이 비활성화된 경우, 차단된 인터넷 접근 시도만 알림)
+ VPN 터널로 나가는 IP 패킷을 필터링합니다. 배터리 사용량이 증가할 수 있습니다.
+ 각 앱 및 주소에서 송수신한 바이트 수를 추적합니다. 배터리 사용량이 증가할 수 있습니다.
+ 차단된 도메인 이름에 대하여 \'구성됨\' DNS 응답 코드로 응답합니다. 호스트 파일을 사용할 수 없는 경우 비활성화됩니다.
+ 기본값은 3(NXDOMAIN)입니다. 이는 \'존재하지 않는 도메인\'이라는 뜻입니다.
+ 포트 443(HTTPS)을 통한 인터넷 연결을 인증하는 데 쓰이는 도메인 이름입니다.
+ TCP 트래픽만이 프록시 서버로 전송될 것입니다
+ NetGuard가 계속 작동하고 있는지 주기적으로 확인합니다. (이 설정을 비활성화하려면 0 입력) 배터리 사용량이 증가할 수 있습니다.
+ 상태 표시줄 알림에 네트워크 속도 그래프를 표시합니다
+ 계속 하시겠습니까?
+ 규칙 적용 중
+ %1$d건 허용됨, %2$d건 차단됨
+ %1$d건 허용됨, %2$d건 차단됨, 호스트 %3$d개
+ 이벤트를 기다리는 중
+ 넷가드가 해제되어 있습니다. 상단 스위치를 사용해 넷가드를 활성화하세요.
+ 다른 VPN 기반 앱이 사용 중이라 NetGuard가 꺼졌습니다
+ \'%1$s\' 설치됨
+ 설치되었습니다
+ %1$s 앱이 인터넷 접속 시도함
+ 인터넷 접속 시도됨
+ 작업 완료
+ NetGuard는 인터넷 트래픽을 필터링하기 위해 로컬 VPN을 이용합니다.
+이에 따라, 다음 창에서 VPN 연결을 허용해주시기 바랍니다.
+당신의 인터넷 트래픽은 원격 VPN 서버로 전송되지 않습니다.
+ NetGuard가 자동으로 시작하는 데 실패했습니다. 사용 중인 Android 버전의 버그로 추정됩니다.
+ 예기치 못한 오류가 발생했습니다: \'%s\'
+ 현재 Android에서 VPN 서비스 시작을 거부했습니다. 해당 Android 버전의 오류로 추정됩니다.
+ NetGuard를 이용해보세요
+ 후원하면 이용 약관 에 동의하게 됩니다
+ 다음 창에서 확인 버튼을 누를 수 없는 경우, 다른(화면 감광 등의) 앱이 화면을 제어하고 있을 가능성이 높습니다.
+ ± %1$.3f▲ %2$.3f▼ MB/일
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %d회
+ NetGuard가 안정적으로 동작하려면 안드로이드 배터리 최적화 설정이 꺼져 있어야 합니다.
+\n\n다음 창에서, 상단의 \"모든 앱\"을 누른 다음, 목록에서 NetGuard를 찾아 누른 다음 제외하십시오.
+ NetGuard가 안정적으로 동작하려면 안드로이드 데이터 절약 설정이 꺼져 있어야 합니다.
+\n\n다음 창에서, \"백그라운드 데이터 사용\" 및 \"무제한 데이터 사용\" 설정을 켜십시오.
+ 필터링을 사용하면 Android에서는 데이터나 배터리를 NetGuard에서 사용하는 것으로 인식할 수 있습니다. 즉 Android는 데이터와 배터리의 사용이 본래 앱이 아닌 NetGuard에서 발생한다고 가정하는 것입니다.
+ 안드로이드 4에서는 필터링을 활성화해야 합니다
+ 트래픽 기록이 꺼졌습니다. 기록을 시작하려면 위 스위치를 누르세요. 트래픽 기록 시 배터리 사용량이 증가할 수 있습니다.
+ 규칙과 조건이 기본값으로 초기화됩니다
+ 허용/차단 규칙이 적용되지 않은 상태에서 접근을 시도한 내역이 삭제됩니다
+ 마지막 파일 추출: %s
+ \n%1s 다운로드 중
+ 호스트 파일 다운로드 됨
+ 마지막 다운로드: %s
+ %1$s 포트 %2$d에서 \'%5$s\'의 %3$s:%4$d로 포워딩을 시작하시겠습니까?
+ %1$s 포트 %2$d의 포워딩을 중단하시겠습니까?
+ 과금 네트워크입니다
+ 인터넷에 연결할 수 없습니다
+ NetGuard가 사용 중입니다
+ 업데이트 이용 가능, 눌러서 다운로드하세요
+ 앱 옆에 있는 아이콘을 눌러 Wi-Fi 또는 모바일 인터넷 접속을 허용(초록) 또는 거부(빨강)할 수 있습니다.
+ 개인정보를 보호하기 위하여 NetGuard를 설치하셨다면, 개인정보 보호를 중시하는 오픈소스 메일 앱인 FairEmail 에도 흥미를 가지실 것 같습니다
+ 인터넷 접근은 기본적으로 허용됩니다(차단 목록 모드). 설정에서 이를 변경할 수 있습니다.
+ 대부분의 수신되는 (푸시) 메시지는 기본적으로 인터넷 접근이 허용되는 Play 서비스 시스템 구성 요소에 의해 처리됩니다.
+ 모든 (시스템) 앱 관리는 설정에서 켤 수 있습니다.
+ 문제와 문제 발생 시점에 대해 설명해주십시오:
+ VPN 연결 취소됨\n다른 VPN을 연결 유지 VPN으로 설정하셨습니까?
+ NetGuard가 켜진 채로 기기의 전원을 끄면, 기기를 켰을 때 NetGuard도 자동으로 실행됩니다
+ 이 안드로이드 버전에서는 지원하지 않는 기능입니다.
+ 다른 VPN이 항상 켜져 있는 VPN으로 설정되어 있습니다
+ 필터링 모드로 NetGuard를 사용하려면 안드로이드 VPN 설정에서 \"VPN 제외 연결 차단\" 설정을 끄십시오
+ 필터링 모드로 NetGuard를 사용하려면 안드로이드 네트워크 설정에서 \"사설 DNS\" 설정을 끄십시오
+ 트래픽이 차단되었습니다
+ 비과금 트래픽 허용됨
+ 비과금 트래픽 차단됨
+ 비과금 규칙이 적용되지 않음
+ 과금 트래픽 허용됨
+ 과금 트래픽 차단됨
+ 과금 규칙이 적용되지 않음
+ 주소가 허용되었습니다
+ 주소가 차단되었습니다
+ 화면이 켜져있을 때 허용
+ 로밍시 차단
+ 일반적으로 Wi-Fi 연결은 비과금, 모바일 데이터 연결은 과금으로 취급합니다
+ 인터넷을 사용할 수 없습니다
+ 꺼짐
+ 메시지는 이 앱이 아닌 Google Play 서비스로부터 받는 것이므로 이 앱의 메시지를 차단한다고 메시지가 차단되지 않습니다
+ 다운로드는 이 앱이 아닌 다운로드 관리자에 의해 수행되므로 이 앱을 차단하여 다운로드를 차단할 수는 없음
+ 규칙 및 조건 적용
+ 조건
+ 화면이 켜져 있을 때 Wi-Fi 허용
+ 화면이 켜져 있을 때 모바일 데이터 허용
+ R
+ 로밍시 차단
+ 차단 모드에서 허용
+ 관련 항목도 필터링
+ 접근 시도
+ 접근 관련 규칙이 다른 규칙보다 우선 적용됨
+ 설정
+ 인터넷 접속 시도 알림
+ 로깅이나 필터링 꺼짐
+ 로깅 및 필터링 켜짐
+ 환경설정
+ 차단된 주소의 로깅만 활성화
+ 허용된 주소도 기록하도록 필터링 활성화
+ 새로 기록된 주소에 대하여 접근 알림 활성화
+ 이 설정은 모든 앱에 적용되는 전역 설정입니다
+ 주소를 개별적으로 허용하거나 차단하려면 필터링도 필요
+ 로그(영향 적음)나 필터링(영향 큼)을 사용하면 배터리 사용량이 증가하고 네트워크 속도에 영향을 끼칠 수 있습니다
+ 평가
+ 허용
+ 차단
+ Wi-Fi 허용
+ Wi-Fi 차단
+ 모바일 데이터 허용
+ 모바일 데이터 차단
+ 루트
+ 미디어 서버
+ 미지정
+ 다시 보지 않기
+ Whois %1$s
+ 포트 %1$d
+ 복사
+ PRO 기능
+ 아래의 PRO 기능들을 이용할 수 있습니다:
+ 차단된 트래픽 내역 보기
+ 네트워크 트래픽 필터
+ 새 앱 알림
+ 네트워크 속도 그래프 알림
+ 표시 (테마, 색상)
+ PRO 버전의 모든 기능
+ 개발 지원
+ 구입
+ 활성화
+ 이용 불가
+ 제목을 눌러 자세한 정보를 확인하세요
+ 도전
+ 응답
+ PRO 기능입니다
+ 월간 구독료 1, 2유로만 지불하여도(지역 세금 제외) 모든 PRO 기능을 이용할 수 있습니다.
+ Play 스토어 앱의 구독 탭에서 구독을 취소하거나 관리할 수 있습니다.
+
+
+ - 암청/주황
+ - 파랑/주황
+ - 보라/빨강
+ - 황토/파랑
+ - 주황/회색
+ - 초록
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-lt-rLT/strings.xml b/NetGuard/app/src/main/res/values-lt-rLT/strings.xml
new file mode 100644
index 0000000..bc34265
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-lt-rLT/strings.xml
@@ -0,0 +1,290 @@
+
+
+ NetGuard užtikrina lengvą ir pažengusį metodus apribojant prieigą prie interneto, nereikalaujančius root teisių. Atskiros programos ir adresai gali būti leidžiami ar blokuojami pasiekti Wi-Fi ir/ar mobiliuosius duomenis.
+ NetGuard veiks su Android 5.1 arba naujesne versija
+ Xposed modulis kelia per daug strigčių, todėl NetGuard gali būti pašalinta iš Google Play parduotuvės. Kol yra įdiegta Xposed modulis, NetGuard nebus palaikoma
+ Privatumo politika
+ NetGuard kūrimui ir bandymams buvo įdėta daug pastangų, vis dėlto neįmanoma užtikrinti, jog NetGuard tinkamai veiks visuose įrenginiuose.
+ Sutinku
+ Nesutinku
+ NetGuard reikia Jūsų pagalbos. Bakstelėkite PRO funkcijų įsigyjimui ir projekto vystymosi palaikymui.
+ Veikiančios paslaugos
+ Bendri pranešimai
+ Prieigos pranešimai
+ Ieškoti programos
+ Programų filtras
+ Rodyti naudotojo programas
+ Rodyti sistemines programas
+ Rodyti programas be interneto
+ Rodyti išjungtas programas
+ Rikiuoti programas
+ Rikiuoti pagal pavadinimą
+ Rikiuoti pagal UID kodą
+ Rikiuoti pagal duomenų naudojimą
+ Rodyti žurnalą
+ Nustatymai
+ Pakviesti
+ Legenda
+ Pagalba
+ Apie
+ Kitos programos
+ Kita
+ Leidžiama
+ Užblokuota
+ Tiesioginiai naujinimai
+ Atnaujinti
+ Rodyti pavadinimus
+ Rodyti organizaciją
+ PCAP režimas įjungtas
+ PCAP kopija
+ Valyti
+ Sukurti kopiją
+ Atstatyti
+ Pridėti
+ Ištrinti
+ Atstatyti
+ Protokolas
+ Šaltinio prievadas
+ Paskirties adresas
+ Paskirties prievadas
+ Paskirties programa
+ Išoriniui serveriui pasirinkite „Nieko“
+ Numatytieji (baltasis/juodasis sąrašas)
+ Blokuoti Wi-Fi
+ Blokuoti mobiliuosius duomenis
+ Leisti Wi-Fi esant aktyviam ekranui
+ Leisti mobiliuosius duomenis esant aktyviam ekranui
+ Blokuoti tarptinklinį ryšį
+ Nustatymai
+ Tema: %1$s
+ Naudoti tamsią temą
+ Pranešti naujo įdiegimo metu
+ Taikyti „aktyvaus ekrano“ taisykles
+ Automatiškai įjungti po %1$s min.
+ Uždelsti ekrano užrakinimą %1$s minučių
+ Naujinių tikrinimas
+ Tinklo nustatymai
+ Potinklio nukreipimas
+ Leisti pririšimą
+ Leisti LAN tinklo prieigą
+ Įjungti IPv6 duomenų srautą
+ Wi-Fi namų tinklai: %1$s
+ Tvarkyti stebimus Wi-Fi tinklus
+ Nestebėti 2G ryšio
+ Nestebėti 3G ryšio
+ Nestebėti LTE ryšio
+ Ignoruoti nacionalinį tarptinklinį ryšį
+ Ignoruoti Europos tarptinklinį ryšį
+ Išjungti skambinant
+ Drausti Wi-Fi
+ Drausti mobiliuosius duomenis
+ Atnaujinti kievienos jungiamumo kaitos metu
+ Išplėstiniai nustatymai
+ Tvarkyti sistemines programas
+ Stebėti interneto prieigos užklausas
+ Pranešti apie interneto prieigos užklausas
+ Filtruoti duomenų srautą
+ Filtruoti UDP duomenų srautą
+ Sklandus VPN ryšio perdavimas atnaujinimo metu
+ Atnaujinant uždaryti prisijungimus
+ Drausti duomenų srautą
+ Sekti tinklo naudojimą
+ Atstatyti tinklo naudojimą
+ Rodyti išspręstus domenų vardus
+ Blokuoti domenų vardus
+ DNS atsakymo kodas: %s
+ Prievado nukreipimas
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Galioja iki: %s
+ Mažiausia DNS TTL reikšmė: %s s
+ Naudoti SOCKS5 tarpinį serverį
+ SOCKS5 adresas: %s
+ SOCKS5 prievadas: %s
+ SOCKS5 naudotojo vardas: %s
+ SOCKS5 slaptažodis: %s
+ PCAP įrašo dydis: %s B
+ PACP didžiausias failo dydis: %s MB
+ Budėtojas: kas %s minučių
+ Tinklo greičio pranešimas
+ Rodyti tinklo greičio pranešimą
+ Rodyti dažniausias programas
+ Bandinio intervalas: %s ms
+ Bandinių skaičius: %s s
+ Atsarginė kopija
+ Nustatymų kopija
+ Įkelti nustatymus
+ Įkelti blokuojamų adresų failą
+ Įkelti blokuojamų adresų failą (papildyti)
+ Blokuojamų adresų failo atsisiuntimo URL
+ Atsisiųsti blokuojamų adresų failą
+ Techninė informacija
+ Bendra
+ Tinklai
+ Prenumeratos
+ Rodyti būsenos juostos pranešimą tiesioginiam naujai įdiegtų programų nustatymui (PRO funkcija)
+ Išjungus valdiklį automatiškai paleisti NetGuard po nustatyto minučių skaičiaus (nustatymo išjungimui įveskite nulį)
+ Užrakinant ekraną išsaugoti aktyvaus ekrano taisykles nustatytą minučių skaičių (nustatymo išjungimui įveskite nulį)
+ Du kartus per dieną tikrinti galimus naujinius GitHub platformoje
+ Ribojimo veikimas priklauso nuo Android versijos. Ribojamas duomenų srautas negali būti filtruojamas.
+ Leisti potinklio nukreipimą; gali leisti Wi-Fi skambinimo funkciją, bet taip pat gali sukelti klaidų Android sistemoje ir padidinti baterijos energijos eikvojimą
+ Leisti programoms jungtis prie vietinio tinklo adresų, tokių kaip 10.0.0.0/8, 172.16.0.0/12 ir 192.168.0.0/16
+ IP 6 versijos duomenų srautą nukreipiamas į NetGuard, kad galėtų būti leidžiamas arba blokuojamas
+ Taikyti Wi-Fi taisykles tik pasirinktam tinklui (taikyti mobiliųjų duomenų tinklo taisykles kitiems Wi-Fi tinklams)
+ Taikyti mobiliųjų duomenų taisykles stebimiems (mokamiems, apribotiems) Wi-Fi tinklams
+ Taikyti Wi-Fi taisykles 2G duomenų ryšiui
+ Taikyti Wi-Fi taisykles 3G duomenų ryšiui
+ Taikyti Wi-Fi taisykles LTE duomenų ryšiui
+ Netaikyti tarptinklinio ryšio taisyklių jei SIM ir mobiliųjų duomenų šalis yra ta pati
+ Netaikyti tarptinklinio ryšio taisyklių jei SIM ir mobiliųjų duomenų šalis yra Europoje (namų tarptinklinis ryšys)
+ Išjungti NetGuard įeinantiems ar išeinantiems telefono skambučiams. Tai gali būti panaudota apeiti IP/Wi-Fi skambinimo sutrikimus.
+ Apibrėžti taisykles sisteminėms programoms (pažengusiems naudotojams)
+ Stebėti programų bandymus gauti interneto ryšio prieigą. Tai gali lemti didesnį baterijos energijos naudojimą.
+ Rodyti būsenos juostos pranešimą programai bandant gauti prieigą prie naujo interneto adreso (išjungus filtravimą, bus panešama tik apie blokuojamus interneto prieigos bandymus)
+ Filtruoti IP adresų paketus, siunčiamus per VPN tunelį. Tai gali lemti didesnį baterijos energijos naudojimą.
+ Stebėti kiekvienos programos ir adreso siunčiamą ir gaunamą baitų kiekį. Tai gali lemti didesnį baterijos energijos naudojimą.
+ Atsakyti nustatytu DNS atsakymo kodu blokuojamiems domenų vardams. Ši funkcija yra išjungta jei nepasiekiamas blokuojamų adresų sąrašas.
+ Numatytoji reikšmė yra 3 (NXDOMAIN), tai reiškia „neegzistuojantis domenas“.
+ Domeno pavadinimas panaudotas interneto prieigos patvirtinimui ties prievadu 443 (https).
+ Tik TCP duomenų srautas bus siunčiamas į tarpinį serverį
+ Periodiškai tikrinti NetGuard aktyvumo būseną (nustatymo išjungimui įveskite nulį). Tai gali lemti didesnį baterijos energijos naudojimą.
+ Rodyti tinklo greičio grafiko pranešimą būsenos juostoje
+ Ar esate įsitikinę?
+ Paslauga aktyvi
+ %1$d leista, %2$d blokuojama
+ %1$d leista, %2$d užblokuota, %3$d blokuojamų adresų
+ Laukiama įvykio
+ NetGuard išjungta, įjungimui naudokite jungiklį aukščiau
+ NetGuard buvo išjungta, greičiausiai dėl kitos VPN programos
+ „%1$s“ įdiegta
+ Buvo įdiegta
+ %1$s bandė gauti prieigą prie interneto
+ Bandyta gauti prieigą prie interneto
+ Veiksmas užbaigtas
+ Interneto srauto filtravimui NetGuard naudoja vietinį VPN.
+Todėl kitame dialoge prašome leisti VPN ryšį.
+Jūsų interneto duomenų srautas nėra siunčiamas į jokį nuotolinį VPN serverį.
+ NetGuard negalėjo automatiškai pasileisti, greičiausiai dėl klaidos Android versijoje.
+ Įvyko netikėta klaida: „%s“
+ Šiuo metu Android atsisakė paleisti VPN, greičiausiai dėl klaidos Android versijoje.
+ Išbandyk NetGuard
+ Paaukodami sutinkate su nuostatomis & sąlygomis
+ Jei kitame lange negalite spausti „Gerai“, greičiausiai ekraną valdo kita (ekrano pritemdymo) programa.
+ ± %1$.3f▲ %2$.3f▼ MB/dieną
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Nuolatiniam NetGuard veikimui programos optimizavimas baterijos optimizavimo nustatymuose turi būti išjungtas.
+\n\nKito lango viršuje pasirinkite „Visos programos“, sąraše pasirinkite NetGuard bei spustelėkite ir patvirtinkite „Neoptimizuoti“.
+ Nuolatiniam NetGuard veikimui Android mobilliųjų duomenų tausojimas turi būti išjungtas.
+\n\nKitame lange pasirinkite „Foninių duomenų naudojimas“ ir „Neriboti duomenų naudojimo“
+ Filtravimo naudojimas priskirs duomenų ir energijos naudojimą NetGuard programai - Android manys, jog duomenys ir energijos naudojimas keliamas NetGuard programos, o ne tikrųjų juos naudojančių pogramų
+ Android 4 versija reikalauja įjungto filtravimo
+ Duomenų srauto stebėjimas sustabdytas, įjungimui naudokite jungiklį aukščiau. Tai gali lemti didesnį baterijos energijos naudojimą.
+ Tai atstatys taisykles ir sąlygas į jų numatytąsias reikšmes
+ Tai ištrins prieigos bandymų žurnalo įrašus be laidžiamų/blokuojamų taisyklių
+ Paskutinis įkėlimas: %s
+ Atsisiunčiama\n%1s
+ Blokuojamų adresų failas atsisiųstas
+ Paskutinis atsiuntimas: %s
+ Pradėti nukreipimą iš %1$s prievado %2$d į %3$s:%4$d iš „%5$s“?
+ Baigti nukreipimą iš %1$s preivado %2$d?
+ Tinklas stebimas
+ Nėra aktyvaus interneto ryšio
+ NetGuard užimta
+ Yra prieinamas naujinys, bakstelėkite atsisiuntimui
+ Galite leisti (žalia) ar užblokuoti (raudona) Wi-Fi ir mobiliųjų duomenų prieigą spustelėdami piktogramas šalia programos
+ Jei įdiegėte NetGuard norėdami apsaugoti savo privatumą, galbūt sudomins FairEmail , privatumą sauganti atvirojo kodo elektroninio pašto programa
+ Interneto prieiga yra leidžiama automatiškai (juodojo sąrašo režimas), tai gali būti keičiama nustatymuose
+ Įeinantys (momentiniai) pranešimai daugiausiai valdomi sisteminių Play paslaugų, kurioms automatiškai leidžiama interneto ryšio prieiga
+ Visų (sisteminių) programų valdymas gali būti įjungtas nustatymuose
+ Aprašykite sutrikimą ir nurodykite sutrikimo atsiradimo laiką:
+ VPN ryšys atšauktas\nGal kita VPN programa nustatyta būti visada įjungta VPN?
+ Išjungus įrenginį esant aktyviai NetGuard, kitą kartą įjungus įrenginį automatiškai bus paleista NetGuard
+ Ši Android versija nepalaiko šios funkcijos
+ Kita VPN programa nustatyta kaip „Visada įjungtas VPN“
+ Norint naudoti NetGuard filtravimo režimą išjunkite „Blokuoti ryšius be VPN“ Android VPN nustatymuose
+ Norint naudoti NetGuard filtravimo režimą išjunkite „Privatus DNS“ Android tinklo nustatymuose
+ Duomenų srautas yra blokuojamas
+ Nestebimas duomenų srautas yra leidžiamas
+ Nestebimas duomenų srautas yra blokuojamas
+ Nestebimos taisyklės netaikomos
+ Stebimas duomenų srautas yra leidžiamas
+ Stebimas duomenų srautas blokuojamas
+ Stebimos taisyklės netaikomos
+ Adresas leidžiamas
+ Adresas blokuojamas
+ Leisti pažadinant ekraną
+ Blokuoti tarptinklinį ryšį
+ Numatyta Wi-Fi ryšį stebėti ir nestebėti mobiliųjų duomenų ryšio
+ neturi interneto prieigos
+ išjungta
+ Ateinantys pranešimai gaunami dėl Google Play paslaugų ir negali būti išjungti blokuojant šią programą
+ Atsisiuntimai vykdomi atsisiuntimų tvarkyklės ir negali būti blokuojami blokuojant šią programą
+ Taikyti taisykles ir sąlygas
+ Sąlygos
+ Leisti Wi-Fi pažadinant ekraną
+ Leisti mobiliuosius duomenis pažadinant ekraną
+ R
+ Blokuoti tarptinklinį ryšį
+ Leisti draudimo režime
+ Susiję su filtru
+ Prieigos bandymai
+ Veiksmo taisyklės turi pirmumą prieš kitas taisykles
+ Nustatymai
+ Pranešti interneto ryšio prieigos bandymus
+ Stebėjimas ar filtravimas neįjungti
+ Stebėjimas ir filtravimas įjungti
+ Nustatyti
+ Įjungti tik blokuojamų adresų stebėjimą
+ Leisti filtravimą leidžiamų adresų stebėjimui
+ Leisti pranešimų prieigą naujai įrašytiems adresams
+ Tai bendrieji nustatymai, taikomi visoms programoms
+ Filtravimui taip pat reikia leisti ar blokuoti atskirus adresus
+ Stebėjimo (naudojama mažiau baterijos energijos) ar filtravimo (naudoja daugiau baterijos energijos) leidimas gali lemti didesnį baterijos energijos naudojimą ir gali paveikti interneto tinklo greitį
+ Įvertinti
+ Leisti
+ Blokuoti
+ Leisti Wi-Fi
+ Blokuoti Wi-Fi
+ Leisti mobiliuosius duomenis
+ Blokuoti mobiliuosius duomenis
+ šaknis
+ tarpinis serveris
+ niekas
+ Daugiau neklausti
+ Whois %1$s
+ Prievadas %1$d
+ Kopijuoti
+ Pro funkcijos
+ Prieinamos šios PRO funkcijos:
+ Žiūrėti blokuojamo duomenų srauto žurnalą
+ Filtruoti tinklo duomenų srautą
+ Naujos programos pranešimas
+ Interneto tinklo greičio grafiko pranešimas
+ Išvaizda (temos, spalvos)
+ Visos anksčiau minėtos PRO funkcijos
+ Paremti kūrimą
+ Įsigyti
+ Įjungta
+ Neprieinama
+ Bakstelėkite pavadinimą išsamesnei informacijai gauti
+ Iššūkis
+ Atsakas
+ Tai PRO funkcija
+ Mėnesinė 1 ar 2 eurų prenumerata (įskaičiuojant vietinius mokesčius) aktyvins visas pro versijos funkcijas. Prenumeratą galite atšaukti ar valdyti prenumeratų skiltyje „Play“ parduotuvės programoje.
+
+ - žalsvai mėlyna/oranžinė
+ - mėlyna/oranžinė
+ - purpurinė/raudona
+ - gintarinė/mėlyna
+ - oranžinė/pilka
+ - žalia
+
+
+ - UDP duomenys
+ - TCP klientas
+
+
diff --git a/NetGuard/app/src/main/res/values-lv-rLV/strings.xml b/NetGuard/app/src/main/res/values-lv-rLV/strings.xml
new file mode 100644
index 0000000..e8a74ff
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-lv-rLV/strings.xml
@@ -0,0 +1,292 @@
+
+
+ NetGuard nodrošina vienkāršu un uzlabotu veidu, kā bloķēt piekļuvi internetam. Lietotnēm un adresēm var individuāli atļaut vai aizliegt piekļuvi internetam caur Wi-Fi un/vai mobilo datu savienojumu.
+ NetGuard nepieciešams Android 5.1 vai jaunāks
+ Xposed rada pārāk daudz avāriju, kas var radīt situāciju, ka NetGuard var tikt izņemts no Google Play veikala, tāpēc NetGuard netiek atbalstīs ar vienlaicīgi instalētu Xposed
+ Privātuma politika
+ Liels darbs ir ieguldīts NetGuard izstrādē un testēšanā. Tai pat laikā nav iespējams garantēt, ka NetGuard darbosies korekti pilnīgi visās ierīcēs.
+ Es piekrītu
+ Nepiekrītu
+ NetGuard ir vajadzīga Tava palīdzība. Spied Pirkt PRO funkcijas, lai nodrošinātu projekta turpmāku attīstību.
+ Servisi, kas darbojās
+ Vispārīgie paziņojumi
+ Piekļuves paziņojumi
+ Meklēt citas lietotnes
+ Filtrēt lietotnes
+ Rādīt lietotāja lietotnes
+ Rādīt sistēmas lietotnes
+ Rādīt lietotnes bez interneta
+ Rādīt atspējotās lietotnes
+ Kārtot lietotnes
+ Kārtot pēc nosaukuma
+ Kārtot pēc uid
+ Kārtot pēc datu lietojuma
+ Rādīt žurnālfailu
+ Iestatījumi
+ Uzaicināt
+ Apzīmējumi
+ Atbalsts
+ Par
+ Citas lietotnes
+ Citi
+ Atļautais
+ Bloķētais
+ Nepārtraukti atsvaidzināt
+ Atsvaidzināt
+ Rādīt nosaukumu
+ Parādīt organizāciju
+ PCAP iespējots
+ PCAP eksports
+ Notīrīt
+ Eksportēt
+ Atiestatīt
+ Pievienot
+ Dzēst
+ Tīrīšana
+ Protokols
+ Avota ports
+ Mērķa adrese
+ Mērķa ports
+ Mērķa lietotne
+ Ārējam serverim izvēlies \'neviens\'
+ Noklusējumi (baltais/melnais saraksts)
+ Bloķēt Wi-Fi
+ Bloķēt mobilos datus
+ Atļaut Wi-Fi, kad ekrāns ir ieslēgts
+ Atļaut mobilos datus, kad ekrāns ir ieslēgts
+ Bloķēt viesabonēšanā
+ Iespējas
+ Tēma: %1$s
+ Izmantot tumšo tēmu
+ Paziņot par jaunu instalāciju
+ Pielietot \'kad ekrāns ieslēgts\' noteikumus
+ Automātiski iespējot pēc %1$s minūtēm
+ Aizturēt ekrāna izslēgšanu %1$s minūtes
+ Pārbaudīt atjauninājumus
+ Tīkla iespējas
+ Apakštīkla maršrutēšana
+ Atļaut Tīklāju
+ Atļaut LAN piekļuvi
+ Iespējot IPv6 datu plūsmu
+ Wi-Fi mājas tīkli: %1$s
+ Organizēt mērītos Wi-Fi tīklus
+ Pieņemt 2G kā nemērāmu
+ Pieņemt 3G kā nemērāmu
+ Pieņemt LTE kā nemērāmu
+ Ignorēt vietējo viesabonēšanu
+ Ignorēt ES viesabonēšanu
+ Atspējot zvana laikā
+ Bloķēt Wi-Fi
+ Bloķēt mobilos datus
+ Pārlādēt pēc katras savienojuma maiņas
+ Paplašinātās iespējas
+ Pārvaldīt sistēmas lietotnes
+ Žurnālot interneta piekļuvi
+ Paziņot par piekļuvi internetam
+ Filtrēt datu plūsmu
+ Filtrēt UDP datu plūsmu
+ Bez pārtraukuma VPN pārslēgšana pārlādes laikā
+ Pārlādes gadījumā aizvērt visus savienojumus
+ Bloķēt datu plūsmu
+ Izsekot tīkla lietojumu
+ Atiestatīt tīkla lietojuma statistiku
+ Rādīt atļautos domēna vārdus
+ Bloķēt domēna vārdus
+ DNS atbildes kods: %s
+ Porta pāradresācija
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Apstiprināt uz: %s
+ Minimums DNS TTL: %s s
+ Lietot SOCKS5 proxy
+ SOCKS5 adrese: %s
+ SOCKS5 ports: %s
+ SOCKS5 lietotājvārds: %s
+ SOCKS5 parole: %s
+ PCAP ieraksta izmērs: %s B
+ PCAP maks. faila izmērs: %s MB
+ Sargsuns: katras %s minūtes
+ Informācija par ātrumu
+ Rādīt informāciju par ātrumu
+ Rādīt top lietotnes
+ Mērījumu intervāls: %s ms
+ Mērījuma ilgums: %s s
+ Rezerves kopija
+ Eksportēt iestatījumus
+ Importēt iestatījumus
+ Importēt hosts failu
+ Importēt hosts failu (pievienot)
+ Hosts faila lejupielādes adrese
+ Lejupielādēt hosts failu
+ Tehniskā informācija
+ Vispārīgi
+ Tīkli
+ Abonējumi
+ Parādīt statusa joslā paziņojumu par jauno instalēto lietotni, lai pa tiešo veiktu konfigurāciju (PRO versija)
+ Pēc atspējošanas ar logrīku, atkal iespējot NetGuard pēc noteikta minūšu skaita (nulle atspējo šo funkciju)
+ Izslēdzot ekrānu, saglabāt ieslēgta ekrāna noteikumus norādītās minūtes (nulle atspējo šo funkciju)
+ Divreiz dienā meklēt jaunāko versiju uz GitHub
+ Atkarībā no Android versijas, Tīklājs var darboties vai nedarboties. Tīklāja datu plūsmu nav iespējams filtrēt.
+ Apakštīkla maršrutēšanas iespējošana; var ļaut veikt Wi-Fi zvanus, bet var arī radīt Android sistēmā kļūdas un palielināt baterijas noslodzi
+ Ļauj lietotnēm pieslēgties iekšējā tīkla adresēm. Tādām kā 10.0.0.0/8, 172.16.0.0/12 un 192.168.0.0/16
+ Maršrutēt IPv6 datu plūsmu uz NetGuard, lai to izlases kārtā varētu atļaut vai bloķēt
+ Piemēro Wi-Fi tīkla noteikumus tikai izvēlētajam tīklam (piemēro mobilā tīkla noteikumus visiem pārējiem Wi-Fi tīkliem)
+ Piemērot mobilo tīklu noteikumus mērītajiem (maksas, Tīklāja) Wi-Fi tīkliem
+ Pielietot Wi-Fi tīkla noteikumus arī 2G datu savienojumiem
+ Pielietot Wi-Fi tīkla noteikumus arī 3G datu savienojumiem
+ Pielietot Wi-Fi tīkla noteikumus arī LTE datu savienojumiem
+ Nepiemērot viesabonēšanas noteikumus, kad SIM kartes un mobilā tīkla valstis ir vienādas
+ Nepiemērot viesabonēšanas noteikumus, kad SIM kartes un mobilā tīkla valstis ir Eiropas Savienībā (viesabonēšana kā mājās)
+ Atspējot NetGuard ienākošo un izejošo telefona zvanu laikā. Tā var novērst IP/Wi-Fi zvanu problēmas.
+ Definēt noteikumus sistēmas lietotnēm (ekspertiem)
+ Žurnālot lietotņu mēģinājumus piekļūt internetam. Tas var palielināt baterijas noslodzi.
+ Parāda statusa laukā paziņojumu, kad lietotne mēģina piekļūt jaunai interneta adresei (kad filtrēšana ir atspējota, tikai bloķētie interneta piekļuves mēģinājumi tiks parādīti)
+ Filtrēt IP paketes, kas iet caur VPN. Tas var izraisīt lielāku baterijas patēriņu.
+ Sekot līdzi baitu skaitam, ko nosūta un saņem katra lietotne un adrese. Tas var izraisīt lielāku baterijas patēriņu.
+ Uz bloķēto domēnu vārdiem atbildēt ar konfigurētu DNS atbildes kodu. Slēdzis ir izslēgts, kad hosts fails nav pieejams.
+ Noklusētā vērtība ir 3 (NXDOMAIN), kas nozīmē \'neeksistējošs domēns\'.
+ Domēna vārds, ko izmanto, lai apstiprinātu interneta savienojumu 443. portā (https).
+ Tikai TCP datu plūsma tiks sūtīta uz proxy serveri
+ Periodiski pārbauda, vai NetGuard vēl joprojām darbojas (nulle atspējo šo funkciju). Var palielināt baterijas noslodzi.
+ Parāda tīkla ātruma grafiku statusa joslā
+ Vai esi pārliecināts?
+ Noteikumu izpilde
+ %1$d atļauts, %2$d bloķēts
+ %1$d atļauts, %2$d bloķēts, %3$d hosti
+ Gaidām notikumu
+ NetGuard ir izslēgts. Lieto slēdzi augšpusē, lai ieslēgtu NetGuard
+ NetGuard tika izslēgts, iespējams, ar kādu citu VPN programmu
+ \'%1$s\' instalēts
+ Tika instalēts
+ %1$s mēģināja piekļūt internetam
+ Mēģinājums piekļūt internetam
+ Darbība pabeigta
+ NetGuard lieto lokālu VPN, lai filtrētu interneta datu plūsmu.
+Šī iemesla dēļ, lūdzu, atļauj VPN savienojumu nākošajā dialoga logā.
+Tava interneta datu plūsma netiks sūtīta uz kādu ārējo VPN serveri.
+ NetGuard nevar startētēties automātiski. Tas, iespējams, ir Andriod versijas kļūdas dēļ.
+ Ir radusies neparedzēta kļūda \'%s\'
+ Android patreiz neļauj startēt VPN servisu. Iespējams, tas ir Android versijas kļūdas dēļ.
+ Izmēģini NetGuard
+ Ziedojot Tu piekrītu noteikumiem un nosacījumiem
+ Ja nākamajā dialog logā nevari nospiest OK, tad visticamākais kāda cita (ekrāna aptumšošanas) lietotne patreiz lieto ekrānu.
+ ± %1$.3f▲ %2$.3f▼ MB/dienā
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Lai nodrošinātu stabilu rezultātu, Android baterijas optimizēšana lietotnei NetGuard ir jābūt atslēgtai.
+\n\nNākamajā dialoglogā augšā izvēlies \"Visas lietotnes\", no saraksta izvēlies NetGuard, izvēlies \"Neoptimizēt\", un to pastiprini.
+ Lai iegūtu stabilu rezultātu, Android datu lietojuma samazinātājam uz NetGuard jābūt izslēgtam.
+\n\nNākamajā dialoglogā lietotnei NetGuard iespējo \"Fona dati\" un \"Neierobežots datu lietojums\"
+ Filtrēšanas funkcija liks Android sistēmai datu plūsmas un baterijas patēriņu piedēvēt NetGuard lietotnei un nevis patiesajām datu plūsmas un baterijas patērējošajām lietotnēm
+ Android 4 nepieciešams, lai filtrēšana būtu iespējota
+ Datu plūsmas žurnālošana ir izslēgta. Lieto slēdzi loga augšā, lai ieslēgtu žurnālošanu. Datu plūsmas žurnālošana var palielināt baterijas noslodzi.
+ Tas atiestatīs visus noteikumus un parametrus uz sākotnējām vērtībām
+ Tas nodzēsīs piekļuves mēģinājumu žurnāla rindiņas nemainot atļaut/bloķēt noteikumus
+ Pēdējais imports: %s
+ Lejupielādē\n%1s
+ Hosts fails lejupielādēts
+ Pēdējā lejupielāde: %s
+ Sākt pāradresāciju no %1$s port %2$d to %3$s:%4$d of \'%5$s\'?
+ Beigt pāradresāciju%1$s port %2$d?
+ Tīkls tiek mērīts
+ Nav savienojuma ar internetu
+ NetGuard ir aizņemts
+ Atjauninājums ir pieejams, spied, lai lejuplādētu
+ Tu vari atļaut (zaļš simbols) vai aizliegt (sārts simbols) Wi-Fi vai mabilo datu plūsmu pārslēdzot tīkla simbolus pretī katrai lietotnei
+ Ja esi instalējis NetGuard, lai aizsargātu savu privātumu, Tu varētu būt ieinteresēts arī FairEmail , draudzīgā, atvērtā koda e-pasta lietotnē
+ Interneta piekļuve ir iespējota pēc noklusējuma (melnā saraksta režīms), to var mainīt iestatījumos
+ Ienākošos (push) paziņojumus pārsvarā gadījumu apstrādā sistēmas komponente \"Play services\", kurai interneta piekļuve pēc noklusējuma ir atļauta
+ Iestatījumos ir iespējama visu (sistēmas) lietotņu pārvaldība
+ Lūdzu apraksti problēmu un kad tā radās:
+ VPN savienojums atcelts\nVai vēlies iestatīt vēl vienu VPN, kas vienmēr būs ieslēgts?
+ Izslēdzot savu ierīci ar iespējotu NetGuard, nākamajā ierīces startēšanas reizē NetGuard tiks palaists automātiski
+ Šī funkcija nav pieejama šai Android versijai
+ Vēl viens VPN ir iestatīts kā \"Vienmēr ieslēgts VPN\"
+ Lai lietotu NetGuard filtrēšanas režīmā, Android VPN iestatījumos izslēdz iestatījumu \"Bloķēt savienojumus bez VPN\"
+ Lai lietotu NetGuard filtrēšanas režīmā, Android VPN iestatījumos izslēdz iestatījumu \"Privātais DNS\"
+ Dataplūsma ir slēgta
+ Nemērītā datu plūsma ir atļauta
+ Nemērītā datu plūsma ir bloķēta
+ Nemērītie noteikumi netiek lietoti
+ Mērītā datu plūsma ir atļauta
+ Mērītā datu plūsma ir bloķēta
+ Mērītie noteikumi netiek lietoti
+ Adrese ir atļauta
+ Adrese ir bloķēta
+ Atļaut, kad ekrāns ir ieslēgts
+ Bloķēt viesabonēšanā
+ Pēc noklusējuma Wi-Fi savienojums tiek uzskatīts kā neierobežots (Nemērīts) un mobilais datu kā ierobežots (Mērīts) savienojums
+ nav atļauts internets
+ ir atspējots
+ Ienākošie ziņojumi tiek saņemti caur Google Play servisiem un nevis no šīs aplikācijas, tāpēc tos nevar nobloķēt bloķējot šo aplikāciju
+ Lejupielādes veic lejupielāžu pārvaldnieks (Download manager) un nevis šī aplikācija, tāpēc tās nevar nobloķēt bloķējot šo aplikāciju
+ Apstiprināt noteikumus un nosacījumus
+ Nosacījumi
+ Atļaut Wi-Fi, kad ekrāns ir ieslēgts
+ Atļaut mobilos datus, kad ekrāns ir ieslēgts
+ R
+ Bloķēt viesabonēšanā
+ Atļaut bloķētas datu plūsmas režīmā
+ Filtrēt saistītos
+ Piekļuves mēģinājumi
+ Piekļuves noteikumiem ir virsroka pār citiem noteikumiem
+ Iespējas
+ Paziņot par interneta piekļuves mēģinājumiem
+ Žurnālošana vai filtrēšana nav iespējota
+ Žurnālošana un filtrēšana ir iespējota
+ Konfigurēt
+ Iespējot tikai bloķēto adrešu žurnālošanu
+ Iespējot arī atļauto adrešu žurnālošanu
+ Iespējot jauno žurnāloto adrešu piekļuves paziņojumus
+ Šie iestatījumi ir globāli un attiecās uz visām lietotnēm
+ Filtrēšana arī ir nepieciešama lai atļautu vai bloķētu individuālas adreses
+ Žurnālošana (mazāk) un filtrēšana (vairāk) var palielināt baterijas noslodzi un atstāt iespaidu uz tīkla ātrumu
+ Vērtēt
+ Atļaut
+ Bloķēt
+ Atļaut Wi-Fi
+ Bloķēt Wi-Fi
+ Atļaut mobilos datus
+ Bloķēt mobilos datus
+ saknes katalogs
+ media serveris
+ neviens
+ Vairs nejautāt
+ Whois %1$s
+ Ports %1$d
+ Kopēt
+ PRO iespējas
+ Sekojošas PRO funkcijas ir pieejamas:
+ Skatīt bloķētās datu plūsmas žurnālu
+ Filtrēt tīkla datu plūsmu
+ Jaunas lietotnes paziņojums
+ Tīkla ātruma grafiks
+ Izskatas (tēma, krāsas)
+ Visas augstāk minētās PRO funkcijas
+ Atbalsts attīstībai
+ Pirkt
+ Iespējots
+ Nav pieejams
+ Spied uz virsrakstu, lai iegūtu vairāk informācijas
+ Izaicinājums
+ Atsauce
+ Šī ir PRO funkcija
+ Mēneša abonements 1 vai 2 eiro apmērā (neieskaitot vietējos nodokļus) aktivizēs visas Pro funkcijas.
+ Abonementu var atcelt vai mainīt jebkurā brīdī Play veikala Abonementi sadaļā.
+
+
+ - zilgans/oranžs
+ - zils/oranžs
+ - violets/sarkans
+ - dzintars/zils
+ - oranžs/pelēks
+ - zaļš
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-ml-rIN/strings.xml b/NetGuard/app/src/main/res/values-ml-rIN/strings.xml
new file mode 100644
index 0000000..0adce52
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-ml-rIN/strings.xml
@@ -0,0 +1,139 @@
+
+
+ NetGuard ഇന്റർനെറ്റിലേക്കുള്ള ആക്സസ് തടയുന്നതിന് ലളിതവും നൂതനവുമായ മാർഗ്ഗങ്ങൾ നൽകുന്നു - റൂട്ട് ആവശ്യമില്ല. അപ്ലിക്കേഷനുകൾക്കും വിലാസങ്ങൾക്കും നിങ്ങളുടെ വൈഫൈ/മൊബൈൽ കണക്ഷനിലേക്ക് വ്യക്തിഗതമായി പ്രവേശനം അനുവദിക്കുകയോ നിരസിക്കുകയോ ചെയ്യാം.
+ NetGuard- ന് Android 5.1 അല്ലെങ്കിൽ അതിനുശേഷമുള്ളത് ആവശ്യമാണ്
+ ഞാൻ അംഗീകരിക്കുന്നു
+ ഞാൻ വിയോജിക്കുന്നു
+ നിങ്ങളുടെ സഹായം ആവശ്യമാണ്. ഈ പ്രോജക്റ്റിനെ പിന്തുണയ്ക്കുന്നതിനായി പ്രോ സവിശേഷതകൾ വാങ്ങുക.
+ പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ
+ പൊതു അറിയിപ്പുകൾ
+ അപ്ലിക്കേഷനായി തിരയുക
+ ആപുകൾ ഫിൽട്ടർ ചെയ്യുക
+ ഉപയോക്തൃ ആപുകൾ ദൃശ്യമാക്കുക
+ സിസ്റ്റം ആപ്സുകള് കാണിക്കുക
+ ഇന്റർനെറ്റ് ഇല്ലാതെ ആപ്പുകൾ പ്രദർശിപ്പിക്കുക
+ പ്രവർത്തനരഹിതമാക്കിയ ആപ്പുകൾ കാണിക്കുക
+ ആപ്പുകൾ തരംതിരിക്കുക
+ ഡാറ്റ ഉപയോഗം അനുസരിച്ച് തരംതിരിക്കുക
+ ലോഗുകൾ കാണിക്കുക
+ ക്രമീകരണങ്ങള്
+ ക്ഷണിക്കുക
+ സൂചന
+ പിന്തുണ
+ കുറിച്ച്
+ മറ്റ് ആപ്പുകൾ
+ മറ്റുള്ളവ
+ തടഞ്ഞിരിക്കുന്നത്
+ തത്സമയ അപ്ഡേറ്റുകൾ
+ പുതുക്കുക
+ പേരുകൾ കാണിക്കുക
+ ഓർഗനൈസേഷൻ കാണിക്കുക
+ PCAP പ്രവർത്തനക്ഷമമാക്കി
+ മായ്ക്കുക
+ എക്സ്പോര്ട്ട്
+ പുനഃക്രമീകരിക്കുക
+ ചേര്ക്കുക
+ ഇല്ലാതാക്കുക
+ പ്രോട്ടോകോൾ
+ സ്ഥിരസ്ഥിതികൾ (വൈറ്റ്/ബ്ലാക്ക്ലിസ്റ്)
+ Wi-Fi തടയുക
+ മൊബൈൽ തടയുക
+ സ്ക്രീൻ ഓണായിരിക്കുമ്പോൾ Wi-Fi അനുവദിക്കുക
+ സ്ക്രീൻ ഓണായിരിക്കുമ്പോൾ മൊബൈൽ അനുവദിക്കുക
+ ഓപ്ഷനുകൾ
+ തീം: %1$s
+ ഇരുണ്ട തീം ഉപയോഗിക്കുക
+ അപ്ഡേറ്റുകൾക്കായി പരിശോധിക്കുക
+ നെറ്റ്വർക്ക് ഓപ്ഷനുകൾ
+ ടെതറിംഗ് അനുവദിക്കുക
+ LAN ആക്സസ്സ് അനുവദിക്കുക
+ കോളിൽ പ്രവർത്തനരഹിതമാക്കുക
+ Wi-Fi ലോക്ക്ഡൗൺ
+ ലോക്ക്ഡൗൺ മൊബൈൽ
+ വിപുലമായ ഓപ്ഷനുകൾ
+ ട്രാഫിക് ഫിൽട്ടർ ചെയ്യുക
+ UDP ട്രാഫിക് ഫിൽട്ടർ ചെയ്യുക
+ നെറ്റ്വർക്ക് ഉപയോഗം നിരീക്ഷിക്കുക
+ നെറ്റ്വർക്ക് ഉപയോഗം പുനഃസജ്ജമാകുക
+ ഡൊമെയ്ൻ നാമങ്ങൾ തടയുക
+ DNS പ്രതികരണ കോഡ്: %s
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ SOCKS5 proxy ഉപയോഗിക്കുക
+ SOCKS5 address: %s
+ SOCKS5 port: %s
+ SOCKS5 ഉപയോക്തൃനാമം: %s
+ വേഗത അറിയിപ്പ്
+ ബാക്കപ്പ്
+ സാങ്കേതിക വിവരങ്ങൾ
+ പൊതുവായ
+ നെറ്റ്വർക്കുകൾ
+ സബ്സ്ക്രിപ്ഷനുകൾ
+ TCP ട്രാഫിക് മാത്രമേ പ്രോക്സി സെർവറിലേക്ക് അയയ്ക്കൂ
+ സ്റ്റാറ്റസ് ബാർ അറിയിപ്പിൽ നെറ്റ്വർക്ക് സ്പീഡ് ഗ്രാഫ് കാണിക്കുക
+ നിങ്ങള്ക്ക് ഉറപ്പാണോ?
+ നിയമങ്ങൾ നടപ്പിലാക്കുന്നു
+ %1$d അനുവദിച്ചു, %2$d തടഞ്ഞു
+ %1$d അനുവദിച്ചു, %2$d തടഞ്ഞു, %3$d ഹോസ്റ്റുകൾ
+ NetGuard പ്രവർത്തനരഹിതമാണ്, NetGuard പ്രവർത്തനക്ഷമമാക്കാൻ മുകളിലേ സ്വിച്ച് ഉപയോഗിക്കുക
+ \'%1$s\' ഇൻസ്റ്റാളുചെയ്തു
+ %1$s ഇന്റർനെറ്റ് ആക്സസ് ചെയ്യാൻ ശ്രമിച്ചു
+ ഇന്റർനെറ്റ് ആക്സസ് ചെയ്യാൻ ശ്രമിച്ചു
+ പ്രവർത്തനം പൂർത്തിയായി
+ ± %1$.3f▲ %2$.3f▼ MB/ദിവസം
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ ഡൗൺലോഡുചെയ്യുന്നു\n%1s
+ അവസാന ഡൗൺലോഡ്: %s
+ സജീവ ഇന്റർനെറ്റ് കണക്ഷനില്ല
+ NetGuard തിരക്കിലാണ്
+ അപ്ഡേറ്റ് ലഭ്യമാണ്, ഡൗൺലോഡുചെയ്യാൻ ടാപ്പുചെയ്യുക
+ ഇന്റർനെറ്റ് അനുമതിയില്ല
+ പ്രവർത്തനരഹിതമാണ്
+ നിയമങ്ങളും വ്യവസ്ഥകളും പ്രയോഗിക്കുക
+ വ്യവസ്ഥകൾ
+ R
+ റോമിംഗ് ചെയ്യുമ്പോൾ തടയുക
+ ലോക്ക്ഡൗൺ മോഡിൽ അനുവദിക്കുക
+ ആക്സസ്സ് ശ്രമങ്ങൾ
+ ഓപ്ഷനുകൾ
+ ക്രമീകരിക്കുക
+ അനുവദിക്കുക
+ തടയുക
+ Wi-Fi അനുവദിക്കുക
+ Wi-Fi തടയുക
+ മൊബൈൽ അനുവദിക്കുക
+ മൊബൈൽ തടയുക
+ വീണ്ടും ചോദിക്കരുത്
+ Whois %1$s
+ Port %1$d
+ പകര്ത്തുക
+ പ്രോ സവിശേഷതകൾ
+ ഇനിപ്പറയുന്ന പ്രോ സവിശേഷതകൾ ലഭ്യമാണ്:
+ തടഞ്ഞ ട്രാഫിക് ലോഗ് കാണുക
+ നെറ്റ്വർക്ക് ട്രാഫിക് ഫിൽട്ടർ ചെയ്യുക
+ പുതിയ അപ്ലിക്കേഷൻ അറിയിപ്പുകൾ
+ നെറ്റ്വർക്ക് വേഗത ഗ്രാഫ് അറിയിപ്പ്
+ രൂപം (തീം, നിറങ്ങൾ)
+ മുകളിലുള്ള എല്ലാ പ്രോ സവിശേഷതകളും
+ വികസനത്തെ പിന്തുണയ്ക്കുക
+ മേടിക്കുക
+ ലഭ്യമല്ല
+ കൂടുതൽ വിവരങ്ങൾക്ക് ശീർഷകത്തിൽ ടാപ്പുചെയ്യുക
+ ഇതൊരു പ്രോ സവിശേഷതയാണ്
+
+ - ടീൽ/ഓറഞ്ച്
+ - നീല/ഓറഞ്ച്
+ - പർപ്പിൾ/ചുവപ്പ്
+ - ആമ്പർ/നീല
+ - ഓറഞ്ച്/ഗ്രേ
+ - പച്ച
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-my-rMM/strings.xml b/NetGuard/app/src/main/res/values-my-rMM/strings.xml
new file mode 100644
index 0000000..6800127
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-my-rMM/strings.xml
@@ -0,0 +1,38 @@
+
+
+ ကျွန်ုပ်သဘောတူတယ်
+ ကျွန်ုပ်သဘောမတူပါ
+ NetGuard မှ သင်တို့ရဲ့ အကူအညီကို လိုအပ်တယ်။ စီမံကိန်းဆက်လက် လုပ်ဆောင်နိုင်ရန် အထူးပြုလုပ်ထားသော Pro လုပ်ဆောင်ချက်များကို ၀ယ်ယူဖို့
+ခလုတ်ကို နှိပ်ပါ။
+ လည်ပတ်နေသောဝန်ဆောင်မှုများ
+ အထွေထွေအသိပေးချက်များ
+ အသိပေးချက်များဆီသို့ ၀င်ရောက်ကြည့်ရှုပါ
+ အက်ပလီကေးရှင်းကိုရှာပါ
+ အက်ပ်များကိုစစ်ထုတ်မယ်
+ အသုံးပြုသူအက်ပ်များကို ပြပါ
+ စစ်စတမ်အက်ပ်များကို ပြပါ
+ အင်တာနက်မပါဘဲ အက်ပ်များကို ပြပါ
+ ပိတ်ထားသော အက်ပ်များကို ပြပါ
+ အက်ပ်များကိုစီပါ
+ နာမည်အလိုက်စီပါ
+ uid အလိုက်စီပါ
+ ဒေတာအသုံးပြုမှုအလိုက် စီပါ
+ မှတ်တမ်းကိုပြပါ
+ ဖိတ်ပါ
+ ပံ့ပိုးမှု
+ အကြောင်း
+ အခြားအက်ပ်များ
+ အခြား
+ ခွင့်ပြုပြီးပြီ
+ အမည်များကို ပြပါ
+ အဖွဲ့အစည်းကိုပြပါ
+ ရှင်းပါ
+ တင်ပို့ပါ
+ ထည့်ပါ
+ ဖျက်ပါ
+ ဒီဇိုင်းပုံစံ - %1$s
+ အမှောင်ဒီဇိုင်းပုံစံကို သုံးပါ
+ အထွေထွေ
+ ကွန်ယက်များ
+ သင်သေချာလား။
+
diff --git a/NetGuard/app/src/main/res/values-nl-rNL/strings.xml b/NetGuard/app/src/main/res/values-nl-rNL/strings.xml
new file mode 100644
index 0000000..772be0b
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-nl-rNL/strings.xml
@@ -0,0 +1,291 @@
+
+
+ NetGuard biedt eenvoudig & geavanceerde manieren om internettoegang te blokkeren - zonder root-toegang. Apps en adressen kunnen individueel toegang worden verleend of geweigerd tot je wifi of mobiele internetverbinding.
+ NetGuard vereist Android 5.1 of hoger
+ Xposed veroorzaakt te veel crashes, wat ertoe kan leiden dat NetGuard uit Google Play wordt verwijderd, daarom wordt NetGuard niet ondersteund als Xposed is geïnstalleerd
+ Privacybeleid
+ NetGuard wordt met veel zorg ontwikkelt en getest, toch is het onmogelijk om te garanderen dat NetGuard op ieder apparaat goed zal werken.
+ Ik ga akkoord
+ Ik ga niet akkoord
+ NetGuard heeft je hulp nodig. Tik en koop de pro-functies om het project te ondersteunen.
+ Actieve services
+ Algemene meldingen
+ Toegang tot meldingen
+ Zoek naar een app
+ Filter apps
+ Toon gebruikers-apps
+ Toon systeem-apps
+ Toon apps zonder internet
+ Toon uitgeschakelde apps
+ Sorteer apps
+ Sorteer op naam
+ Sorteer op UID
+ Sorteer op datagebruik
+ Toon log
+ Instellingen
+ Nodig uit
+ Legenda
+ Support
+ Over
+ Andere apps
+ Overige
+ Toegestaan
+ Geblokkeerd
+ Live updates
+ Vernieuw
+ Toon namen
+ Toon organisatie
+ PCAP ingeschakeld
+ Exporteer PCAP
+ Wissen
+ Exporteer
+ Reset
+ Voeg toe
+ Verwijder
+ Opruimen
+ Protocol
+ Bronpoort
+ Bestemmingsadres
+ Bestemmingspoort
+ Bestemmings-app
+ Selecteer voor een externe server \'niemand\'
+ Standaard (white/blacklist)
+ Blokkeer wifi
+ Blokkeer mobiel
+ Sta wifi toe als scherm aan
+ Sta mobiel toe als scherm aan
+ Blokkeer roaming
+ Opties
+ Thema: %1$s
+ Gebruik donker thema
+ Notificatie bij nieuwe installatie
+ Pas \'wanneer scherm aan\'-regels toe
+ Automatisch inschakelen na %1$s minuten
+ Vertraag schermuitzetten met %1$s minuten
+ Controleer op updates
+ Netwerkopties
+ Subnet-routering
+ Sta tethering toe
+ LAN-toegang toestaan
+ Schakel IPv6-verkeer in
+ Wifi-thuisnetwerken: %1$s
+ Beheer gemeten wifi-netwerken: %1$s
+ Beschouw 2G als ongemeten
+ Beschouw 3G als ongemeten
+ Beschouw 4G als ongemeten
+ Negeer nationale roaming
+ Negeer EU-roaming
+ Schakel uit tijdens telefoongesprek
+ Vergrendel wifi
+ Vergrendel mobiel
+ Herlaad bij elke connectiviteitswijziging
+ Geavanceerde opties
+ Beheer systeemapplicaties
+ Log internet-toegang
+ Melding bij internettoegang
+ Filter dataverkeer
+ Filter UDP-verkeer
+ Naadloze VPN-overdracht bij herladen
+ Sluit verbindingen bij herladen
+ Vergrendel verkeer
+ Houd het netwerkgebruik bij
+ Reset netwerkgebruik
+ Toon opgeloste domeinnamen
+ Blokkeer domeinnamen
+ DNS-antwoordcode: %s
+ Port-forwarding
+ VPN-IPv4: %s
+ VPN-IPv6: %s
+ VPN-DNS: %s
+ Valideer op: %s
+ Minimale DNS TTL: %s s
+ Gebruik SOCKS5-proxy
+ SOCKS5-adres: %s
+ SOCKS5-poort: %s
+ SOCKS5-gebruikersnaam: %s
+ SOCKS5-wachtwoord: %s
+ PCAP-recordgrootte: %s B
+ PCAP max. bestandsgrootte: %s MB
+ Watchdog: iedere %s minuten
+ Snelheidsmelding
+ Toon snelheidsmelding
+ Toon populairste apps
+ Voorbeeldinterval: %s ms
+ Aantal voorbeelden: %s s
+ Back-up
+ Exporteer instellingen
+ Importeer instellingen
+ Importeer hosts-bestand
+ Importeer hosts-bestanden (toevoegen)
+ Download-URL hosts-bestand
+ Download hosts-bestand
+ Technische informatie
+ Algemeen
+ Netwerken
+ Abonnementen
+ Toon melding om direct nieuw geïnstalleerde apps te configureren (pro functie)
+ Na het geselecteerde aantal minuten schakelt NetGuard automatisch weer in, bij het uitschakelen van de widget (voer nul in om deze optie uit te schakelen)
+ Houdt \"scherm aan houden\" regels actief voor een bepaald aantal minuten (vul 0 in om deze optie uit te schakelen) na het uitzetten van het scherm
+ Controleer GitHub twee keer per dag voor nieuwe versies
+ Afhankelijk van de Android-versie werkt tethering mogelijk wel of niet. Dataverkeer via tethering kan niet worden gefilterd.
+ Schakel subnet-routering in; kan bellen via wifi inschakelen, maar kan ook bugs in Android veroorzaken en het batterijgebruik verhogen
+ Sta apps toe verbinding te maken met lokale netwerkadressen, zoals 10.0.0.0/8, 172.16.0.0/12 en 192.168.0.0/16
+ Routeer IP versie 6-verkeer naar NetGuard zodat het selectief kan worden toegestaan of geblokkeerd
+ Pas wifi-netwerkregels alleen toe voor het geselecteerde netwerk (pas mobiele netwerkregels toe voor andere wifi-netwerken)
+ Pas regels voor mobiele netwerken toe op gemeten (betaalde, getetherde) wifi-netwerken
+ Pas wifi-netwerkregels toe op 2G-verbindingen
+ Pas wifi-netwerkregels toe op 3G-verbindingen
+ Pas wifi-netwerkregels toe op 4G-verbindingen
+ Pas geen roamingregels toe als het land van de simkaart en het mobiele netwerk hetzelfde zijn
+ Pas geen roamingregels toe als het sim- en mobiele netwerkland zich binnen de EU bevindt (roamen zoals thuis)
+ Schakel NetGuard uit bij inkomend of uitgaand telefoongesprek. Dit kan worden gebruikt om problemen met bellen via IP/wifi te omzeilen.
+ Definieer regels voor systeem-apps (voor experts)
+ Log pogingen voor internettoegang door apps. Dit kan het batterijgebruik verhogen.
+ Toon een statusbalkmelding wanneer een app probeert toegang te krijgen tot een nieuw internetadres (wanneer filteren is uitgeschakeld, worden alleen geblokkeerde internettoegangspogingen op de hoogte gesteld)
+ Filter IP-pakketten die de VPN-tunnel verlaten. Dit kan resulteren in extra batterijgebruik.
+ Houd het aantal verzonden en ontvangen bytes bij voor elke app en elk adres. Dit kan resulteren in extra batterijgebruik.
+ Reageer met de geconfigureerde DNS-antwoordcode voor geblokkeerde domeinnamen. Deze schakelaar is uitgeschakeld als er geen hosts-bestand beschikbaar is.
+ De standaardwaarde is 3 (NXDOMAIN), wat \'niet-bestaand domein\' betekent.
+ Domeinnaam die wordt gebruikt om de internetverbinding op poort 443 (https) te valideren.
+ Alleen TCP-verkeer zal worden verzonden naar de proxyserver
+ Controleer regelmatig of NetGuard nog actief is (voer nul in om deze optie uit te schakelen). Dit kan resulteren in extra batterijgebruik.
+ Geef netwerksnelheidsgrafiek weer in statusbalkmelding
+ Weet je het zeker?
+ Regels worden toegepast
+ %1$d toegestaan, %2$d geblokkeerd
+ %1$d toegestaan, %2$d geblokkeerd, %3$d hosts
+ Wachten op gebeurtenis
+ NetGuard staat uit, gebruik de schakelaar boven om NetGuard aan te zetten
+ NetGuard is uitgezet, waarschijnlijk door een andere VPN applicatie
+ \'%1$s\' geïnstalleerd
+ Is geïnstalleerd
+ %1$s benaderde het internet
+ Probeerde verbinding te maken met het internet
+ Actie uitgevoerd
+ NetGuard gebruikt een lokale VPN om internetverkeer te filteren.
+Sta daarom een VPN-verbinding toe in het volgende dialoogvenster.
+Je internetverkeer wordt niet naar een externe VPN-server gestuurd.
+ NetGuard kon niet automatisch worden gestart tijdens het opstarten vanwege een bug in uw Android-versie.
+ Er is een onverwachte fout opgetreden: \'%s\'
+ Android weigert de VPN-service te starten. Dit komt waarschijnlijk door een bug in je Android-versie.
+ Probeer NetGuard
+ Door te doneren ga je akkoord met de algemene & voorwaarden
+ Als je niet op \'OK\' kan tikken in het dialoogvenster, is een (schermdimmende) app waarschijnlijk actief.
+ ± %1$.3f▲ %2$.3f▼ MB/dag
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Voor consistente resultaten moeten de Android-batterijoptimalisaties worden uitgeschakeld voor NetGuard.
+\n\nSelecteer in het volgende dialoogvenster bovenaan \"Alle apps\", tik op NetGuard in de lijst en selecteer en bevestig \'niet optimaliseren\'.
+ Voor consistente resultaten moeten de Android-opties voor het opslaan van gegevens worden uitgeschakeld voor. NetGuard. \n\nSelecteer in het volgende dialoogvenster de opties \'achtergrondgegevens\' en \'onbeperkt gegevensgebruik\' in
+ Het gebruik van filteren zorgt ervoor dat Android gegevens- en batterijgebruik aan NetGuard toewijst - Android denkt dat de gegevens en batterij door NetGuard worden gebruikt i.p.v. door de originele apps.
+ Android 4 vereist dat filtering is ingeschakeld
+ Internetverkeer loggen is uitgeschakeld. Gebruik de schakelaar hierboven om het loggen in te schakelen. Internetverkeer loggen kan het batterijgebruik verhogen.
+ Dit zet alle regels en instellingen terug naar de standaardinstelling
+ Hiermee worden logregels voor toegangspogingen verwijderd zonder regels voor toestaan/blokkeren
+ Laatste import: %s
+ Downloaden \n%1s
+ Hosts-bestand gedownload
+ Laatste download: %s
+ Begin met forwarded van %1$s poort %2$d naar %3$s:%4$d van \'%5$s\'?
+ Stop met het doorsturen van %1$s poort %2$d?
+ Netwerk is gemeten
+ Geen actieve internetverbinding
+ NetGuard is bezig
+ Update beschikbaar, tik om te downloaden
+ Je kunt wifi of mobiel internet toestaan (groenachtig) of weigeren (roodachtig) door op de pictogrammen naast een app te tikken
+ Heb je NetGuard geïnstalleerd om je privacy te beschermen? Dan ben je misschien ook geïnteresseerd in FairEmail : een open source en privacyvriendelijke e-mailapp
+ Internettoegang is standaard toegestaan (blacklist-modus), dit kan worden gewijzigd in de instellingen
+ Inkomende (push) berichten worden meestal afgehandeld door de systeemcomponent Play-services, die standaard internettoegang is toegestaan
+ Het beheren van alle (systeem) apps kan worden ingeschakeld in de instellingen
+ Beschrijf het probleem en geef het tijdstip van het probleem aan:
+ VPN-verbinding geannuleerd \nHeb je een andere VPN geconfigureerd als een always-on VPN?
+ Als je het apparaat uitschakelt terwijl NetGuard is ingeschakeld, wordt NetGuard automatisch gestart bij het opstarten van je apparaat
+ Deze functie is niet beschikbaar op deze Android-versie
+ Een andere VPN is ingesteld als een always-on VPN
+ Schakel \"Verbindingen zonder VPN blokkeren\" uit in de Android VPN-instellingen om NetGuard in filtermodus te gebruiken
+ Schakel \"Private DNS\" uit in de Android-netwerkinstellingen om NetGuard in filtermodus te gebruiken
+ Dataverkeer is vergrendeld
+ Ongelimiteerde verkeer is toegestaan
+ Ongelimiteerde verkeer wordt geblokkeerd
+ Ongelimiteerde regels worden niet toegepast
+ Gemeten verkeer is toegestaan
+ Gemeten verkeer wordt geblokkeerd
+ Gemeten regels worden niet toegepast
+ Adres is toegestaan
+ Adres is geblokkeerd
+ Sta toe als scherm aan is
+ Blokkeer bij roamen
+ Standaard is een Wi-Fi verbinding een ongelimiteerde verbinding en een mobiele verbinding een gelimiteerde
+ heeft geen internet toegang
+ is uitgezet
+ Inkomende berichten worden ontvangen door Google Play-services en niet door deze app en kunnen daarom niet worden geblokkeerd door deze app te blokkeren
+ Downloads worden uitgevoerd door de downloadmanager en niet door deze app. Hierdoor kunnen ze niet geblokkeerd of verwijderd worden
+ Pas regels en voorwaarden toe
+ Condities
+ Sta Wi-Fi toe als het scherm aan is
+ Sta mobiel toe als het scherm aan is
+ R
+ Blokkeer bij roamen
+ Toestaan in vergrendelmodus
+ Verwante filteren
+ Toegangspogingen
+ Toegangsregels hebben voorrang op andere regels
+ Opties
+ Houdt mij op de hoogte van toegangspogingen op het internet
+ Logging of filteren is niet ingeschakeld
+ Logging en filteren zijn ingeschakeld
+ Configureer
+ Schakel alleen het loggen van geblokkeerde adressen in
+ Schakel filteren in om ook toegestane adressen te loggen
+ Schakel toegangsmeldingen in voor nieuw geregistreerde adressen
+ Deze instellingen zijn algemene instellingen die van toepassing zijn op alle apps
+ Filteren is ook nodig om individuele adressen toe te staan of te blokkeren
+ Door loggen (minder) of filteren (meer) in te schakelen, kan het batterijgebruik toenemen en de netwerkschelheid beïnvloed worden
+ Beoordeel
+ Sta toe
+ Blokkeer
+ Sta wifi toe
+ Blokkeer wifi
+ Sta mobiel toe
+ Blokkeer mobiel
+ root
+ mediaserver
+ niemand
+ Niet opnieuw vragen
+ Whois %1$s
+ Poort %1$d
+ Kopieer
+ Pro-functies
+ De volgende pro-functies zijn beschikbaar:
+ Bekijk logs geblokkeerd verkeer
+ Filter netwerkverkeer
+ Nieuwe app-meldingen
+ Netwerksnelheidgrafiek-melding
+ Uiterlijk (thema, kleuren)
+ Alle bovenstaande pro-functies
+ Support development
+ Koop
+ Ingeschakeld
+ Niet beschikbaar
+ Tik op een titel voor meer info
+ Uitdaging
+ Antwoord
+ Dit is een pro-functie
+ Een maandelijks abonnement van één of twee euro (exclusief belasting) activeert alle pro-functies.
+ Je kunt je abonnement opzeggen of beheren via het tabblad \'Abonnementen\' in de Google Play Store.
+
+
+ - groenblauw/oranje
+ - blauw/oranje
+ - paars/rood
+ - amber/blauw
+ - oranje/grijs
+ - groen
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-no-rNO/strings.xml b/NetGuard/app/src/main/res/values-no-rNO/strings.xml
new file mode 100644
index 0000000..b7a16eb
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-no-rNO/strings.xml
@@ -0,0 +1,247 @@
+
+
+ NetGuard gir enkle og avanserte måter å blokkere tilgang til internett - ingen root er nødvendig. Apper og adresser kan enkelt tillates eller nektes tilgang til Wi-Fi- og/eller mobilforbindelsen din.
+ NetGuard krever Android 5.1 eller nyere
+ Xposed forårsaker for mange krasjer, noe som kan føre til at NetGuard blir fjernet fra Google Play Store, derfor støttes ikke NetGuard mens Xposed er installert
+ Privatlivsretningslinjer
+ Stort omhu er brukt i utvikling og testing av NetGuard, men det umulig å garantere at NetGuard vil fungere korrekt på alle enheter.
+ Jeg aksepter
+ Jeg aksepter ikke
+ NetGuard trenger din hjelp. Trykk for å kjøpe Pro-funksjoner for å holde prosjektet gående.
+ Kjørende tjenester
+ Generelle varslinger
+ Tilgang til varslinger
+ Søk etter app
+ Filtrer apper
+ Vis brukerapper
+ Vis systemapper
+ Vis apper uten internett
+ Vis avskrudde apper
+ Sorter apper
+ Sorter etter navn
+ Sorter etter uid
+ Sorter etter databruk
+ Vis loggboken
+ Innstillinger
+ Inviter
+ Forklaring
+ Støtte
+ Om
+ Andre apper
+ Andre
+ Tillatt
+ Blokkert
+ Sanntidsoppdateringer
+ Oppfrisk
+ Vis navnene
+ Vis organisasjonene
+ PCAP er aktivert
+ PCAP-eksport
+ Tøm
+ Eksporter
+ Tilbakestill
+ Legg til
+ Slett
+ Rydd opp
+ Protokoll
+ Kildeport
+ Måladresse
+ Målport
+ Målapp
+ For en ekstern tjener, velg «ingen»
+ Standardene (hvite- og svarte-listene)
+ Blokker Wi-Fi
+ Blokker mobilnett
+ Tillat Wi-Fi når skjermen er på
+ Tillat mobilnett når skjermen er på
+ Blokker roaming
+ Innstillinger
+ Tema: %1$s
+ Bruk mørkt tema
+ Meld ifra om nye installeringer
+ Benytt \'når skjermen er på\'-regler
+ Skru på automatisk etter %1$s minutter
+ Forsink avskruing av skjermen med %1$s minutter
+ Se etter oppdateringer
+ Nettverksinnstillinger
+ Subnet ruting
+ Tillat USB-nettverksvidereføring
+ Tillat LAN-tilgang
+ Skru på IPv6-trafikk
+ Wi-Fi-hjemmenettverk: %1$s
+ Håndter forbruksmålte Wi-Fi-nettverk
+ Anse 2G for å ikke være forbruksmålt
+ Anse 3G for å ikke være forbruksmålt
+ Anse LTE for å ikke være forbruksmålt
+ Ignorer innenriks-roaming
+ Ignorer EU-roaming
+ Skru av ved telefonanrop
+ Skru av Wi-Fi
+ Skru av mobilnett
+ Last inn på nytt ved hvert nettverksskifte
+ Avanserte innstillinger
+ Behandle systemapper
+ Loggfør internettilgang
+ Meld ifra om internettilgang
+ Filtrer trafikk
+ Sett_filter_udp
+ Lukk tilkoblinger ved ominnlastinger
+ Skru av trafikk
+ Spor nettverksbruk
+ Tilbakestill nettverksbruk
+ Vis oppklarte domenenavn
+ Blokker domenenavn
+ DNS-responskode: %s
+ Portvideresending
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Valider på: %s
+ Minimum DNS TTL: %s s
+ Bruk SOCKS5-mellomtjener
+ SOCKS5-adresse: %s
+ SOCKS5-port: %s
+ SOCKS5-brukernavn: %s
+ SOCKS5-passord: %s
+ PCAP-loggstørrelse: %s B
+ PCAP sin maks filstørrelse: %s MB
+ Vakthund: Hvert %s. minutt
+ Fartsvarsling
+ Vis fartsvarslingen
+ Vis toppappene
+ Utdragsintervall: %s ms
+ Antall utdrag: %s s
+ Sikkerhetskopier
+ Eksporter innstillingene
+ Importér innstillinger
+ Importer «hosts»-fil
+ Importer hosts-fil (legges ved)
+ «hosts»-filnedlastningsnettadresse
+ Last ned «hosts»-fil
+ Teknisk informasjon
+ Generelt
+ Nettverk
+ Abonnementer
+ Se etter nye utgivelser på GitHub to ganger daglig
+ Aktiver ruting på nettet; kan aktivere Wi-Fi-anrop, men kan også utløse feil i Android og øke batteribruken
+ Tillat apper å koble seg til lokale nettverksadresser, for eksempel 10.0.0.0/8, 172.16.0.0/12 og 192.168.0.0/16
+ Rute IP versjon 6-trafikk til NetGuard slik at den selektivt kan tillates eller blokkeres
+ Logg forsøker å få tilgang til internett for apper. Dette kan føre til ekstra batteribruk.
+ Filtrer utgående IP-pakker fra VPN-tunnelen. Dette kan føre til ekstra batteribruk.
+ Spor antall bytes sendt og mottatt for hver app og adresse. Dette kan medføre ekstra batteriforbruk.
+ Bare TCP-trafikk vil bli sendt til proxy-serveren
+ Vis nettverkshastighetsgraf i statuslinjevarsling
+ Er du sikker?
+ Overholder regler
+ %1$d tillatt, %2$d blokkert
+ %1$d tillatt, %2$d blokkert, %3$d verter
+ Avventer hendelse
+ NetGuard er deaktivert, bruk bryteren ovenfor for å aktivere NetGuard
+ NetGuard er deaktivert, sannsynligvis ved å bruke en annen VPN-basert app
+ \'%1$s\' installert
+ Har blitt installert
+ %1$s forsøk på Internettilgang
+ Forsøk på Internettilgang
+ Handlingen er utført
+ NetGuard bruker en lokal VPN for å filtrere internettrafikk.
+Av denne grunn kan du tillate en VPN-tilkobling i neste dialog.
+Internett-trafikken din blir ikke sendt til en ekstern VPN-server.
+ NetGuard kunne ikke starte automatisk. Dette er sannsynligvis på grunn av en feil i Android-versjonen din.
+ En uventet feil har oppstått: \'%s\'
+ Android nektet å starte VPN-tjenesten i dette øyeblikket. Dette er sannsynligvis på grunn av en feil i Android-versjonen din.
+ Prøv NetGuard
+ Ved å donere godtar du vilkår og betingelser
+ Dersom du ikke kan trykke OK i neste dialog, er det mulig at en annen (skjermdimmings-)app påvirker skjermen.
+ ± %1$.3f▲ %2$.3f▼ MB/dag
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Android 4 krever filtrering for å bli aktivert
+ Trafikkloggføring er deaktivert, bruk bryteren ovenfor for å aktivere loggføring. Trafikkloggføring kan føre til ekstra batteriforbruk.
+ Dette vil tilbakestille reglene og forholdene til sine standardverdier
+ Dette vil slette tilgangsforsøks-loggføringslinjer som ikke har tillatelses- eller blokkerings-regler
+ Seneste importering: %s
+ Laster ned\n%1s
+ «hosts»-filen har blitt lastet ned
+ Seneste nedlastning: %s
+ Vil du avslutte viderekoblingen av %1$s-porten %2$d?
+ Nettverket er forbrukspriset
+ Ingen aktiv internettforbindelse
+ NetGuard er opptatt
+ En oppdatering er tilgjengelig, trykk for å laste ned
+ Trafikken er stengt av
+ Ikke-forbruksmålt trafikk er tillatt
+ Ikke-forbruksmålt trafikk er blokkert
+ U-forbruksmålte regler er ikke i bruk
+ Forbruksmålt trafikk er tillatt
+ Forbruksmålt trafikk er blokkert
+ Forbruksmålte regler er ikke i bruk
+ Adressen er tillatt
+ Adressen er blokkert
+ Tillat når skjermen er skrudd på
+ Blokker under roaming
+ Som standard er en Wi-Fi-tilkobling ansett for å ikke være forbruksmålt, mens en mobilnettilkobling ansees for å være forbruksmålt
+ har ikke tilgang til internettet
+ er skrudd av
+ Benytt regler og forhold
+ Forhold
+ Tillat Wi-Fi når skjermen er skrudd på
+ Tillat mobilnett når skjermen er skrudd på
+ R
+ Blokker under roaming
+ Filtrer relaterte
+ Tilgangsforsøk
+ Tilgangsregler tar presedens over andre regler
+ Innstillinger
+ Meld ifra om internettilgangsforsøk
+ Loggføring eller filtrering er ikke skrudd på
+ Loggføring og filtrering er skrudd på
+ Sett opp
+ Aktiver tilgangsvarsler for nylig loggførte adresser
+ Disse innstillingene er globale innstillinger som gjelder for alle apper
+ Filtrering er også nødvendig for å tillate eller blokkere individuelle adresser
+ Aktivering av logging (mindre) eller filtrering (mer) kan øke batteribruken og kan påvirke nettverkshastigheten
+ Vurder
+ Tillat
+ Blokker
+ Tillat Wi-Fi
+ Blokker Wi-Fi
+ Tillat mobilnett
+ Blokker mobilnett
+ root
+ medietjener
+ ingen
+ Ikke spør igjen
+ Whois %1$s
+ Port %1$d
+ Kopier
+ Pro-funksjoner
+ De følgende Pro-funksjonene er tilgjengelige:
+ Vis loggboken over blokkert trafikk
+ Filtrer nettverkstrafikk
+ Nye appvarslinger
+ Nettverksfartsgrafvarsling
+ Utseende (tema, farger)
+ Alle ovenstående Pro-funksjoner
+ Støtt utviklingen
+ Kjøp
+ Aktivert
+ Utilgjengelig
+ Trykk på en tittel for mere informasjon
+ Utfordring
+ Svar
+ Dette er en Pro-funksjon
+
+ - teal/orange
+ - blå/oransje
+ - lilla/rød
+ - amber/blue
+ - oransje/grå
+ - grønn
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-or-rIN/strings.xml b/NetGuard/app/src/main/res/values-or-rIN/strings.xml
new file mode 100644
index 0000000..8d279de
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-or-rIN/strings.xml
@@ -0,0 +1,55 @@
+
+
+ ମୁଁ ସହମତ
+ ମୁଁ ସହମତ ନୁହେଁ
+ ସେଟିଂସମୂହ
+ ସମର୍ଥନ
+ ବିଷୟରେ
+ ଅନ୍ୟ
+ ପ୍ରୋଟୋକଲ୍
+ ଥିମ୍: %1$s
+ ଗାଢ଼ ଥିମ୍ ବ୍ୟବହାର କରିବା
+ SOCKS5 ପ୍ରକ୍ସି ବ୍ୟବହାର କରିବା
+ ବ୍ୟାକଅପ୍
+ ସେଟିଂସ୍ ରପ୍ତାନି କରନ୍ତୁ
+ ସେଟିଂସ୍ ଆମଦାନୀ କରନ୍ତୁ
+ ସାଧାରଣ
+ ± %1$.3f▲ %2$.3f▼ MB/ଦିନ
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dଗୁଣ
+ ସର୍ତ୍ତାବଳୀ
+ R
+ ବିକଳ୍ପଗୁଡ଼ିକ
+ ବିନ୍ୟାସ କରନ୍ତୁ
+ ମୂଲ୍ୟାୟନ
+ ଅନୁମତି ଦିଅନ୍ତୁ
+ ଅବରୋଧ କରନ୍ତୁ
+ ପୁଣି ପଚାରନ୍ତୁ ନାହିଁ
+ କପି କରନ୍ତୁ
+ ପ୍ରୋ ବୈଶିଷ୍ଟ୍ୟଗୁଡ଼ିକ
+ ନିମ୍ନଲିଖିତ ପ୍ରୋ ବୈଶିଷ୍ଟ୍ୟଗୁଡ଼ିକ ଉପଲବ୍ଧ ଅଛି:
+ ରୂପ (ଥିମ୍, ରଙ୍ଗ)
+ ସମସ୍ତ ଉପରୋକ୍ତ ପ୍ରୋ ବୈଶିଷ୍ଟ୍ୟଗୁଡ଼ିକ
+ ବିକାଶକୁ ସମର୍ଥନ କରନ୍ତୁ
+ କିଣନ୍ତୁ
+ ସକ୍ଷମ ହୋଇଛି
+ ଅନୁପଲବ୍ଧ
+ ଅଧିକ ସୂଚନା ପାଇଁ ଏକ ଆଖ୍ୟା ଉପରେ ଟ୍ୟାପ୍ କରନ୍ତୁ
+ ଆହ୍ବାନ
+ ପ୍ରତିକ୍ରିୟା
+ ଏହା ଏକ ପ୍ରୋ ବୈଶିଷ୍ଟ୍ୟ
+
+ - ଟିଲ୍/କମଳା
+ - ନୀଳ/କମଳା
+ - ବାଇଗଣୀ/ନାଲି
+ - ଆମ୍ବର/ନୀଳ
+ - କମଳା/ଧୂସର
+ - ସବୁଜ
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-pl-rPL/strings.xml b/NetGuard/app/src/main/res/values-pl-rPL/strings.xml
new file mode 100644
index 0000000..598533a
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-pl-rPL/strings.xml
@@ -0,0 +1,288 @@
+
+
+ NetGuard umożliwia w prosty i zaawansowany sposób zarządzać dostępem do Internetu - root nie jest wymagany. Można zezwolić bądź zabronić dostępu do Twojego Wi-Fi i/lub połączenia mobilnego indywidualnym aplikacjom lub do wybranych adresów IP.
+ NetGuard wymaga systemu Android 5.1 lub nowszego
+ Xposed może powodować wiele błędów w działaniu aplikacji, które mogą skutkować usunięciem aplikacji NetGuard ze Sklepu Play, z tego też powodu NetGuard nie jest wspierany w przypadku istniejącej instalacji Xposed
+ Polityka prywatności
+ Z wielką starannością opracowano i przetestowano NetGuard. Nie można jednak zagwarantować bezbłędnego działania na wszystkich urządzeniach.
+ Zgadzam się
+ Nie zgadzam się
+ NetGuard potrzebuje Twojej pomocy. Kliknij, aby zakupić funkcje pro i wspomóc dalszy rozwój projektu.
+ Uruchomione usługi
+ Ogólne powiadomienia
+ Powiadomienia dostępu
+ Szukaj aplikacji
+ Filtruj aplikacje
+ Pokaż aplikacje użytkownika
+ Pokaż aplikacje systemowe
+ Pokaż aplikacje bez Internetu
+ Pokaż aplikacje wyłączone
+ Sortuj aplikacje
+ Sortuj wg nazwy
+ Sortuj wg uid
+ Sortuj wg użycia danych
+ Wyświetl dziennik
+ Ustawienia
+ Zaproś
+ Legenda
+ Wsparcie
+ Informacje o aplikacji
+ Inne aplikacje
+ Inne
+ Dozwolone
+ Zablokowane
+ Aktualizacje
+ Odśwież
+ Pokaż nazwy
+ Pokaż organizację
+ PCAP włączone
+ Eksport PCAP
+ Wyczyść
+ Eksportuj
+ Resetuj
+ Dodaj
+ Usuń
+ Wyczyść
+ Protokół
+ Port źródłowy
+ Adres docelowy
+ Port docelowy
+ Docelowa aplikacja
+ Dla serwera zewnętrznego wybierz \'nobody\'
+ Domyślne (biała/czarna lista)
+ Blokuj Wi-Fi
+ Blokuj dane komórkowe
+ Zezwól na Wi-Fi przy włączonym ekranie
+ Zezwól na dane komórkowe przy włączonym ekranie
+ Blokuj roaming
+ Opcje
+ Motyw: %1$s
+ Użyj ciemny motyw
+ Powiadamiaj o nowych instalacjach
+ Aktywuj reguły \"Gdy ekran włączony\"
+ Automatyczne włączenie po %1$s min
+ Opóźnienie wyłączenia reguł ekranu %1$s min
+ Sprawdź aktualizacje
+ Opcje sieciowe
+ Podsieci routingu
+ Umożliwiaj tethering
+ Zezwalaj na dostęp do sieci LAN
+ Włącz ruch IPv6
+ Gniazdo sieci Wi-Fi: %1$s
+ Obsługuj taryfowe sieci Wi-Fi
+ Przyjmuj 2G za nietaryfowe
+ Przyjmuj 3G za nietaryfowe
+ Przyjmuj LTE za nietaryfowe
+ Ignoruj roaming krajowy
+ Ignoruj roaming w EU
+ Zablokuj w czasie rozmowy
+ Zablokuj WiFi
+ Zablokuj internet mobilny
+ Załaduj przy każdej zmianie rodzaju połączenia
+ Opcje zaawansowane
+ Zarządzaj aplikacjami systemowymi
+ Loguj dostęp do internetu
+ Powiadom o próbie dostępu do internetu
+ Filtruj ruch
+ Filtruj ruch UDP
+ Płynne przekazywanie VPN po przeładowaniu
+ Zamknij połączenia i połącz ponownie
+ Zablokuj ruch sieciowy
+ Rejestruj użycie sieci
+ Resetuj użycie sieci
+ Uaktywnij translację adresów na domeny
+ Blokuj nazwy domen
+ Kod odpowiedzi DNS: %s
+ Przekierowanie portów
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Potwierdź w: %s
+ Minimalny DNS TTL: %s s
+ Użyj serwera proxy SOCKS5
+ Adres SOCKS5: %s
+ Port SOCKS5: %s
+ Użytkownik SOCKS5: %s
+ Hasło SOCKS5: %s
+ Wielkość rekordu PCAP: %s B
+ Maksymalna wielkość pliku PCAP: %s MB
+ Watchdog: co %s minut
+ Wykres prędkości
+ Pokazuj wskaźnik prędkości
+ Pokaż aplikacje z najwyższym transferem
+ Częstotliwość próbkowania: %s ms
+ Ilość próbek: %s s
+ Kopia zapasowa
+ Eksportuj ustawienia
+ Importuj ustawienia
+ Importuj plik hosts
+ Importuj plik hosts (podłącz)
+ Adres URL pliku hosts
+ Pobierz plik hosts
+ Informacje techniczne
+ Główne
+ Sieci
+ Subskrypcje
+ Pokaż powiadomienia w pasku statusu by bezpośrednio skonfigurować nowo zainstalowane aplikacje (wersja Pro)
+ Po wyłączeniu poprzez widget, automatycznie włącz NetGuard po podanej liczbie minut (wprowadzenie zera wyłącza tą opcję)
+ Po wyłączeniu ekranu, podtrzymuj działanie reguły \"Zezwól na ... przy włączonym ekranie\" przez podaną liczbę minut (wprowadzenie zera wyłącza tą opcję)
+ Sprawdzaj nowe wersje na GitHub, dwa razy dziennie
+ W zależności od wersji Androida tethering może działać bądź nie. Ruch tetheringu nie może być filtrowany.
+ Włączanie routingu podsieci; może umożliwić rozmowy przez WiFi, ale może również powodować błędy w systemie Android i zwiększyć zużycie baterii
+ Pozwól aplikacjom łączyć się z adresami sieci lokalnej, takimi jak 10.0.0.0/8, 172.16.0.0/12 i 192.168.0.0/16
+ Przekieruj ruch IPv6 do NetGuard, aby ruch był wybiórczo dozwolony lub zablokowany
+ Zastosuj reguły sieci Wi-Fi tylko do zaznaczonej sieci (do pozostałych sieci Wi-Fi zastosowane zostaną reguły sieci komórkowej)
+ Zastosuj reguły z danych komórkowych, do taryfowych sieci Wi-Fi (tethering, prepaid)
+ Zastosuj reguły sieci Wi-Fi do połączeń 2G
+ Zastosuj reguły sieci Wi-Fi do połączeń 3G
+ Zastosuj reguły sieci Wi-Fi do połączeń LTE
+ Nie stosuj ustawień dotyczących roamingu, gdy karta SIM oraz sieć komórkowa są z tego samego kraju
+ Nie stosuj ustawień dotyczących roamingu, gdy karta SIM oraz sieć komórkowa są z tego samego kraju (roaming krajowy)
+ Wyłącz NetGuard w czasie przychodzących lub wychodzących połączeń telefonicznych. To może być pomocne przy rozwiązywaniu problemów podczas wykonywania połączeń VoIP / WiFi.
+ Stwórz reguły dla aplikacji systemowych (zaawansowane)
+ Zapisuj próby uzyskania dostępu do internetu przez aplikacje. Może spowodować większe użycie baterii.
+ Pokaż powiadomienia w pasku stanu, gdy aplikacja próbuje uzyskać dostęp do nowego adresu IP (w przypadku gdy filtrowanie jest wyłączone, tylko zablokowane próby dostępu do internetu zostaną pokazane)
+ Filtruj pakiety wychodzące z tunelu VPN. Może spowodować większe użycie baterii.
+ Rejestruj ilość bajtów wysłanych i odebranych dla każdej aplikacji i adresu. Może zwiększyć użycie baterii.
+ Odpowiadaj jako skonfigurowana odpowiedź DNS dla zablokowanych nazw domen. Przełącznik ten jest wyłączony gdy plik hosts nie jest dostępny.
+ Wartość domyślna to 3 (NXDOMAIN), co oznacza \'nieistniejąca domena\'.
+ Nazwa domeny używanej do weryfikacji połączenia z Internetem w porcie 443 (https).
+ Tylko ruch TCP zostanie przesłany do serwera proxy
+ Sprawdź okresowo, czy NetGuard nadal działa (wpisz zero, aby wyłączyć tę opcję). Może to spowodować większe zużycie baterii.
+ Pokazuj wykres prędkości sieci w powiadomieniach aplikacji
+ Czy jesteś pewien?
+ Wymuś Reguły
+ %1$d dozwolone, %2$d zablokowane
+ %1$d zezwolono, %2$d zablokowano, %3$d hosts
+ Czekam na zdarzenie
+ NetGuard jest wyłączony, użyj przełącznika u góry by go uruchomić
+ NetGuard został wyłączony, prawdopodobnie poprzez inną aplikację bazującą na VPN
+ \'%1$s\' zainstalowane
+ Został zainstalowany
+ %1$s żąda dostępu do internetu
+ Próba dostępu do Internetu
+ Wykonano
+ NetGuard używa lokalnego VPN aby filtrować ruch. Z tego powodu proszę umożliwić połączenie VPN w kolejnym oknie dialogowym. Twój ruch internetowy nie będzie wysyłany do zdalnego serwera VPN.
+ NetGuard nie może zostać uruchomiony automatycznie przy starcie systemu ze względu na błąd w twojej wersji Androida
+ Wystąpił nieoczekiwany błąd: \'%s\'
+ System nie może uruchomić usługi VPN w tej chwili. Jest to prawdopodobnie ze względu na błąd w wersji systemu Android.
+ Wypróbuj NetGuard
+ Przekazując darowiznę wyrażam zgodę na terms & conditions
+ Jeśli nie możesz nacisnąć OK w następnym oknie, prawdopodobnie inna aplikacja zarządza ekranem (przygaszanie ekranu).
+ ± %1$.3f▲ %2$.3f▼ MB/dzień
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Dla spójnych rezultatów, należy wyłączyć optymalizację baterii w systemie Android dla NetGuard. \n\n W następnym oknie dialogowym, wybierz \"Wszystkie aplikacje\" na górze, naciśnij NetGuard na liście i wybierz \"Nie optymalizuj\" potwierdzając przyciskiem \"Gotowe\".
+ W celu osiągnięcia lepszych rezultatów, ograniczenie zużycia danych w systemie powinno być wyłączone dla aplikacji NetGuard \n\n |W następnym oknie dialogowym, włącz opcje \"Dane w tle\" i \"Transmisja danych bez ograniczeń\"
+ Użycie filtrowanie spowoduje, że Android przekaże sterowanie użyciem danych do NetGuard - Android będzie używał NetGuard zamiast dedykowanej aplikacji do kontroli danych
+ Android w wersji 4 wymaga aktywnej funkcji filtrowania
+ Logowanie ruchu jest wyłączone, użyj przełącznika aby włączyć. Logowanie ruchu może zwiększyć użycie baterii.
+ Spowoduje to zresetowanie reguł i warunków do wartości domyślnych
+ Spowoduje to usunięcie zawartości logu dostępu do internetu bez reguł zezwól/blokuj
+ Ostatni import: %s
+ Pobieranie\n%1s
+ Plik hosts pobrany
+ Ostatnio pobrane: %s
+ Rozpocząć przekierowanie z %1$s port %2$d do %3$s:%4$d przez \'%5$s\'?
+ Zatrzymać przekierowanie z %1$s port %2$d?
+ Sieć jest taryfowa
+ Brak aktywnego połączenia z Internetem
+ NetGuard jest zajęty
+ Aktualizacja jest dostępna, stuknij aby pobrać
+ Można zezwolić (zielonkawy) lub zablokować (czerwonawy) dostęp do Wi-Fi lub internetu mobilnego poprzez dotknięcie ikony obok aplikacji
+ Jeśli zainstalowałeś NetGuard w celu ochrony swojej prywatności, możesz być również zainteresowany FairEmail , klientem poczty e-mail o otwartym kodzie źródłowym
+ Dostęp do Internetu jest dozwolony domyślnie (tryb \"czarna lista\"). To można zmienić w ustawieniach
+ Przychodzące wiadomości (push) są głównie obsługiwane przez składnik systemowej usługi Play, który domyślnie ma dostęp do Internetu
+ Zarządzanie wszystkimi (systemowymi) aplikacjami może być włączone w ustawieniach
+ Prosimy o opisanie problemu i wskazanie czasu, kiedy wystąpił problem:
+ Połączenie do sieci VPN anulowane\n Czy ustawiłeś inne połączenie VPN, w trybie zawsze włączone?
+ Wyłączenie urządzenia z już uruchomioną aplikacją, spowoduje automatyczne uruchomienie aplikacji NetGuard po włączeniu urządzenia
+ Ta funkcja nie jest dostępna w tej wersji
+ Inny usługa VPN jest ustawiona jako \"Włączony zawsze\"
+ Wyłącz „Blokuj połączenie bez VPN” w ustawieniach VPN systemu Android, aby korzystać z trybu filtrowania NetGuard
+ Wyłącz „Prywatny DNS” w ustawieniach sieci Androida, aby używać NetGuard w trybie filtrowania
+ Ruch sieciowy zablokowany
+ Połączenia nietaryfowe są dozwolone
+ Połączenia nietaryfowe są zablokowane
+ Zasady \'Połączenia nielimitowane\' nie są stosowane
+ Połączenia taryfowe są dozwolone
+ Połączenia taryfowe są zablokowane
+ Zasady \'Połączenia limitowane\' nie są stosowane
+ Adres jest dozwolony
+ Adres jest zablokowany
+ Zezwól gdy ekran jest włączony
+ Blokuj gdy roaming
+ Domyślnie połączenie Wi-Fi jest uważane za nietaryfowe a połączenie komórkowe za taryfowe
+ brak uprawnień do Internetu
+ jest niesprawny
+ Wiadomości przychodzące są odbierane przez usługi Google Play, a nie przez tę aplikację i dlatego nie mogą być blokowane przez zablokowanie tej aplikacji
+ Pobieranie jest wykonywane przez menedżera pobierania, a nie przez tę aplikację i dlatego nie może być zablokowane przez zablokowanie tej aplikacji
+ Zastosuj reguły i warunki
+ Warunki
+ Zezwól na Wi-Fi przy włączonym ekranie
+ Zezwól komórkowe przy włączonym ekranie
+ R
+ Blokuj gdy roaming
+ Zezwalaj w trybie blokady
+ Powiązane z filtrowaniem
+ Próby dostępu
+ Reguły dostępu mają pierwszeństwo przed innymi regułami
+ Opcje
+ Powiadom o próbach dostępu do internetu
+ Rejestrowanie i filtrowanie są wyłączone
+ Rejestrowanie i filtrowanie są włączone
+ Konfiguracja
+ Włącz rejestrowanie tylko zablokowanych adresów
+ Włącz filtrowanie do rejestrowania również dozwolonych adresów
+ Włącz powiadomienia dostępu dla nowo zarejestrowanych adresów
+ Te ustawienia są ustawieniami globalnymi, które mają zastosowanie do wszystkich aplikacji
+ Filtrowanie jest również wymagane, aby umożliwić lub zablokować poszczególne adresy
+ Włączanie rejestrowania (mniej) lub filtrowanie (więcej) może zwiększyć zużycie baterii i może wpływać na prędkość połączeń sieciowych
+ Oceń
+ Zezwól
+ Blokuj
+ Zezwalaj WiFi
+ Blokuj WiFi
+ Zezwalaj internet mobilny
+ Blokuj internet mobilny
+ root
+ mediaserver
+ nobody
+ Nie pytaj więcej
+ Whois %1$s
+ Port %1$d
+ Kopiuj
+ Funkcje Pro
+ Dostępne są następujące funkcje pro:
+ Pokaż log ruchu blokowanego
+ Filtruj ruch sieciowy
+ Powiadomienia z nowych aplikacji
+ Wykres prędkości sieci w powiadomieniach
+ Wygląd (motyw, kolor)
+ Wszystkie powyższe cechy Pro
+ Wesprzyj rozwój
+ Kup
+ Włączone
+ Niedostępny
+ Kliknij na tytuł aby uzyskać więcej informacji
+ Wezwanie
+ Odpowiedź
+ Jest to funkcja Pro
+ Miesięczne subskrypcje w wysokości 1 lub 2 euro (nie licząc lokalnego opodatkowania) aktywują wszystkie funkcje pro.
+ Możesz anulować lub zarządzać subskrypcją w zakładce subskrypcji w aplikacji Sklep Play.
+
+
+ - teal/orange
+ - blue/orange
+ - purple/red
+ - amber/blue
+ - orange/grey
+ - zielony
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-pt-rBR/strings.xml b/NetGuard/app/src/main/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..2432028
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-pt-rBR/strings.xml
@@ -0,0 +1,291 @@
+
+
+ NetGuard fornece maneiras simples e avançadas para bloquear o acesso à internet - sem necessidade de root. Apps e endereços podem ter o acesso permitido ou negado individualmente via Wi-Fi e ou dados móveis.
+ NetGuard requer Android versão 5.1 ou superior
+ Xposed provoca muitos erros, que podem resultar no NetGuard sendo removido da Google Play Store, portanto NetGuard não é suportado quando o Xposed estiver instalado
+ Política de privacidade
+ Muito cuidado foi tomado para desenvolver e testar o NetGuard, entretanto, é impossível garantir que o NetGuard funcionará corretamente em todos os dispositivos.
+ Eu concordo
+ Eu discordo
+ NetGuard precisa da sua ajuda. Toque para comprar Recursos Pro para manter o projeto.
+ Serviços em execução
+ Notificações Gerais
+ Acessar notificações
+ Buscar aplicativo
+ Filtrar aplicativos
+ Mostrar apps do usuário
+ Mostrar apps do sistema
+ Mostrar apps sem internet
+ Mostrar apps desabilitados
+ Ordenar aplicativos
+ Ordenar por nome
+ Ordenar por uid
+ Ordenar por uso de dados
+ Mostrar registro
+ Configurações
+ Convidar
+ Legenda
+ Suporte
+ Sobre
+ Outros apps
+ Outros
+ Permitido
+ Bloqueado
+ Atualizações em tempo real
+ Atualizar
+ Mostrar nomes
+ Mostrar organização
+ PCAP ativado
+ Exportar PCAP
+ Limpar
+ Exportar
+ Resetar
+ Adicionar
+ Deletar
+ Limpeza
+ Protocolo
+ Porta de origem
+ Endereço de destino
+ Porta de destino
+ Aplicativo de destino
+ Para um servidor externo, selecione \'ninguém\'
+ Padrões (lista branca/negra)
+ Bloquear Wi-Fi
+ Bloquear Dados Móveis
+ Permitir Wi-Fi ao ligar a tela
+ Permitir Dados Móveis ao ligar a tela
+ Bloquear roaming
+ Opções
+ Tema: %1$s
+ Utilizar tema escuro
+ Notificar sobre novas instalações
+ Aplicar regras \'quando tela estiver ligada\'
+ Auto habilitar após %1$s minutos
+ Atraso de %1$s minutos após desligar o ecrã
+ Procurar por atualizações
+ Opções de rede
+ Roteamento de subrede
+ Permitir tethering
+ Permitir acesso à rede local
+ Habilitar tráfego IPv6
+ Redes Wi-Fi Domésticas: %1$s
+ Manipular redes Wi-Fi Limitadas
+ Considerar 2G ilimitado
+ Considerar 3G ilimitado
+ Considerar 4G ilimitado
+ Ignorar roaming nacional
+ Ignorar roaming EU
+ Desativar durante ligações
+ Bloqueio total de Wi-Fi
+ Bloqueio total de Dados Móveis
+ Atualizar a cada alteração de conectividade
+ Opções avançadas
+ Administrar aplicativos do sistema
+ Registrar acesso à internet
+ Notificar ao acessar a internet
+ Filtrar tráfego
+ Filtrar tráfego UDP
+ Transição VPN automática ao recarregar
+ Fechar conexões ao recarregar
+ Bloqueio total de tráfego
+ Controlar o uso de rede
+ Redefinir o uso da rede
+ Mostrar nomes de domínio resolvidos
+ Bloquear nomes de domínio
+ Código de resposta DNS:%s
+ Encaminhamento de porta
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Validar em: %s
+ DNS TTL Mínimo: %s s
+ Usar proxy SOCKS5
+ Endereço do SOCKS5: %s
+ Porta do SOCKS5: %s
+ Nome de usuário do SOCKS5: %s
+ Senha de usuário do SOCKS5: %s
+ Tamanho de registro PCAP: %s B
+ Tamanho máximo de arquivo PCAP: %s MB
+ Monitoramento: a cada %s minutos
+ Notificação de velocidade
+ Mostrar notificação de velocidade
+ Mostrar apps mais usados
+ Freqüência da amostra: %s ms
+ Número de amostras: %s s
+ Backup
+ Exportar configurações
+ Importar configurações
+ Importar arquivos de hosts
+ Importar arquivo de hosts (anexar)
+ URL de download de arquivos de hosts
+ Baixar arquivos de hosts
+ Informações técnicas
+ Geral
+ Redes
+ Inscrições
+ Mostrar notificação na barra de status para configurar aplicativos recém-instalados (Versão Pro)
+ Após desabilitar usando o widget, automaticamente habilitar outra vez após o número de minutos selecionados
+(Insira zero para desabilitar essa opção)
+ Após desligar tela, manter as regras ativas pelo número de minutos selecionados (digite 0 para desabilitar essa opção)
+ Procurar por novos releases no GitHub duas vezes ao dia
+ Dependendo da versão do Android, tethering pode não funcionar. Trafego via tethering não pode ser filtrado.
+ Ativa o roteamento de sub-rede; pode ativar chamada de Wi-Fi, mas pode também desencadear bugs no Android e aumentar o uso da bateria
+ Permitir que os aplicativos se conectem a endereços de rede local, como 10.0.0.0/8, 172.16.0.0/12 e 192.168.0.0/16
+ Rotear o tráfego IP versão 6 para o NetGuard para então, seletivamente, ser permitido ou bloqueado
+ Aplicar regras Wi-Fi somente a rede selecionada (aplica regras de dados móveis à outras redes Wi-Fi)
+ Aplicar regras de Dados Móveis a redes Wi-Fi limitadas (pagas, via tethering)
+ Aplicar regras Wi-Fi para conexões 2G
+ Aplicar regras Wi-Fi para conexões 3G
+ Aplicar regras Wi-Fi para conexões 4G
+ Não aplicar regras de roaming quando o chip SIM e a rede móvel forem do mesmo país
+ Não aplicar regras de roaming quando o país do cartão SIM e da rede móvel estiverem dentro da EU (roaming como em casa)
+ Desabilite NetGuard ao receber ou realizar chamadas. Isso pode ser usado para contornar problemas em chamadas IP/Wi-Fi.
+ Definir regras para aplicativos do sistema (usuários experientes)
+ Registar tentativas de acesso à internet para aplicações. Isto pode resultar no uso extra da bateria.
+ Mostrar uma notificação na barra de notificações quando um aplicativo tentar acessar um novo endereço de internet (quando a filtragem é desativada, apenas tentativas de acesso de internet bloqueados serão notificadas)
+ Filtrar pacotes de IP que saem da VPN. Isso pode resultar em um maior uso da bateria.
+ Controle o número de bytes enviados e recebidos para cada aplicativo e endereço. Isso pode resultar no uso da bateria extra.
+ Responde os pedidos DNS com o código de resposta configurado para bloqueio de nomes de domínio. Esta opção é desabilitada quando não houver arquivo hosts disponível.
+ O valor padrão é 3 (NXDDOMAIN), que significa \'domínio não existente\'.
+ Nome do domínio utilizado para validar a conexão de internet na porta 443 (https).
+ Somente tráfico TCP será enviado ao servidor proxy
+ Verificar periodicamente se NetGuard ainda está rodando (coloque zero para desativar essa opção). Isso pode resultar em consumo adicional de bateria.
+ Mostrar gráfico de velocidade da rede na barra de notificação
+ Tem certeza?
+ Impondo Regras
+ %1$d permitido, %2$d bloqueado
+ %1$d permitido, %2$d bloqueado, %3$d hosts
+ Aguardando evento
+ NetGuard desativado, use o interruptor acima para ativá-lo
+ NetGuard foi desativado, provavelmente outro aplicativo baseado em VPN esta sendo usado
+ \'%1$s\' instalado
+ Foi instalado
+ %1$s não tem acesso à internet
+ Tentativa de acesso à Internet
+ Ação concluída
+ NetGuard usa uma VPN local para filtrar o tráfego de internet.
+Por este motivo, por favor, permita uma conexão VPN na caixa de diálogo seguinte.
+O seu tráfego de internet não está sendo enviado para um servidor VPN remoto.
+ NetGuard não pôde ser iniciado automaticamente. A causa mais provável seria um bug na sua versão do Android.
+ Um erro inesperado ocorreu: \'%s\'
+ Android recusou-se a iniciar o serviço VPN nesse momento. A causa mais provável seria um bug na sua versão do Android.
+ Testar NetGuard
+ Doando, você concorda com os termos & condições
+ Caso não consiga pressionar OK no dialogo a seguir, então provavelmente algum aplicativo está manipulando a tela (sobreposição sobre outros apps, aplicativos que diminuem o brilho ou alteram a coloração da tela).
+ ± %1$.3f▲ %2$.3f▼ MB/dia
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Para resultados consistentes, as otimizações de bateria Android devem ser desabilitadas para NetGuard. \n\nNa próxima caixa de diálogo, selecione \"Todos os apps\" na parte superior, toque no NetGuard na lista e selecione e confirme \"Não otimizar\".
+ Para resultados consistentes, as opções de guardar dados do Android devem ser desabilitadas para o NetGuard \n\nNa próxima caixa de diálogo, ative as opções \"dados em segundo plano\" e \"uso de dados sem restrições\"
+ Usar filtragem pode fazer com que o Android atribua uso de dados e consumo de energia ao NetGuard - Android assume que o uso de dados e consumo de bateria são usados pelo NetGuard e não pelas aplicações originais
+ Android 4 requer que filtragem esteja acionada
+ Log de tráfego está desabilitado, utilize o botão acima para habilitar o log. Log do tráfego pode resultar no uso extra da bateria.
+ Isto irá redefinir as regras e condições para os seus valores padrões
+ Isto irá apagar as linhas de registo relativas a tentativas de acesso sem regras de permitir/bloquear
+ Última importação: %s
+ Baixando\n%1s
+ Arquivos de hosts baixados
+ Último download: %s
+ Iniciar encaminhamento de %1$s porta %2$d para %3$s:%4$d de \'%5$s\'?
+ Parar encaminhamento de %1$s porta %2$d?
+ A rede é limitada
+ Não há conexão ativa com a internet
+ NetGuard esta ocupado
+ Atualização disponível, toque para baixar
+ Você pode permitir (verde) ou negar (vermelho) Wi-Fi ou acesso à internet móvel clicando nos ícones ao lado de um aplicativo
+ Se você instalou o NetGuard para proteger sua privacidade, você pode estar interessado em FairEmail , um aplicativo de e-mail aberto, amigável à privacidade também
+ Acesso à internet é permitido por padrão, isto pode ser mudado nas definições
+ Mensagens recebidas (por push) são normalmente geridas pelo componente de sistema do aplicativo \"Play Services\", ao qual é permitido o acesso à internet por padrão
+ Gerenciamento de aplicativos do sistema pode ser ativado em opções avançadas
+ Por favor, descreva o problema e indique o momento em que ocorreu:
+ Conexão VPN cancelada\nVocê configurou outra VPN para ser uma VPN sempre ativa?
+ Ao desligar seu dispositivo com o Netguard habilitado, fará com que o Netguard inicie automaticamente após o reinício
+ Este recurso não está disponível nesta versão Android
+ Outra aplicação VPN está definida como VPN sempre ativa
+ Desabilite a opção \"Bloquear conexões sem VPN\" nas configurações de VPN do Android para usar NetGuard em modo filtro
+ Desabilite \"DNS privado\" nas configurações de rede do Android para usar NetGuarf em modo filtro
+ Tráfego está bloqueado
+ Tráfego ilimitado permitido
+ Tráfego ilimitado bloqueado
+ Regras para conexões ilimitadas não são aplicadas
+ Tráfego limitado permitido
+ Tráfego limitado bloqueado
+ Regras para conexões limitadas não são aplicadas
+ Endereço permitido
+ Endereço bloqueado
+ Permitir com a tela ligada
+ Bloquear quando em roaming
+ Por padrão, uma conexão Wi-Fi é considerada ilimitada e uma conexão móvel limitada
+ não tem permissão de acesso a internet
+ está desativado
+ As mensagens são recebidas pelos serviços do Google Play e não por esse aplicativo e por isso não podem ser bloqueadas simplesmente bloqueando esse aplicativo
+ Os downloads são executados pelo gerenciador de downloads e não por esse aplicativo, portanto, não podem ser bloqueados simplesmente bloqueando esse aplicativo
+ Aplicar regras e condições
+ Condições
+ Permitir Wi-Fi com a tela ligada
+ Permitir Dados Móveis com a tela ligada
+ R
+ Bloquear quando em roaming
+ Permitir modo de bloqueio
+ Filtrar relacionados
+ Tentativas de acesso
+ As regras de acesso têm precedência sobre outras regras
+ Opções
+ Notificar tentativas de acesso à internet
+ Registro e filtragem não ativados
+ Registro e filtragem ativados
+ Configurar
+ Habilitar o registro apenas de endereços bloqueados
+ Também habilitar o registro para endereços permitidos
+ Habilitar notificações de acesso para endereços registrados recentemente
+ Essas configurações são configurações globais que se aplicam a todos os apps
+ A filtragem também é necessária para permitir ou bloquear endereços individuais
+ Habilitar o registro (menos) ou a filtragem (mais) geram acréscimos no uso da bateria e pode afetar a velocidade da conexão
+ Avaliar
+ Permitir
+ Bloquear
+ Permitir Wi-Fi
+ Bloquear Wi-Fi
+ Permitir dados móveis
+ Bloquear dados móveis
+ raiz
+ Servidor de Mídia
+ ninguém
+ Não pergunte novamente
+ Whois %1$s
+ Porta %1$d
+ Copiar
+ Versão PRO
+ Os seguintes recursos da versão PRO estão disponíveis:
+ Visualizar registro de tráfego bloqueado
+ Filtrar tráfego de rede
+ Notificação de novos aplicativos
+ Notificação gráfica de velocidade da rede
+ Aparência (tema, cores)
+ Todas as funções PRO acima
+ Ajude no desenvolvimento
+ Comprar
+ Ativado
+ Indisponível
+ Toque em um título para obter mais informações
+ Código de verificação
+ Resposta
+ Essa é uma funcionalidade Pro
+ Uma assinatura mensal de 1 ou 2 euros (excluindo taxas locais) irá ativar todas as funcionalidades Pro.
+ Você pode cancelar ou gerenciar uma assinatura através da guia de assinaturas do aplicativo da Play Store.
+
+
+ - verde-azulado/laranja
+ - azul/laranja
+ - roxo/vermelho
+ - âmbar/azul
+ - laranja/cinza
+ - verde
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-pt-rPT/strings.xml b/NetGuard/app/src/main/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..d771a51
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-pt-rPT/strings.xml
@@ -0,0 +1,288 @@
+
+
+ NetGuard fornece maneiras simples e avançadas para bloquear o acesso à internet - sem exigir o acesso root. As aplicações e os endereços podem ser individualmente permitidas ou negadas para ter acesso à rede Wi-Fi e/ou à rede de telemóveis.
+ NetGuard requer Android 5.1 ou superior
+ Xposed provoca muitas falhas, que podem resultar no NetGuard ser removido da Google Play Store. Portanto, o NetGuard não é suportado enquanto o Xposed estiver instalado
+ Política de privacidade
+ Houve um grande cuidado a desenvolver e testar a NetGuard, contudo é impossível garantir que o NetGuard funcione corretamente em todos os dispositivos.
+ Concordo
+ Discordo
+ NetGuard necessita da sua ajuda. Toque para comprar funcionalidades pro para manter o projeto em andamento.
+ Serviços em execução
+ Notificações gerais
+ Aceder às notificações
+ Procurar por aplicação
+ Filtrar aplicações
+ Mostrar aplicações de utilizador
+ Mostrar aplicações de sistema
+ Mostrar aplicações sem internet
+ Mostrar aplicações desativadas
+ Ordenar aplicações
+ Ordenar por nome
+ Ordenar por uid
+ Ordenar por uso de dados
+ Mostrar registo
+ Definições
+ Convidar
+ Legenda
+ Suporte
+ Sobre
+ Outras aplicações
+ Outro
+ Permitido
+ Bloqueado
+ Atualizações em direto
+ Atualizar
+ Mostrar nomes
+ Mostrar organização
+ PCAP ativado
+ Exportar PCAP
+ Limpar
+ Exportar
+ Repor
+ Adicionar
+ Eliminar
+ Limpeza
+ Protocolo
+ Porta de origem
+ Endereço de destino
+ Porta de destino
+ Aplicação de destino
+ Para um servidor externo, selecione \'ninguém\'
+ Predefinições (lista branca/negra)
+ Bloquear Wi-Fi
+ Bloquear dados móveis
+ Permitir Wi-Fi com o ecrã ligado
+ Com o ecrã ligado permitir dados móveis
+ Bloquear roaming
+ Opções
+ Tema: %1$s
+ Usar tema escuro
+ Notificar nova instalação
+ Aplicar regras \'com ecrã ligado\'
+ Auto habilitar após %1$s minutos
+ Atraso de %1$s minutos após desligar o ecrã
+ Procurar atualizações
+ Opções de rede
+ Encaminhamento subnet
+ Permitir tethering
+ Permitir o acesso à LAN
+ Ativar tráfego IPv6
+ Rede Wi-Fi Doméstica: %1$s
+ Lidar com redes Wi-Fi limitadas
+ Considerar 2G ilimitado
+ Considerar 3G ilimitado
+ Considerar LTE ilimitado
+ Ignorar roaming nacional
+ Ignorar roaming UE
+ Desativar durante chamada
+ Bloquear Wi-Fi
+ Bloquear rede de dados
+ Recarregar em todas as alterações de conectividade
+ Opções avançadas
+ Gerir aplicações do sistema
+ Registar acesso à internet
+ Notificar acesso à internet
+ Filtrar tráfego
+ Filtrar tráfego UDP
+ Controlar o VPN sem interrupção ao recarregar
+ Fechar as conexões ao recarregar
+ Bloquear tráfego
+ Controlar o uso de rede
+ Redefinir o uso de rede
+ Mostrar nomes de domínio resolvidos
+ Bloquear nomes de domínio
+ Código de resposta DNS: %s
+ Reencaminhamento de porta
+ IPv4 VPN: %s
+ VPN IPv6: %s
+ DNS da VPN: %s
+ Validar com: %s
+ TTL mínimo de DNS: %s s
+ Usar proxy SOCKS5
+ Endereço SOCKS5: %s
+ Porto SOCKS5: %s
+ Nome de utilizador SOCKS5: %s
+ Palavra-passe do SOCKS5: %s
+ Tamanho de registo PCAP: %s B
+ Tamanho máx. do ficheiro PCAP: %s MB
+ Watchdog: cada %s minutos
+ Notificação de velocidade
+ Mostrar notificação de velocidade
+ Mostrar aplicações principais
+ Frequência da amostra: %s ms
+ Número de amostras: %s s
+ Cópia de segurança
+ Exportar definições
+ Importar definições
+ Importar ficheiro hosts
+ Importar ficheiro de hosts (acrescentar)
+ URL de descarregamento do ficheiro de hosts
+ Descarregar ficheiro hosts
+ Informações técnicas
+ Geral
+ Redes
+ Subscrições
+ Mostrar notificação na barra de notificações para configurar diretamente aplicações acabadas de instalar (funcionalidade pro)
+ Após desativar usando o widget, ativar automaticamente outra vez após o número de minutos selecionados\nInsira zero para desativar esta opção
+ Após desligar o ecrã, manter as regras ativas pelo número de minutos selecionados (digite 0 para desativar esta opção)
+ Procurar novos lançamentos no GitHub duas vezes por dia
+ Dependendo da versão do Android, o tethering pode ou não funcionar. O tráfego em tethering não pode ser filtrado.
+ Ativar encaminhamento subnet. Pode permitir chamadas em Wi-Fi, mas pode também desencadear erros no Android e aumentar a utilização da bateria
+ Permitir que as aplicações se conectem a endereços de rede local, como 10.0.0.0/8, 172.16.0.0/12 e 192.168.0.0/16
+ Encaminhar tráfego IP versão 6 para o NetGuard para que possa ser seletivamente permitido ou bloqueado
+ Aplicar regras Wi-Fi apenas à rede selecionada (aplica regras de dados móveis às outras redes Wi-Fi)
+ Aplicar regras de dados móveis a redes Wi-Fi partilhadas (pagas, limitadas)
+ Aplicar regras de rede Wi-Fi para ligações de dados em 2G
+ Aplicar regras de rede Wi-Fi para ligações de dados em 3G
+ Aplicar regras de rede Wi-Fi para ligações de dados em LTE
+ Não aplicar regras de roaming quando o cartão SIM e a rede móvel forem do mesmo país
+ Não aplicar regras de roaming quando o país do cartão SIM e da rede móvel estiverem dentro da EU (roaming como em casa)
+ Desactivar o NetGuard em chamadas telefónicas. Isto pode ser usado para contornar problemas de chamadas em IP/Wi-Fi.
+ Definir regras para aplicações de sistema (para utilizadores experientes)
+ Registar tentativas de acesso à internet para aplicações. Isto pode resultar no uso extra da bateria.
+ Mostrar uma notificação na barra de estado quando uma aplicação tenta aceder um endereço de internet novo (quando a filtragem está desativada, só serão indicadas tentativas de acesso bloqueadas)
+ Filtrar pacotes de IP que saem do sumidouro VPN. Isto pode resultar num uso adicional de bateria.
+ Controlar o número de bytes enviados e recebidos para cada aplicação e endereço. Isto pode resultar num uso adicional da bateria.
+ Responder com o código de resposta do DNS configurado para nomes de domínio bloqueados. Esta opção é desativada quando não está disponível nenhum ficheiro hosts.
+ O valor padrão é 3 (NXDOMAIN), que significa \"domínio inexistente\".
+ Nome de domínio utilizado para validar a conexão de Internet na porta 443 (https).
+ Apenas o tráfego TCP será enviado para o servidor proxy
+ Verificar periodicamente se o NetGuard ainda está em execução (introduza zero para desativar esta opção). Isto pode resultar na utilização adicional da bateria.
+ Mostrar gráfico de velocidade da rede na barra de notificação
+ Tem a certeza?
+ A impor regras
+ %1$d permitidos, %2$d bloqueados
+ %1$d permitidos, %2$d bloqueados, %3$d anfitriões
+ A aguardar o evento
+ NetGuard desativado, use o interruptor acima para o ativar
+ NetGuard foi desativado, provavelmente está a ser utilizada outra aplicação que usa uma VPN
+ \'%1$s\' instalado
+ Foi instalada
+ %1$s tentaram acesso à internet
+ Tentativa de acesso à internet
+ Ação concluída
+ NetGuard usa uma VPN local para filtrar o tráfego de internet. Por este motivo, por favor, permita uma conexão VPN na caixa de diálogo seguinte. O seu tráfego de internet não está a ser enviado para um servidor VPN remoto.
+ NetGuard não pôde ser iniciado automaticamente na inicialização por causa de um erro na sua versão do Android.
+ Ocorreu um erro inesperado: \'%s\'
+ Android recusou iniciar o serviço de VPN neste momento. Isto deve-se provavelmente a um erro na sua versão do Android.
+ Testar NetGuard
+ Ao fazer um donativo, concorda com os termos e condições
+ Caso não consiga pressionar OK no diálogo a seguir, então provavelmente alguma aplicação (escurecimento do ecrã) está a manipular o ecrã.
+ ± %1$.3f▲ %2$.3f▼ MB/dia
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Para resultados consistentes, as otimizações de bateria do Android devem ser desativadas para o NetGuard. \n\nNa próxima caixa de diálogo, selecione \"Todas as aplicações\" na parte superior, toque em NetGuard na lista, selecione e confirme \"Não otimizar\".
+ Para resultados consistentes, as opções de guardar dados do Android devem ser desativadas para o NetGuard \n\nNa próxima caixa de diálogo, ative as opções \"dados em segundo plano\" e \"acesso a dados sem restrições\"
+ Usar a filtragem faz com que o Android atribua o uso de dados e energia ao NetGuard - o Android assume que os dados e a energia estão a ser usados pelo NetGuard, e não pelas aplicações efetivas
+ Android 4 requer que a filtragem esteja ativa
+ Registo de tráfego desativado. Use o botão acima para ativar o registo. Registar o tráfego pode resultar numa utilização extra da bateria.
+ Isto irá repor as regras e condições nos seus valores padrão
+ Isto irá apagar as linhas de registo relativas a tentativas de acesso sem regras de permitir/bloquear
+ Última importação: %s
+ A descarregar\n%1s
+ Ficheiro hosts descarregado
+ Último descarregamento: %s
+ Começar o reencaminhamento de %1$s porta %2$d a %3$s:%4$d de \'%5$s\'?
+ Parar o reencaminhamento de %2$d na porta %1$s?
+ Rede é limitada
+ Sem ligação à Internet
+ NetGuard está ocupado
+ Atualização disponível, toque para descarregar
+ Pode permitir (esverdeado) ou negar (avermelhado) o acesso Wi-Fi ou aos dados móveis tocando nos ícones ao lado de uma aplicação
+ Se instalou o NetGuard para proteger a sua privacidade, poderá estar também interessado em FairEmail , uma aplicação de e-mail, de código aberto e amiga da privacidade
+ Acesso à internet é permitido por omissão, isto pode ser mudado nas definições
+ Mensagens push são geridas principalmente pelo componente de serviço do Play, a que é permitido o acesso à internet por omissão
+ A gestão de todas as aplicações de sistema pode ser ativada nas definições
+ Por favor descreva o problema e indique quando ocorreu:
+ Ligação VPN cancelada\nConfigurou outra VPN para estar sempre ligada?
+ Ao desligar o seu dispositivo com o NetGuard ativado, este será iniciado automaticamente ao ligar o dispositivo
+ Este recurso não está disponível nesta versão do Android
+ Outra VPN está definida como VPN sempre ligada
+ Desligar \"Bloquear conexões sem VPN\" nas configurações de VPN do Android para utilizar o modo de filtragem do NetGuard
+ Desligar \"VPN Privada\" nas configurações de rede do Android para utilizar o modo de filtragem do NetGuard
+ Tráfego está bloqueado
+ Tráfego ilimitado é permitido
+ Tráfego ilimitado é bloqueado
+ Regras de dados ilimitados não estão aplicadas
+ Tráfego limitado é permitido
+ Tráfego limitado é bloqueado
+ Regras de dados limitados não estão a ser aplicadas
+ Endereço é permitido
+ Endereço é bloqueado
+ Permitir quando o ecrã está ligado
+ Bloquear quando em roaming
+ Por padrão uma ligação Wi-Fi é considerada ilimitada e uma ligação móvel é considerada limitada
+ não tem permissão de acesso à internet
+ está desativado
+ As mensagens são recebidas pelos serviços Google Play e não por esta aplicação. Por este motivo não podem ser bloqueadas bloqueando esta aplicação
+ Os descarregamentos são realizados pelo gestor de descarregamentos e não por esta aplicação, por isso não podem ser bloqueados pelo bloqueio desta aplicação
+ Aplicar as regras e condições
+ Condições
+ Permitir Wi-Fi quando o ecrã estiver ligado
+ Permitir dados móveis quando o ecrã estiver ligado
+ R
+ Bloquear quando em roaming
+ Permitir em modo de bloqueio
+ Filtrar relacionados
+ Tentativas de acesso
+ As regras de acesso têm precedência sobre outras regras
+ Opções
+ Notificar das tentativas de acesso à internet
+ O registo ou filtragem não está ativo
+ O registo ou filtragem está ativo
+ Configurar
+ Ativar apenas o registo de endereços bloqueados
+ Ativar filtragem para o registo também dos endereços permitidos
+ Ativar acesso às notificações para endereços registados recentemente
+ Estas definições são definições gerais, que se aplicam a todas as aplicações
+ A filtragem também é necessária para permitir ou bloquear endereços individuais
+ Ativando o registo (menos impacto na bateria) ou filtragem (mais impacto) pode aumentar o uso da bateria e pode afetar a velocidade da rede
+ Classificar
+ Permitir
+ Bloquear
+ Permitir Wi-Fi
+ Bloquear Wi-Fi
+ Permitir dados móveis
+ Bloquear dados móveis
+ root
+ mediaserver
+ ninguém
+ Não voltar a perguntar
+ Whois %1$s
+ Porta %1$d
+ Copiar
+ Funcionalidades pro
+ Os seguintes recursos pro estão disponíveis:
+ Visualizar registo de tráfego bloqueado
+ Filtrar o tráfego de rede
+ Notificações de nova aplicação
+ Notificação gráfica de velocidade da rede
+ Aparência (tema, cores)
+ Todos os recursos pro acima
+ Suporte o desenvolvimento
+ Comprar
+ Ativado
+ Indisponível
+ Toque num título para obter mais informações
+ Código de verificação
+ Resposta
+ Esta é uma funcionalidade da versão pro
+ Uma assinatura mensal de 1 ou 2 euros (excluindo impostos locais) ativará todos os recursos profissionais.
+ Pode cancelar ou gerir a assinatura através do guia de assinaturas na aplicação da Play Store.
+
+
+ - verde-azulado/laranja
+ - azul/laranja
+ - roxo/vermelho
+ - âmbar/azul
+ - laranja/cinzento
+ - verde
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-ro-rRO/strings.xml b/NetGuard/app/src/main/res/values-ro-rRO/strings.xml
new file mode 100644
index 0000000..cdfd2c3
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-ro-rRO/strings.xml
@@ -0,0 +1,291 @@
+
+
+ NetGuard oferă modalități simple și avansate de a bloca accesul la internet, ce nu necesită acces root. Accesul aplicațiilor la conexiunile Wi-Fi și/sau mobile poate fi permis sau blocat atât la nivel individual cât și la nivel de adresă.
+ NetGuard necesită Android 5.1 sau mai nou
+ Xposed cauzează prea multe erori care ar putea duce la ștergerea NetGuard din Google Play Store, prin urmare NetGuard nu este suportat atâta timp cât Xposed este instalat
+ Politica de confidențialitate
+ NetGuard este dezvoltat și testat cu mare atenție, cu toate acestea este imposibil de garantat că va funcționa corect pe oricare dispozitiv.
+ Accept
+ Nu accept
+ NetGuard are nevoie de ajutorul dumneavoastră. Atingeți pentru a achiziționa funcții Pro și a susține proiectul.
+ Serviciile care rulează
+ Notificări generale
+ Notificări acces
+ Caută app
+ Filtrează app
+ Arată aplicațiile utilizatorului
+ Arată aplicații de sistem
+ Arată aplicații fără permisiuni internet
+ Arată aplicațiile dezactivate
+ Sortează aplicațiile
+ Sortare după nume
+ Sortare după UID
+ Sortare după traficul de date
+ Arată jurnal
+ Setări
+ Invită
+ Legendă
+ Suport tehnic
+ Despre
+ Alte aplicații
+ Altele
+ Permis
+ Blocat
+ Actualizare în timp real
+ Actualizare
+ Arată nume domenii
+ Arată organizația
+ Activează PCAP
+ Exportă PCAP
+ Golește jurnalul
+ Exportă
+ Resetează
+ Adaugă
+ Şterge
+ Curățare
+ Protocol
+ Portul sursă
+ Adresa de destinație
+ Portul de destinație
+ Aplicație destinație
+ Pentru un server extern alegeți \'Proces fără utilizator\'
+ Setări implicite (listă albă/listă neagră)
+ Blochează Wi-Fi
+ Blochează datele mobile
+ Permite Wi-Fi cu ecranul pornit
+ Permite datele mobile cu ecranul pornit
+ Blochează în roaming
+ Opțiuni
+ Tema: %1$s
+ Folosește tema întunecată
+ Notificare la o instalare nouă
+ Aplică regulile pentru \'ecran pornit\'
+ Activează automat după %1$s minute
+ Întârzie regulile pentru \"ecran oprit\" %1$s minute
+ Verificați dacă există actualizări
+ Opțiuni rețea
+ Rutare subrețea
+ Permite partajarea conexiunii
+ Permite acces LAN
+ Permite traficul IPv6
+ Rețea Wi-Fi de domiciliu: %1$s
+ Gestionați conexiunile Wi-Fi contorizate
+ Consideră 2G necontorizat
+ Consideră 3G necontorizat
+ Consideră 4G/LTE necontorizat
+ Ignoră roamingul național
+ Ignoră roaming în UE
+ Dezactivare în timpul apelului
+ Închide Wi-Fi
+ Închide date mobile
+ Reîncarcă regulile la fiecare schimbare de conectivitate
+ Opțiuni avansate
+ Gestionare aplicații de sistem
+ Înregistrează în jurnal accesul la internet
+ Notifică la accesarea internetului
+ Filtru de trafic
+ Filtru de trafic UDP
+ Transferul fără întrerupere a conexiunii VPN la reîncărcare
+ Închide conexiunile la reîncărcare
+ Închide traficul internet
+ Urmărește folosirea conexiunii
+ Resetează folosirea conexiunii
+ Arată numele de domenii rezolvate
+ Blochează domenii
+ Cod de răspuns DNS: %s
+ Redirecționare port
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Validează cu: %s
+ DNS TTL minim: %s s
+ Utilizați proxy SOCKS5
+ SOCKS5 adresa: %s
+ SOCKS5 port: %s
+ SOCKS5 nume utilizator: %s
+ SOCKS5 parola: %s
+ Mărime înregistrare PCAP: %s B
+ Mărime max. fișier PCAP: %s MB
+ Repornire automată: o dată la %s minute
+ Notificare viteză conexiune
+ Arată notificare viteză
+ Arată aplicațiile consumătoare
+ Interval de eșantionare: %s ms
+ Număr de eșantioane: %s s
+ Copie de siguranță
+ Exportă setări
+ Importă setări
+ Importă lista de domenii de blocat
+ Importare fișier cu domenii (se vor adăuga)
+ Adresa URL a listei de nume de domenii de blocat
+ Descarcă lista de nume de domenii de blocat
+ Informații tehnice
+ Generale
+ Reţele
+ Abonamente
+ Arată o notificare în bara de stare pentru a configura aplicațiile noi instalate (versiune pro)
+ După dezactivare din widget, activează automat NetGuard după numărul selectat de minute (valoarea zero dezactivează opțiunea)
+ După oprirea ecranului, păstrează regulile ecran pornit pentru numărul selectat de minute (valoarea zero dezactivează opțiunea)
+ De două ori pe zi se va verifica dacă a fost publicată pe GitHub o nouă versiune
+ În funcție de versiunea de Android, partajarea conexiunii (tethering/hotspot) ar putea funcționa sau nu. Traficul partajat nu poate fi filtrat.
+ Ar putea ajuta la apelurile prin Wi-Fi, dar la fel de bine ar putea declanșa erori prezente în Android și ar putea crește consumul de baterie
+ Permite aplicațiilor să se conecteze la adresele de rețea locală precum 10.0.0.0/8, 172.16.0.0/12 și 192.168.0.0/16
+ Rutează traficul IPv6 în NetGuard pentru a putea fi permis sau blocat selectiv
+ Aplică regulile de rețea Wi-Fi numai pentru conexiunile selectate (pentru alte rețele Wi-Fi se aplică regulile de date mobile)
+ Trateaza conexiunile Wi-Fi contorizate (cu plata, hot-spot) precum date mobile
+ Aplică regulile Wi-Fi pentru conexiunile de date 2G
+ Aplică regulile Wi-Fi pentru conexiunile de date 3G
+ Aplică regulile Wi-Fi pentru conexiunile de date 4G/LTE
+ Nu folosi regulile de roaming atunci când țara de origine a SIM-ului și țara rețelei mobile sunt identice
+ Nu se aplică regulile de roaming atunci când atât SIM-ul cât si reţeaua de telefonie sunt din si în Europa
+ Atunci când efectuați sau primiți un apel NetGuard se dezactivează temporar. Aceasta ar putea rezolva problemele legate de apelurile IP/Wi-Fi.
+ Definește reguli pentru aplicațiile de sistem (pentru experți)
+ Înregistrează în jurnal încercările de acces la internet ale aplicațiilor. Aceasta poate duce la un consum mai mare al bateriei.
+ Arată o notificare în bara de stare atunci când o aplicație încearcă să acceseze o nouă adresă de internet (când filtrarea este dezactivată, numai accesul internet blocat va apărea în notificare)
+ Filtrează pachetele IP ce ies prin tunelul VPN. Această opțiune poate duce la un consum în plus al bateriei.
+ Urmărește numărul de octeți trimiși și primiți de fiecare aplicație și adresă. Aceasta poate duce la un consum mai mare al bateriei.
+ Răspunde cu acest cod DNS pentru domeniile blocate. Acestă opțiune este dezactivată dacă nu a fost încărcată o lista cu nume de domenii de blocat.
+ Valoarea implicită este 3 (NXDOMAIN), ceea ce înseamnă \"domeniu inexistent\".
+ Numele domeniului folosit la validarea conexiunii de internet pe portul 443 (https).
+ Dar traficul de date TCP va fi rutat spre serverul proxy
+ Verifică periodic dacă NetGuard rulează (introdu zero pentru a dezactiva). Această opțiune poate duce la un consum ridicat al bateriei.
+ Arată graficul de viteză al rețelei în bara de notificări
+ Ești sigur(ă)?
+ Limitări activate
+ %1$d permise, %2$d blocate
+ %1$d permise, %2$d blocate, %3$d domenii blocate
+ Așteptare eveniment
+ NetGuard este momentan dezactivat, folosește comutatorul de mai sus pentru a îl activa
+ NetGuard a fost dezactivat, probabil de o altă aplicație ce folosește o conexiune VPN
+ \'%1$s\' instalat
+ A fost instalat
+ %1$s a încercat să acceseze internetul
+ Tentativă de acces la internet
+ Acțiune realizată
+ NetGuard utilizează o conexiune VPN locală pentru a filtra traficul pe internet.
+Din acest motiv, va rugăm să permiteți conexiunea VPN în caseta de dialog următoare. Traficul de internet nu este trimis la un server VPN extern.
+ NetGuard nu a putut fi pornit automat după repornirea dispozitivului din cauza unei erori din această versiune de Android.
+ A intervenit o eroare neașteptată: \'%s\'
+ Sistemul Android a refuzat să pornească serviciul VPN în acest moment. Cel mai probabil din cauza unei erori din această versiune de Android.
+ Încearcă NetGuard
+ Donand esti de acord cu termenii si conditiile
+ Dacă în următoarea fereastră de dialog nu puteți apasă OK înseamnă că o aplicație ce manipulează ecranul (luminozitatea sau nuanță) blochează interacțiunea.
+ ± %1$.3f▲ %2$.3f▼ MB/zi
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Pentru o funcționare consistentă, optimizările Android de baterie trebuie dezactivate pentru NetGuard.
+\n\nÎn următoarea fereastră de dialog selectați de sus \"Toate aplicațiile\" apoi selectați NetGuard în listă și confirmați \"Nu se optimizează\".
+ Pentru rezultate consecvente, opțiunile Android de economisire a datelor ar trebui dezactivate pentru NetGuard
+\n\nÎn caseta de dialog următoare, activați opțiunile \"Date de fundal\" și \"Utilizare de date nelimitată\"
+ Android va asocia consumul de baterie și date lui NetGuard atunci când activați filtrarea. De fapt aplicațiile ce accesează internetul consumă
+ Android 4 necesită filtrul de trafic activat
+ Înregistrarea traficului în jurnal este dezactivată, utilizați butonul de mai sus pentru a o activa. Opțiunea de înregistrare ar putea duce la un consum suplimentar al bateriei.
+ Se vor reseta regulile și condițiile la valorile implicite
+ Se vor șterge din jurnal adresele accesate ce nu au fost condiționate cu permite/blochează
+ Ultima importare: %s
+ Se descarcă\n%1s
+ Lista de domenii de blocat descărcată
+ Ultima descărcare: %s
+ Pornește redirecționarea de la %1$s port %2$d la %3$s:%4$d al \'%5$s\'?
+ Oprește redirecționarea %1$s port %2$d?
+ Rețeaua este contorizată
+ Nu există conexiune la internet
+ NetGuard este ocupat
+ Actualizare disponibilă, atingeți pentru a descărca
+ Puteți permite (verzui) sau bloca (roșiatic) accesul la internet prin Wi-Fi sau date mobile atingând iconițele din dreptul unei aplicații
+ Dacă ați instalat NetGuard pentru a vă proteja intimitatea, poate vă interesează și FairEmail , o aplicație client de e-mail cu sursă deschisă, prietenoasă cu intimitatea
+ Accesul la internet este permis în mod implicit (modul listă neagră), acest lucru poate fi schimbat în meniul setări
+ Mesajele \"push\" sunt de obicei gestionate de componentele de sistem ale serviciilor Google Play. cărora le este permis în mod implicit accesul la internet
+ Gestionarea aplicațiilor de sistem se activează din opțiunile avansate
+ Vă rog să descrieți problema și să indicați momentul când s-a produs:
+ Conexiunea VPN a fost anulată\nS-a configurat cumva un alt VPN ca activat permanent?
+ Oprind dispozitivul atunci când NetGuard este pornit va face ca NetGuard să pornească automat la repornirea lui
+ Această caracteristică nu este disponibilă în această versiune de Android
+ O altă rețea VPN este setată ca activată permanent
+ Opriți \"Blocare conexiuni fără VPN\" în setările VPN ale sistemului Android pentru a putea folosi filtrul în NetGuard
+ Opriți modul \"DNS privat\" în setările de rețea Android pentru a putea folosi NetGuard în modul filtrare
+ Traficul este închis
+ Traficul de date necontorizat este permis
+ Traficul de date necontorizat este blocat
+ Regulile traficului necontorizat nu sunt aplicate
+ Traficul de date contorizat este permis
+ Traficul de date contorizat este blocat
+ Regulile traficului contorizat nu sunt aplicate
+ Adresa este permisă
+ Adresa este blocată
+ Permite doar când ecranul este pornit
+ Blochează în roaming
+ În mod implicit conexiunile Wi-Fi sunt considerate necontorizate iar cele mobile drept contorizate
+ nu are permisiunea de a accesa internetul
+ este dezactivată
+ Mesajele primite sunt recepționate de către serviciile Google Play și nu de către această aplicație, în consecință nu pot fi blocate prin blocarea acesteia
+ Descărcările sunt realizate de către managerul de descărcări și nu de către această aplicație, în consecință nu pot fi blocate prin blocarea acesteia
+ Aplică regulile și condițiile
+ Restricții
+ Permite Wi-Fi când ecranul este pornit
+ Permite date mobile când ecranul este pornit
+ R
+ Blochează în roaming
+ Permite când traficul este închis
+ Filtrează aplicațiile asociate
+ Încercări de a accesa
+ Regulile de acces ale acestor adrese au prioritate
+ Opțiuni
+ Notifică la încercările de acces la internet
+ Jurnalul sau filtrul de trafic nu sunt activate
+ Jurnalul și filtrul de trafic sunt activate
+ Configurare
+ Activează jurnalul doar pentru adresele blocate
+ Activează filtrul de trafic pentru a înregistra în jurnal și adresele permise
+ Activează notificările la accesarea unor adrese noi
+ Aceste setări sunt globale și se aplică pentru toate aplicațiile
+ Filtrul de trafic este necesar pentru a permite sau bloca adrese individuale
+ Activarea jurnalului (mai puțin) sau filtrul de trafic (mai mult) cresc consumul bateriei și ar putea afecta viteza conexiunii
+ Evaluează aplicația
+ Permite
+ Blochează
+ Permite Wi-Fi
+ Blochează Wi-Fi
+ Permite date mobile
+ Blochează datele mobile
+ Proces root
+ Proces Mediaserver
+ proces fără utilizator
+ Nu întreba din nou
+ Identitate %1$s
+ Portul %1$d
+ Copiere
+ Caracteristici versiune Pro
+ Următoarele funcții avansate sunt disponibile:
+ Arată jurnalul de trafic
+ Filtrează traficul de rețea
+ Notificare aplicație nou instalată
+ Notificare cu grafic viteza conexiune
+ Aspect (temă, culori)
+ Toate funcțiile avansate de mai sus
+ Sprijină dezvoltarea
+ Cumpără
+ Activat
+ Indisponibil
+ Atingeți un titlu pentru mai multe informații
+ Întrebare de verificare
+ Răspuns
+ Aceasta este o caracteristică Pro
+ Un abonament lunar de 1 sau 2 euro (cu excepția impozitelor locale) va activa toate funcțiile Pro.
+ Puteți anula sau administra un abonament prin intermediul tab-ului de abonamente din aplicația Play Store.
+
+
+ - verde albăstrui/portocaliu
+ - albastru/portocaliu
+ - mov/roșu
+ - culoarea chihlimbarului/albastru
+ - portocaliu/gri
+ - verde
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-ru-rRU/strings.xml b/NetGuard/app/src/main/res/values-ru-rRU/strings.xml
new file mode 100644
index 0000000..d33e630
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-ru-rRU/strings.xml
@@ -0,0 +1,290 @@
+
+
+ NetGuard обеспечивает простые и широкие способы заблокировать доступ к интернету, который ещё и не требует root-прав. Приложениям и адресам можно индивидуально разрешить или заблокировать доступ к Wi-Fi и/или мобильной связи.
+ Для работы NetGuard требуется Android 5.1 или более поздняя версия
+ Xposed вызывает слишком много сбоев, что может привести к удалению NetGuard из магазина Google Play, поэтому NetGuard не поддерживается, пока установлен Xposed
+ Политика конфиденциальности
+ Разработке и тестированию NetGuard было уделено большое внимание, однако невозможно гарантировать, что NetGuard будет корректно работать на каждом устройстве.
+ Я согласен
+ Я не согласен
+ NetGuard нуждается в вашей помощи. Нажмите, чтобы приобрести функции PRO для помощи проекту.
+ Запущенные службы
+ Общие уведомления
+ Доступ к уведомлениям
+ Поиск приложения
+ Фильтр приложений
+ Показать пользовательские приложения
+ Показать системные приложения
+ Показать приложения без интернета
+ Показать отключенные приложения
+ Сортировка приложений
+ Сортировать по имени
+ Сортировать по UID
+ Сортировать по исп. данным
+ Журнал
+ Настройки
+ Пригласить
+ Легенда
+ Поддержка
+ О приложении
+ Другие приложения
+ Другое
+ Разрешено
+ Заблокировано
+ Обновления в реальном времени
+ Обновить
+ Показать названия
+ Показать организацию
+ PCAP включен
+ PCAP экспорт
+ Очистить
+ Экспорт
+ Сброс
+ Добавить
+ Удалить
+ Очистка
+ Протокол
+ Исходный порт
+ Адрес назначения
+ Порт назначения
+ Целевое приложение
+ Для внешнего сервера выберите \"никто\"
+ По умолчанию
+ Блокировать Wi-Fi по умолч.
+ Блокировать моб. сеть по умолч.
+ Разрешить Wi-Fi при вкл. экране по умолч.
+ Разрешить моб. сеть при вкл. экране по умолч.
+ Блокировать роуминг по умолч.
+ Опции
+ Тема: %1$s
+ Использовать темную тему
+ Уведомлять о новой установке
+ Применить правила при вкл. экране
+ Авто запуск через %1$s минут
+ Задержка экрана %1$s минут
+ Проверять наличие обновлений
+ Параметры сети
+ Маршрутизация подсети
+ Разрешить привязку
+ Разрешить доступ к LAN
+ Включить IPv6-трафик
+ Домашняя сеть Wi-Fi: %1$s
+ Регулировать огранич. Wi-Fi сети
+ Не учитывать 2G
+ Не учитывать 3G
+ Не учитывать LTE
+ Игнорировать роуминг внутри страны
+ Игнорировать роуминг ЕС
+ Отключить при звонке
+ Блокировка Wi-Fi
+ Блокировка моб. сети
+ Перезагрузка при каждом изменении подключения
+ Дополнительные опции
+ Управлять сист. приложениями
+ Журнал доступа к сети интернет
+ Уведомить при доступе в интернет
+ Фильтр трафика
+ Фильтр UDP трафика
+ Бесшовная передача VPN при перезагрузке
+ Закрыть соединения при перезагрузке
+ Блокировка трафика
+ Отслеживание использования сети
+ Сброс сетевого использования
+ Показать разрешенные доменные имена
+ Блокировать доменные имена
+ Код ответа DNS: %s
+ Перенаправление портов
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Проверить на: %s
+ Минимальный DNS TTL: %s сек
+ Использовать прокси SOCKS5
+ Адрес SOCKS5: %s
+ Порт SOCKS5: %s
+ Логин SOCKS5: %s
+ Пароль SOCKS5: %s
+ Размер записи PCAP: %s Б
+ Макс. размер PCAP файла: %s МБ
+ Сторожевой таймер: каждые %s минут
+ Скорость в статус-баре
+ Показать скорость в статус-баре
+ Показать топовое приложение
+ Частота замеров: %s мс
+ Число замеров: %s с
+ Резервное копирование
+ Экспорт настроек
+ Импорт настроек
+ Импорт hosts-файла
+ Импорт hosts-файла (добавить)
+ Ссылка для скачивания hosts-файла
+ Скачать hosts-файл
+ Техническая информация
+ Общее
+ Сеть
+ Подписки
+ Показать уведомление в статус-баре для непосредственной настройки недавно установленных приложений (Pro-функция)
+ После отключения через виджет, автоматически включить NetGuard снова после указанного количества минут (введите ноль, чтобы отключить эту опцию)
+ После выключения экрана, держать экран активным в течение выбранного количества минут (введите ноль, чтобы отключить эту опцию)
+ Проверять наличие новых версий на GitHub два раза в день
+ В зависимости от версии Android, привязывание может либо работать, либо не работать. Привязанный трафик не может быть отфильтрован.
+ Включение маршрутизации подсети; может дать возможность использования Wi-Fi звонков, но также может вызвать ошибки в Android и увеличить расход заряда батареи
+ Разрешить приложениям подключаться к локальным сетевым адресам таким, как 10.0.0.0/8, 172.16.0.0/12 и 192.168.0.0/16
+ Пересылка трафика IPv6 к NetGuard может быть выборочно разрешена или заблокирована
+ Применить правила Wi-Fi сети только для выбранной сети (для других Wi-Fi сетей применяются правила мобильной сети)
+ Применить правила для лимитированных (платных, ограниченных) Wi-Fi сетей
+ Применить правила Wi-Fi-сети для передачи данных через 2G
+ Применить правила Wi-Fi-сети для передачи данных через 3G
+ Применить правила Wi-Fi-сети для передачи данных через LTE
+ Не применять правила роуминга, если SIM-карта и мобильная сеть из одной страны
+ Не применять правила роуминга, если страна SIM-карты и мобильная сеть находится в пределах Евросоюза (как у себя дома)
+ Отключить NetGuard при входящем или исходящем телефонном звонке. Эту опцию можно использовать для решения проблем с IP/Wi-Fi.
+ Определить правила для системных приложений (для профи)
+ Журнал попыток доступа приложений к сети интернет. Это может привести к большему потреблению заряда аккумулятора.
+ Показать уведомление в строке состояния, когда приложение пытается получить доступ к новому Интернет-адресу (когда фильтрация отключена, будут показаны только заблокированные попытки доступа в Интернет)
+ Фильтровать IP-пакеты, проходящие через VPN. Это может привести к большему потреблению заряда аккумулятора.
+ Отслеживать количество отправленных и полученных байтов для каждого приложения и адресов. Это может привести к большему потреблению заряда аккумулятора.
+ Отвечать кодом ответа настроенного DNS для заблокированных доменных имен. Этот переключатель отключен, если доступных host-файлов нет.
+ Значение по умолчанию - 3 (NXDOMAIN); это означает «несуществующий домен».
+ Доменное имя, используемое для проверки интернет-соединения через порт 443 (https).
+ На прокси-сервер будет направляться только TCP трафик
+ Периодически проверять, запущен ли NetGuard (введите ноль, чтобы отключить эту опцию). Это может привести к большему потреблению заряда аккумулятора.
+ Показать график скорости сети в статус-баре
+ Вы уверены?
+ Определить правила
+ %1$d разрешено, %2$d заблокировано
+ %1$d разрешен, %2$d заблокирован, %3$d хостов
+ Ожидание события
+ NetGuard отключен, используйте переключатель выше для его включения
+ NetGuard был отключен, скорее всего, из-за применения другого VPN-подключения
+ \'%1$s\' установлено
+ Было установлено
+ %1$s попыток доступа в интернет
+ Попытка доступа в интернет
+ Действие завершено
+ NetGuard использует локальный VPN для фильтрации интернет-трафика.
+По этой причине, пожалуйста, разрешите VPN-подключение в следующем диалоговом окне. Удаленному VPN-серверу ваш интернет-трафик не отправляется.
+ NetGuard не может быть запущен автоматически при загрузке из-за ошибки в вашей версии Android
+ Произошла непредвиденная ошибка: \'%s\'
+ В данный момент, Android отказался запустить VPN-сервис. Вероятно, это из-за ошибки в вашей версии Android.
+ Попробуйте новый фаервол NetGuard
+ Делая пожертвование, Вы соглашаетесь с условиями & положениями
+ Если вам не удается нажать ОК в следующем диалоговом окне (затемнение экрана), то, скорее всего, какое то другое приложение использует экран.
+ ± %1$.3f▲ %2$.3f▼ МБ/день
+ %1$7.3f▲ %2$7.3f▼ КБ
+ %1$7.3f▲ %2$7.3f▼ МБ
+ %1$7.3f▲ %2$7.3f▼ ГБ
+ %dx
+ Для достижения стабильных результатов экономия заряда аккумулятора Android для NetGuard должна быть отключена. \n\nВ следующем диалоговом окне, в верхней части, выберите «Все приложения», найдите NetGuard в списке и выберете его, затем выберите «Не экономить» и подтвердите.
+ Для достижения стабильных результатов, ограничение данных Android должно быть отключено для NetGuard.
+\n\nВ следующем диалоговом окне включите опции \"Фоновые данные\" и \"Неограниченное использование данных\"
+ Использование данной функции приводит к тому, что Android передает сетевые данные и использование заряда аккумулятора в пользование NetGuard; Android будет считать, что данные и заряд используются NetGuard, а не стандартными, для работы этой функции, приложениями.
+ На Android 4 фильтрация должна быть включена
+ Ведение журнала трафика отключено, используйте переключатель выше для его включения. Это может привести к большему потреблению заряда аккумулятора.
+ Это сбросит правила и условия на их значения по умолчанию
+ Это удалит строки журнала попыток доступа правил разрешения/блокирования
+ Прошлый импорт: %s
+ Загрузка\n%1s
+ hosts-файл загружен
+ Последняя загрузка: %s
+ Начать пересылку из %1$s порта %2$d в %3$s:%4$d из %5$s?
+ Остановить пересылку из %1$s порта %2$d?
+ Лимитированные сети
+ Отсутствует подключение к сети интернет
+ NetGuard занят
+ Доступно обновление, нажмите, чтобы загрузить
+ Вы можете разрешить (зеленоватый цвет значка) или запретить (красноватый цвет значка) Wi-Fi или мобильный интернет, нажав на значок рядом с приложением
+ Если вы установили NetGuard для защиты вашей конфиденциальности, вас может заинтересовать FairEmail , с открытым исходным кодом, дружественное приложение для конфиденциальности электронной почты
+ Доступ в интернет разрешен по умолчанию, это может быть изменено в настройках
+ Push-сообщения, в основном, обрабатываются системными компонентами Google Play, которым по умолчанию разрешен доступ в Интернет
+ Управление системными приложениями может быть включено в дополнительных опциях
+ Пожалуйста, опишите проблему и укажите момент возникновения проблемы:
+ VPN соединение отменено\nХотите настроить другое соединение, чтобы VPN был всегда?
+ Выключение устройства с запущенным NetGuard автоматически запустит NetGuard при включении вашего устройства
+ Эта функция недоступна в этой версии Android
+ Новый VPN установлен, как базовый VPN
+ Отключите «Блокировать подключения без VPN» в настройках Android VPN, чтобы использовать NetGuard в режиме фильтрации
+ Отключите «Частный DNS» в настройках сети Android, чтобы использовать NetGuard в режиме фильтрации
+ Трафик заблокирован
+ Безлимитный трафик разрешен
+ Безлимитный трафик блокируется
+ Безлимитные правила не применяются
+ Лимитированный трафик разрешен
+ Лимитированный трафик блокируется
+ Лимитированные правила не применяются
+ Адрес разрешен
+ Адрес заблокирован
+ Разрешить, когда экран включен
+ Блокировать в роуминге
+ По умолчанию Wi-Fi соединение считается безлимитным, а мобильная связь лимитированной
+ не имеет доступа в интернет
+ отключено
+ Входящие сообщения принимаются службами Google Play, а не этим приложением, поэтому не могут быть им заблокированы
+ Загрузки выполняются менеджером загрузки, а не этим приложением, и поэтому не могут быть заблокированы путем блокировки этого приложения
+ Применить правила и условия
+ Условия
+ Разрешить Wi-Fi при включенном экране
+ Разрешить мобильную сеть при включенном экране
+ Р
+ Блокировать в роуминге
+ Разрешить в режиме блокировки трафика
+ Фильтровать связные
+ Попытки доступа
+ Правила доступа имеют приоритет над другими правилами
+ Опции
+ Уведомить о попытке доступа в интернет
+ Ведение журнала или фильтрация не включены
+ Ведение журнала и фильтрация включены
+ Настроить
+ Включить ведение журнала только заблокированных адресов
+ Включить фильтрацию для регистрации разрешенных адресов
+ Включить уведомления о доступе для недавно зарегистрированных адресов
+ Эти настройки являются глобальными, которые применяются ко всем приложениям
+ Фильтрация также необходима для разрешения или блокировки отдельных адресов
+ Включение ведения журнала или фильтрации может увеличить расход батареи и повлиять на скорость сети
+ Оценить
+ Разрешить
+ Блокировать
+ Разрешить Wi-Fi
+ Блокировать Wi-Fi
+ Разрешить моб. сеть
+ Блокировать моб. сеть
+ root
+ медиасервер
+ никто
+ Больше не спрашивать
+ Протокол WHOIS: %1$s
+ Порт: %1$d
+ Копировать
+ Pro-функции
+ Доступны следующие Pro-функции:
+ Просмотр журнала заблокированного трафика
+ Фильтр сетевого трафика
+ Новые уведомления
+ График скорости сети
+ Внешний вид (темы, цвета)
+ Все выше перечисленные Pro-функции
+ Поддержать разработчика
+ Купить
+ Добавлено
+ Недоступно
+ Нажмите на название для получения дополнительной информации
+ Задание
+ Ответ
+ Доступно в Pro-версии
+ Ежемесячная подписка за 1 или 2 евро (без учета местных налогов) активирует все функции Pro.
+ Вы можете отменить или управлять подпиской через вкладку подписок в Google Play Маркет.
+
+
+ - бирюзовый/оранжевый
+ - синий/оранжевый
+ - фиолетовый/красный
+ - янтарный/синий
+ - оранжевый/серый
+ - зеленый
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-si-rLK/strings.xml b/NetGuard/app/src/main/res/values-si-rLK/strings.xml
new file mode 100644
index 0000000..03ffa3c
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-si-rLK/strings.xml
@@ -0,0 +1,45 @@
+
+
+ පරිශීලක යෙදුම් පෙන්වන්න
+ සැකසුම්
+ සහාය
+ පිලිබඳ
+ වෙනත් යෙදුම්
+ වෙනත්
+ යලි පිහිටුවන්න
+ එකතු කරන්න
+ මකන්න
+ කෙටුම්පත
+ විකල්ප
+ තේමාව: %1$s
+ අඳුරු තේමාව භාවිතා කරන්න
+ යාවත්කාලීනයන් සඳහා පිරික්සන්න
+ පද්ධති යෙදුම් කළමනාකරණය
+ වසම් නාම අවහිර කරන්න
+ ජාල
+ ඔබට විශ්වාසද?
+ \n%1s බාගත වෙමින්
+ කොන්දේසි
+ විකල්ප
+ වින්යාසගත කරන්න
+ නැවත අසන්න එපා
+ පිටපත්
+ නව යෙදුම් දැනුම්දීම්
+ ජාල වේග ප්රස්ථාර දැනුම්දීම
+ පෙනුම (තේමාව, වර්ණ)
+ මිලදී ගන්න
+ සබල කර ඇත
+ ප්රතිචාරය
+
+ - teal/orange
+ - නිල්/තැඹිලි
+ - දම්/රතු
+ - amber/blue
+ - තැඹිලි/අළු
+ - කොළ
+
+
+ - යූ.ඩී.පී.
+ - ස.පා.කෙ (TCP)
+
+
diff --git a/NetGuard/app/src/main/res/values-sk-rSK/strings.xml b/NetGuard/app/src/main/res/values-sk-rSK/strings.xml
new file mode 100644
index 0000000..3501a1e
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-sk-rSK/strings.xml
@@ -0,0 +1,223 @@
+
+
+ NetGuard poskytuje jednoduché a pokročilé spôsoby blokovania prístupu na internet - nevyžadujúcich root prístup. Aplikáciám a adresám môže byť individuálne povolený alebo odmietnutý prístup k Wi-Fi alebo mobilnému pripojeniu.
+ NetGuard vyžaduje Android vo verzii 5.1 alebo novšej
+ Xposed spôsobuje veľa spadnutí, ktoré môžu viesť k tomu, že NetGuard by mohol byť odstránený z Google Play Obchodu. Z tohto dôvodu NetGuard nieje podporovaný ak Xposed je nainštalovaný.
+ Skvelá starostlivosť bola venovaná pri vývoji a testovaní NetGuardu, avšak je nemožné garantovať, že NetGuard bude pracovať správne na každom jednom zariadení.
+ Súhlasím
+ Odmietam
+ NetGuard potrebuje tvoju pomoc. Klikni na zakúpiť pro vymoženosti, aby projekt mohol ďalej fungovať.
+ Všeobecné notifikácie
+ Prístupové notifikácie
+ Hľadať aplikáciu
+ Filtrovať aplikácie
+ Zobraziť používateľské aplikácie
+ Zobraziť systémové aplikácie
+ Zobraziť aplikácie bez internetu
+ Zobraziť zakázané aplikácie
+ Zoradiť aplikácie
+ Zoradenie podľa názvu
+ Zoradiť podľa uid
+ Zoradiť na využitia dát
+ Zobraziť záznam
+ Nastavenia
+ Pozvať
+ Legenda
+ Podpora
+ O aplikácii
+ Ďalšie aplikácie
+ Iné
+ Povolené
+ Blokované
+ Živé aktualizácie
+ Obnoviť
+ Zobraziť názvy
+ Zobraziť organizáciu
+ PCAP povolené
+ Exportovať PCAP
+ Vyčistiť
+ Exportovať
+ Resetovať
+ Pridať
+ Vymazať
+ Vyčistiť
+ Protokol
+ Zdrojový port
+ Cieľová adresa
+ Cieľový port
+ Cieľová aplikácia
+ Pre externý server vyberte \"nikto\"
+ Predvolené nastavenia
+ Predvolene blokovať Wi-Fi
+ Predvolene blokovať mobilné dáta
+ Zapnúť Wi-Fi po zapnutí obrazovky
+ Zapnúť mobilné dáta po zapnutí obrazovky
+ Predvolene blokovať roaming
+ Možnosti
+ Téma: %1$s
+ Použiť tmavú tému
+ Upozorniť na novú inštaláciu
+ Automaticky zapnúť po %1$s minútach
+ Oneskoriť vypnutie obrazovky o %1$s minút
+ Skontrolovať aktualizácie
+ Možnosti siete
+ Podsieťové smerovanie
+ Povoliť zdieľanie internetu
+ Povoliť LAN prístup
+ Povoliť IPv6 prenos
+ Wi-Fi domáce siete: %1$s
+ Spravovať merané Wi-Fi siete
+ Považovať 2G za nemeranú sieť
+ Považovať 3G za nemeranú sieť
+ Považovať LTE za nemeranú sieť
+ Ignorovať národný roaming
+ Ignorovať EU roaming
+ Zabezpečiť cez Wi-Fi
+ Zabezpečiť cez mobilné dáta
+ Obnoviť pri každej zmene pripojenia
+ Pokročilé možnosti
+ Spravovať systémové aplikácie
+ Zaznamenávať prístup k internetu
+ Upozorniť na pripojenie k internetu
+ Filtrovať prenos
+ Filtrovať UDB prenos
+ Zatvoriť pripojenie pri obnovení
+ Sledovať používanie siete
+ Resetovať využitie siete
+ Ukázať vyriešené názvy domény
+ Blokovať názvy domén
+ Presmerovanie portu
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Veľkosť záznamu PCAP: %s B
+ Maximálna veľkosť súboru PCAP: %s MB
+ Oznámenie o rýchlosti
+ Zobraziť oznámenie o rýchlosti
+ Zobraziť top aplikácie
+ Interval vzorkovania: %s ms
+ Počet vzoriek: %s s
+ Zálohovať
+ Exportovať nastavenia
+ Importovať nastavenia
+ Importovať súbor hosts
+ Adresu URL pre sťahovanie súboru hosts
+ Stiahnuť súbor hosts
+ Technické informácie
+ Všeobecné
+ Siete
+ Odbery
+ Zobraziť oznámenie v stavovom riadku na priame nastavenie novonainštalovaných aplikácií (pro funkcia)
+ Po vypnutí pomocou miniaplikácie znovu spustiť NetGuard po vybratom počte minút (zadajte nulu pre vypnutie tejto možnosti)
+ Ponechať po vypnutí obrazovky pravidlá zapnutia obrazovky aktívne na vybratý počet minút (zadajte nulu pre vypnutie tejto možnosti)
+ Kontrolovať nové vydania na GitHube dvakrát denne
+ V závislosti na verziu systému Android, zdieľanie internetu môže alebo nemusí fungovať. Zdieľaný prenos nie je možné filtrovať.
+ Povoliť podsieťové presmerovanie; môže umožniť Wi-Fi volania, ale môže tiež vyvolať chyby v Androide a zvýšiť spotrebu batérie
+ Povoliť aplikáciam pripojenie na adresy miestnej sieti, ako 10.0.0.0/8, 172.16.0.0/12 a 192.168.0.0/16
+ Smerovať IPv6 prenos do NetGuard, takže môžete selektívne povolený alebo blokovaný
+ Použiť pravidlá Wi-Fi sietí len na vybrané siete (použite pravidlá mobilných sietí pre ostatné Wi-Fi siete)
+ Použiť pravidlá mobilných sietí na merané (platené, zdieľané) Wi-Fi siete
+ Použiť pravidlá Wi-Fi sietí na 2G dátové pripojenia
+ Použiť pravidlá Wi-Fi sietí na 3G dátové pripojenia
+ Použiť pravidlá Wi-Fi sietí na LTE dátové pripojenia
+ Nepoužiť pravidlá roamingu, keď krajina mobilnej siete a SIM sú rovnaké
+ Určiť pravidlá pre systémové pravidlá (pre expertov)
+ Zaznamenať pokusy o získanie prístupu na internet u aplikácií. Môže to spôsobiť zvýšenú spotrebu batérie.
+ Filtrovanie IP paketov smerujúcich z VPN tunela. Môže to spôsobiť zvýšenú spotrebu batérie.
+ Sledovať počet odoslaných a prijatých bajtov pre každú aplikáciu a adresu. Môže to spôsobiť zvýšenú spotrebu batérie.
+ Zobraziť oznámenie s graf rýchlosti siete v stavovom riadku
+ Ste si istý?
+ Pravidlá vynútenia
+ Povolené: %1$d, blokované: %2$d
+ Povolené: %1$d, blokované: %2$d, hostitelia: %3$d
+ Čaká na udalosť
+ NetGuard je vypnutý, použite prepínač vyššie na zapnutie NetGuard
+ NetGuard bol zakázaný, pravdepodobne použitím inej aplikácie založenej na VPN
+ Aplikácia \'%1$s\' bola nainštalovaná
+ Nainštalované
+ Aplikácia %1$s sa pokúsila o prístup k internetu
+ Pokus o pripojenie na internet
+ Akcia bola dokončená
+ NetGuard používa miestne VPN pripojenie na filtrovanie internetového prenosu.
+Z tohto dôvodu povoľte VPN pripojenie v ďalšom dialógovom okne. Váš internetový prenos nie je zasielaný na vzdialený VPN server.
+ Aplikácii NetGuard sa nepodarilo spustiť automaticky. To je pravdepodobne spôsobené z dôvodu chyby vo vašej verzii systému Android.
+ Vyskytla sa neočakávaná chyba: \'%s\'
+ Skúsiť NetGuard
+ Darovaním súhlasíte s podmienkami služby
+ Ak nemôžete stlačiť tlačidlo OK na ďalšom okne, tak iná aplikácia (na ovladanie jasu) prekrýva obrazovkou.
+ ± %1$.3f▲ %2$.3f▼ MB/deň
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Zaznamenávanie prenosu je vypnuté, použite prepínač vyššie na povolenie zaznamenávanie. Zaznamenávanie prenosu môže spôsobiť zvýšenú spotrebu batérie.
+ Týmto sa obnovia pravidlá a podmienky na predvolené hodnoty
+ Týmto odstránite riadky záznamu pokusov o prístup bez pravidiel povolenia/blokovania
+ Posledné importovanie: %s
+ Sťahovanie\n%1s
+ Súbor hosts bol stiahnutý
+ Posledné sťahovanie: %s
+ Zastaviť presmerovanie z %1$s port %2$d na %3$s:%4$d z \'%5$s\'?
+ Zastaviť presmerovanie z %1$s port %2$d?
+ Meraná sieť
+ NetGuard je zaneprázdnený
+ K dispozícii je aktualizácia, dotykom ju stiahnite
+ Prístup k internetu je povolený v predvolenom nastavení, túto možnosť môžete zmeniť v nastaveniach
+ Push správy sú väčšinou riadené systémovou súčasťou Služby Google Play, ktorej je povolený prístup k internetu v predvolenom nastavení
+ Spravovanie systémových aplikácií môže byť povolené v nastaveniach
+ Prosím, opíšte problém a uveďte jeho čas:
+ Nemeraný prenos je povolený
+ Nemeraný prenos je blokovaný
+ Meraný prenos je povolený
+ Meraný prenos je blokovaný
+ Adresa je povolená
+ Adresa je blokovaná
+ Povoliť pri zapnutej obrazovke
+ Blokovať pri roamingu
+ V predvolenom nastavení Wi-Fi pripojenie je považované za nemerané a mobilné pripojenie za merané
+ Nemá prístup k internetu
+ Zakázané
+ Použiť pravidlá a podmienky
+ Podmienky
+ Povoliť Wi-Fi pri zapnutej obrazovke
+ Povoliť mobilné dáta pri zapnutej obrazovke
+ R
+ Blokovať pri roamingu
+ Filtrovať súvisiace
+ Pokusy o prístup
+ Pravidlá prístupu má prednosť pred inými pravidlami
+ Možnosti
+ Upozorniť na pokusy o prístup k internetu
+ Ohodnotiť
+ Povoliť
+ Blokovať
+ root
+ server médií
+ nikto
+ Nepýtať sa znovu
+ Whois %1$s
+ Port %1$d
+ Vlastnosti verzie Pro
+ Nasledujúce PRO funkcie sú dostupné:
+ Zobraziť záznam zablokovaného prenosu
+ Filtrovať sieťový prenos
+ Oznámenia nových aplikácií
+ Oznámenie s grafom rýchlosti siete
+ Vzhľad (téma, farby)
+ Všetky vyššie uvedené PRO funkcie
+ Povolené
+ Výzva
+ Odpoveď
+
+ - modrozelená/oranžová
+ - modrá/oranžová
+ - fialová/červená
+ - jantárová/modrá
+ - oranžová/šedá
+ - zelená
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-sl-rSI/strings.xml b/NetGuard/app/src/main/res/values-sl-rSI/strings.xml
new file mode 100644
index 0000000..e206748
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-sl-rSI/strings.xml
@@ -0,0 +1,216 @@
+
+
+ NetGuard zagotavlja preprost in napreden način za blokiranje interneta - koren nu potreben. Aplikacije in naslovi so lahko posamično dovoljeni ali blokirani pri dostopanju do vašega Wi-Fi in/ali mobilne povezave.
+ Xposed povzroča preveč zrušitev, ki lahko vodijo k odstranitvjiji NetGuard iz Google Play Store, zato NetGuard nemore delovati ko je Xposed naložen
+ Politika zasebnosti
+ Strinjam se
+ Ne strinjam se
+ Izvajajo storitve
+ Splošna obvestila
+ Dostopanje do obvestil
+ Iskalnik aplikacij
+ Filter aplikacij
+ Prikaži uporabniške aplikacije
+ Prikaži sistemske aplikacije
+ Pokaži aplikacije brez interneta
+ Pokaži nedelujoče aplikacije
+ Razvrsti aplikacije
+ Razvrsti po imenu
+ Razvrsti po Uid
+ Razvrsti po porabi podatkov
+ Pokaži dvenvnik
+ Nastavitve
+ Povabi
+ Legenda
+ Pomoč
+ O programu
+ Drugo
+ Dovoljenje
+ Blokirano
+ Posodobitve v živo
+ Osveži
+ Pokaži imena
+ Pokaži organizacije
+ PCAP omogočeno
+ PCAP izvoz
+ Počisti
+ Ponastavitavi
+ Dodaj
+ Izbriši
+ Počisti
+ Protokol
+ Izvorna vrata
+ Ciljni naslova
+ Namembno pristanišče
+ Namembna aplikacija
+ Za zunjani strežnik izberite \"nihče\"
+ Privzete nastavitve (bela/črna lista)
+ Blokiraj Wi-Fi
+ Blokiraj moblini
+ Dovoli Wi-Fi kadar je zaslon prižgan
+ Dovoli mobilno ko je zaslon prižgan
+ Blokiraj gostovanje
+ Možnosti
+ Tema:%1$s
+ Uporabi temno temo
+ Obvesti ko je na novo nameščeno
+ Uporabi pravila \'ko je zaslon vklopljen\'
+ Samedojeno omogoči po %1$s minutah
+ Zakasnitev ko je zaslon izključen po %1$s
+ Preverite za posodobitev
+ Možnosti omrežja
+ Podmrežno usmerjenje
+ Omogoči privezovanje
+ Dovoli LAN dostop
+ Omogočenje IPv6 prometa
+ Wi-Fi domače omrežke:%1$s
+ Razmislite 2G nemerjeno
+ Razmislite 3G nemerjeno
+ Razmislite LTE nemerjeno
+ Prezri nacionalno gostovanje
+ Prezri Eu gostovanje
+ Onemogoči na klic
+ Zakleni Wi-Fi
+ Zakleni mobilne
+ Napredne nastavitve
+ Upravljanje sistema aplikacij
+ Dnevnik internetnega dostopa
+ Obvesti o dostopu do interneta
+ Filtriranje prometa
+ Zakleni promet
+ Sledite usporabi omrežja
+ Ponastavitev omrežne porabe
+ Pokaži rešitev domenskih imen
+ Blokiraj lokalne domene
+ DNS odzivna koda: %s
+ Posredovanje portov
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Minimalen DNS TTL: %s s
+ Uporabi SOCK5 proxy
+ SOCKS5 naslov: %s
+ SOCKS5 vrata: %s
+ SOCKS5 uporabniško ime: %s
+ SOCKS5 geslo: %s
+ PCAP zapis velikosti: %s B
+ PCAP max. file size: %s MB
+ Varuh: every %s minut
+ Hitrost obvestil
+ Pokaži hitrost obvestil
+ Pokaži najvišje aplikacije
+ Vzorčni interval: %s ms
+ Število vzorcev: %s s
+ Varnostna kopija
+ Izvoz nastavitev
+ Uvoz nastavitev
+ Uvoz datotek gostov
+ Prenos datotek gostov
+ Splošno
+ Omrežje
+ Naročnina
+ Pokaži obvestila o novo nameščenih aplikacijah in njihovih configuracijah (profesionalne funkcije)
+ Ko onemogočite uporabo widge samodejno vklopi NetGuard za izbrano število minut ( vnesite 0 za izklopitev te možnosti)
+ Po izklopitvi zaslona pustite na zaslona pravila za določeno število minut ( vnesite 0 za izklopitev te možnosti)
+ Poišči nove izdaje na GitHub dvakrat dnevno
+ Odvisno od različice Androida bo vezanje delovalo ali pa tudi ne. Vezanje prometa ni mogoče filtrirati.
+ Omogoči podmrežno usmerjanje; lahko omogoči Wi-Fi klicanje ampak lahko sproži hrošče v Androidu in poveča uporabo porabe baterije
+ Dovoli aplikacijam povezavo z naslovi lokalnih omrežji kot so 10.0.0.0/8, 172.16.0.0/12 in 192.168.0.0/16
+ Usmeri IP različice 6promet NetGuard tako da je lahko selektivno dovoljen ali blokiran
+ Omogoči Wi-Fi pravila samo za izbrano omrežje (omogoči pravila mobilnega omrežja za ostala Wi-Fi omrežja)
+ Pravila mobilnega omrežja veljajo tudi za (plačana, pripeta) Wi-Fi omrežja
+ Wi-Fi omrežna pravila veljajo za 2G podatkovne povezave
+ Wi-Fi omrežna pravila veljajo za 3G podatkovne povezave
+ Wi-Fi omrežna pravila veljajo za LTE podatkovne povezave
+ Pravila gostovanje ne veljajo ko so SIM in moblna omrežja države enaka
+ Pravila gostovanja ne veljajo kadar so SIM in mobila omrežja v EU (gostuj kot doma)
+ Onemogoči NetGuard ob dohodnih klicih ali odhodnih klicih. To se lahko uporablja za delo okoli IP/Wi-Fi klicnih težav.
+ Definirana pravila za sistem aplikacije (za strokovnjake)
+ Ali ste prepričani?
+ Uveljavljanje pravil
+ %1$d dovoljen, %2$d blokiran
+ %1$d dovoljen, %2$d blokiran, %3$d gostitelj
+ Čakanje na dogodek
+ NetGuard je onemogočen uporabi stikalo zgoraj da omogočite NetGuard
+ NetGuard je bil onemogočen vrjetno z uporabo druge VPN aplikacije
+ %1$s je nameščen
+ Je bila nameščena
+ %1$s poskus dostopa do interneta
+ Poskus dostopa do interneta
+ Dejanje se je dokončalo
+ Poskusi NetGuard
+ Z doniranjem se strinjate z & pogoji
+ Če v naslednjem pogovornem oknu ne morete pritisniti OK, po usej vrjetnosti druga aplikacija upravlja zaslon naprave (zatemnitev zaslona).
+ ± %1$.3f▲ %2$.3f▼ MB/day
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Zadnji uvoz: %s
+ Prenos\n%1s
+ Prenos gostiteljevih datotek
+ Zadnji prenos: %s
+ Začetek posredovanja %1$s port %2$d do %3$s:%4$d od%5$s?
+ Prenehajte s posredovanjem %1$s port %2$d?
+ Omrežje je merjeno
+ Ni aktivne internetne povezave
+ NetGuard je zaseden
+ Naslov je dovoljen
+ Naslov je blokiran
+ Dovoli ko je zaslon vklopljen
+ Blokiraj med gostovanjem
+ Privzeto je Wi-Fi povezava tretirana tako da je neomejena in mobile povezave lahko merijo
+ nima internetnih dovoljenj
+ je onemogočen
+ Uporabljaj pravila in pogoje
+ Pogoji
+ Dovoli Wi-Fi ko je zaslon vklopljen
+ Dovoli mobilno ko je zaslon vkloplejn
+ R
+ Blokiraj med gostovanjem
+ Dovoli v zaklenjenem načinu
+ Filtriraj povezane
+ Poskusi dostopa
+ Možnosti
+ Konfiguracija
+ Oceni
+ Dovoli
+ Blokiraj
+ Omogočajo Wifi
+ Blokirajo Wi-Fi
+ Dovoli mobilno
+ Blokirajo mobilno
+ izvor
+ mediaserver
+ nihče
+ Ne sprašuj več
+ Whois %1$s
+ Pristanišče %1$d
+ Profesionalne funkcije
+ Naslednje profesionalne funkcije so na voljo:
+ Pogled dnevnika blokiranega prometa
+ Filter omrežnega prometa
+ Nova obvestila aplikacij
+ Graf omrežne hitrosti
+ Videz (barva, tema)
+ Vse zgoraj navedene profesionalne funkcije
+ Podproa razvoja
+ Kupi
+ Omogočeno
+ Ni na voljo
+ Pritisnite na naslov za več informacij
+ Izziv
+ Odziv
+
+ - modro zelena/oranžna
+ - modra/oranžna
+ - violična/rdeča
+ - jantarna/modra
+ - oranžna/siva
+ - zelena
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-sr-rSP/strings.xml b/NetGuard/app/src/main/res/values-sr-rSP/strings.xml
new file mode 100644
index 0000000..48e9e5c
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-sr-rSP/strings.xml
@@ -0,0 +1,292 @@
+
+
+ Нетгард нуди једноставне и напредне начине блокирања приступа интернету без потребе за рутовањем. Апликацијама и адресама се може појединачно дозволити или одбити приступ бежичној и/или мобилној вези.
+ Нетгард захтева Андроид 5.1 или новији
+ \'Xposed\' изазива превише грешака које могу резултирати да Нетгард буде уклоњен са Гугл плеј продвнице. Стога, Нетгард није подржан док је \'Xposed\' инсталиран
+ Политика приватности
+ Огромна пажња је посвећена развоју и тестирању Нетгард апликације. Међутим, немогуће је гарантовати да ће Нетгард радити исправно на сваком уређају.
+ Слажем се
+ Не слажем се
+ Нетгарду треба ваша помоћ. Кликните да купите профи могућности да би пројекат живео.
+ Покренути сервиси
+ Општа обавештења
+ Обавештења о приступу
+ Тражење апликације
+ Филтер апликација
+ Приказ корисничких
+ Приказ системских
+ Приказ апл. без интернета
+ Приказ искључених
+ Сортирање апликација
+ Сложи по називу
+ Сложи по УИД
+ Сложи по утрошку података
+ Приказ дневника
+ Поставке
+ Позивница
+ Легенда
+ Подршка
+ О програму
+ Остале апликације
+ Остало
+ Дозвољено
+ Блокирано
+ Жива ажурурања
+ Освежи
+ Приказ назива
+ Приказ организација
+ „PCAP“ укључен
+ „PCAP“ извоз
+ Очисти
+ Извоз
+ Ресет
+ Додај
+ Обриши
+ Чишћење
+ Протокол
+ Изворни порт
+ Адреса одредишта
+ Порт одредишта
+ Апликација одредишта
+ За спољни сервер изаберите „нико“
+ Подразумевано (бела/црна листа)
+ Блокирај бежичну
+ Блокирај мобилну
+ Дозволи бежичну кад екран ради
+ Дозволи мобилну кад екран ради
+ Блокирај роминг
+ Опције
+ Тема: %1$s
+ Користи тамну тему
+ Обавести при новим инсталацијама
+ Примени правило \'укљученог екрана\'
+ Сам укључи након %1$s мин.
+ Одложи угашен екран %1$s мин.
+ Провери ажурирања
+ Мрежне опције
+ Подмрежно рутирање
+ Дозволи тетеринг
+ Дозволи ЛАН приступ
+ Укључи ИПв6 саобраћај
+ Кућне бежичне мреже: %1$s
+ Управљај мереним бежичним мрежама
+ Сматрај 2Г без мерења
+ Сматрај 3Г без мерења
+ Сматрај ЛТЕ без мерења
+ Занемари национални роминг
+ Занемари ЕУ роминг
+ Искључи при позиву
+ Закључај бежичну
+ Закључај мобилну
+ Учитај при свакој промени везе
+ Напредне опције
+ Управљај системским апликацијама
+ Бележи приступ интернету
+ Обавести о приступу интернету
+ Филтрирај саобраћај
+ Филтрирај УДП саобраћај
+ Глатко преузимање ВПН везе при поновном учитавању
+ Затварање веза при учитавању
+ Закључај саобраћај
+ Прати коришћење мреже
+ Ресетуј коришћење мреже
+ Прикажи разрешене називе домена
+ Блокирај домене
+ ДНС код одговора: %s
+ Прослеђивање порта
+ ВПН ИПв4: %s
+ ВПН ИПв6: %s
+ ВПН ДНС: %s
+ Провери на: %s
+ Време истека ДНС упита: %s сек.
+ Користи СОКС5 прокси
+ СОКС5 адреса: %s
+ СОКС5 порт: %s
+ СОКС5 корисничко име: %s
+ СОКС5 лозинка: %s
+ „PCAP“ величина записа: %s B
+ „PCAP“ макс. вел. фајла: %s MB
+ Вочдог: сваких %s мин.
+ Обавештење о брзини
+ Приказ обавештења о брзини
+ Прикажи најкоришћеније
+ Интервал узорковања: %s ms
+ Број узорака: %s s
+ Резервна копија
+ Извези поставке
+ Увези поставке
+ Увези \'hosts\' фајл
+ Увези \'hosts\' фајл (придодај)
+ УРЛ за преузимање \'hosts\' фајла
+ Преузми \'hosts\' фајл
+ Технички подаци
+ Опште
+ Мрежe
+ Претплате
+ Приказ у статусној траци за директно подешавање ново инсталираних апликација (профи могућност)
+ Након искључивања путем виџета, аутоматски укључи Нетгард након изабраног броја минута (унесите нулу да искључите ову опцију)
+ Након гашења екрана, правила за упаљени екран биће активна изабрани број минута (унесите нулу да искључите опцију)
+ Провери нова издања на Гитхабу два пута дневно
+ Зависно од верзије Андроида, тетеринг ће можда радити а можда и не. Његов саобраћај се не може филтрирати.
+ Укључује подмрежно рутирање. Може укључити бежично позивање али може изазвати грешке и повећати потрошњу батерије
+ Дозвољава апликацијама повезивање са адресама локалне мреже попут 10.0.0.0/8, 172.16.0.0/12 и 192.168.0.0/16
+ Рутира ИПв6 саобраћај на Нетгард како би могао бити дозвољен или блокиран
+ Примени правила бежичне мреже само за изабране (на остале бежичне, примењуј правила мобилне мреже)
+ Примени правила мобилне мреже на мерене (плаћене, тетероване) бежичне мреже
+ Примени правила бежичне мреже за 2Г мреже
+ Примени правила бежичне мреже за 3Г мреже
+ Примени правила бежичне мреже за ЛТЕ мреже
+ Не примењуј роминг правила када су државе СИМ картице и мобилне мреже исте
+ Не примењуј роминг правила када су државе СИМ картице и мобилне мреже из ЕУ (роминг као код куће)
+ Искључи Нетгард код телефонских позива. Ово може решити проблем позива преко ИП/бежичне везе.
+ Одреди правила за системске апликације (за стручњаке)
+ Бележи покушаје приступа интернету. Може повећати потрошњу батерије.
+ Прикажи обавештење кад апликација покуша приступ новој интернет адреси (кад је филтрирање искључено, само блокирани покушаји биће објављени)
+ Филтрирај ИП пакете који излазе из ВПН тунела. Може повећати потрошњу батерије.
+ Прати број послатих и примљених бајтова за сваку апликацију и адресу. Може повећати потрошњу батерије.
+ Одговори са подешеним ДНС кодом одговора за блокиране називе домена. Искључено је када \'hosts\' фајл није доступан.
+ Подразумевана вредност је 3 (NXDOMAIN), што значи „непостојећи домен“.
+ Назив домена где се проверава интернет веза на порту 443 (https).
+ Само ТЦП саобраћај ће бити послат на проокси сервер
+ Периодично проверава да ли Нетгард и даље ради (нула искључује ову опцију). Може повећати потрошњу батерије.
+ Приказује график брзине мреже у обавештењима
+ Да ли сте сигурни?
+ Примењујем правила
+ дозвољено %1$d, блокирано %2$d
+ дозвољено %1$d, блокирано %2$d, домаћина %3$d
+ Чекам на догађај
+ Нетгард је искључен. Користите прекидач изнад да га укључите
+ Нетгард је искључен. Вероватно од стране друге ВПН апликације
+ инсталирано \'%1$s\'
+ Је инсталирано
+ %1$s покушава приступ интернету
+ Покушан приступ интернету
+ Радња извршена
+ Нетгард користи локални ВПН за филтрирање интернет саобаћаја.
+Зато дозволите ВПН везе у следећем дијалогу.
+Ваш интернет саобраћај се не шаље на удаљени ВПН сервер.
+ Нетгард се није покренуо аутоматски. Могуће је да је то услед грешке у вашој верзији Андроида.
+ Дошло је до неочекиване грешке: %s
+ Андроид тренутно одбија да покрене ВПН сервис. Могуће је да је због грешке у вашој верзији Андроида.
+ Пробајте Нетгард
+ Донирајући, сагласни сте са одредбама и условима
+ Ако на следећем дијалогу не можете да изаберете „У реду“, могуће је да нека апликација управља екраном.
+ ± %1$.3f▲ %2$.3f▼ MB/дневно
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Ради добрих резултата, Нетгард треба искључити из Андроидове оптимизације батерије.
+\n\nУ следећем дијалогу изаберите „Све апликације“, тапните на Нетгард у листи и изаберите „Не оптимизуј“.
+ Ради добрих резултата, Нетгард треба искључити из Андроидове опције уштеде података
+\n\nУ следећем дијалогу изаберите опције „Подаци у позадини“ и „Неограничено коришћење података“
+ Употреба филтрирања ће довести да Андроид припише саобраћај и потрошњу батерије Натгарду а не оним апликацијама које заиста, преко Натгарда, покушавају повезивање
+ Андроид 4 захтева да филтрирање буде укључено
+ Бележење саобраћаја је искључено. Прекидачем изнад, укључите бележење. Може повећати потрошњу батерије.
+ Ово ће ресетовати правила и услове на подразумеване вредности
+ Ово ће обрисати линије без дозволи/блокирај правила из дневника покушаја приступа
+ Последњи увоз: %s
+ Преузимам\n%1s
+ \'hosts\' фајл преузет
+ Последње преузимање: %s
+ Да прослеђујем са %1$s порт %2$d на %3$s:%4$d за „%5$s“?
+ Да зауставим прослеђивање %1$s порт %2$d?
+ Проток се мери
+ Не постоји веза са интернетом
+ Нетгард је заузет
+ Ажурирање доступно. Тапните за преузимање
+ Можете дозволити (зеленкасто) или одбити (црвенкасто) бежични или мобилн приступ интернету додиром на иконицу поред апликације
+ Ако сте инсталирали Нетгард ради заштите своје приватности, можда ћете бити заинтересовани и за Фер Е-пошту - FairEmail , апликацију за е-пошту отвореног кода
+ Интернет приступ је подразумевано дозвољен (црна листа). Ово се може променити у поставкама
+ Долазне (push) поруке углавном стижу преко системске компоненте „Плеј сервиси“ којој је подразумевано дозвољен приступ интернету
+ Управљање свим (и системским) апликацијама може бити укључено у поставкама
+ Опишите проблем и наведите време када се догодио:
+ ВПН веза је отказана\nДа ли сте подесили други ВПН који је стално активан?
+ Искљичивањем уређаја док је Нетгард активан, обезбеђујете да се Нетгард покрене и при паљењу уређаја
+ Ова могућност није доступна на овој верзији Андроида
+ Други ВПН је постављен као увек активан ВПН
+ Искључите „Блокирај везе без ВПН“ у Андроид подешавањима да бисте користили режим филтрирања
+ Искључите „Лични ДНС“ у мрежним подешавањима да бисте користили режим филтрирања
+ Саобраћај је онемогућен
+ Немерени саобраћај је дозвољен
+ Немерени саобраћај је блокиран
+ Немерена правила нису примењена
+ Мерени саобраћај је дозвољен
+ Мерени саобраћај је блокиран
+ Мерена правила нису примењена
+ Адреса је дозвољена
+ Адреса је блокирана
+ Дозволи када је екран укључен
+ Блокирај у ромингу
+ Бежична мрежа је подразумевано немерена док се мобилна сматра да је са мереним протоком
+ нема дозволе за интернет
+ је онемогућена
+ Долазне поруке се примају преко Гугл плеј сервиса тако да се не могу онемогућити блокирањем саме апликације
+ Преузимања одрађује менаџер преузимања а не сама апликација па се не могу онемогућити блокирањем саме апликације
+ Примени правила и услове
+ Услови
+ Дозволи бежичну кад екран ради
+ Дозволи мобилну кад екран ради
+ R
+ Блокирај у ромингу
+ Дозволи и у блокади
+ Везано за филтер
+ Покушаји приступа
+ Правила приступа су важнија од осталих правила
+ Опције
+ Обавести о покушајима приступа
+ Бележење или филтрирање није укључено
+ Бележење и филтрирање је укључено
+ Подешавање
+ Укључи бележење само блокираних адреса
+ Укључи филтрирање да би се бележиле и дозвољене адресе
+ Укључи обавештење о приступу за нове убележене адресе
+ Ове поставке су глобалне и примењују се на све апликације
+ Филтрирање је неопходно за контролу појединачних адреса
+ Укључивање бележења или филтрирања може довести до трошења батерије и утицати на брзину мреже
+ Оцени
+ Дозволи
+ Блокирај
+ Дозволи бежичну
+ Блокирај бежичну
+ Дозволи мобилну
+ Блокирај мобилну
+ root
+ сервер медија
+ нико
+ Не питај поново
+ Ко је %1$s
+ Порт %1$d
+ Копирај
+ Профи могућности
+ Следеће профи могућности су доступне:
+ Преглед дневника блокираног саобраћаја
+ Филтрирање мрежног саобраћаја
+ Обавештење о новој апликацији
+ Обавештење о брзини мреже
+ Приказ (теме, боје)
+ Све профи могућности
+ Подржите развој
+ Купите
+ Укључено
+ Недоступно
+ Тапните на наслов за више детаља
+ Изазов
+ Одговор
+ Ово је профи могућност
+ Месечна претплата у износу од 1 или 2 € (без пореза) активираће све профи могућности.
+ Претплату можете отказати или управљати њоме преко језичка Претплате у Плеј продавници.
+
+
+ - тиркизно/наранџасто
+ - плаво/наранџасто
+ - пурпурно/црвено
+ - жуто/плаво
+ - наранџасто/сиво
+ - зелено
+
+
+ - УДП
+ - ТЦП
+
+
diff --git a/NetGuard/app/src/main/res/values-sv-rSE/strings.xml b/NetGuard/app/src/main/res/values-sv-rSE/strings.xml
new file mode 100644
index 0000000..08ff0ee
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-sv-rSE/strings.xml
@@ -0,0 +1,292 @@
+
+
+ NetGuard ger enkla och avancerade sätt att blockera åtkomst till internet - ingen root krävs. Appar och adresser kan individuellt tillåtas eller nekas åtkomst till din Wi-Fi- och/eller mobildata-anslutning.
+ NetGuard kräver Android 5.1 eller senare
+ Xposed orsakar alltför många krascher, vilket kan resultera i NetGuard tas bort från Google Play Store, därför stöds inte NetGuard medan Xposed är installerat
+ Sekretesspolicy
+ Stor omsorg har tagits för att utveckla och testa NetGuard, men det är omöjligt att garantera att NetGuard fungerar korrekt på alla enheter.
+ Jag godkänner
+ Jag godkänner inte
+ NetGuard behöver din hjälp. Tryck för att köpa pro-funktioner för att hålla projektet igång.
+ Aktiva tjänster
+ Allmänna aviseringar
+ Tillgång meddelanden
+ Sök efter app
+ Filtrera appar
+ Visa användarappar
+ Visa systemappar
+ Visa appar utan internet
+ Visa inaktiverade appar
+ Sortera appar
+ Sortera efter namn
+ Sortera på uid
+ Sortera på dataanvändning
+ Visa logg
+ Inställningar
+ Bjud in
+ Förklaring
+ Support
+ Om
+ Andra appar
+ Övrigt
+ Tillåtna
+ Blockerade
+ Live uppdateringar
+ Uppdatera
+ Visa namn
+ Visa organisation
+ PCAP aktiverad
+ PCAP export
+ Rensa
+ Exportera
+ Återställ
+ Lägg till
+ Ta bort
+ Städa
+ Protokoll
+ Käll port
+ Destinationsadress
+ Destinationsport
+ Destinationsapp
+ För en extern server, välj \'nobody\'
+ Standardvärden (vit-/svartlista)
+ Blockera Wi-Fi
+ Blockera mobildata
+ Tillåt Wi-Fi när skärmen är påslagen
+ Tillåt mobildata när skärmen är påslagen
+ Blockera roaming
+ Alternativ
+ Tema: %1$s
+ Använd mörkt tema
+ Meddela vid ny installation
+ Tillämpa regler \'när skärmen är påslagen\'
+ Aktivera automatiskt efter %1$s minuter
+ Dröj skärmavstängning i %1$s minuter
+ Sök efter uppdateringar
+ Nätverksinställningar
+ Subnet routing
+ Tillåt sammanlänkning
+ Tillåt LAN-åtkomst
+ Aktivera IPv6-trafik
+ Wi-Fi hemmanätverk: %1$s
+ Hantera uppmätta Wi-Fi-nätverk
+ Överväg 2G obegränsad
+ Överväg 3G obegränsad
+ Överväg LTE obegränsad
+ Ignorera nationell roaming
+ Ignorera EU-roaming
+ Inaktivera under samtal
+ Lås Wi-Fi
+ Lås mobildata
+ Uppdatera vid förändrad uppkoppling
+ Avancerade inställningar
+ Hantera systemappar
+ Logga internetåtkomst
+ Meddela vid internetåtkomst
+ Filtrera trafik
+ Filtrera UDP-trafik
+ Sömlös VPN-överlämning vid omladdning
+ Stäng anslutningar vid omladdning
+ Lås trafik
+ Spåra nätverksanvändning
+ Återställ nätverksanvändning
+ Visa lösta domännamn
+ Blockera domännamn
+ DNS-svarskod: %s
+ Vidarebefordring av port
+ VPN-IPv4: %s
+ VPN-IPv6: %s
+ VPN-DNS: %s
+ Validera på: %s
+ Minsta DNS-TTL: %s s
+ Använd SOCKS5-proxy
+ SOCKS5-adress: %s
+ SOCKS5-port: %s
+ SOCKS5-användarnamn: %s
+ SOCKS5-lösenord: %s
+ PCAP-poststorlek: %s B
+ PCAP max. filstorlek: %s MB
+ Watchdog: varje %s minuter
+ Hastighetsavisering
+ Visa hastighetsaviseringar
+ Visa topp appar
+ Samplingsintervallet: %s ms
+ Antal prover: %s s
+ Säkerhetskopiering
+ Exportera inställningar
+ Importera inställningar
+ Importera hosts-filen
+ Importera värdfil (lägg till)
+ Hosts-filens hämtningswebbadress
+ Hämta hosts-filen
+ Teknisk information
+ Allmänt
+ Nätverk
+ Prenumerationer
+ Visa statusfält aviseringar för att direkt konfigurera nyinstallerade appar (pro-funktion)
+ När du har inaktiverat gränssnittskomponenten aktiverar du automatiskt NetGuard igen efter det valda antalet minuter (ange noll för att inaktivera det här alternativet)
+ När du har stängt av skärmen, behåll regler för skärmen på aktiva för det valda antalet minuter (ange noll för att inaktivera det här alternativet)
+ Sök efter nya utgåvor på GitHub två gånger dagligen
+ Beroende på Android-versionen, kan sammanlänkning fungera eller inte fungera. Sammanlänkad trafik kan inte filtreras.
+ Aktivera subnätsrouting; kan aktivera Wi-Fi-samtal, men kan också utlösa buggar i Android och öka batterianvändningen
+ Tillåt apparna att ansluta till LAN-adresser, som 10.0.0.0/8, 172.16.0.0/12 och 192.168.0.0/16
+ Vidarebefodra IP-version 6 trafik till NetGuard så det kan selektivt tillåtas eller blockeras
+ Tillämpa Wi-Fi-nätverksregler endast för valt nätverk (tillämpa regler för mobilt nätverk för andra Wi-Fi-nätverk)
+ Tillämpa regler för mobilnät på uppmätta (betalda, bundna) Wi-Fi-nätverk
+ Använd Wi-Fi-nätverksregler för 2G dataanslutningar
+ Använd Wi-Fi nätverksregler för anslutningar till 3G
+ Använd Wi-Fi nätverksregler för LTE dataanslutningar
+ Använd inte roamingregler när SIM-kortet och mobilnätets land är desamma
+ Tillämpa inte roamingregler när SIM-kortet och mobilnätet är inom EU (använd roaming som hemma)
+ Inaktivera NetGuard för inkommande eller utgående telefonsamtal. Detta kan användas för att arbeta runt IP/Wi-Fi-samtalsproblem.
+ Definiera regler för systemappar (för experter)
+ Logga försök att ansluta till internet för appar. Detta kan resultera i extra batterianvändning.
+ Visa ett meddelande i statusfältet när en app försöker komma åt en ny Internetadress (när filtrering är inaktiverad kommer endast blockerade försök till Internetanslutning att meddelas)
+ Filtrera IP-paket som går ut från VPN-tunneln. Detta kan resultera i extra batterianvändning.
+ Spåra antalet byte som skickas och tas emot för varje app och adress. Detta kan leda till extra batterianvändning.
+ Svara med den konfigurerade DNS-svarskoden för blockerade domännamn. Detta reglage är inaktiverad när ingen värdfil finns tillgänglig.
+ Standardvärdet är 3 (NXDOMAIN), vilket betyder \"obefintlig domän\".
+ Domännamn som används för att validera internetanslutningen vid port 443 (https).
+ Endast TCP-trafik kommer att sändas till proxyservern
+ Kontrollera regelbundet om NetGuard fortfarande körs (ange noll för att inaktivera det här alternativet). Detta kan leda till extra batterianvändning.
+ Visa nätverkshastighetsdiagram i statusfältet
+ Är du säker?
+ Tvingande regler
+ %1$d tillåtna, %2$d blockerade
+ %1$d tillåtna, %2$d blockerade, %3$d värdar
+ Väntar på händelse
+ NetGuard är inaktiverad, använd skjutreglage ovan för att aktivera NetGuard
+ NetGuard har inaktiverats, sannolikt för att en annan VPN-baserade app används
+ \'%1$s\' installerad
+ Har installerats
+ %1$s försökte få tillgång till internet
+ Försökte få tillgång till internet
+ Åtgärdad
+ NetGuard använder en lokal VPN för att filtrera internettrafik.
+Av denna anledning, vänligen tillåt en VPN-anslutning i nästa dialogruta.
+Din internettrafik skickas inte till en avlägsen VPN-server.
+ NetGuard kunde inte starta automatiskt. Detta är sannolikt på grund av ett fel i din Android-version.
+ Ett oväntat fel har inträffat: \'%s\'
+ Android vägrade att starta VPN-tjänsten just nu. Detta är sannolikt på grund av ett fel i din Android-version.
+ Prova NetGuard
+ Genom att donera samtycker du till villkor
+ Om du inte kan klicka på OK i nästa dialogruta kommer en annan (skärmdimnings)app sannolikt att manipulera skärmen.
+ ± %1$.3f▲ %2$.3f▼ MB/dag
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ För konsekventa resultat bör Android-batterioptimeringarna inaktiveras för NetGuard.
+\n\nI nästa dialogruta väljer du \"Alla appar\" högst upp, tryck på NetGuard i listan och välj och bekräfta \"Optimera inte\".
+ För konsekventa resultat ska Android-databesparingsalternativen inaktiveras för NetGuard
+\n\nI nästa dialogruta, aktivera alternativen \"Bakgrundsdata\" och \"Obegränsad dataanvändning\"
+ Genom att använda filtrering kommer Android att tillskriva data och strömförbrukning till NetGuard - Android förutsätter att data och ström används av NetGuard, snarare än de ursprungliga apparna
+ Android 4 kräver att filtrering är aktiverat
+ Trafikloggning är inaktiverad, använd reglage ovan för att aktivera loggning. Trafikloggning kan resultera i extra batterianvändning.
+ Detta kommer att återställa regler och villkor till deras standardvärden
+ Detta tar bort åtkomstförsökslogglinjer utan tillåt-/blockregler
+ Senaste import: %s
+ Hämtar\n%1s
+ Hosts-filen hämtad
+ Senaste hämtning: %s
+ Börja vidarebefodra från %1$s port %2$d till %3$s:%4$d av \'%5$s\'?
+ Sluta vidarebefordra %1$s port %2$d?
+ Nätverket är uppmätt
+ Ingen aktiv internetanslutning
+ NetGuard är upptagen
+ Uppdatering tillgänglig, tryck för att hämta
+ Du kan tillåta (grön) eller neka (röd) Wi-Fi eller mobilt Internet genom att trycka på ikonerna bredvid en app
+ Om du har installerat NetGuard för att skydda din integritet kan du också vara intresserad av FairEmail , e-postapp med öppen källkod som respekterar din integritet
+ Internetåtkomst är tillåtet som standard (svartlistläge), detta kan ändras i inställningarna
+ Inkommande (push) meddelanden hanteras mestadels av systemkomponenten Play-tjänster, vilket är tillåten Internetåtkomst som standard
+ Hantering av alla (system)appar kan aktiveras i inställningarna
+ Beskriv problemet och ange tidpunkten för problemet:
+ VPN-anslutning annulleras\nHar du konfigurerat en annan VPN för att vara en alltid-på VPN?
+ Stänga av enheten med NetGuard aktiverat, startar automatiskt NetGuard när du startar enheten
+ Denna funktion är tillgänglig för denna Android-version
+ En annan VPN är inställd som alltid-på VPN
+ Stäng av \"blockera anslutningar utan VPN\" i Android VPN-inställningar för att använda NetGuard i filtreringsläge
+ Stäng av \"Private DNS\" i Android-nätverksinställningar för att använda NetGuard i filtreringsläge
+ Trafiken är låst
+ Ouppmätt trafik är tillåten
+ Ouppmätt trafik är blockerad
+ Mätningsregler tillämpas inte
+ Uppmätt trafik tillåts
+ Uppmätt trafik blockeras
+ Mätningsregler tillämpas inte
+ Adressen är blockerad
+ Adressen är blockerad
+ Tillåt när skärmen är påslagen
+ Blockera vid roaming
+ Som standard anses en Wi-Fi-anslutning vara obestämd och en mobilanslutning som uppmätt
+ saknar internetbehörighet
+ är inaktiverad
+ Inkommande meddelanden tas emot av Google Play-tjänster och inte av den här appen och kan därför inte blockeras genom att blockera den här appen
+ Hämtningar utförs av hämtningshanteraren och inte av denna app och kan därför inte blockeras genom att blockera denna app
+ Tillämpa regler och villkor
+ Villkor
+ Tillåt Wi-Fi när skärmen är påslagen
+ Tillåt mobildata när skärmen är påslagen
+ R
+ Blockera vid roaming
+ Tillåt i låst läge
+ Filter relaterat
+ Åtkomstförsök
+ Åtkomstregler har företräde framför andra regler
+ Inställningar
+ Meddela försök till internetåtkomst
+ Loggning eller filtrering är inte aktiverad
+ Loggning och filtrering är aktiverade
+ Konfigurera
+ Aktivera loggning av endast blockerade adresser
+ Aktivera filtrering för att logga tillåtna adresser
+ Aktivera åtkomstmeddelanden för nyloggade adresser
+ Dessa inställningar är globala inställningar som gäller för alla appar
+ Filtrering krävs också för att tillåta eller blockera enskilda adresser
+ Att aktivera loggning (mindre) eller filtrering (mer) kan öka batterianvändningen och kan påverka nätverkshastigheten
+ Betygsätt
+ Tillåt
+ Blockera
+ Tillåt Wi-Fi
+ Blockera Wi-Fi
+ Tillåt mobildata
+ Blockera mobildata
+ root
+ mediaserver
+ ingen
+ Fråga inte igen
+ Whois %1$s
+ Port %1$d
+ Kopiera
+ Pro-funktioner
+ Följande pro-funktioner är tillgängliga:
+ Visa blockerad trafiklogg
+ Filtrera nätverkstrafik
+ Nya app-aviseringar
+ Avisering om nätverkshastighet
+ Utseende (tema, färger)
+ Alla ovanstående pro-funktioner
+ Stöd utvecklingen
+ Köp
+ Aktiverad
+ Otillgängligt
+ Tryck på en titel för mer information
+ Utmaning
+ Svar
+ Detta är en pro-funktion
+ Ett månatlig abonnemang på 1 eller 2 euro (exklusive lokala skatter) aktiverar alla profunktioner.
+ Du kan avbryta eller hantera ett abonnemang via abonnemangsfliken i appen Play store.
+
+
+ - teal/orange
+ - blå/orange
+ - lila/röd
+ - amber/blå
+ - orange/grå
+ - grön
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-ta-rIN/strings.xml b/NetGuard/app/src/main/res/values-ta-rIN/strings.xml
new file mode 100644
index 0000000..4e70ee8
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-ta-rIN/strings.xml
@@ -0,0 +1,287 @@
+
+
+ NetGuard இணைய - தேவை இல்லை வேர் தடுக்க எளிய மற்றும் மேம்பட்ட வழிகளை வழங்குகிறது. பயன்பாடுகள் மற்றும் முகவரிகளை தனித்தனியாக அனுமதிக்கப்பட்ட அல்லது இயலும் உங்கள் Wi-Fi மற்றும்/அல்லது மொபைல் இணைப்பை அணுகல் மறுக்கப்பட்டது.
+ நெட்கார்டுக்கு Android 5.1 அல்லது அதற்குப் பிறகு தேவைப்படுகிறது
+ எக்ஸ்போஸ் பல செயலிழப்புகளை ஏற்படுத்துகிறது, இதன் விளைவாக கூகிள் பிளே ஸ்டோரிலிருந்து நெட்கார்ட் அகற்றப்படலாம், எனவே எக்ஸ்போஸ் நிறுவப்பட்டிருக்கும் போது நெட்கார்ட் ஆதரிக்கப்படவில்லை
+ தனியுரிமைக் கொள்கை
+ நெட்கார்ட்டை உருவாக்க மற்றும் சோதிக்க மிகுந்த கவனம் செலுத்தப்பட்டுள்ளது, இருப்பினும் ஒவ்வொரு சாதனத்திலும் நெட்கார்ட் சரியாக வேலை செய்யும் என்று உத்தரவாதம் அளிக்க முடியாது.
+ நான் ஏற்கிறேன்
+ நான் மறுக்கிறேன்
+ நெட்கார்டுக்கு உங்கள் உதவி தேவை. திட்டத்தை தொடர சார்பு அம்சங்களை வாங்க தட்டவும்.
+ இயங்கும் சேவைகள்
+ பொது அறிவிப்புகள்
+ அறிவிப்புகளை அணுகவும்
+ செயலியை தேட
+ செயலிகளை வடிகட்ட
+ பயனர் செயலிகளை காண்பி
+ காட்சி அமைப்பு பயன்பாடுகள்
+ இணையம் இல்லா செயலிகளை காண்பி
+ முடக்கப்பட்ட பயன்பாடுகள் காண்பி
+ செயலிகளை வரிசைப்படுத்த
+ பெயரால் வரிசைப்படுத்த
+ uid-ஆல் வரிசைப்படுத்து
+ தரவு பயன்பாட்டால் வரிசைப்படுத்து
+ பதிவை காண்பி
+ அமைப்புகள்
+ அழை
+ உள் பட்டியல்
+ ஆதரவு
+ பற்றி
+ பிற செயலிகள்
+ பிற
+ அனுமதிக்கப்பட்டவை
+ தடுக்கப்பட்டவை
+ நேரடி புதுப்பித்தல்கள்
+ புதுப்பி
+ பெயர்களை காண்பி
+ நிறுவனத்தை காண்பி
+ PCAP செயலாக்கம்
+ PCAP ஏற்றுமதி
+ அகற்று
+ ஏற்றுமதி
+ மீட்டமை
+ சேர்
+ அழி
+ சுத்தமாக்கு
+ நெறிமுறை
+ மூல முணையம்
+ இலக்கு முகவரி
+ இலக்கு முணையம்
+ இலக்குச் செயலி
+ ஒரு வெளிப்புற சேவையகத்திற்காக தேர்ந்தெடுத்து \'யாரும்\'
+ இயல்புநிலைகள்
+ Wi-Fi-யை தடு
+ மொபைல் தடு
+ Wi-Fi அனுமதிக்கும் போது திரை மீது
+ மொபைல் எப்போது திரை அனுமதி
+ சுற்றும் தடு
+ விருப்பங்கள்
+ கருப்பொருள்: %1$s
+ கருத்த கருப்பொருளை உபயோகி
+ புதிய நிறுவல்களை தெரிவி
+ \'ஸ்கிரீன் ஆன்\' விதிகளைப் பயன்படுத்துங்கள்
+ %1$s நிமிடங்களுக்கு பிறகு தானாக இயக்கு
+ அணை %1$s நிமிடங்கள் தாமதம் திரை
+ மேம்படுத்தலுக்கு சோதி
+ பிணைய விருப்பங்கள்
+ துணைவலை வழியமை
+ Tethering அனுமதி
+ LAN அணுகலை அனுமதி
+ IPv6 போக்குவரத்து செயலாக்கம்
+ Wi-Fi வீட்டு வலைப்பின்னல்கள்: %1$s
+ நடத்தி metered Wi-Fi வலைப்பின்னல்கள்
+ 2G unmetered சிந்திக்கவும்
+ 3G unmetered சிந்திக்கவும்
+ LTE unmetered சிந்திக்கவும்
+ தேசிய சுற்றும் புறக்கணி
+ ஐரோப்பிய ஒன்றிய ரோமிங்கை புறக்கணிக்கவும்
+ அழைப்பில் முடக்கு
+ வைஃபையை பூட்டு
+ மொபைலை பூட்டு
+ ஒவ்வொரு இணைப்பு மாற்றத்திலும் மீண்டும் ஏற்றவும்
+ மேம்பட்ட விருப்பங்கள்
+ கணினி பயன்பாடுகள் நிர்வகி
+ பதிவை இணைய அணுகல்
+ இணைய அணுகல் தெரிவி
+ போக்குவரத்தை வடிகட்டு
+ யுடிபி போக்குவரத்தை வடிகட்டவும்
+ மீண்டும் ஏற்றும்போது தடையற்ற VPN கையளிப்பு
+ மீண்டும் ஏற்றும்போது இணைப்புகளை மூடு
+ போக்குவரத்தை பூட்டு
+ பிணைய பயன்பாடு அறி
+ பிணைய பயன்பாடு மீட்டமை
+ தீர்க்கப்பட்ட டொமைன் பெயர்களைக் காட்டு
+ டொமைன் பெயர்களை தடு
+ டிஎன்எஸ் மறுமொழி குறியீடு:%s
+ முணையம் மேலனுப்ப
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ %s - இல் சரிபார்க்கவும்
+ குறைந்தபட்ச DNS TTL:%s s
+ SOCKS5 பதிலி பயன்படுத்தவும்
+ SOCKS5 முகவரி: %s
+ SOCKS5 போர்ட்: %s
+ SOCKS5 பயனர் பெயர்: %s
+ SOCKS5 கடவுச்சொல்: %s
+ PCAP சாதனை அளவு: %s B
+ PCAP அதிகபட்ச கோப்பு அளவு: %s MB
+ கண்காணிப்பு: ஒவ்வொரு %s நிமிடங்களும்
+ வேக அறிவிப்பு
+ வேக அறிவிப்பை காண்பி
+ மேல் பயன்பாடுகள் காண்பி
+ மாதிரி இடைவேளை: %s ms
+ மாதிரிகளின் எண்ணிக்கை: %s s
+ மறுபிரதி
+ ஏற்றுமதி அமைப்புகள்
+ இறக்குமதி அமைப்புகள்
+ சேவையகங்கள் கோப்பு இறக்குமதி
+ ஹோஸ்ட்கள் கோப்பை இறக்குமதி செய்க (சேர்க்கவும்)
+ சேவையகங்கள் கோப்பு பதிவிறக்கம் URL
+ சேவையகங்கள் கோப்பு பதிவிறக்கம்
+ தொழில்நுட்ப தகவல்கள்
+ பொது
+ வலைப்பின்னல்கள்
+ சந்தாக்கள்
+ நிலை பட்டி அறிவிக்கை புதிதாக நிறுவப்பட்ட பயன்பாடுகள் (ப்ரோ அம்சம்) நேரடியாக உள்ளமைக்க காண்பி
+ இந்த விட்ஜெட்டை பயன்படுத்தி முடக்குகிறது, பின்னர் தானாகவே செயல்படுத்த NetGuard தேர்ந்தெடுத்த எண்ணிக்கை நிமிடங்கள் (இந்த விருப்பத்தை முடக்க பூஜ்யம் உள்ளிட) பிறகு மீண்டும்
+ திரை அணைப்பது, பிறகு வைத்துக் விதிகள் உள்ள திரை நடப்பு நிலையில் தேர்ந்தெடுத்த எண்ணிக்கை (இந்த விருப்பத்தை முடக்க பூஜ்யம் உள்ளிட) நிமிடங்கள்
+ தினமும் இருமுறை புதிய வெளியீடுகள் GitHub சரிபார்க்க
+ பொறுத்து அண்ட்ராய்டு பதிப்பு, tethering வேலை இருக்கலாம் அல்லது வேலை செய்யாது. Tethered போக்குவரத்து வடிகட்ட இயலாது.
+ துணைவலை வழியமை; செயலாக்கம் இருக்கலாம் செயல்படுத்த Wi-Fi அழைத்தல், ஆனால் இருக்கலாம் மேலும் குண்டுகளை வெடிக்கச் செய்வதற்கு உபயோகப்படுத்தப்பட்ட அறியப் அண்ட்ராய்டு மற்றும் பேட்டரி பயன்பாடு அதிகரிக்கும்
+ லோக்கல் ஏரியா நெட்வொர்க் முகவரிகள், 10.0.0.0/8, 172.16.0.0/12 மற்றும் 192.168.0.0/16 போன்ற இணைய பயன்பாடுகளை
+ IP பதிப்பு 6 போக்குவரத்து NetGuard வழியமை அதனால் அது முடிச்சுப்பைகளை அனுமதிக்கப்பட்ட அல்லது இயலும் தடுக்கப்பட்டது
+ தேர்ந்தெடுத்த பிணைய மட்டும் Wi-Fi பிணைய விதிகளை பயன்படுத்து (Wi-Fi பிணையங்களுக்காக மற்ற மொபைல் நெட்வொர்க் விதிகளை பயன்படுத்து)
+ Metered (செலுத்தப்படாத, tethered) Wi-Fi வலைப்பின்னல்கள் மொபைல் நெட்வொர்க் விதிகளை பயன்படுத்து
+ 2G தரவு இணைப்புகளுக்கு Wi-Fi பிணைய விதிகளை பயன்படுத்து
+ 2G தரவு இணைப்புகளுக்கு Wi-Fi பிணைய விதிகளை பயன்படுத்து
+ 2G தரவு இணைப்புகளுக்கு Wi-Fi பிணைய விதிகளை பயன்படுத்து
+ பயன்படுத்தப்படாது நடமாடும் விதிகள், சிம் மற்றும் மொபைல் நெட்வொர்க் நாடு இருக்கும் போது ஒரே
+ சிம் மற்றும் மொபைல் நெட்வொர்க் நாடு ஐரோப்பிய ஒன்றியத்திற்குள் இருக்கும்போது ரோமிங் விதிகளைப் பயன்படுத்த வேண்டாம் (வீட்டில் இருப்பது போல் சுற்றவும்)
+ உள்வரும் அல்லது வெளிச்செல்லும் தொலைபேசி அழைப்பில் நெட்கார்டை முடக்கு. ஐபி / வைஃபை அழைப்பு சிக்கல்களைச் சரிசெய்ய இது பயன்படுத்தப்படலாம்.
+ முறைமை விண்ணப்பங்கள் (நிபுணர்கள்) விதிகளை விவரி
+ பதிவை பயன்பாடுகள், இணையத்தை அணுக முயற்சிக்கும். கூடுதல் மின்கல பயன்பாட்டு இது இதனால் இருக்கலாம்.
+ நிலை பட்டி அறிவிக்கை பயன்பாட்டை ஒரு புதிய இணைய முகவரி அணுக முயற்சிக்கும் போது காண்பி (முடக்கப்பட்டது வடித்தல், போது மட்டும் தடுக்கப்பட்ட இணைய அணுகல் முயற்சிகள் உங்களுக்கு அறிவிக்கப்பட)
+ IP தயாரிப்புகளை VPN துவங்கப்பட்டது வெளியே செல்லும் வடிகட்டி. கூடுதல் மின்கல பயன்பாட்டு இது இதனால் இருக்கலாம்.
+ தடம் பைட்கள் அனுப்பிய மற்றும் பெறப்பட்ட ஒவ்வொரு பயன்பாடு மற்றும் முகவரி எண்ணிக்கை. கூடுதல் மின்கல பயன்பாட்டு இது இதனால் இருக்கலாம்.
+ தடுக்கப்பட்ட டொமைன் பெயர்களுக்கான கட்டமைக்கப்பட்ட டிஎன்எஸ் மறுமொழி குறியீட்டைக் கொண்டு பதிலளிக்கவும். புரவலன் கோப்பு எதுவும் கிடைக்காதபோது இந்த சுவிட்ச் முடக்கப்பட்டுள்ளது.
+ இயல்புநிலை மதிப்பு 3 (NXDOMAIN), அதாவது \'இல்லாத டொமைன்\'.
+ போர்ட் 443 (https) இல் இணைய இணைப்பை சரிபார்க்க டொமைன் பெயர் பயன்படுத்தப்படுகிறது.
+ TCP போக்குவரத்து மட்டும் பதிலிச் சேவையகம் அனுப்பப்படும்
+ அவ்வப்போது என்றால் NetGuard இயங்கிக்கொண்டிருக்கும் சரிபார்க்கவும் (இந்த விருப்பத்தை முடக்க பூஜ்யம் உள்ளிட). கூடுதல் மின்கல பயன்பாட்டு இது இதனால் இருக்கலாம்.
+ நிலை பட்டி அறிவிக்கை பிணைய வேகம் வரைபடம் காண்பி
+ உறுதியாக?
+ விதிகளை அமலாக்கம்
+ %1$d அனுமதிக்கப்பட்டவை, %2$d தடுக்கப்பட்டவை
+ %1$d அனுமதிக்கப்பட்டவை, %2$d தடுக்கப்பட்டவை, %3$d மந்தமான
+ நிகழ்வுக்காக காத்திருக்கிறது
+ NetGuard முடக்கப்பட்டது, NetGuard செயல்படுத்த மேலுள்ள பொத்தான் பயன்படுத்தவும்
+ NetGuard முடக்கப்பட்டுள்ளது, தெரிகிறது நாளுக்கு பயன்படுத்தி வேறு VPN அடிப்படையிலான பயன்பாடு
+ \'%1$s\' நிறுவப்பட்டவை
+ நிறுவப்பட்டது
+ %1$s முற்பட்டபோது இணைய அணுகல்
+ முயற்சிக்காக இணைய அணுகல்
+ செயல் நிறைவுற்றது
+ இணைய போக்குவரத்து வடிகட்ட உள்ளூர் VPN NetGuard பயன்படுத்துகிறது. இந்த காரணத்திற்காக, தயவுசெய்து ஒரு VPN இணைப்பை அனுமதிக்க அடுத்த உரையாடலில். உங்கள் இணைய போக்குவரத்து ஒரு தொலைநிலை VPN சேவையகத்திற்கு அனுப்பப்பட்டுள்ளது இல்லை.
+ NetGuard தொடங்க இயலாது தானாகவே. இது பயன்பாட்டையும் காரணமாக உங்கள் Android பதிப்பில் போன்று.
+ ஒரு எதிர்பாராத பிழை ஏற்பட்டது: \'%s\'
+ இந்த நேரத்தில் VPN சேவையைத் தொடங்க Android மறுத்துவிட்டது. உங்கள் Android பதிப்பில் உள்ள பிழை காரணமாக இது இருக்கலாம்.
+ NetGuard-யை முயற்சிசெய்
+ கொடுப்பதன் மூலம் நீங்கள் ஒப்புக்கொள்கிறீர்கள், விதிமுறைகள் & நிபந்தனைகள்
+ நீங்கள், அடுத்த உரையாடலில் உள்ள சரி என்பதை அழுத்தினால் முடியாது, வேறு (திரை dimming) பயன்பாடு என்பது தெரிகிறது manipulating திரை.
+ ± %1$.3f▲ %2$.3f▼ MB/நாள்
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ ஒத்திருக்கும் முடிவுகளுக்கு, அண்ட்ராய்டு மின்கல optimizations வேண்டும் இருக்க முடக்கப்பட்டுள்ளது NetGuard. \n\nIn அடுத்த உரையாடல், மேலே \"அனைத்து பயன்பாடுகள்\" தேர்ந்தெடுக்கவும், துறையில் உள்ள NetGuard பட்டியல் மற்றும் தேர்வு செய்து உறுதி \"வேண்டாம் உகப்பாக்கு\".
+ ஒத்திருக்கும் முடிவுகளுக்கு, அண்ட்ராய்டு தரவு விருப்பங்கள் சேமிக்க வேண்டும் முடக்க NetGuard \n\nIn அடுத்த உரையாடல், விருப்பங்கள் \"பின்னணி தகவல்\" மற்றும் \"கட்டுப்பாடற்ற தரவு பயன்பாட்டு\" செயல்படுத்த திட்டம்
+ வடிகட்டல் பயன்படுத்தி அவை ஆண் போன்ற பண்பு தரவு மற்றும் மின் பயன்பாடு NetGuard செய்ய வேண்டும் - ஆண் போன்ற பதிலுடன் தரவு மற்றும் மின் இருக்கும் மற்றோரு NetGuard அல்லாமல் மூல பயன்பாடுகள்
+ Android 4 க்கு வடிகட்டுதல் இயக்கப்பட வேண்டும்
+ போக்குவரத்து பதிவெடுத்தல் முடக்கப்பட்டது, பெற்றால் மேற்படி பொத்தான் பயன்படுத்தவும். போக்குவரத்து பதிவெடுத்தல் கூடுதல் மின்கல பயன்பாட்டு இதனால் இருக்கலாம்.
+ இது உரைகளையும் விதிகள் மற்றும் நிபந்தனைகள் தங்களுடைய இயல்பு நிலைக்கு
+ அணுகல் முயற்சி பதிவை வரிகள் இல்லாமல் அனுமதி/தடு விதிகளை நீக்கி விடும்
+ கடைசி இறக்குமதி: %s
+ பதிவிறக்கப்படுகிறது \n%1s
+ சேவையகங்கள் கோப்பு தகவலிறக்கம்
+ கடைசி பதிவிறக்கம்: %s
+ மேலனுப்ப \'%5$s\' %3$s:%4$d %1$s போர்ட் %2$d இருந்து தொடங்கும்?
+ %1$s போர்ட் %2$d மேலனுப்ப நிறுத்து?
+ பிணைய metered
+ இணைய இணைப்பு இல்லை
+ NetGuard பணியில் உள்ளது
+ புதிய பதிப்பு உள்ளது, பதிவிறக்க தட்டவும்
+ நீங்கள் அனுமதி (வண்ணச்சாயலில்) அல்லது (சிவந்த) Wi-Fi அல்லது மொபைல் இணைய அணுகலை அருகில் ஒரு பயன்பாடு படவுருக்களை ஒட்டுக்கேட்பு மூலம் மறு
+ உங்கள் தனியுரிமையைப் பாதுகாக்க நீங்கள் நெட்கார்டை நிறுவியிருந்தால், திறந்த மூல, தனியுரிமை நட்பு மின்னஞ்சல் பயன்பாடான FairEmail இல் நீங்கள் ஆர்வமாக இருக்கலாம்
+ இணைய அணுகல் அனுமதிக்கப்படும் இயல்பாக, இது முடியும் மாற்ற அமைப்புகளில்
+ தள்ளு செய்திகளை ஆகியவை பெரும்பாலும் வேண்டுமெனக் முறைமை உபகரணம் இயக்கு சேவைகள், இயல்புநிலை இணைய அணுகல் இது அனுமதிக்கப்பட்ட உள்ளது
+ நிர்வாக முறைமை பயன்பாடுகள் முடியும் செயலாக்கம் செய்யப்படும் அமைப்புகளில்
+ தயவுசெய்து சிக்கலை விளக்க மற்றும் பிரச்சினையின் நேரம் என்பதை குறிப்பிடவும்:
+ VPN இணைப்பு ரத்துசெய்யப்பட்டது. \nமற்றொரு VPN ஐ எப்போதும் இயங்கும் VPN ஆக உள்ளமைக்கிறீர்களா?
+ நெட்கார்ட் இயக்கப்பட்ட நிலையில் உங்கள் சாதனத்தை இயக்குவது, உங்கள் சாதனத்தை இயக்குவதில் தானாகவே நெட்கார்டைத் தொடங்கும்
+ இந்த அம்சம் இந்த Android பதிப்பில் இல்லை
+ மற்றொரு VPN எப்போதும் இயங்கும் VPN ஆக அமைக்கப்பட்டுள்ளது
+ வடிகட்டுதல் பயன்முறையில் நெட்கார்டைப் பயன்படுத்த Android VPN அமைப்புகளில் \"VPN இல்லாமல் இணைப்புகளைத் தடு\" என்பதை முடக்கு
+ வடிகட்டுதல் பயன்முறையில் நெட்கார்டைப் பயன்படுத்த Android பிணைய அமைப்புகளில் \"தனியார் டிஎன்எஸ்\" ஐ முடக்கு
+ போக்குவரத்து பூட்டப்பட்டுள்ளது
+ Unmetered போக்குவரத்து அனுமதிக்கப்படும்
+ Unmetered போக்குவரத்து தடைசெய்யப்பட்டது
+ அளவிடப்படாத விதிகள் பயன்படுத்தப்படாது
+ Metered போக்குவரத்து அனுமதிக்கப்படும்
+ Metered போக்குவரத்து தடைசெய்யப்பட்டது
+ மீட்டர் விதிகள் பயன்படுத்தப்படவில்லை
+ முகவரி அனுமதிக்கப்பட்டது
+ முகவரி தடுக்கப்பட்டது
+ திரை இயக்கத்தில் இருந்தால் அனுமதி
+ தொகுதி சுற்றும் போது
+ இயல்புநிலை ஒரு Wi-Fi இணைப்பு இருக்கும்படி கொள்ளப்படும் unmetered மற்றும் மொபைல் இணைப்பை metered இருக்க
+ இணைய அனுமதி இல்லை
+ %s முடக்கப்பட்டது
+ உள்வரும் செய்திகள் Google Play சேவைகளால் பெறப்படுகின்றன, இந்த பயன்பாட்டின் மூலம் அல்ல, எனவே இந்த பயன்பாட்டைத் தடுப்பதன் மூலம் தடுக்க முடியாது
+ பதிவிறக்கங்கள் பதிவிறக்க மேலாளரால் செய்யப்படுகின்றன, இந்த பயன்பாட்டால் அல்ல, எனவே இந்த பயன்பாட்டைத் தடுப்பதன் மூலம் தடுக்க முடியாது
+ விதிகள் மற்றும் நிபந்தனைகள் பயன்படுத்து
+ நிபந்தனைகள்
+ Wi-Fi திரை இயக்கத்தில் இருந்தால் அனுமதி
+ மொபைல் எப்போது திரை அனுமதி
+ ஆர்
+ தொகுதி சுற்றும் போது
+ பூட்டுதல் பயன்முறையில் அனுமதிக்கவும்
+ தொடர்புடைய வடிகட்டு
+ அணுகல் முயற்சிகள்
+ அனுமதி விதிகளை எடுத்துக் நடிகையும் மற்ற விதிகள்
+ விருப்பங்கள்
+ இணைய அணுகல் முயற்சிகள் தெரிவி
+ பதிவுசெய்தல் அல்லது வடிகட்டுதல் இயக்கப்படவில்லை
+ பதிவு மற்றும் வடிகட்டுதல் இயக்கப்பட்டன
+ உள்ளமைக்கவும்
+ தடுக்கப்பட்ட முகவரிகளின் பதிவை மட்டும் இயக்கு
+ அனுமதிக்கப்பட்ட முகவரிகளையும் பதிவு செய்ய வடிகட்டலை இயக்கவும்
+ புதிதாக உள்நுழைந்த முகவரிகளுக்கான அணுகல் அறிவிப்புகளை இயக்கவும்
+ இந்த அமைப்புகள் எல்லா பயன்பாடுகளுக்கும் பொருந்தும் உலகளாவிய அமைப்புகள்
+ தனிப்பட்ட முகவரிகளை அனுமதிக்க அல்லது தடுக்க வடிகட்டலும் தேவை
+ உள்நுழைவு (குறைவாக) அல்லது வடிகட்டுதல் (மேலும்) இயக்குவது பேட்டரி பயன்பாட்டை அதிகரிக்கக்கூடும் மற்றும் பிணைய வேகத்தை பாதிக்கலாம்
+ மதிப்பிடு
+ அனுமதி
+ தடு
+ வைஃபையை அனுமதி
+ வைஃபையை தடு
+ மொபைலை அனுமதி
+ மொபைலைத் தடு
+ வேர்
+ mediaserver
+ யாருமில்லை
+ மீண்டும் கேட்காதே
+ Whois %1$s
+ போர்ட் %1$d
+ நகலெடு
+ ப்ரோ அம்சங்கள்
+ கீழ்கண்ட ப்ரோ அம்சங்கள் உள்ளன:
+ போக்குவரத்து குறிப்பேட்டு காண் தடுக்கப்பட்டது
+ பிணைய போக்குவரத்தை வடிகட்ட
+ புதிய பயன்பாட்டு அறிவிப்புகள்
+ பிணைய வேக வரைபட அறிவிப்பு
+ தோற்றம் (கருப்பொருள், நிறங்கள்)
+ மேலுள்ள எல்லா ப்ரோ அம்சங்கள்
+ வளர்ச்சியை ஆதரிக்க
+ வாங்கு
+ வாங்கப்பட்டது
+ கிடைக்கவில்லை
+ மேலும் தகவலுக்கு ஒரு தலைப்பில் தட்டு
+ சவால்
+ பதில்
+ இது ஒரு சார்பு அம்சமாகும்
+ 1 அல்லது 2 யூரோக்களின் மாதாந்திர சந்தாக்கள் (உள்ளூர் வரிகளைத் தவிர) அனைத்து சார்பு அம்சங்களையும் செயல்படுத்தும்.
+ பிளே ஸ்டோர் பயன்பாட்டில் உள்ள சந்தா தாவல் வழியாக சந்தாவை ரத்து செய்யலாம் அல்லது நிர்வகிக்கலாம்.
+
+ - வெளிர்நீலம்/ஆரஞ்சு
+ - நீலம்/ஆரஞ்சு
+ - ஊதா/சிவப்பு
+ - பொன்/நீலம்
+ - ஆரஞ்சு/சாம்பல்
+ - பச்சை
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-tl-rPH/strings.xml b/NetGuard/app/src/main/res/values-tl-rPH/strings.xml
new file mode 100644
index 0000000..68b7d49
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-tl-rPH/strings.xml
@@ -0,0 +1,271 @@
+
+
+ Ang NetGuard ay nagbibigay daan sa payak at pinahusay na mga pamamaraan upang hadlangan ang pag-access sa internet - na hindi nangangailangan ng pag-root. Ang mga app at mga addresses ay maaring isa-isang pahintulutan o hadlangan sa pag-access sa iyong Wi-Fi at/o koneksiyon sa mobile.
+ Ang Xposed ay nagdudulot ng maraming pagkakataon ng pag-crash, na maaaring magresulta sa pagtanggal ng NetGuard mula sa Google Play Store, dahil dito and NetGuard ay hindi suportado habang naka-install ang Xposed
+ Patakaran sa Pagiging Pribado
+ Sumasang-ayon ako
+ Hindi ako sumasang-ayon
+ Gumaganang mga serbisyo
+ Karaniwang mga notipikasyon
+ I-access ang mga notipikasyon
+ Maghanap ng app
+ Salain ang mga app
+ Ipakita ang mga app ng user
+ Ipakita ang mga app ng system
+ Ipakita ang mga app na walang internet
+ Ipakita ang mga hindi pinagaganang app
+ Isaayos ang mga app
+ Ayusin ayon sa pangalan
+ Ayusin ayon sa uid
+ Ayusin ayon sa paggamit ng data
+ Ipakita ang mga tala
+ Mga setting
+ Imbitahan
+ Paliwanag ng mga simbolong ginamit
+ Suporta
+ Tungkol sa
+ Iba pa
+ Pinahihintulutan
+ Nakablock
+ Live na mga update
+ I-refresh
+ Ipakita ang mga pangalan
+ Ipakita ang organisasyon
+ Gumagana sa PCAP
+ PCAP export
+ Nalinis
+ I-reset
+ Idagdag
+ Burahin
+ Linisin
+ Protocol
+ Port na pinagmulan
+ Address na patutunguhan
+ Port na patutunguhan
+ App na patutunguhan
+ Para sa panlabas na server piliin ang \'nobody\'
+ Mga default (white/blacklist)
+ Harangan ang Wi-Fi
+ Harangan ang mobile
+ Pahintulutan ang Wi-Fi kung buhay ang screen
+ Pahintulutan ang mobile kung buhay ang screen
+ Harangan ang roaming
+ Mga pagpipilian
+ Tema: %1$s
+ Gamitin ang madilim na theme
+ Abisuhan sa bagong install
+ Gamitin ang mga \'kung buhay ang screen\' na tuntunin
+ Awtomatikong paganahin matapos ang %1$s minuto
+ Ipagpaliban ang pagpatay ng screen ng %1$s minuto
+ Magsaliksik ng mga update
+ Mga opsyon para sa Network
+ Pag-route gamit ang subnet
+ Pahintulutan ang pag-tether
+ Pahintulutan ang LAN access
+ Paganahin ang IPv6 traffic
+ Mga network para sa Wi-Fi sa tahanan: %1$s
+ Pangasiwaan ang de-metrong mga network ng Wi-Fi
+ Kilalanin ang 2G bilang unmetered
+ Kilalanin ang 3G bilang unmetered
+ Kilalanin ang LTE bilang unmetered
+ Huwag pansinin ang pambansang roaming
+ Huwag pansinin ang EU roaming
+ Huwag paganahin pag may tawag
+ I-lockdown ang Wi-Fi
+ I-lockdown ang mobile
+ I-reload sa bawat pagbabago ng koneksyon
+ Mas pinahusay na mga option
+ Pangasiwaan ang mga system app
+ I-tala ang access sa internet
+ Abisuhan sa pag-access ng internet
+ Salain ang traffic
+ Isara ang konesyon kapag nag-reload
+ I-lockdown ang traffic
+ Alamin ang gamit sa network
+ I-reset and paggamit ng network
+ Ipakita ang mga pangalan ng naresolbang domain
+ Harangan ang mga domain name
+ Code para sa sagot ng DNS: %s
+ Pagpasa ng Port
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Minimum DNS TTL: %s s
+ Use SOCKS5 proxy
+ SOCKS5 address: %s
+ SOCKS5 port: %s
+ SOCKS5 username: %s
+ SOCKS5 password: %s
+ PCAP record size: %s B
+ Pinakamataas na limitasyon ng PCAP para sukat ng file: %s MB
+ Watchdog: kada %s minuto
+ Notipikasyon ng bilis
+ Ipakita ang notipikasyon ng bilis
+ Ipakita ang mga pangunahing app
+ Halimbawa ng agwat: %s ms
+ Bilang ng mga halimbawa: %s s
+ Backup
+ I-export ang mga setting
+ I-import ang mga setting
+ I-angkat ang mga host file
+ Ang URL sa pag-download ng mga host file
+ I-download ang mga host file
+ Impormasyong pang-teknikal
+ Pangkalahatan
+ Mga network
+ Mga subskripsyon
+ Ipakita ang notipikasyon sa status bar upang direktang makompigura ang mga bagong install na app (pro feature)
+ Pagkatapos i-disable gamit ang widget, automatikong paganahin ang NetGuard muli matapos ang bilang ng minuto na iyong napili (ilagay ang zero upang hindi gumana ang opsyon na ito)
+ Matapos patayin ang screen, patuloy na paganahin ang mga tuntunin ayon sa piniling bilang ng minuto (ilagay ang 0 upang di paganahin ito)
+ Magsaliksik ng mga bagong labas sa GitHub dalawang beses sa isang araw
+ Depende sa bersyon ng Android, ang pag-tether ay maaring gumana o hindi gumana. Ang traffic dulot ng pagtether ay hindi maaaring salain.
+ Paganahin ang routing ng subnet; maaaring magpagana ng pagtawag gamit ang Wi-Fi, ngunit maaari ding magresulta sa mga bugs sa Android at magpataas ng paggamit ng baterya
+ Pahintulutan ang mga app na komunekta sa local area network addresses, gaya ng 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16
+ I-route ang ika-anim na bersyon ng IP sa NetGuard upang makapili kung pahihintulutan o haharangan
+ Ipatupad ang mga tuntunin ng Wi-Fi network para sa mga piling network lamang (ipatupad ang mga tuntunin ng mobile network para sa ibang mga Wi-Fi network)
+ Ipatupad ang mga tuntunin ng mobile network sa mga de-metrong (bayad, naka-tether) mga Wi-Fi network
+ Gamitin ang mga tuntunin sa Wi-Fi para sa koneksiyong 2G data
+ Gamitin ang mga tuntunin sa Wi-Fi para sa koneksiyong 3G data
+ Gamitin ang mga tuntunin sa Wi-Fi para sa koneksiyong LTE data
+ Huwag gamitin ang mga tuntunin sa roaming kung ang bansa ng SIM at mobile network ay pareho
+ Huwag gamitin ang mga tuntunin sa roaming kung ang bansa ng SIM at mobile network ay parehong nasa EU (roam like at home)
+ Huwag paganahin ang NetGuard kapag may papasok o papalabas na tawag sa telepono. Maaari itong gamitin upang maresolba ang mga problema sa IP/Wi-Fi na mga tawag.
+ Tukuyin ang mga alituntunin para sa mga app ng sistema (para sa mga dalubhasa)
+ I-lista ang mga tangkang pag-gamit ng internet para sa mga app. Maaari itong magresulta sa dagdag na gamit sa baterya.
+ Ipakita ang isang status bar na magbibigay abiso kapag ang isang app ay magsusubok na gumamit ng bagong internet address (kapag ang pag-sasala ay naka -disable, ang mga hinarangan lamang na tangkang pag-access sa internet ang itatala)
+ Salain ang mga IP packet na palabas sa VPN tunnel. Maaari itong magresulta sa dagdag na gamit sa baterya.
+ Alamin ang bilang ng mga byte na napadala at natanggap para sa bawat isang app at address. Maaari itong magresulta sa dagdag na gamit sa batterya.
+ Sumagot gamit ang na-configure response code ng DNS para sa mga nahaharangang mga pangalan ng domain. Ang switch ay hindi gumagana kapag walang magagamit na hosts file.
+ Ang nakatalagang value ay 3 (NXDOMAIN), na ang ibig sabihin ay \'hindi umiiral na domain\'.
+ Tanging ang TCP traffic ang ipapadala sa proxy serber
+ Maya\'t mayang suriin kung ang NetGuard ay tumatakbo pa (ilagay ang zero upang di paganahin ito). Ito ay maaaring magresulta sa mas malakas ng pagamit ng baterya.
+ Ipakita ang graph para sa bilis ng network bilang isang abiso sa status bar
+ Sigurado ka ba?
+ Pinatutupad ang mga tuntunin
+ %1$d pinahihintulutan, %2$d hinaharangan
+ %1$d pinahihintulutan, %2$d hinaharangan, %3$d mga host
+ Naghihintay ng kaganapan
+ Ang NetGuard ay hindi pinagagana, gamitin ang switch sa itaas upang paganahin ang NetGuard
+ Ang NetGuard ay tumigil sa pag-gana, marahil dahil sa pagamit ng iba pang app na VPN based
+ \'%1$s\' naka-install
+ Ay naka-install na
+ %1$s tangkang pag-access sa internet
+ Tangkang pag-access sa internet
+ Tapos na ang Aksyon
+ Ang NetGuard ay gumagamit ng lokal na VPN upang masala ang internet traffic.
+Sa kadahilanang ito, mangyari lamang pahintulutan ang isang koneksyon sa VPN sa susunod na dialogo.
+Ang iyong internet traffic ay hindi pinapadala sa isang liblib na vpn serber.
+ Hindi awtomatikong makapag-umpisa ang NetGuard. Marahil dahil ito sa isang bug sa bersyon ng iyong Android.
+ Naganap ang hindi inaasahang error: \'%s\'
+ Tumanggi ang Android na simulang ang serbisyo ng VPN sa sandaling ito. Marahil dahil ito sa isang bug sa bersyon ng iyong Android.
+ Subukan ang NetGuard
+ Sa pagbibigay ng donasyon ikaw ay sumasang-ayon sa mga tuntunin& mga kundisyon
+ Kung hindi mo mapindot ang OK sa susunod na dialog, maaaring may ibang (screen dimming) na mga app ang nagmamanipula sa screen.
+ ± %1$.3f▲ %2$.3f▼ MB/araw
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Para sa pare-parehong resulta, ang pag-optimize ng baterya sa Android ay dapat hindi paganahin para sa NetGuard.\n\nSa susunod na diyalogo, piliin ang \"Lahat ng mga app\" sa itaas, pindutin ang NetGuard mula sa listahan at piliin at kumpirmahin \"Huwag I-optimize\".
+ Para sa pare-parehong resulta, ang pagtitipid ng datos sa Android ay dapat hindi paganahin para sa NetGuard\n\nSa susunod na diyalogo, piliin ang \"datos na sanligan\" at \"malayang pagamit ng datos\"
+ Ang paggamit ng pagsasala ay magdudulot sa Android na ipalagay na nagbibigay ito sa NetGuard ng datos at gamit sa baterya - inaakala ng Android na ang datos at baterya ay ginagamit ng NetGuard, at hindi ang orihinal na mga app
+ Nangangailangan ng pagsasala ang Android 4 upang mapagana
+ Ang paglilista ng traffic ay hindi gumagana, gamitin ang switch sa itaas upang mapagana ang paglilista. Ang paglilista ng traffic ay maaaring magdulot ng dagdag na gamit sa baterya.
+ Ito ay magtatalaga muli ng orihinal na mga value sa alituntunin at mga kundisyon
+ Buburahin nito ang mga listahan ng tangkang pag-access nang walang alituntunin sa pagpapahintulot o paghahadlang
+ Huling pag-angkat: %s
+ Nagda-download\n%1s
+ Ang mga file ng mga host ay na-download na
+ Huling download: %s
+ Simulan ang pagpapasa mula sa %1$s port %2$d papunta sa %3$s:%4$d ng %5$s?
+ Ihinto ang pagpapasa ng %1$s port %2$d?
+ De-metro ang network
+ Kasalukuyang walang koneksyon sa internet
+ Ang NetGuard ay may iba pang ginagawa
+ May update na magagamit, pindutin upang i-download
+ Maaari mong pahintulutan (mala-luntian) or tanggihan (mamula-mula) ang pag-access sa internet ng Wi-Fi o mobile sa pamamagitan ng pagpindot ng mga imahe na nasa tabi ng isang app
+ Ang pag-access sa internet ay pinahihintulutan (blacklist mode), ito ay maaring ibahin sa mga setting
+ Ang paparating (push) na mga mensahe ay karaniwan pinangangasiwaan ng system component Play services, na may pahintulot na i-access ang internet
+ Ang pangangasiwa ng lahat (sistema) ng mga app ay maaaring paganahin sa mga setting
+ Mangyari lamang ilarawan ang problema at isaad ang oras ng problema:
+ Ang konekesyon sa VPN ay nakansela\nMayroon bang iba pang VPN na naka-configure para maging VPN na palaging nakabukas?
+ Kapag pinower-down mo ang iyong device na naka-enable ang NetGuard, awtomatikong gagana ang NetGuard sa pag-power up ng iyong device
+ Ang katangiang ito ay hindi magagamit sa bersyon ng iyong Android
+ May isa pang VPN na nakatalaga bilang VPN na palaging nakabukas
+ Ang traffic ay naka-lock down
+ Ang hindi de-metrong traffic ay pinapahintulutan
+ Ang hindi de-metrong traffic ay hinaharangan
+ Ang hindi de-metrong alituntunin ay hindi ginagamit
+ Pahintulutan ang metered traffic
+ Hinaharangan ang metered traffic
+ Ang mga de-metrong alituntunin ay hindi ginagamit
+ Pinapahintulutan ang address
+ Hindi pinapahintulutan ang address
+ Pahintulutan kung buhay ang screen
+ Harangan kapag naka-roaming
+ Ang koneksyon sa Wi-Fi ay kinikilala bilang hindi de-metro at ang koneksyon sa mobile bilang de-metro
+ walang pahintulot para sa internet
+ ay hindi gumagana
+ Gamitin ang mga tuntunin at mga kondisyones
+ Mga kundisyon
+ Pahintulutan ang Wi-Fi kung buhay ang screen
+ Pahintulutan ang mobile kung buhay ang screen
+ R
+ Harangan kapag roaming
+ Pahintulutan sa mode na lockdown
+ Salain sa may kaugnayan
+ Mga pagtatangka na i-access
+ Ang mga tuntunin sa pag-access ay mas mauuna kaysa sa ibang mga tuntunin
+ Mga pagpipilian
+ Abisuhan ukol sa mga tangkang pag-access sa internet
+ Ang paglilista o pagsasala ay hindi gumagana
+ Ang paglilista at pagsasala ay gumagana
+ I-configure
+ Paganahinang paglilista ng mga hinaharangang mga address lamang
+ Paganahin ang pagsasala upang mailista rin ang mga address na may pahintulot
+ Paganahin ang mga abiso para sa access ng mga bagong listang mga address
+ Ang mga setting na ito ay pangkalahatang setting na magagamit sa lahat ng mga app
+ Ang pagsasala ay kinakailangan upang pahintulutan o harangan ang mga indibidwal na mga address
+ Ang pagpapagana ng paglilista (mas kaunti) o pagsasala (mas marami) ay maaaring dumagdag sa paggamit ng baterya at maaaring makaapekto sa bilis ng network
+ Halgahan
+ Pahintulutan
+ Harangan
+ Pahintulutan ang Wi-Fi
+ Harangan ang Wi-Fi
+ Pahintulutan ang mobile
+ Harangan ang mobile
+ root
+ mediaserver
+ walang sinuman
+ Huwag mong itanong ulit
+ Sinosi %1$s
+ Port %1$d
+ Kopyahin
+ Features ng Pro
+ Ang mga susunod na features ng pro ay maaaring gamitin:
+ Tinganan ang listahan ng hinarangang traffic
+ Salain ang network traffic
+ Mga abiso para sa bagong app
+ Abiso para sa graph ng bilis ng network
+ Anyo (tema, mga kulay)
+ Lahat ng mga feature ng pro sa itaas
+ Suportahan ang pagpapaunlad
+ Bilhin
+ Pinagana
+ Hindi Magagamit
+ Pinduting ang tile para sa mas maraming impormasyon
+ Hamon
+ Sagot
+
+ - teal/kahel
+ - asul/kahel
+ - lila/pula
+ - amber/asul
+ - kahel/kulay-abo
+ - luntian
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-tr-rTR/strings.xml b/NetGuard/app/src/main/res/values-tr-rTR/strings.xml
new file mode 100644
index 0000000..cd362ad
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-tr-rTR/strings.xml
@@ -0,0 +1,292 @@
+
+
+ NetGuard, internet erişimini engellemek için basit ve gelişmiş yollar sunar - root gerektirmez. Uygulamaların ve adreslerin, Wi-Fi ve/veya mobil bağlantınıza erişimine ayrı ayrı izin verilebilir veya reddedilebilir.
+ NetGuard, Android 5.1 veya üzerini gerektirir
+ Xposed, NetGuard\'ın Google Play Store\'dan kaldırılmasına neden olabilecek kadar fazla çökmeye sebebiyet verir, bu nedenle NetGuard, Xposed yüklüyken desteklenmez
+ Gizlilik ilkesi
+ NetGuard\'ın geliştirilip test edilmesi için büyük özen gösterilmiştir fakat her cihazda doğru çalışacağını garanti etmek imkansızdır.
+ Kabul ediyorum
+ Reddediyorum
+ Netguard\'ın yardımınıza ihtiyacı var. Projenin devam etmesi için pro özelliklerini satın almak için dokunun.
+ Çalışan hizmetler
+ Genel bildirimler
+ Erişim bildirimleri
+ Uygulama ara
+ Uygulamaları filtrele
+ Kullanıcı uygulamalarını göster
+ Sistem uygulamalarını göster
+ İnternetsiz uygulamaları göster
+ Devre dışı uygulamaları göster
+ Uygulamaları sırala
+ Ada göre sırala
+ UID\'ye göre sırala
+ Veri kullanımına göre sırala
+ Günlüğü göster
+ Ayarlar
+ Davet et
+ Semboller
+ Destek
+ Hakkında
+ Diğer uygulamalar
+ Diğer
+ İzin verilen
+ Engellenen
+ Canlı güncellemeler
+ Yenile
+ Adları göster
+ Kuruluşu göster
+ PCAP etkinleştirildi
+ PCAP dışa aktarma
+ Temizle
+ Dışa aktar
+ Sıfırla
+ Ekle
+ Sil
+ Temizlik
+ Protokol
+ Kaynak bağlantı noktası
+ Hedef adres
+ Hedef bağlantı noktası
+ Hedef uygulama
+ Harici bir sunucu için \'hiçkimse\' seçin
+ Varsayılanlar
+ Kablosuz engellensin
+ Mobil veri engellensin
+ Ekran açıkken kablosuza izin verilsin
+ Ekran açıkken mobil veriye izin verilsin
+ Dolaşım engellensin
+ Seçenekler
+ Tema: %1$s
+ Karanlık tema kullan
+ Yeni uygulamaları bildir
+ Ekranın açıklığına bağlı kurallar uygulansın
+ %1$s dakika sonra otomatik etkinleştir
+ Ekranın kapalı olarak algılanmasını %1$s dakika ertele
+ Güncellemeleri kontrol et
+ Ağ seçenekleri
+ Alt ağ yönlendirmesi
+ İnternet paylaşımına izin ver
+ Yerel ağ erişimine izin ver
+ IPv6 trafiğini etkinleştir
+ Kablosuz ev ağları: %1$s
+ Veri kullanımının ölçüldüğü kablosuz ağları yönet
+ 2G kotasız olarak sayılsın
+ 3G kotasız olarak sayılsın
+ 4G kotasız olarak sayılsın
+ Ulusal dolaşımı yoksay
+ AB dolaşımını yoksay
+ Aramada devre dışı bırak
+ Kablosuz engellensin
+ Mobil veri engellensin
+ Her bağlantı değişikliğinde tekrar yüklensin
+ Gelişmiş seçenekler
+ Sistem uygulamaları yönet
+ İnternet erişimlerini kaydet
+ İnternet erişimini bildir
+ Trafiği filtrele
+ UDP trafiğini filtrele
+ Yeniden yüklemede kesintisiz VPN devredilmesi
+ Yeniden yüklemede bağlantıları sonlandır
+ Trafiği durdur
+ Veri kullanımını ölç
+ Veri kullanımını sıfırla
+ Çözümlenmiş alan adlarını göster
+ Alan adlarını engelle
+ DNS yanıt kodu: %s
+ Bağlantı noktası yönlendirme
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Doğrulama adresi: %s
+ En düşük DNS TTL: %s s
+ SOCKS5 kullan
+ SOCKS5 adresi: %s
+ SOCKS5 bağlantı noktası: %s
+ SOCKS5 kullanıcı adı: %s
+ SOCKS5 parolası: %s
+ PCAP kayıt boyutu: %s B
+ PCAP dosya boyutu sınırı: %s MB
+ Bekçi: her %s dakika
+ Hız bildirimi
+ Hız bildirimini göster
+ En çok kullanan uygulamaları göster
+ Yenileme aralığı: %s ms
+ Yenileme geçmişi: %s s
+ Yedekleme
+ Ayarları dışa aktar
+ Ayarları içe aktar
+ Hosts dosyasını içe aktar
+ Hosts dosyasını içe aktar (ek)
+ Hosts dosyası indirme adresi
+ Hosts dosyasını indir
+ Teknik bilgiler
+ Genel
+ Ağlar
+ Abonelikler
+ Yeni yüklenen uygulamaları doğrudan yapılandırmak için durum çubuğunda bildirim göster (pro özelliği)
+ Widget ile devre dışı bırakıldığında, seçili süre sonrasında NetGuard otomatik olarak tekrar etkinleştirilsin (bu seçeneği devre dışı bırakmak için sıfır olarak ayarlayın)
+ Ekran kapatıldıktan sonra, ekranın açık olduğundaki kuralları seçili süre boyunca aktif tut (bu seçeneği devre dışı bırakmak için sıfır olarak ayarlayın)
+ Yeni sürümler için GitHub üzerinden günde iki defa kontrol et
+ Android sürümüne bağlı olarak, internet paylaşımı çalışabilir yada çalışmayabilir. Paylaşılan internet trafiği filtrelenemez.
+ Alt ağ yönlendirmesini etkinleştir; Wi-Fi aramasını etkinleştirebilir, fakat Android\'de hatalara sebep olup pil kullanımını arttırabilir
+ Uygulamaların 10.0.0.0/8, 172.16.0.0/12 ve 192.168.0.0/16 gibi yerel ağ adreslerine bağlanmasına izin ver
+ IPv6 trafiğini, yönetilmesi için Netguard\'a yönlendir
+ Yalnızca seçili ağlarda kablosuz kurallarını uygula (diğer kablosuz ağlarda mobil ağ kuralları uygulanır)
+ Kotalı kablosuz ağlarına (paylaşım, ücretli) mobil veri kurallarını uygula
+ 2G bağlantılar için kablosuz kurallarını uygula
+ 3G bağlantılar için kablosuz kurallarını uygula
+ 4G bağlantılar için kablosuz kurallarını uygula
+ Yurtdışında olunmadığı sürece dolaşım kurallarını etkinleştirme
+ AB içerisinde olunmadığı sürece dolaşım kurallarını etkinleştirme
+ Telefon aramalarında NetGuard devre dışı bırakılsın. IP/Kablosuz üzerinden arama sorunlarını çözmek için kullanılabilir.
+ Sistem uygulamalarına kural tanımlanmasını sağlar (gelişmiş kullanıcılar için)
+ Uygulamaların internet erişimlerini kaydeder. Pil kullanımını arttırabilir.
+ Uygulama yeni bir adrese erişmek istediğinde bildirim göster (filtreleme devre dışıyken yalnızca engellenen internet erişimlerinin bildirimi gösterilecektir)
+ VPN tünelinden çıkan IP paketlerini filtrele. Pil kullanımını arttırabilir.
+ Her uygulama ve adres tarafından gönderilip alınan veri miktarını izleyin. Bu pil kullanımını arttırabilir.
+ Engellenen alan adları için ayarlanmış DNS yanıt kodu ile yanıt ver. Hosts dosyası mevcut olmadığı zaman bu seçenek devre dışıdır.
+ Varsayılan değer 3 (NXDOMAIN), yani \'mevcut olmayan alan adı\'.
+ İnternet bağlantısını 443 (https) bağlantı noktasında doğrulamak için kullanılacak alan adı.
+ Sadece TCP trafiği vekil sunucuya gönderilecek
+ NetGuard\'ın çalışıp çalışmadığını zaman zaman kontrol et (bu seçeneği devre dışı bırakmak için sıfır olarak ayarlayın). Pil kullanımını arttırabilir.
+ İnternet hız grafiği bildirimini göster
+ Emin misiniz?
+ Kuralları uygulanıyor
+ %1$d izinli, %2$d engelli
+ %1$d izinli, %2$d engelli, %3$d hosts
+ Eylem bekleniyor
+ NetGuard devre dışı, yukarıdan etkinleştirebilirsiniz
+ Netguard muhtemelen farklı bir VPN tabanlı uygulama kullanıldığı için devre dışı bırakıldı
+ \'%1$s\' yüklendi
+ Yüklendi
+ %1$s internete erişmeye çalıştı
+ İnternete erişmeye çalıştı
+ Eylem tamamlandı
+ NetGuard internet trafiğini filtrelemek için yerel olarak VPN çalıştırır.
+Bu yüzden bir sonraki diyalogda lütfen VPN bağlantısına izin verin.
+İnternet trafiğiniz herhangi bir VPN sunucusuna gönderilmemektedir.
+ NetGuard otomatik olarak başlatılamadı. Android sürümünüzdeki bir hata buna sebep oluyor olabilir.
+ Beklenmedik bir hata oluştu: \'%s\'
+ Android VPN hizmeti başlatmayı reddetti. Android sürümünüzdeki bir hata buna sebep oluyor olabilir.
+ NetGuard\'ı deneyin
+ Bağış yaparak şart ve koşulları kabul etmiş sayılırsınız
+ Sonraki diyalogda TAMAM\'a basamıyorsanız, farklı bir (ekran karartma) uygulama ekranı kontrol ediyor olabilir.
+ ± %1$.3f▲ %2$.3f▼ MB/gün
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ NetGuard\'ın daha istikrarlı çalışması için Android pil optimizasyonları devre dışı bırakılmalıdır.
+\n\nSonraki diyalogda yukarıdan \"Tüm Uygulamalar\" seçip listeden Netguard\'ı bulun ve \"Optimize Etme\" seçeneğine dokunun.
+ NetGuard\'ın daha istikrarlı çalışması için Android veri tasarrufu devre dışı bırakılmalıdır.
+\n\nSonraki diyalogda \"Arkaplan verileri\" ve \"Sınırsız veri kullanımı\" izinlerini verin.
+ Filtreleme kullanmak, Android\'in veri ve güç kullanımını Netguard\'a atfetmesine sebep olur - Android veri ve güç kullanımının uygulamalar tarafından değil, NetGuard tarafından kullanıldığını varsayar
+ Android 4 filtrelemenin etkinleştirilmesini gerektirir
+ Trafik günlüğü devre dışı bırakıldı, yukarıdan etkinleştirebilirsiniz. Trafik günlüğünü etkinleştirmek pil kullanımını arttırabilir.
+ Bu kural ve koşulları varsayılan değerlerine sıfırlar
+ Bu eylem, kuralı olmayan internet erişim kayıtlarını siler
+ Son içe aktarma: %s
+ İndiriliyor\n%1s
+ Hosts dosyası indirildi
+ Son indirme: %s
+ \'%5$s\' için %1$s:%2$d -> %3$s:%4$d yönlendirmesi başlatılsın mı?
+ %1$s:%2$d yönlendirmesi durdurulsun mu?
+ Mevcut ağ kotalı
+ İnternet bağlantısı yok
+ NetGuard meşgul
+ Güncelleme mevcut, indirmek için dokunun
+ Uygulamanın yanındaki simgelere dokunarak kablosuz veya mobil veri erişimine izin verip (yeşil) engelleyebilirsiniz (kırmızı)
+ Gizliliğinizi korumak için NetGuard yüklediyseniz, açık kaynaklı, gizlilik dostu eposta uygulaması olan FairEmail ilginizi çekebilir
+ İnternet erişimine varsayılan olarak izin verilir (karaliste), bu ayarlardan değiştirilebilir
+ Gelen (anlık) iletiler genellikle internet erişimi varsayılan olarak verilen Play hizmetleri tarafından yönetilir
+ Tüm uygulamaların (sistem) yönetimi ayarlardan etkinleştirilebilir
+ Lütfen sorunu açıklayın ve sorunun oluştuğu zamanını girin:
+ VPN bağlantısı iptal edildi\nFarklı bir VPN\'i daima açık olarak ayarlamış olabilir misiniz?
+ Netguard etkinken cihazınızı kapatırsanız,, cihazınız açılırken NetGuard otomatik olarak başlayacaktır
+ Bu özellik, bu Android sürümünde mevcut değil
+ Farklı bir VPN daima açık olarak ayarlanmış
+ NetGuard filtrelemesini kullanmak için Android VPN ayarlarından \"VPN olmadığında bağlantıları engelle\" seçeneğini kapatın
+ NetGuard filtrelemesini kullanmak için Android ağ ayarlarından \"Özel DNS\" seçeneğini kapatın
+ Trafik durduruldu
+ Kotasız trafiğe izin veriliyor
+ Kotasız trafik engelleniyor
+ Kotasız kurallar uygulanmıyor
+ Kotalı trafiğe izin veriliyor
+ Kotalı trafik engelleniyor
+ Kotalı kurallar uygulanmıyor
+ Adrese izin veriliyor
+ Adres engelleniyor
+ Ekran açıkken izin veriliyor
+ Dolaşımdayken engelleniyor
+ Kablosuz ağlar kotasız, mobil bağlantılar kotalı olarak sayılır
+ internet izni yok
+ devre dışı
+ İletiler bu uygulama tarafından değil, Google Play hizmetleri tarafından alınmakta bundan dolayı bu uygulamayı engellemek işe yaramaz
+ İndirmeler bu uygulama tarafından değil, indirme yöneticisi tarafından yapılmakta bundan dolayı bu uygulamayı engellemek işe yaramaz
+ Kurallar ve koşullar uygulansın
+ Koşullar
+ Ekran açıkken kablosuza izin ver
+ Ekran açıkken mobil veriye izin ver
+ D
+ Dolaşımdayken engelle
+ Trafik durdurulduğunda izin verilsin
+ İlgilileri filtrele
+ Erişim denemeleri
+ Erişim kuralları diğer kurallara göre önceliklidir
+ Seçenekler
+ İnternet erişim denemelerini bildir
+ Günlüğe kaydetme veya filtreleme etkin değil
+ Günlüğe kaydetme ve filtreleme etkin
+ Yapılandır
+ Engellenen adresler kaydedilsin
+ İzin verilen adresler kaydedilsin
+ Yeni kaydedilen adresler bildirilsin
+ Bu ayarlar tüm uygulamalar için uygulanan genel ayarlardır
+ Adresleri ayrı ayrı yönetmek için filtreleme gereklidir
+ Günlük (az) veya filtreleme (fazla) pil kullanımını arttırabilir ve ağ hızını etkileyebilir
+ Değerlendir
+ İzin ver
+ Engelle
+ Kablosuza izin ver
+ Kablosuzu engelle
+ Mobil veriye izin ver
+ Mobil veriyi engelle
+ root
+ mediaserver
+ hiçkimse
+ Tekrar sorma
+ Whois %1$s
+ Bağlantı noktası %1$d
+ Kopyala
+ Pro özellikleri
+ Pro sürümde aşağıdaki özellikler mevcuttur:
+ Engellenen trafiği görüntüleme
+ Ağ trafiğini filtreleme
+ Yeni uygulama bildirimleri
+ İnternet hızı bildirimi
+ Arayüz görünümü (tema ve renkler)
+ Yukarıdaki tüm pro özellikleri
+ Geliştiriciyi destekleyin
+ Satın al
+ Etkin
+ Mevcut değil
+ Daha fazla bilgi için başlığa dokunun
+ Challenge
+ Response
+ Bu bir pro özelliğidir
+ Aylık 1 veya 2 euroluk abonelik (vergiler hariç) tüm pro özelliklerini etkinleştirir.
+ Aboneliği yönetmek için Play store uygulamasındaki abonelikler sekmesini kullanabilirsini.
+
+
+ - deniz mavisi/turuncu
+ - mavi/turuncu
+ - mor/kırmızı
+ - kehribar/mavi
+ - turuncu/gri
+ - yeşil
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-ug-rCN/strings.xml b/NetGuard/app/src/main/res/values-ug-rCN/strings.xml
new file mode 100644
index 0000000..bb5229d
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-ug-rCN/strings.xml
@@ -0,0 +1,251 @@
+
+
+ روتسىز تورنى توسۇشقا بولىدۇ. wifi ۋە سىمسىز تورنى باشقۇرغىلى بولىدۇ.
+ قوشۇلىمەن
+ قوشۇلمايمەن
+ ئەپ ئىزدەش
+ ئەپ تاسقاش
+ ئىشلەتكۈچى ئەپ كۆرۈنۈش
+ سىستېما ئەپلىرى كۆرۈنۈش
+ تورسىز ئەپ كۆرۈنۈش
+ تاقالغان ئەپ كۆرۈنۈش
+ ئەپ تەرتىپى
+ ئىسىم تەرتىپ
+ Uid تەرتىپ
+ تور ئىشلىتىش تەرتىپى
+ تارىخ كۆرۈنۈش
+ تەڭشەش
+ تەكلىپ
+ چۈشەندۈرۈش
+ قوللاش
+ ھەققىدە
+ باشقا
+ يول قويۇلدى
+ توسۇلدى
+ ۋاقتىدا يېڭلاش
+ يېڭىلاڭ
+ نامى كۆرۈنۈش
+ گورۇپپا كۆرۈنۈش
+ PCAP قوزغىتىش
+ PCAP چىقىرىش
+ تازىلاش
+ ئەسلىگە قايتۇرۇش
+ قوشۇش
+ ئۆچۈرۈش
+ تازىلاش
+ كېلىشىم
+ مەنبە ئېغزى
+ ئورنى
+ چىقىرىش ئورنى
+ نىشانلىق ئەپ
+ سىرتقى مۇلازىمىترغا تاللاش \'nobody\'
+ سۈكۈتتىكى (ئاق/قارا تىزىملىك)
+ توسۇش Wi-Fi
+ ئېقىم توسۇش
+ يول قويۇش Wi-Fi ئېكران يورۇن ۋاقىتتا
+ ئېكران يورۇن ۋاقىتتا ئېقىمغا يول قويۇش
+ كەزمە مۇلازىمەت توسۇش
+ تاللاشلار
+ ئۇسلۇب: %1$s
+ قاراڭغۇ ئۆرنەك ئىشلەت
+ يېڭى قاچىلاشتا ئۇقتۇرۇش
+ \'ئېكران ئوچۇق\' قائىدىسنى ئىشلىتىش
+ ئاپتۇماتىك يول قويۇش %1$s مىنۇتتىن كېيىن
+ ئېكران ئۆچۈش %1$s مىنۇت كىچكىش
+ يېڭىلانمىنى تەكشۈرۈش
+ تور تاللاش
+ روتىر
+ باغلاشقا يول قويۇش
+ Root ھوقۇقىغا يول قويۇش
+ قوزغىتىش IPv6 traffic
+ Wi-Fi باش توربەت: %1$s
+ تورىنى ئۆلچەشنى بىرتەرەپ قىلىش Wi-Fi
+ 2G ھىسابلىمغان تورنى قوشۇش
+ 3G ھىسابلىمغان تورنى قوشۇش
+ LTE ھىسابلىمغان تورنى قوشۇش
+ روتىر تورىنى ھېسابلىماسلىق
+ EU كەزمە تورنى موھىم بىلمەسلىك
+ قۇلۇپلانغان Wi-Fi
+ تور ئېتىلگەن
+ ئالىي تاللانما
+ سىستېما ئەپلىرى باشقۇرۇش
+ ئىنتېرنېتنى زىيارەت ھوقۇقى
+ ئىنتېرنېتنى زىيارەت ھوقۇقى ئۇقتۇرۇش
+ تور ئۆتكۈزۈش
+ قايتا قوشۇلغاندا ئۇلىغاننى ئۈزۈش
+ تور قۇلۇپلاش
+ تور ئىشلىتىشقا ئەگىشىش
+ تور ئىشلىتىشقا قايتا تەڭشىەش
+ يەشكەن ئادرېس كۆرۈنۈش
+ توسۇلغان ئادىرس نام
+ DNS كود: %s
+ يۆتكەش ئېغىز
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ ئەڭ كىچىك DNS TTL: %s s
+ ئىشلىتىش ۋاكالەتلىك SOCKS5
+ SOCKS5 ئادرېس: %s
+ SOCKS5 ئېغىزى: %s
+ SOCKS5 ئابونىت نام: %s
+ SOCKS5 پارول: %s
+ PCAP نۇمۇر چوڭلۇقى: %s B
+ PCAP ئەڭ چوڭ. ھۆججەت: %s MB
+ كۈزۈتۈش: ھەر %s مىنۇت
+ سۈرئەت ئۇقتۇرۇش
+ سۈرئەت ئۇقتۇرۇش كۆرۈنۈش
+ كۆپ ئىشلىتىدىغىنى كۆرۈنۈش
+ ۋاقىت ئارلىقى: %s ms
+ سانى: %s s
+ زاپاسلاش
+ چىقىرىش تەڭشەك
+ كىرگۈزۈش تەڭشەك
+ ئاساسىي ھۆججەت كىرگۈزۈش
+ ھۆججەت چۈشۈرۈش URL
+ چۈشۈرۈلگەن ھۆججەت
+ تېخنىك ئۇچۇرى
+ ئاممىباب
+ تور
+ زاكاس
+ ئىستون ئوقتۇرشىدا كۆرۈنۈش يېڭى قاچىلانغان ئەپلەرگە ئىشلىتىلدۇ (Pro نەشر)
+ قوشۇمچە ئەپچىنى ئىشلىتىشنى چەكلىگەندىن كېيىن،تاللىغان ۋاقىتتىن كېيىن NetGuard ئاپتۇماتىك قوزغىلىدۇ(0 نى كىرگۈزۈپ بۇ ئىقتىدارنى چەكلەش)
+ ئېكران ئۆچكەندىن كېيىن، ئېكراندىكى تاللىغان ۋاقىتىنىڭ ئاكتىپ ھالىتىنى ساقلاڭ(0 نى كىرگۈزۈپ بۇ ئىقتىدارنى چەكلەش)
+ كۈندە GitHub يېڭى نەشرنى تەكشۈرۈش
+ Android نەشرى ئوخشىماسلىقىشا ئاساسەن،باشقۇرىدۇ.
+ يەرلىك تورغا ئۇلىنىشقا يول قويۇش مەسلەن 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16
+ IP 6 بۇ ئەپ ئارقىلىق يول قويۇشقا ياكى توسۇشقا بولىدۇ
+ پەقەت تاللىغانغا تورغا Wi-Fi تور قائىدىسنى ئىشلىتىش(باشقا Wi-Fi تورىغا كۆچمە تور قائىدىسنى ئىشلىتىش)
+ كۆچمە تور قائىدىسى Wi-Fi ،(ھەقلىق) نى ھىسابلاشقا ئىشلىتىلدۇ
+ 2G تورغا wifi تۇر ئۇلاش ئۇسۇلىنى قوللىنىش
+ 3G تورغا wifi تۇر ئۇلاش ئۇسۇلىنى قوللىنىش
+ LTE تورغا wifi تۇر ئۇلاش ئۇسۇلىنى قوللىنىش
+ SIM كارتىسى ۋە كۆچمە تور، خەلقئارا \ رايون ، كەزمە مۇلازىمەت ئوخشاش بولغاندا قائىدىسى ئىشلەتمەيدۇ
+ ئىشلىتىش قائىدىسىگە چۈشەنچە(كەسپى)
+ ئەپنىڭ تورغا ئولىنىشنى خاتىرلەيدۇ،بۇ قوشۇمچە توك ئىشلتشى مومكىن.
+ بىر ئەپ يېڭى تور ئادىرسىغا ئۇلانغاندا ئۇقتۇرۇش ئىستونىدا كۆرۈنۈش،(تور ئۇلىندىغىنىلا كۆرۈنىدۇ)
+ VPN دىن چىققان IP سانلىق مەلۇماتىنى شاللاش،قوشۇمچە توك ئىشلىتشى مومكىن.
+ ھەر بىر ئەپنىڭ ئىشلىتىش ۋە يوللاش خاتىرسىنى تەكشۈرۈش توكنى كۆپ ئىسراپ قىلىدۇ.
+ سۈكۈتتىكى قىممەت 3 (NXDOMAIN)،\"يوق ئادىرس\" نى بىلدۈرىدۇ.
+ پەقەت TCP ئېقىم مىقدارى ۋاكالىتەن مۇلازىمەتچى ئەۋەتىپ بېرىلىدۇ
+ ۋاقىت بەلگىلەپ NetGuard نىڭ ھەرىكىتىنى تەكشۈرۈش.(0 نى كىرگۈزۈپ بۇ تاللاشنى چەكلەش)، بۇ بەلكىم توك ئىسراپچىلىقىنى كەلتۈرۈپ چېقىرىشى مومكىن.
+ ئىستوندا تور سۈرئىتى كۆرۈنۈش
+ جەزىملەشتۈرەمسىز?
+ ئىجرا قانۇقى
+ %1$d تول قويۇلدى, %2$d توسۇلدى
+ %1$d يول قويۇلدى, %2$d توسۇلدىd, %3$d hosts
+ يېڭى پائالىيەتنى ساقلاش
+ NetGuard توسۇلدى،ئۈستىدىن قوزغىتىڭ
+ NetGuard چەكلەندى،بەلكىم باشقا بىر ئەپ تەرپىدىن بولغان
+ \'%1$s\' قاچىلاندى
+ قاچىلانغان
+ %1$s تور چىقىشنى سىناش
+ تور چىقىشنى سىناش
+ تامام
+ NetGuard uses a local VPN to filter internet traffic.
+For this reason, please allow a VPN connection in the next dialog.
+VPN مۇلازىمىتى چېقىرۋىتىش يوللانمىغان.
+ NetGuard ئاپتۇماتىك قوزغىلالمىدى،سىزنىڭ تېلېىفونىڭىزنىڭ نەشردىكى مەسلە بولشى مومكىن.
+ ئويلىمغان خاتالىق: \'%s\'
+ VPN مۇلازىمتىنى رەت قىلدى،سىزنىڭ تېلېىفونىڭىزنىڭ نەشردىكى مەسلە بولشى مومكىن.
+ سىناش NetGuard
+ قوشۇلسىڭىز terms & conditions
+ ئەگەر سىز مۇقۇملاشنى باسالمىسىڭىز. يەنە بىر (كۆزنەك) ئەپ ئىجرا بولىدۇ.
+ ± %1$.3f▲ %2$.3f▼ MB/كۈن
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Android 4 ئۆتكۈزۈش ئىقتىدارىنى ئېچىش كېرەك
+ قائىدە ۋە تەڭشەكنى ئەسلىگە كەلتۈرىدۇ
+ تول قويغان/توسۇۋالغان زىيارەت خاتىرسىنى ئۆچۈرىدۇ
+ ئاخىرقى قوشۇش: %s
+ چۈشۈرۋاتىدۇ\n%1s
+ چۈشۈرۈلدى
+ يېقىندا چۈشۈرگىنى: %s
+ يوللاشنى باشلاش %1$s port %2$d to %3$s:%4$d of \'%5$s\'?
+ يوللاشنى توختىتىش %1$s port %2$d?
+ تور ئۆلچەش
+ ئىنتېرنېت باغلىنىشى يوق
+ تور باشقۇرغۇچ ئالدىراش
+ بېسىپ، يېڭلاڭ
+ ئەپ يىنىدىكى رەسىمنى بېسىپ تور ۋە wifi غا ئۇلىنىشنى باشقۇرالايسىز،يول قويۇش(يېشىل) ياكى رەت قىلىش(قىزىل)
+ تورغا ئۇلىنىش سۈكۈتتىكى ھالەت(قارا تىزىملىك)،تەڭشەكتىن ئۆزگەرتكىلى بولىدۇ
+ بارلىق (سىستېما) ئەپنى تەڭشەكتىن باشقۇرغىلى بولىدۇ
+ خاتالىق يۈز بەرگەندىكى مەسلىنى دوكلات قىلىڭ:
+ VPN ئۇلاش بىكار قىلىندى\nيەنە بىر VPN تەڭشەكنى مەڭگۈلۈك ئىشلىتەمسىز?
+ NetGuard نى ئىشلىتىپ توك مەنبەسىنى ئېتىشنى قوزغىتىش،تېلېفون قوزغالغاندا NetGuard ئاپتۇماتىك قوزغىلىدۇ
+ Android نەشىر بۇ ئىقتىدار ئىشلەيدۇ
+ قۇلۇپلاندى
+ يول قويۇلدى
+ قۇلۇپلاندى
+ ئۆلچىمىگەن قانۇنى ئىشلىتىلمىدى
+ تور ئۆلچەش يول قويۇلدى
+ تور ئۆلچەش توسۇلدى
+ تور ئۆلچەش قانۇنى ئىشلىتىلمىدى
+ ئادرېس يول قويۇلدى
+ ئادرېس توسۇلدى
+ ئېكران يورۇن ۋاقىتتا يول قويۇش
+ كەزمە مۇلازىمەت توسۇش
+ سۈكۈتتىكى ھالەتتە Wifi تورىنى ھىسابلىمايدۇ. كۆچمە تور ھىسابلىندۇ
+ تور ھوقوقى يوق
+ توسۇلدى
+ ئىشلىتىش قائىدىسى ۋە شەرت
+ شەرت
+ ئېكران يورۇن ۋاقىتتا Wi-Fiيول قويۇش
+ ئېكران يورۇن ۋاقىتتا ئېقىمغا يول قويۇش
+ R
+ كەزمە مۇلازىمەت توسۇش
+ قۇلۇپ ھالىتىدە يول قويۇش
+ مۇناسۋەتلىك ئەپنى ئۆتكۈزۈش
+ زىيارەتنى سىناش
+ زىيارەت تەرتىپ ئەڭ ئالدىدا
+ تاللاشلار
+ تور ئۇقتۇرۇشنى سىناش
+ خاتىرىلەش قوزغالمىدى
+ خاتىرىلەش قوزغاىتىش
+ ئورۇنلاشتۇرۇش
+ تورسۇلغان ئادىرىسنىلا خاتىرلەش
+ يول قويغان ئادىرىسنى تاسقاشنى قوزغىتىش
+ تاق ئادىرسنى توسۇش ياكى يول قويۇشنى ئۆتكۈزۈش
+ كۈندىلىك خاتىرىنى قوزغىتىش(ئازراق) ياكى ئۆتكۈزىۋىتىش (كۆپ) توكنى كۆپ ئىشلىتىشى ۋە تور سۈرئىتىگە تەسىر كۆرسىتشى مومكىن
+ سۈرئەت
+ يول قويۇش
+ توسۋېلىش
+ يول قويۇش Wi-Fi
+ توسۇش Wi-Fi
+ كۆچمە تور يول قويۇش
+ كۆچمە ئېقىم توسۇش
+ روتroot
+ ۋاسىتە مۇلازىمېتىر
+ ھىچكىشى
+ قايتا سورىما
+ كىم %1$s
+ ئېغىز %1$d
+ Pro نەشر
+ Pro نەشردە تۆۋەندىكى ئىقتىدار بار:
+ توسۇلغان تارىخنى كۆرۈش
+ تور ئىقىم ئۆتكۈزۈش
+ يېڭى ئەپ ئۇقتۇرشى
+ تور سۈرئەت ئۇقتۇرۇش
+ كۆرۈنۈش (ئۇسلۇپ, رەڭ)
+ Pro يۇقىرقى ئىقتىدار
+ قوللاش
+ سېتىۋىلىش
+ قوزغىتىلغان
+ ئىشلەتكىلى بولمايدۇ
+ تېىمىنى بېسىپ كۆپ ئۇچۇرغا ئېرشىڭ
+ چاقىرماق
+ ئىنكاس
+
+ - كۆك يېشىل/سىرىق
+ - كۆك/سىرىق
+ - بىنەپشە رەڭ/قىزىل
+ - كەھرىۋا رەڭلىك/كۆك
+ - سىرىق/كۈل رەڭ
+ - يېشىل
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-uk-rUA/strings.xml b/NetGuard/app/src/main/res/values-uk-rUA/strings.xml
new file mode 100644
index 0000000..d4f80ec
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-uk-rUA/strings.xml
@@ -0,0 +1,289 @@
+
+
+ NetGuard забезпечує простий і розширений способи блокування доступу в Інтернет - рут не потрібен. Можна надавати або забороняти доступ до Wi-Fi та/або мобільного зв\'язку для кожної програми й адреси окремо.
+ Для роботи NetGuard потрібна ОС Android 5.1 або новіша
+ Xposed спричиняє багато помилок. Це може призвести до видалення NetGuard з магазину Google Play. Тому NetGuard не підтримується, доки встановлено Xposed
+ Політика конфіденційності
+ До розробки й тестування NetGuard було докладено багато зусиль, але неможливо гарантувати, що NetGuard працюватиме належним чином на будь-якому пристрої.
+ Погоджуюся
+ Не погоджуюся
+ NetGuard потребує вашої допомоги. Торкніться, щоб придбати професійні функції й підтримати подальше продовження проекту.
+ Запущені служби
+ Загальні сповіщення
+ Сповіщеня про доступ
+ Шукати програму
+ Фільтрувати програми
+ Показати користувацькі програми
+ Показати системні програми
+ Показати програми без інтернету
+ Показати вимкнені програми
+ Сортувати програми
+ Сортувати за назвою
+ Сортувати за uid
+ Сортувати за використанням даних
+ Показати журнал
+ Налаштування
+ Запросити
+ Легенда
+ Підтримка
+ Про
+ Інші програми
+ Інше
+ Дозволено
+ Заблоковано
+ Актуальні оновлення
+ Оновити
+ Показати імена
+ Показати організацію
+ PCAP увімкнуто
+ Експорт PCAP
+ Очистити
+ Експорт
+ Скинути
+ Додати
+ Вилучити
+ Очищення
+ Протокол
+ Вихідний порт
+ Адреса призначення
+ Порт призначення
+ Цільова програма
+ Для зовнішнього сервера оберіть «ніхто»
+ Стандартні (дозволені/заблоковані)
+ Блокувати Wi-Fi
+ Блокувати мобільні дані
+ Дозволити Wi-Fi, коли екран активний
+ Дозволити мобільні мережі, коли екран активний
+ Блокувати у роумінгу
+ Налаштування
+ Тема: %1$s
+ Використовувати темну тему
+ Сповіщати про нове встановлення
+ Застосувати правила «коли екран увімкнено»
+ Автоматично увімкнути через %1$s хв
+ Затримка вимкення екрана — %1$s хв
+ Перевірити наявність оновлень
+ Налаштування мережі
+ Маршрутизація підмережі
+ Дозволити прив\'язку
+ Дозволити доступ до LAN
+ Увімкнути IPv6-трафік
+ Домашня Wi-Fi мережа: %1$s
+ Регулювати лімітовані Wi-Fi мережі
+ Не враховувати 2G
+ Не враховувати 3G
+ Не враховувати LTE
+ Ігнорувати національний роумінг
+ Ігнорувати європейський роумінг
+ Вимкнути під час виклику
+ Блокування Wi-Fi
+ Блокування моб. мережі
+ Перезавантажувати при кожній зміні підключення
+ Розширенні налаштування
+ Керувати системними програмами
+ Записувати доступ до мережі інтернет
+ Сповіщувати про доступ до інтернету
+ Фільтрувати трафік
+ Фільтрувати трафік UDP
+ Безшовна передача VPN у разі перезавантаження
+ Розривати з’єднання при перезавантаженні
+ Блокування трафіка
+ Відслідковувати використання мережі
+ Скинути використання мережі
+ Показати вирішені доменні імена
+ Блокувати доменні імена
+ Код відповіді DNS: %s
+ Перенаправлення портів
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Перевірити: %s
+ Мінімальний DNS TTL: %s с
+ Використовувати проксі SOCKS5
+ Адреса SOCKS5: %s
+ Порт SOCKS5: %s
+ Ім’я користувача SOCKS5: %s
+ Пароль SOCKS5: %s
+ Розмір запису PCAP: %s Б
+ Макс. розмір файлу PCAP: %s МБ
+ Сторожовий таймер: кожні %s хв
+ Швидкість у сповіщенні
+ Показувати сповіщення щодо швидкості
+ Показати топові програми
+ Частота замірів: %s мс
+ Кількість замірів: %s s
+ Резервне копіювання
+ Експортувати налаштування
+ Імпортувати налаштування
+ Імпортувати host-файл
+ Імпортувати host-файли (додати)
+ Посилання для завантаження host-файлу
+ Завантажити host-файл
+ Технічна інформація
+ Загальне
+ Мережі
+ Підписки
+ Показати повідомлення в рядку стану для безпосереднього налаштування нещодавно встановлених програм (Pro-функція)
+ Після відключення через віджет вмикати NetGuard автоматично через вказану кількість хвилин (щоб вимкнути цю функцію, введіть 0)
+ Тримати екран активним упродовж вказаної кількості хвилин після вимикання (0 вимикає функцію)
+ Перевіряти нові випуски з GitHub двічі на день
+ Прив\'язування може працювати або ні - це залежить від версії Android. Прив\'язаний трафік не може бути відфільтрований.
+ Увімкнути маршрутизацію підмережі; може уможливити дзвінки по Wi-Fi, але й викликати помилки в Android і збільшити витрату заряду акумулятора
+ Дозволити програмам підключатися до локальних мережевих адрес, як-от 10.0.0.0/8, 172.16.0.0/12 та 192.168.0.0/16
+ Маршрутизувати IPv6-трафік до NetGuard, щоб він міг бути вибірково дозволений або заблокований
+ Застосувати правила Wi-Fi-мережі лише для вказаної мережі (для інших застосовуються правила мобільної мережі)
+ Застосувати правила до лімітованих (платних, обмежених) Wi-Fi-мереж
+ Застосувати правила Wi-Fi-мережі до 2G-з’єднання
+ Застосувати правила Wi-Fi-мережі до 3G-з’єднання
+ Застосувати правила Wi-Fi-мережі до LTE-з’єднання
+ Не застосовувати правила роумінгу, якщо SIM-карта відповідає країні перебування
+ Не застосовувати правила роумінгу, якщо країна походження SIM-карти або мобільної мережі входять до складу ЄС (трактувати роумінг як місцеву мережу)
+ Вимкнути NetGuard під час вхідного або вихідного телефонного виклику. Цю опцію можна використовувати для вирішення проблем з IP/Wi-Fi дзвінками.
+ Визначити правила для системних програм (для експертів)
+ Журнал спроб доступу програм до інтернету. Це може збільшити споживання заряду акумулятора.
+ Показати сповіщення в рядку стану, коли програма намагається отримати доступ до нової інтернет-адреси (коли фільтрація вимкнена, показуватимуться лише заблоковані спроби доступу в Інтернет)
+ Фільтрувати IP-пакети, які проходять через VPN. Це може збільшити витрату заряду акумулятора.
+ Відслідковувати кількість надісланих і отриманих байтів для кожної програми й адреси. Це може призвести до збільшення витрати заряду акумулятора.
+ Відповідати кодом відповіді налаштованого DNS для заблокованих доменних імен. Цей перемикач вимкнено, якщо доступних host-файлів немає.
+ Значенням за замовчуванням є 3 (NXDOMAIN) - це означає «неіснуючий домен».
+ Доменне ім’я, використовуване для перевірки інтернет-з’єднання через порт 443 (https).
+ На проксі-сервер направлятиметься лише TCP-трафік
+ Періодично перевіряти, чи запущено NetGuard (введіть нуль, щоб вимкнути цю опцію). Це може призвести до збільшення витрати заряду акумулятора.
+ Показувати графік швидкості мережі у рядку сповіщень
+ Ви впевнені?
+ Застосування правил
+ %1$d дозволено, %2$d заблоковано
+ %1$d дозволено, %2$d заблоковано, хостів - %3$d
+ Очікування події
+ NetGuard вимкнено. Для увімкнення скористайтеся перемикачем, розташованим вище
+ NetGuard було вимкнено, найімовірніше, через використання іншого VPN-підключення
+ %1$s встановлено
+ Було встановлено
+ Спроб доступу до інтернету: %1$s
+ Спроба отримати доступ в Інтернет
+ Дію завершено
+ NetGuard використовує локальний VPN для фільтрації інтернет-трафіку. З огляду на це, будь ласка, дозвольте VPN-підключення в наступному діалоговому вікні. На віддалені VPN-сервери ваш трафік не надсилатиметься.
+ NetGuard не вдається запустити автоматично - імовірно, унаслідок помилки у вашій версії системи Android.
+ Сталася непередбачена помилка: \'%s\'
+ Наразі Android відмовився запустити VPN-сервіс. Імовірно, це спричинено помилкою у вашій версії Android.
+ Спробуйте NetGuard
+ Здійснюючи пожертвування, ви погоджуєтесь із умовами & положення
+ Якщо вам не вдається натиснути ОК у наступному діалоговому вікні (затемнення екрана), імовірно, екран використовується якою-небудь іншою програмою.
+ ± %1$.3f▲ %2$.3f▼ МБ/день
+ %1$7.3f▲ %2$7.3f▼ КБ
+ %1$7.3f▲ %2$7.3f▼ МБ
+ %1$7.3f▲ %2$7.3f▼ ГБ
+ %dx
+ Для досягнення стабільних результатів необхідно вимкнути економію заряду акумулятора Android для NetGuard.\n\nУ верхній частині наступного діалогового вікна виберіть «Усі програми», знайдіть у списку NetGuard і виберіть його, а потім виберіть «Не економити» і підтвердьте.
+ Для досягнення стабільних результатів обмеження даних Android необхідно вимкнути для NetGuard.
+\n\nУ наступному діалоговому вікні увімкніть опції «Фонові дані» та «Необмежене використання даних»
+ Використання фільтрування призведе до того, що Android приписуватиме споживання даних та енергії NetGuard; Android вважатиме, що дані та енергія використовуються не програмами, які їх використовують, а NetGuard\'ом
+ На Android 4 фільтрацію необхідно увімкнути
+ Журналювання трафіку вимкнуто, використовуйте перемикач вище, аби увімкнути журналювання. Це може підвищити споживання заряду акумулятора.
+ Це скине правила й умови на стандартні значення
+ Це видалить рядки журналу спроб доступу, що не містять правил дозволу/блокування
+ Крайній імпорт: %s
+ Завантаження\n%1s
+ Host-файл завантажено
+ Останнє завантаження: %s
+ Почати перенаправлення з %1$s порту %2$d до %3$s:%4$d з «%5$s»?
+ Зупинити перенаправлення з %1$s порту %2$d?
+ Лімітована мережа
+ Немає активного з\'єднання з Інтернетом
+ NetGuard зайнятий
+ Доступне оновлення, торкніться для завантаження
+ Ви можете дозволити (зеленуватий колір значка) або заборонити (червонуватий колір значка) доступ до Wi-Fi або мобільного Інтернету, натиснувши на значок поряд із програмою
+ Якщо ви встановили NetGuard для захисту своєї конфіденційності, вас може зацікавити також FairEmail — це корисна програма з відкритим вихідним кодом, призначена для захисту конфіденційності
+ Доступ в Інтернет за замовчуванням дозволено (режим списку блокування). Це можна змінити в налаштуваннях
+ Вхідні повідомлення (push) опрацьовуються здебільшого системними компонентами Google Play, яким за замовчуванням дозволено доступ в Інтернет
+ Керування всіма (системними) програмами можна увімкнути в додаткових налаштуваннях
+ Опишіть проблему й зазначте момент її виникнення:
+ VPN-з’єднання скасовано\nБажаєте налаштувати інше VPN-з’єднання, щоб VPN було увімкнено завжди?
+ Вимкнення пристрою із запущеним NetGuard автоматично запустить NetGuard під час увімкнення вашого пристрою
+ Ця функція недоступна в цій версії Android
+ Інший VPN встановлено як завжди увімкнений VPN
+ Вимкніть параметр \"Блокувати підключення без VPN\" у параметрах VPN в Android, щоб використовувати NetGuard у режимі фільтрування
+ Щоб використовувати NetGuard у режимі фільтрування, вимкніть параметр «Приватний DNS» у мережевих параметрах Android
+ Трафік заблоковано
+ Безлімітний трафік дозволено
+ Безлімітний трафік заблоковано
+ Необмежені правила не застосовуються
+ Лімітований трафік дозволено
+ Лімітований трафік заблоковано
+ Лімітовані правила не застосовуються
+ Адреса дозволена
+ Адреса заблокована
+ Дозволити, коли екран активний
+ Блокувати у роумінгу
+ За замовчуванням Wi-Fi-з\'єднання вважається безлімітним, а мобільна мережа - лімітованою
+ не має доступу до інтернету
+ вимкнено
+ Вхідні повідомлення отримуються службами Google Play, а не цією програмою, а тому можуть не блокуватися нею
+ Завантаження виконує менеджер завантаження, а не ця програма, і тому їх не можна заблокувати шляхом блокування цієї програми
+ Застосувати правила та умови
+ Умови
+ Дозволити Wi-Fi, коли екран увімкнено
+ Дозволити мобільні мережі, коли екран увімкнено
+ Р
+ Блокувати у роумінгу
+ Дозволити в режимі блокування трафіка
+ Фільтрувати пов’язані
+ Спроби доступу
+ Правила доступу мають вищій пріоритет над іншим правилами
+ Налаштування
+ Сповістити при спробі доступу до інтернету
+ Реєстрація подій або фільтрування не увімкнені
+ Реєстрація подій і фільтрування увімкнені
+ Налаштувати
+ Увімкнути реєстрацію подій лише для заблокованих адрес
+ Увімкнути фільтрування лише для заблокованих адрес
+ Увімкнути сповіщення щодо доступу до нещодавно зареєстрованих адрес
+ Ці налаштування є глобальними і застосовуються до всіх програм
+ Фільтрування необхідне також для дозволу або блокування окремих адрес
+ Увімкнення реєстрації подій або фільтрування може прискорити витрату заряду і справити вплив на швидкість у мережі
+ Оцінити
+ Дозволити
+ Блокувати
+ Дозволити Wi-Fi
+ Блокувати Wi-Fi
+ Дозволити мобільні дані
+ Блокувати мобільні дані
+ root
+ медіасервер
+ ніхто
+ Надалі не запитувати
+ Whois %1$s
+ Порт %1$d
+ Копіювати
+ Pro-можливості
+ Доступні такі Pro-можливості:
+ Переглянути журнал заблокованого трафіку
+ Фільтрувати мережевий трафік
+ Сповіщення про нові програми
+ Графік швидкості мережі в сповіщенні
+ Зовнішній вигляд (тема, кольори)
+ Усі зазначені вище pro-можливості
+ Підтримати розробку
+ Придбати
+ Увімкнено
+ Недоступно
+ Для отримання додаткової інформації натисніть на заголовок
+ Завдання
+ Відповідь
+ Це функція професійної версії
+ Щомісячна підписка на 1 або 2 євро (без врахування місцевих податків) активує всі професійні функції.
+ Ви можете скасувати або керувати підпискою через вкладку Підписки в додатку Play Store.
+
+
+ - бірюзовий/рудий
+ - синій/помаранчевий
+ - фіолетовий/червоний
+ - бурштиновий/синій
+ - помаранчевий/сірий
+ - зелений
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-v14/styles.xml b/NetGuard/app/src/main/res/values-v14/styles.xml
new file mode 100644
index 0000000..7578cb0
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-v14/styles.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/values-v21/styles.xml b/NetGuard/app/src/main/res/values-v21/styles.xml
new file mode 100644
index 0000000..2375be7
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-v21/styles.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/values-vi-rVN/strings.xml b/NetGuard/app/src/main/res/values-vi-rVN/strings.xml
new file mode 100644
index 0000000..aeaae5a
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-vi-rVN/strings.xml
@@ -0,0 +1,288 @@
+
+
+ NetGuard cung cấp những cách đơn giản và nâng cao để chặn quyền truy cập vào internet - không yêu cầu root. Ứng dụng và địa chỉ có thể được cá nhân cho phép hoặc từ chối truy cập Wi-Fi và/hoặc kết nối di động của bạn.
+ NetGuard yêu cầu Android 5.1 hoặc cao hơn
+ Xposed gây ra quá nhiều lỗi, mà có ảnh hưởng đến NetGuard bị gỡ bỏ khỏicửa hàng Google Play; Do đó, NetGuard sẽ không được hỗ trợ nếu Xposed được cài đặt.
+ Chính sách riêng tư
+ Tôi đã rất cẩn thận để phát triển và thử nghiệm NetGuard, tuy nhiên không thể đảm bảo NetGuard sẽ làm việc chính xác trên mọi thiết bị.
+ Tôi đồng ý
+ Tôi không đồng ý
+ NetGuard cần sự giúp đỡ của bạn. Nhấn để mua các tính năng Pro để giữ cho dự án hoạt động.
+ Các dịch vụ đang chạy
+ Thông báo chung
+ Truy cập thông báo
+ Tìm kiếm ứng dụng
+ Lọc ứng dụng
+ Hiển thị ứng dụng của người dùng
+ Hiển thị các ứng dụng hệ thống
+ Hiển thị các ứng dụng không có internet
+ Hiển thị các ứng dụng bị tắt
+ Sắp xếp ứng dụng
+ Sắp xếp theo tên
+ Sắp xếp theo uid
+ Sắp xếp theo mức dữ liệu sử dụng
+ Xem lịch sử
+ Cài đặt
+ Mời
+ Chú giải
+ Hỗ trợ
+ Giới thiệu
+ Ứng dụng khác
+ Khác
+ Cho phép
+ Đã chặn
+ Cập nhật trực tiếp
+ Làm mới
+ Tên hiển thị:
+ Hiển thị các tổ chức
+ Kích hoạt PCAP
+ Xuất PCAP
+ Xóa
+ Xuất ra
+ Thiết lập lại
+ Thêm
+ Xoá
+ Dọn dẹp
+ Giao thức
+ Cổng nguồn
+ Địa chỉ nơi đến
+ Cổng nơi đến
+ Ứng dụng đích đến
+ Đối với một máy chủ bên ngoài chọn \'nobody\'
+ Mặc định (white/blacklist)
+ Chặn Wi-Fi
+ Chặn mạng di động
+ Cho phép Wi-Fi khi màn hình bật
+ Cho phép mạng di động khi màn hình bật
+ Chặn chuyển vùng
+ Tuỳ chọn
+ Chủ đề: %1$s
+ Sử dụng chủ đề tối
+ Thông báo khi có ứng dụng mới
+ Áp dụng quy tắc (khi bật màn hình)
+ Tự động kích hoạt sau %1$s phút
+ Trì hoãn màn hình tắt %1$s phút
+ Kiểm tra cập Nhật
+ Tùy chọn mạng
+ Định tuyến mạng con
+ Cho phép giới hạn
+ Cho phép truy cập mạng LAN
+ Kích hoạt lưu lượng truy cập IPv6
+ Wi-Fi nhà mạng: %1$s
+ Xử lý các mạng Wi-Fi có trả phí
+ Xem xét mạng 2G miễn phí
+ Xem xét mạng 3G miễn phí
+ Xem xét mạng LTE miễn phí
+ Bỏ qua chuyển vùng quốc gia
+ Bỏ qua chuyển vùng EU
+ Vô hiệu hoá khi gọi
+ Khoá Wi-Fi
+ Khóa di động
+ Tải lại mỗi lần đổi kết nối
+ Tùy chọn nâng cao
+ Quản lý ứng dụng hệ thống
+ Thông báo truy cập internet
+ Thông báo truy cập internet
+ Lọc lưu lượng truy cập
+ Lọc lưu lượng truy cập
+ Chuyển giao VPN khi tải lại
+ Đóng kết nối khi tải lại
+ Khóa truy cập
+ Theo dõi cách sử dụng mạng
+ Đặt lại sử dụng mạng
+ Hiển thị tên miền giải quyết
+ Chặn tên miền
+ Mã phản hồi DNS: %s
+ Cổng chuyển tiếp
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Xác thực tại: %s
+ Tối thiểu DNS TTL: %s s
+ Dùng Socks5 proxy
+ Địa chỉ (Socks5): %s
+ Cổng (Socks5):%s
+ Username: %s
+ Password: %s
+ Kích thước ghi PCAP: %s B
+ Kích thước tập tin PCAP lớn nhất: %s MB
+ Thời gian giám sát: mỗi %s phút
+ Hiển thị thông báo tốc độ
+ Hiển thị thông báo tốc độ
+ Hiển thị các ứng dụng hàng đầu
+ Khoảng thời gian mẫu: %s ms
+ Số mẫu: %s s
+ Sao lưu
+ Xuất cài đặt
+ Nhập cài đặt
+ Nhập file hosts
+ Chọn file host
+ URL tải file hosts
+ Tải về file hosts
+ Thông tin kỹ thuật
+ Cài đặt chung
+ Mạng
+ Câu hỏi thường gặp
+ Hiển thị thanh thông báo trạng thái trực tiếp cấu hình ứng dụng mới được cài đặt (tính năng pro)
+ Sau khi vô hiệu hóa bằng cách sử dụng các widget, tự động bật NetGuard một lần nữa sau số phút được chọn (nhập 0 để tắt tùy chọn này)
+ Sau khi màn hình tắt, giữ cho các quy tắc khi màn hình bật hoạt động trong số phút được chọn (nhập 0 để tắt tùy chọn này)
+ Kiểm tra các phiên bản mới trên GitHub hai lần mỗi ngày
+ Tùy thuộc vào phiên bản Android, việc giới hạn có thể làm việc hoặc có thể không làm việc. Giới hạn lưu lượng truy cập không thể được lọc.
+ Kích hoạt định tuyến mạng con; có thể bật Wi-Fi calling, nhưng có thể cũng gây ra lỗi trong Android và làm tăng việc sử dụng pin
+ Cho phép các ứng dụng kết nối với địa chỉ mạng nội bộ, như 10.0.0.0/8, 172.16.0.0/12 và 192.168.0.0/16
+ Định tuyến IPv6 lưu lượng truy cập đến NetGuard vì vậy nó có chọn lọc có thể được cho phép hoặc chặn
+ Áp dụng quy tắc mạng Wi-Fi cho mạng đã chọn (áp dụng quy tắc mạng di động cho các mạng Wi-Fi khác)
+ Áp dụng quy tắc mạng di động cho mạng Wi-Fi có trả phí (có thể mất phí)
+ Áp dụng quy tắc mạng Wi-Fi cho kết nối dữ liệu 2G
+ Áp dụng quy tắc mạng Wi-Fi cho kết nối dữ liệu 3G
+ Áp dụng quy tắc mạng Wi-Fi cho kết nối dữ liệu LTE
+ Không áp dụng quy tắc chuyển vùng khi SIM và mạng di động mạng quốc gia giống nhau
+ Không áp dụng quy tắc chuyển vùng khi SIM và mạng di động mạng quốc gia giống nhau
+ Vô hiệu hóa NetGuard khi có cuộc gọi đến hoặc đi. Điều này có thể được sử dụng để khắc phục các sự cố gọi IP / Wi-Fi.
+ Định nghĩa quy tắc cho các ứng dụng hệ thống (đối với các chuyên gia)
+ Thông báo cố gắng truy cập internet cho các ứng dụng. Điều này có thể dẫn đến việc hao pin.
+ Hiển thị một thanh thông báo trạng thái khi một ứng dụng cố gắng để truy cập vào một địa chỉ internet mới (khi lọc bị tắt, chỉ cố gắng truy cập internet bị chặn được thông báo)
+ Lọc gói tin IP đi ra khỏi đường hầm VPN. Điều này có thể dẫn đến việc hao pin.
+ Theo dõi số lượng byte gửi và nhận được cho mỗi ứng dụng và địa chỉ. Điều này có thể dẫn đến việc hao pin.
+ DNS được định cấu hình cho các tên miền bị chặn. Tùy chọn này bị vô hiệu hóa khi không có sẵn file hosts.
+ Giá trị mặc định là 3 (NXDOMAIN), có nghĩa là \'không tồn tại tên miền\'.
+ Tên miền được sử dụng để xác thực kết nối internet tại cổng 443 (https).
+ Lưu lượng TCP sẽ được gửi đến máy chủ proxy
+ Định kỳ kiểm tra nếu NetGuard vẫn chạy (nhập 0 để tắt tùy chọn này). Điều này có thể dẫn đến việc hao pin.
+ Hiển thị đồ thị tốc độ mạng trên thanh thông báo trạng thái
+ Bạn có chắc không?
+ Đang thực thi các quy tắc
+ %1$d cho phép, %2$d bị chặn
+ %1$d cho phép, %2$d chặn, %3$d hosts
+ Đang chờ đợi sự kiện
+ NetGuard bị vô hiệu hóa, sử dụng nút gạt bên trên để kích hoạt NetGuard
+ NetGuard đã bị vô hiệu hóa, rất có thể do đang sử dụng một ứng dụng dựa trên VPN khác
+ \'%1$s\' được cài đặt
+ Đã được cài đặt
+ %1$s cố gắng truy cập internet
+ Cố gắng truy cập internet
+ Hoàn tất hành động
+ NetGuard sử dụng một local VPN để lọc lưu lượng truy cập internet. Vì lý do này, xin vui lòng cho phép một kết nối VPN trong hộp thoại tiếp theo. Lưu lượng truy cập internet của bạn không được gửi đến một máy chủ VPN từ xa.
+ NetGuard không thể tự động khởi động. Điều này có khả năng là do một lỗi trong phiên bản Android của bạn.
+ Lỗi không xác định đã xảy ra: \'%s\'
+ Đã từ chối để kết nối dịch vụ VPN tại. Điều này có khả năng do một lỗi trong phiên bản Android của bạn.
+ Thử NetGuard
+ Bằng cách tặng, bạn đồng ý với các điều khoản & điều kiện
+ Nếu bạn không thể nhấn OK trong hộp thoại kế tiếp, rất có thể một ứng dụng khác (màn hình mờ) đang thao tác với màn hình.
+ ± %1$.3f▲ %2$.3f▼ MB/ngày
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ Để có kết quả phù hợp, tối ưu hóa pin Android nên bị vô hiệu hóa cho NetGuard. \n\nTrong hộp thoại kế tiếp, chọn \"Tất cả ứng dụng\" ở phía trên cùng, bấm vào NetGuard trong danh sách và chọn và xác nhận \"Don\'t optimize\".
+ Để có kết quả phù hợp, tùy chọn tiết kiệm dữ liệu Android nên được vô hiệu hóa cho NetGuard \n\nTrong trong hộp thoại kế tiếp, cho phép tùy chọn \"Background data\" và \"Unrestricted data usage\"
+ Sử dụng bộ lọc sẽ làm cho Android hiểu lầm NetGuard sử dụng dữ liệu và năng lượng - Android giả định dữ liệu và năng lượng đang được sử dụng bởi NetGuard, chứ không phải là các ứng dụng ban đầu
+ Android 4 yêu cầu lọc phải được kích hoạt
+ Thông báo lưu lượng truy cập bị vô hiệu hóa, sử dụng nút gạt bên trên để cho phép thông báo. Thông báo lưu lượng truy cập có thể dẫn đến việc sử dụng pin phụ.
+ Điều này sẽ đặt lại các quy tắc và trạng thái về giá trị mặc định
+ Việc này sẽ xóa các dòng thông báo cố gắng truy cập mà không có quy tắc cho phép/chặn
+ Lần nhập cuối: %s
+ Đang tải về\n%1s
+ Đã tải về file hosts
+ Lần tải về cuối: %s
+ Bắt đầu chuyển tiếp từ %1$s cổng %2$d đến %3$s:%4$d của \'%5$s\'?
+ Dừng chuyển tiếp %1$s cổng %2$d?
+ Mạng có trả phí
+ Không có kết nối internet
+ NetGuard đang bận
+ Đã có phiên bản mới, bấm vào để tải về
+ Bạn có thể cho phép (xanh lục) hoặc từ chối (màu đỏ) truy cập internet Wi-Fi hoặc mạng di động bằng cách bấm vào biểu tượng bên cạnh ứng dụng
+ Nếu bạn cài đặt NetGuard để bảo vệ riêng tư của bạn, bạn có thể quan tâm đến FairEmail , một mã nguồn mở, các ứng dụng thân thiện với email bảo mật...
+ Truy cập Internet mặc định được cho phép, điều này có thể thay đổi trong cài đặt
+ Đưa tin nhắn chủ yếu được xử lý bởi các thành phần Play services của hệ thống, mà mặc định cho phép truy cập internet
+ Quản lý ứng dụng hệ thống có thể được kích hoạt trong cài đặt
+ Xin vui lòng mô tả các vấn đề và cho biết thời gian của vấn đề:
+ Đã hủy kết nối VPN \nBạn đã đặt cấu hình VPN thành luôn bật chưa?
+ NetGuard sẽ tự động khởi động khi bật nguồn thiết bị
+ Tính năng này không được cung cấp trong phiên bản này.
+ Một VPN khác đã được bật, vui lòng tắt đi
+ Tắt \"Chặn các kết nối mà không cần VPN\" trong cài đặt Android VPN sử dụng NetGuard của chế độ lọc
+ Tắt \"DNS riêng\" trong cài đặt mạng Android để sử dụng NetGuard ở chế độ lọc
+ Lưu lượng bị khóa
+ Lưu lượng truy cập không trả phí được cho phép
+ Lưu lượng truy cập không trả phí bị chặn
+ Quy tắc kiểm tra chưa được áp dụng
+ Lưu lượng truy cập có trả phí được phép
+ Lưu lượng truy cập có trả phí bị chặn
+ Quy tắc kiểm tra chưa được áp dụng
+ Địa chỉ được cho phép
+ Địa chỉ bị chặn
+ Cho phép khi màn hình bật
+ Chặn khi chuyển vùng
+ Theo mặc định, kết nối Wi-Fi được coi là không trả phí và kết nối điện thoại di động được coi là có trả phí
+ không có sự cho phép của internet
+ bị vô hiệu hóa
+ Các thông báo đến được dịch vụ Google Play nhận và không phải ứng dụng này và do đó không thể bị chặn bằng cách chặn ứng dụng này
+ Các lượt tải xuống được trình quản lý tải xuống thực hiện và không phải ứng dụng này và do đó không thể bị chặn bằng cách chặn ứng dụng này
+ Áp dụng các quy tắc và trạng thái
+ Điều kiện
+ Cho phép Wi-Fi khi màn hình bật
+ Cho phép mạng di động khi màn hình bật
+ R
+ Chặn khi chuyển vùng
+ Cho phép ở chế độ khóa
+ Lọc liên quan
+ Cố gắng truy cập
+ Quy tắc truy cập được ưu tiên hơn các quy tắc khác
+ Tuỳ chọn
+ Thông báo các cố gắng truy cập internet
+ Ghi nhật ký hoặc lọc không được kích hoạt
+ Ghi nhật ký hoặc lọc không được kích hoạt
+ Đặt cấu hình
+ Chỉ cho phép ghi nhật ký các địa chỉ bị chặn
+ Cho phép lọc để ghi nhật ký địa chỉ được phép
+ Cho phép thông báo truy cập cho các địa chỉ mới đăng nhập
+ Các cài đặt này là cài đặt chung áp dụng cho tất cả các ứng dụng
+ Lọc cũng được yêu cầu để cho phép hoặc chặn các địa chỉ riêng lẻ
+ Bật ghi nhật ký (ít hơn) hoặc lọc (nhiều hơn) có thể làm tăng mức sử dụng pin và có thể ảnh hưởng đến tốc độ mạng
+ Đánh giá
+ Cho phép
+ Chặn
+ Cho phép sử dụng Wi-Fi
+ Chặn Wi-fi
+ Cho phép điện thoại di động
+ Chặn điện thoại di động
+ root
+ Máy chủ media
+ không ai
+ Không hỏi lại
+ Whois %1$s
+ Cổng %1$d
+ Sao chép
+ Tính năng phiên bản Pro
+ Các tính năng phiên bản pro có sẵn:
+ Xem lưu lượng truy cập bị chặn
+ Lọc lưu lượng truy cập mạng
+ Thông báo ứng dụng mới
+ Thông báo biểu đồ tốc độ mạng
+ Giao diện (chủ đề, màu sắc)
+ Tất cả các tính năng phiên bản pro trên
+ Hỗ trợ phát triển sản phẩm
+ Mua
+ Kích hoạt
+ Không có sẵn
+ Nhấn vào một tiêu đề để biết thêm thông tin
+ Thử thách
+ Phản ứng:
+ Đây là một tính năng pro
+ Một gói đăng ký 1 hoặc 2 euro (chưa bao gồm thuế ở địa phương) sẽ kích hoạt tất cả tính năng pro.
+ Bạn có thể huỷ hoặc quản lý gói đăng ký qua tab gói đăng ký trong ứng dụng CH Play.
+
+
+ - xanh mòng két/cam
+ - xanh dương/cam
+ - tím/đỏ
+ - hổ phách/xanh dương
+ - cam/xám
+ - xanh lá cây
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-w820dp/dimens.xml b/NetGuard/app/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000..63fc816
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/NetGuard/app/src/main/res/values-zh-rCN/strings.xml b/NetGuard/app/src/main/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..76ff61e
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-zh-rCN/strings.xml
@@ -0,0 +1,292 @@
+
+
+ NetGuard无须root权限,能简便专业地阻止应用连接网络,亦可允许或拒绝个别应用和地址使用Wi-Fi和移动数据。
+ NetGuard只可用于Android 5.1或更新版本
+ NetGuard不能与Xposed并用,因为Xposed经常崩溃,从而导致NetGuard从Google Play移除。
+ 隐私政策
+ 尽管我们已精心努力开发和测试NetGuard,我们依然无法保证NetGuard将在每台设备上正常运作。
+ 同意
+ 拒绝
+ NetGuard需要您帮助。请点击购买应用的专业版,支持此项目的开发工作。
+ 正在运行的服务
+ 常规通知
+ 访问通知
+ 搜索应用
+ 筛选应用
+ 显示用户应用
+ 显示系统应用
+ 显示不能上网的应用
+ 显示已停用的应用
+ 应用排序
+ 按名称排序
+ 按UID排序
+ 按数据使用量排序
+ 显示日志
+ 设置
+ 邀请
+ 图例
+ 帮助
+ 关于应用
+ 其他应用
+ 其他
+ 已允许
+ 已拦截
+ 实时更新
+ 刷新
+ 显示名称
+ 显示机构
+ 已启用PCAP
+ PCAP导出
+ 清除
+ 导出
+ 重置
+ 添加
+ 删除
+ 清理
+ 协议
+ 源端口
+ 目标地址
+ 目标端口
+ 目标应用
+ 对外部的服务器选择“nobody”
+ 默认(黑白名单)
+ 禁用Wi-Fi
+ 禁用移动数据
+ 亮屏时允许使用Wi-Fi
+ 亮屏时允许使用移动数据
+ 阻止漫游上网
+ 选项
+ 配色:%1$s
+ 使用深色主题
+ 安装新应用时通知我
+ 使用亮屏时的规则
+ %1$s分钟后自动启用
+ 推迟%1$s分钟关屏
+ 检查更新
+ 网络选项
+ 子网路由
+ 允许网络共享
+ 允许 LAN 访问
+ 允许IPv6流量
+ 家庭Wi-Fi网络:%1$s
+ 控制按流量计费的Wi-Fi网络
+ 将2G网络视为不计量连接
+ 将3G网络视为不计量连接
+ 将LTE网络视为不计量连接
+ 国内漫游例外
+ 欧盟漫游例外
+ 通话期间禁用
+ 锁定无线网络
+ 锁定移动网络
+ 连接每次更改时重新加载
+ 高级选项
+ 管理系统应用
+ 记录网络访问
+ 网络连接通知
+ 过滤流量
+ 过滤UDP流量
+ 重新加载时无缝切换VPN
+ 重新加载时关闭连接
+ 锁定流量
+ 记录网络使用
+ 清空网络使用记录
+ 显示已解析的主机名称
+ 屏蔽域名
+ DNS回应码:%s
+ 端口转发
+ VPN IPv4:%s
+ VPN IPv6:%s
+ VPN DNS:%s
+ 验证地址:%s
+ 最短DNS TTL:%s秒
+ 使用SOCKS5代理
+ SOCKS5地址:%s
+ SOCKS5端口:%s
+ SOCKS5用户名:%s
+ SOCKS5密码:%s
+ PCAP记录大小:%s B
+ PCAP最大文件大小:%s MB
+ 监控:每%s分钟
+ 网速通知
+ 显示网速通知
+ 显示最高流量的应用
+ 采样频率:%s ms
+ 样本数:%s s
+ 备份
+ 导出设置
+ 导入设置
+ 导入 hosts 文件
+ 导入hosts文件(追加)
+ Hosts文件下载地址
+ 下载hosts文件
+ 技术信息
+ 一般
+ 网络
+ 付费订阅
+ 显示状态栏通知,直接设置刚安装的应用(专业版功能)
+ 禁用微件后,在设定时间后自动重启NetGuard(输入“0”可忽略此项)
+ 关屏后,保持亮屏规则在指定时间内有效(输入“0”可忽略此项)
+ 每日两次检查GitHub上的更新
+ 网络共享可因Android版本而无法运作。NetGuard不可过滤共享的网络流量。
+ 启用子网路由。启用后您有可能使用Wi-Fi通话,但系统或许会出错和消耗更多电量
+ 允许应用连接至局域网地址,如:10.0.0.0/8、172.16.0.0/12及192.168.0.0/16
+ 将IPv6流量导至NetGuard,以便允许或拦截相关流量
+ 仅将Wi-Fi规则应用于某些网络(将移动网络规则应用于其他Wi-Fi网络)
+ 将移动网络规则应用于按流量计费的Wi-Fi网络(如付费或共享网络)
+ 将Wi-Fi网络规则应用于2G数据连接
+ 将Wi-Fi网络规则应用于3G数据连接
+ 将Wi-Fi网络规则应用于LTE数据连接
+ SIM卡与移动网络为相同国家时不使用漫游规则
+ 使用欧洲国家SIM卡与移动网络时不应用漫游规则(如家漫游)
+ 通话时停用NetGuard。这可解决IP/Wi-Fi呼叫问题。
+ 设订系统应用规则(仅供高级用户使用)
+ 记录应用的网络访问尝试。装置可能会消耗更多电量。
+ 当应用程序试图访问一个新的互联网地址时显示状态栏通知(过滤禁用时仅通知被阻止网络的访问尝试)
+ 筛选经由VPN重定向导出的IP数据包。装置可能会消耗更多电量。
+ 跟踪每个应用程序和地址发送和接收的字节数。装置可能会消耗更多电量。
+ 使用配置的DNS回应码回应已封禁的域名。此选项将在hosts文件不可用时禁用。
+ 默认值为3 (NXDOMAIN),即“域名不存在”。
+ 用于验证网络连接端口为443(https)的域名。
+ 仅将TCP流量导向至代理服务器
+ 定时检查NetGuard是否在运行(输入“0”以忽略禁用此项)。装置可能会消耗更多电量。
+ 在状态栏通知中显示网速示意图
+ 确认?
+ 正在执行规则
+ 已允许%1$d个应用,拦截%2$d个应用
+ 已允许%1$d个应用,拦截%2$d个应用,%3$d个host
+ 等待中
+ NetGuard已停用,请使用上方的开关启用NetGuard
+ NetGuard已停用,您可能启动了另一个VPN应用
+ 已安装“%1$s”
+ 已安装
+ %1$s曾尝试连接网络
+ 连接网络尝试
+ 操作完成
+ NetGuard使用本地VPN过滤网络流量。
+因此,请在下一个对话框允许建立VPN连接。
+您的流量不会送到任何远程VPN服务器。
+ 此Android版本可能有误,导致NetGuard无法开机自启。
+ 发生未知错误:“%s”
+ 此Android版本可能有误,导致Android拒绝启动VPN服务。
+ 试用NetGuard
+ 捐赠即表明您同意相关条款细则
+ 如果您在下一个对话框中不能点击确定,另一个应用可能在控制屏幕(如屏幕亮度调节的软件)。
+ 每天 ± %1$.3f▲ %2$.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ NetGuard若要正常运作,Android的电池优化功能应豁免NetGuard。
+\n\n请在下一步选择上方的“所有应用”,从列表中点击NetGuard,并选择“不要优化”。
+ NetGuard若要正常运作,Android的流量控制功能应豁免NetGuard。
+\n\n请在下一步选择启用“后台数据”和“不限制数据使用”。
+ 使用过滤功能将导致系统认为 NetGuard 使用了额外的电量和数据流量, 尽管这些使用量是由原应用所致.
+ Android 4须启用过滤
+ 流量记录已停用,请使用上方的开关以启用日志。记录流量可能会增加电量消耗。
+ 此操作将重置所有规则和条件至默认值
+ 此操作将删除访问尝试日志中无允许或阻止规则的记录
+ 上次导入时间:%s
+ 下载中\n%1s
+ 已下载hosts文件
+ 最近下载:%s
+ 要开始从%1$s端口%2$d转发至“%5$s”的%3$s:%4$d吗?
+ 要停止转发%1$s端口%2$d吗?
+ 网络按流量计费
+ 无网络连接
+ NetGuard正忙
+ 现可更新NetGuard,请点击下载
+ 您可以点击应用旁的图标来允许(绿色)或禁止(红色)Wi-Fi或移动网络连接
+ 如果您是为了保护隐私而安装NetGuard的,你也许会对FairEmail 感兴趣。FairEmail是个开源、隐私友好的电子邮件应用。
+ 默认允许网络连接(黑名单模式)。此设定可在设置中更改
+ 大部分通知推送由系统Play服务发出,因此Play服务默认允许连接网络
+ 您可在高级选项中启用管理系统应用
+ 请具体描述问题及问题发生的时间:
+ VPN连接已取消\n您是否选择“始终启用”另一个VPN应用?
+ 如果NetGuard在关机时已启用,在下次开机时NetGuard将自动启动。
+ 此功能在此Android版本上不可用
+ 另一个 VPN 已设置为始终开启
+ 在 Android VPN 设置中关闭 “阻止不使用虚拟专用网络的连接” 来以过滤模式使用网络守护
+ 在Android网络设置中关闭“私人DNS”以过滤模式使用NetGuard
+ 已锁定流量
+ 已允许非按流量计费的网络数据
+ 已拦截非按流量计费的网络数据
+ 不应用于未计费规则
+ 已允许按流量计费的网络数据
+ 已拦截按流量计费的网络数据
+ 不应用计费规则
+ 网络地址已允许
+ 已拦截网络地址
+ 亮屏时允许
+ 漫游时拦截
+ Wi-Fi默认为非按流量计费的连接方式,移动数据连接则默认为按流量计费的方式
+ 无网络访问权限
+ 已禁用
+ 接收消息由Google Play服务接收,非此应用,因此不能通过屏蔽此应用来阻止接收消息
+ 下载是通过下载管理器经手,非此应用,因此不能通过屏蔽此应用来阻止下载
+ 应用规则和条件
+ 条件
+ 亮屏时允许Wi-Fi网络
+ 亮屏时允许移动网络
+ 漫
+ 漫游时拦截
+ 锁定模式中启用
+ 筛选相关
+ 访问尝试
+ 访问规则优先于其他规则
+ 选项
+ 有网络访问尝试时通知我
+ 流量记录或筛选功能已禁用
+ 流量记录和筛选功能已启用
+ 配置
+ 只记录拦截过的网址
+ 同时筛选准许过的网址进行
+ 启用对新网址的访问通知
+ 这些设置为应用于所有应用程序的全局设置
+ 过滤同样需要允许或封禁独立地址
+ 启用流量记录或者筛选功能(影响更大)可能将增加电量消耗和影响网速。
+ 评分
+ 允许
+ 拦截
+ 允许Wi-Fi连接
+ 拦截Wi-Fi连接
+ 允许移动数据
+ 拦截移动数据
+ root
+ mediaserver
+ 没有人
+ 下次不再询问
+ Whois %1$s
+ 端口%1$d
+ 复制
+ 专业版
+ 专业版有下列功能:
+ 查看遭拦截的流量
+ 过滤网络流量
+ 新应用通知
+ 网速示图通知
+ 外观(主题、颜色)
+ 以上所有专业版功能
+ 支持应用开发
+ 购买
+ 已启用
+ 无法使用
+ 点击标题查看更多信息
+ 验证口令
+ 验证应答
+ 这是专业版功能
+ 每月订阅1或2欧元(不包括地方税)将激活所有专业功能。
+ 您可以通过Play商店应用中的“订阅”标签取消或管理订阅。
+
+
+ - 蓝绿色及橙色
+ - 蓝色及橙色
+ - 紫色及红色
+ - 琥珀及蓝色
+ - 橙色及灰色
+ - 绿色
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values-zh-rTW/strings.xml b/NetGuard/app/src/main/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..14f3176
--- /dev/null
+++ b/NetGuard/app/src/main/res/values-zh-rTW/strings.xml
@@ -0,0 +1,291 @@
+
+
+ NetGuard 提供簡易與進階方式封鎖網際網路存取 - 無須 root 權限。您可以個別允許或拒絕 apps 與網址存取您的 Wi-Fi 和/或行動數據連線。
+ NetGuard 需要 5.1 版以上的 Android
+ Xpose 框架會引發過多崩潰,那會導致 Google Play 商店將 NetGuard 移除,因此當您安裝 Xposed 框架時,NetGuard 將不被支援。
+ 隱私權政策
+ 雖然我們已花費許多心力維護及開發 NetGuard,但我們無法保證 NetGuard 能在每種裝置上正常運作。
+ 我同意
+ 我不同意
+ NetGuard 需要您的協助。請點選購買 Pro 版本,使這個專案能繼續開發下去。
+ 正在運行的服務
+ 一般通知
+ 存取通知
+ 搜尋 app
+ 過濾 apps
+ 顯示使用者 apps
+ 顯示系統 apps
+ 顯示不使用網際網路的 apps
+ 顯示已停用的 apps
+ 排序 apps
+ 依名稱排序
+ 依 uid 排序
+ 依資料用量排序
+ 顯示記錄
+ 設定
+ 邀請
+ 圖例
+ 支援
+ 關於
+ 其他 apps
+ 其他
+ 允許
+ 已封鎖
+ 線上更新
+ 重新整理
+ 顯示名稱
+ 顯示組織
+ PCAP 已啟用
+ PCAP 匯出
+ 清除
+ 匯出
+ 重置
+ 新增
+ 刪除
+ 清理
+ 協定
+ 來源埠
+ 目的網址
+ 目的埠
+ 目的 app
+ 若為外部伺服器請選 \"nobody\"
+ 預設 (白名單/黑名單)
+ 封鎖 Wi-Fi
+ 封鎖行動數據
+ 當螢幕開啟時允許使用 Wi-Fi
+ 當螢幕開啟時允許使用行動數據
+ 封鎖漫遊
+ 選項
+ 主題:%1$s
+ 使用深色主題
+ 有新安裝動作時通知
+ 套用 \"當螢幕亮起\" 規則
+ 在 %1$s 分鐘後自動啟用
+ 延遲 %1$s 分鐘關閉螢幕
+ 檢查更新
+ 網路選項
+ 子網路路由
+ 允許網路共用
+ 允許 LAN 存取
+ 啟用 IPv6 流量
+ 家用 Wi-Fi 網路:%1$s
+ 處理計量型 Wi-Fi 網路
+ 將 2G 視為非計量型網路
+ 將 3G 視為非計量型網路
+ 將 LTE 視為非計量型網路
+ 忽略國際漫遊
+ 忽略歐盟 (EU) 漫遊
+ 在通話期間停用
+ 全面封鎖 Wi-Fi
+ 全面封鎖行動數據
+ 每當連線改變時均重新載入
+ 進階選項
+ 管理系統 apps
+ 記錄網際網路存取
+ 當出現網際網路存取時通知
+ 過濾流量
+ 過濾 UDP 流量
+ 重載後無縫切換 VPN
+ 重新載入後關閉連線
+ 全面封鎖網路流量
+ 追蹤網路用量
+ 重置網路用量記錄
+ 顯示已解析的網域名稱
+ 封鎖網域名稱
+ DNS 回應碼:%s
+ 埠轉接
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ 驗證於:%s
+ DNS TTL 最小值:%s s
+ 使用 SOCKS5 代理
+ SOCKS5 網址:%s
+ SOCKS5 連接埠:%s
+ SOCKS5 帳號:%s
+ SOCKS5 密碼:%s
+ PCAP 記錄大小:%s B
+ PCAP 最大檔案大小:%s MB
+ 監控:每 %s 分鐘
+ 網路速度通知
+ 顯示網路速度通知
+ 顯示用量最高的 apps
+ 取樣間隔:%s ms
+ 取樣數:%s s
+ 備份
+ 匯出設定
+ 匯入設定
+ 匯入 hosts 檔
+ 匯入 hosts 檔 (附加)
+ Hosts 檔下載 URL
+ 下載 hosts 檔
+ 技術資訊
+ 一般
+ 網路
+ 訂閱
+ 顯示狀態列通知,並可直接修改新安裝 apps 的配置 (Pro 版功能)
+ 透過小工具停用 NetGuard 後,在選定的分鐘數後自動啟用 (輸入 0 停用此選項)
+ 在關閉螢幕後,在選定的分鐘數後啟用 \"保持螢幕開啟規則\" (輸入 0 停用此選項)
+ 每日檢查 GitHub 上的新版本二次
+ 依 Android 版本而定,網路共用 (tethering) 或許可用,或許不可用。共用流量將無法過濾。
+ 啟用子網路路由;也許能啟用 Wi-Fi 通話,但也有可能會觸發 Android 當中的臭蟲,導致耗電量增加。
+ 允許 apps 連接到 LAN 網址,例如 10.0.0.0/8、172.16.0.0/12 以及 192.168.0.0/16
+ 將 IPv6 流量路由至 NetGuard,使流量能選擇性地被允許或封鎖
+ 僅將 Wi-Fi 網路規則套用到選定的網路 (對其他 Wi-Fi 網路套用行動網路規則)
+ 套用行動網路規則到計量型 (付費、共用) Wi-Fi 網路
+ 套用 Wi-Fi 網路規則到 2G 數據連線
+ 套用 Wi-Fi 網路規則到 3G 數據連線
+ 套用 Wi-Fi 網路規則到 LTE 數據連線
+ 當 SIM 卡與行動網路的國家不相同時不要套用漫遊規則
+ 當 SIM 卡與行動網路屬於歐盟 (EU) 國家時,不要套用漫遊規則 (即配合歐盟取消境內收取漫遊費的 roam like at home 新政策)。
+ 在接聽或撥打電話時停用 NetGuard。這可以解決 IP/Wi-Fi 網路電話的通話問題。
+ 為系統 apps 程式定義規則 (專家用)
+ 記錄 apps 存取網際網路的嘗試。這可能會導致額外的耗電量。
+ 當某個 app 試圖存取新的網際網路位址時顯示狀態列通知 (當過濾停用時,只有被封鎖的網際網路存取嘗試,才會顯示通知)
+ 過濾經由 VPN 通道離開的 IP 封包。這可能會導致額外的耗電量。
+ 追蹤每個 app 與網址所傳送與接收的 bytes 數。這可能會導致額外的耗電量。
+ 回應設定好的 DNS 回應碼 (R-code) 以封鎖網域名稱。當無法使用 hosts 檔時,該選項停用。
+ 預設值是 3 (NXDOMAIN),意思是 “不存在的網域”。
+ 用於驗證埠號 443 (https) 網際網路連線的網域名稱。
+ 僅 TCP 流量會被送到代理伺服器
+ 定時檢查 NetGuard 是否仍在運行 (輸入 0 停用此選項)。這可能導致額外的耗電量。
+ 在狀態欄通知列上顯示網路速度圖
+ 您確定?
+ 執行規則
+ 已允許 %1$d,已封鎖 %2$d
+ 已允許 %1$d,已封鎖 %2$d,%3$d hosts
+ 等待事件
+ NetGuard 已停用,請透過上方開關切換成啟用 NetGuard
+ NetGuard 已停用,很可能是使用其他具 VPN 功能的 app 所致
+ 已安裝 \'%1$s\'
+ 已經安裝了
+ %1$s 試圖存取網際網路
+ 試圖存取網際網路
+ 動作完成
+ NetGuard 使用本地端 VPN 來過濾網際網路流量。
+因此,請在下一個對話方塊允許 VPN 連線。
+您的網際網路流量不會被送到遠端的 VPN 伺服器。
+ NetGuard 無法在開機時自動執行。這很可能是您所用的 Android 版本中的臭蟲所致。
+ 發生未預期的錯誤:\'%s\'
+ Android 拒絕啟動 VPN 服務。這很可能是您所用的 Android 版本中的臭蟲所致。
+ 請試試看 NetGuard
+ 捐款代表你同意terms & conditions
+ 如果您在下一個對話方塊無法按下 OK,很可能有其他 app (藍光過濾器) 在操控您的螢幕。
+ ± %1$.3f▲ %2$.3f▼ MB/日
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ 為使結果一致,應將 NetGuard 的 Android 電池最佳化選項停用
+\n\n請在下一個對話方塊中,在上方選擇 \"所有應用程式\",然後點選清單中的 NetGuard 並選擇 \"不要最佳化\" 並按下 \"完成\"
+ 為使結果一致,應將 NetGuard 的 Android 數據節省選項停用
+\n\n請在下一個對話方塊中,啟用 \"背景數據\" 以及 \"數據用量不受限\"
+ 使用過濾功能將導致 Android 系統把數據用量與耗電量歸在 NetGuard 底下 -- 即 Android 會以為是 NetGuard 耗用這些數據用量及耗電量,而非那些被過濾的 apps 所致。
+ Android 4 需啟用過濾
+ 流量記錄已停用,請用上方的切換開關啟用記錄。流量記錄可能會導致額外的耗電量。
+ 這將使所有規則和狀態被重置為預設值
+ 這將會刪除不含允許/封鎖規則的存取嘗試記錄。
+ 最近匯入:%s
+ 下載中\n%1s
+ Hosts 檔已下載
+ 最近下載:%s
+ 開始從 %1$s 埠 %2$d 轉送至 \'%5$s\' 的 %3$s:%4$d?
+ 停止轉送 %1$s 埠 %2$d?
+ 此為計量型網路
+ 無網際網路連線
+ NetGuard 正在忙
+ 有更新版本,請點選下載
+ 您可以點選 app 旁邊的圖示以允許 (綠色) 或禁止 (紅色) app 存取 Wi-Fi 或行動網路
+ 如果您安裝 NetGuard 是為了保護您的隱私,那麼您對 FairEmail 也許會感興趣,那是一種開原的、對隱私友善的 email app。
+ 預設允許存取網際網路 (黑名單模式),這可以在設置中更改
+ 收到的 (推送) 訊息通常由系統元件 Play 服務所處理,那預設允許存取網際網路
+ 您可在進階選項中啟用所有 (包含系統) apps 之管理
+ 請具體描述問題及問題發生的時間:
+ VPN 連接已取消\n您是否把另一個 VPN 連線配置為「永遠連線的 VPN」?
+ 若您在執行 NetGuard 時關機,當您重新開機後,NetGuard 將會自動執行。
+ 此功能無法在這個版本的 Android 上執行。
+ 另一個 VPN 連線被設定成 \"永遠連線的 VPN\"
+ 在 Android 的 VPN 設定中關閉 \"永遠連線的 VPN\" 以使用 NetGuard 的過濾模式
+ 在 Android 的網路設定中關閉 “Private DNS” 以使用 NetGuard 的過濾模式。
+ 網路流量已全面封鎖
+ 已允許非計量型網路流量
+ 已封鎖非計量型網路流量
+ 並未套用非計量型規則
+ 已允許計量型網路流量
+ 已封鎖計量型網路流量
+ 並未套用計量型規則
+ 已允許網址
+ 已封鎖網址
+ 當螢幕開啟時允許
+ 漫遊時封鎖
+ 一般來說,Wi-Fi 連線可被視為非計量型網路,而行動數據連線可被視為計量型網路。
+ 沒有網際網路權限
+ 已停用
+ 您所收到的訊息是由 Google Play 服務所接收,而非本 app ,因此無法由本 app 封鎖。
+ 檔案下載是由下載管理員所完成,而非透過本 app,因此,您無法藉由封鎖本 app 來阻止檔案下載。
+ 套用規則與狀態
+ 狀態
+ 在螢幕開啟時啟用 Wi-fi
+ 在螢幕開啟時啟用行動數據
+ R
+ 漫遊時阻擋
+ 在全面封鎖模式中允許
+ 過濾器相關
+ 存取嘗試
+ 存取規則會凌駕其他規則
+ 選項
+ 通知網際網路存取嘗試
+ 記錄或過濾功能未啟用
+ 記錄與過濾功能已啟用
+ 配置
+ 僅針對被封鎖的網址啟用記錄功能
+ 啟用過濾功能,即使是被允許的網址,亦記錄下來
+ 針對新記錄下來的網址啟用存取通知
+ 這些設定為全域設定,將套用到所有 apps
+ 過濾功能還需要您允許或封鎖個別網址
+ 啟用記錄 (耗電較少) 或過濾 (耗電較多) 也許會增加耗電量,且會影響網路速度
+ 評分
+ 允許
+ 封鎖
+ 允許 Wi-Fi
+ 封鎖 Wi-Fi
+ 允許行動數據
+ 封鎖行動數據
+ 根
+ 媒體伺服器
+ nobody
+ 不再詢問
+ Whois %1$s
+ 埠 %1$d
+ 複製
+ Pro 版功能
+ 下列為 Pro 版所提供的功能
+ 檢視被封鎖的流量記錄
+ 過濾網路流量
+ 新 app 通知
+ 網路速度圖通知
+ 外觀 (主題、顏色)
+ 以上為 Pro 版功能
+ 支持本 app 開發
+ 購買
+ 啟用
+ 無法使用
+ 點選標題以獲得更多資訊
+ 挑戰
+ 回應
+ 這是專業 (PRO) 版功能
+ 月付訂閱費 1 至 2 歐元(包含當地稅賦)將啟用所有 Pro 版功能。
+您可以在 Google Play 商店 app 當中的「訂閱」頁籤中取消或管理訂閱。
+
+ - 藍綠/橙
+ - 藍/橙
+ - 紫/紅
+ - 琥珀/藍
+ - 橙/灰
+ - 綠
+
+
+ - UDP
+ - TCP
+
+
diff --git a/NetGuard/app/src/main/res/values/colors.xml b/NetGuard/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..92aa35e
--- /dev/null
+++ b/NetGuard/app/src/main/res/values/colors.xml
@@ -0,0 +1,45 @@
+
+
+
+
+ #009688
+ #00796B
+ #FF5722
+ #009688
+ #FF5722
+
+ #2196F3
+ #1976D2
+ #FF5722
+ #2196F3
+ #FF5722
+
+ #9C27B0
+ #7B1FA2
+ #FF5252
+ #9C27B0
+ #FF5252
+
+ #FFC107
+ #FFA000
+ #448AFF
+ #448AFF
+ #FFC107
+
+ #FF5722
+ #E64A19
+ #607D8B
+ #607D8B
+ #FF5722
+
+ #4CAF50
+ #388E3C
+ #8BC34A
+ #8BC34A
+ #F44336
+
+ #FF0000
+ #0000FF
+
+ #AAAAAA
+
diff --git a/NetGuard/app/src/main/res/values/dimens.xml b/NetGuard/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..6ad9f7e
--- /dev/null
+++ b/NetGuard/app/src/main/res/values/dimens.xml
@@ -0,0 +1,4 @@
+
+ 0dp
+ 0dp
+
diff --git a/NetGuard/app/src/main/res/values/ic_launcher_background.xml b/NetGuard/app/src/main/res/values/ic_launcher_background.xml
new file mode 100644
index 0000000..c5d5899
--- /dev/null
+++ b/NetGuard/app/src/main/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #FFFFFF
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/values/strings.xml b/NetGuard/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..e8d46d3
--- /dev/null
+++ b/NetGuard/app/src/main/res/values/strings.xml
@@ -0,0 +1,362 @@
+
+ NetGuard
+ NetGuard provides simple and advanced ways to block access to the internet - no root required. Apps and addresses can individually be allowed or denied access to your Wi-Fi and/or mobile connection.
+ Copyright \u00A9 2015–2022 by M. Bokhorst (M66B)
+ NetGuard requires Android 5.1 or later
+ Xposed causes too many crashes, which might result in NetGuard being removed from the Google Play Store, therefore NetGuard isn\'t supported while Xposed is installed
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR \'\'AS IS\'\' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Privacy policy
+ Great care has been taken to develop and test NetGuard, however it is impossible to guarantee NetGuard will work correctly on every device.
+ I agree
+ I disagree
+ NetGuard needs your help. Tap to purchase pro features to keep the project going.
+
+ Running services
+ General notifications
+ Access notifications
+
+ Search for app
+ Filter apps
+ Show user apps
+ Show system apps
+ Show apps without internet
+ Show disabled apps
+ Sort apps
+ Sort by name
+ Sort by uid
+ Sort by data usage
+ Show log
+ Settings
+ Invite
+ Legend
+ Support
+ About
+ Other apps
+
+ UDP
+ TCP
+ Other
+ Allowed
+ Blocked
+ Live updates
+ Refresh
+ Show names
+ Show organization
+ PCAP enabled
+ PCAP export
+ Clear
+ Export
+ Reset
+
+ Add
+ Delete
+
+ Cleanup
+
+ Protocol
+ Source port
+ Destination address
+ Destination port
+ Destination app
+ For an external server select \'nobody\'
+
+ Defaults (white/blacklist)
+ Block Wi-Fi
+ Block mobile
+ Allow Wi-Fi when screen on
+ Allow mobile when screen on
+ Block roaming
+
+ Options
+ Theme: %1$s
+ Use dark theme
+ Notify on new install
+ Apply \'when screen on\' rules
+ Auto enable after %1$s minutes
+ Delay screen off %1$s minutes
+ Check for updates
+
+ Network options
+ Subnet routing
+ Allow tethering
+ Allow LAN access
+ Enable IPv6 traffic
+ Wi-Fi home networks: %1$s
+ Handle metered Wi-Fi networks
+ Consider 2G unmetered
+ Consider 3G unmetered
+ Consider LTE unmetered
+ Ignore national roaming
+ Ignore EU roaming
+ Disable on call
+ Lockdown Wi-Fi
+ Lockdown mobile
+ Reload on every connectivity change
+
+ Advanced options
+ Manage system apps
+ Log internet access
+ Notify on internet access
+ Filter traffic
+ Filter UDP traffic
+ Seamless VPN handover on reload
+ Close connections on reload
+ Lockdown traffic
+ Track network usage
+ Reset network usage
+ Show resolved domain names
+ Block domain names
+ DNS response code: %s
+ Port forwarding
+ VPN IPv4: %s
+ VPN IPv6: %s
+ VPN DNS: %s
+ Validate at: %s
+ Minimum DNS TTL: %s s
+ Use SOCKS5 proxy
+ SOCKS5 address: %s
+ SOCKS5 port: %s
+ SOCKS5 username: %s
+ SOCKS5 password: %s
+ PCAP record size: %s B
+ PCAP max. file size: %s MB
+ Watchdog: every %s minutes
+
+ Speed notification
+ Show speed notification
+ Show top apps
+ Sample interval: %s ms
+ Number of samples: %s s
+
+ Backup
+ Export settings
+ Import settings
+ Import hosts file
+ Import hosts file (append)
+ Hosts file download URL
+ Download hosts file
+
+ Technical information
+ General
+ Networks
+ Subscriptions
+
+ Show status bar notification to directly configure newly installed apps (pro feature)
+ After disabling using the widget, automatically enable NetGuard again after the selected number of minutes (enter zero to disable this option)
+ After turning the screen off, keep screen on rules active for the selected number of minutes (enter zero to disable this option)
+ Check for new releases on GitHub twice daily
+
+ Depending on the Android version, tethering may work or may not work. Tethered traffic cannot be filtered.
+ Enable subnet routing; might enable Wi-Fi calling, but might also trigger bugs in Android and increase battery usage
+ Allow apps to connect to local area network addresses, like 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16
+ Route IP version 6 traffic to NetGuard so it can selectively be allowed or blocked
+ Apply Wi-Fi network rules for selected network only (apply mobile network rules for other Wi-Fi networks)
+ Apply mobile network rules to metered (paid, tethered) Wi-Fi networks
+ Apply Wi-Fi network rules for 2G data connections
+ Apply Wi-Fi network rules for 3G data connections
+ Apply Wi-Fi network rules for LTE data connections
+ Do not apply roaming rules when the SIM and mobile network country are the same
+ Do not apply roaming rules when the SIM and mobile network country are within the EU (roam like at home)
+ Disable NetGuard on incoming or outgoing telephone call. This can be used to work around IP/Wi-Fi calling problems.
+
+ Define rules for system apps (for experts)
+ Log attempts to access the internet for apps. This might result in extra battery usage.
+ Show a status bar notification when an app attempts to access a new internet address (when filtering is disabled, only blocked internet access attempts will be notified)
+ Filter IP packets going out of the VPN tunnel. This might result in extra battery usage.
+ Track the number of bytes sent and received for each app and address. This might result in extra battery usage.
+ Respond with the configured DNS response code for blocked domain names. This switch is disabled when no hosts file is available.
+ The default value is 3 (NXDOMAIN), which means \'non-existent domain\'.
+ Domain name used to validate the internet connection at port 443 (https).
+ Only TCP traffic will be sent to the proxy server
+ Periodically check if NetGuard is still running (enter zero to disable this option). This might result in extra battery usage.
+
+ Show network speed graph in status bar notification
+
+
+
+ Are you sure?
+ Enforcing rules
+ %1$d allowed, %2$d blocked
+ %1$d allowed, %2$d blocked, %3$d hosts
+ Waiting for event
+ NetGuard is disabled, use the switch above to enable NetGuard
+ NetGuard has been disabled, likely by using another VPN based app
+ \'%1$s\' installed
+ Has been installed
+ %1$s attempted internet access
+ Attempted internet access
+ Action completed
+ NetGuard uses a local VPN to filter internet traffic.
+For this reason, please allow a VPN connection in the next dialog.
+Your internet traffic is not being sent to a remote VPN server.
+ NetGuard could not start automatically. This is likely because of a bug in your Android version.
+ An unexpected error has occurred: \'%s\'
+ Android refused to start the VPN service at this moment. This is likely because of a bug in your Android version.
+ Try NetGuard
+ By donating you agree to the terms & conditions
+ If you cannot press OK in the next dialog, another (screen dimming) app is likely manipulating the screen.
+ ± %1$.3f▲ %2$.3f▼ MB/day
+ %7.3f KB/s
+ %7.3f MB/s
+ %1$7.3f▲ %2$7.3f▼ KB
+ %1$7.3f▲ %2$7.3f▼ MB
+ %1$7.3f▲ %2$7.3f▼ GB
+ %dx
+ For consistent results, the Android battery optimizations should be disabled for NetGuard.
+\n\nIn the next dialog, select \"All apps\" at the top, tap on NetGuard in the list and select and confirm \"Don\'t optimize\".
+ For consistent results, the Android data saving options should be disabled for NetGuard
+\n\nIn the next dialog, enable the options \"Background data\" and \"Unrestricted data usage\"
+ Using filtering will cause Android to attribute data and power usage to NetGuard - Android assumes the data and power are being used by NetGuard, rather than the original apps
+ Android 4 requires filtering to be enabled
+ Traffic logging is disabled, use the switch above to enable logging. Traffic logging might result in extra battery usage.
+ This will reset the rules and conditions to their default values
+ This will delete access attempt log lines without allow/block rules
+ Last import: %s
+ Downloading\n%1s
+ Hosts file downloaded
+ Last download: %s
+ Start forwarding from %1$s port %2$d to %3$s:%4$d of \'%5$s\'?
+ Stop forwarding of %1$s port %2$d?
+ Network is metered
+ No active internet connection
+ NetGuard is busy
+ Update available, tap to download
+ You can allow (greenish) or deny (reddish) Wi-Fi or mobile internet access by tapping on the icons next to an app
+ If you installed NetGuard to protect your privacy, you might be interested in FairEmail , an open source, privacy friendly email app, too
+ Internet access is allowed by default (blacklist mode), this can be changed in the settings
+ Incoming (push) messages are mostly handled by the system component Play services, which is allowed internet access by default
+ Managing all (system) apps can be enabled in the settings
+ Please describe the problem and indicate the time of the problem:
+ VPN connection cancelled\nDid you configure another VPN to be an always-on VPN?
+ Powering down your device with NetGuard enabled, will automatically start NetGuard on powering up your device
+ This feature is not available on this Android version
+ Another VPN is set as Always-on VPN
+ Turn off "Block connections without VPN" in Android VPN settings to use NetGuard in filtering mode
+ Turn off "Private DNS" in Android network settings to use NetGuard in filtering mode
+
+ Traffic is locked down
+ Unmetered traffic is allowed
+ Unmetered traffic is blocked
+ Unmetered rules are not applied
+ Metered traffic is allowed
+ Metered traffic is blocked
+ Metered rules are not applied
+ Address is allowed
+ Address is blocked
+ Allow when screen is on
+ Block when roaming
+ By default a Wi-Fi connection is considered to be unmetered and a mobile connection to be metered
+
+ has no internet permission
+ is disabled
+ Incoming messages are received by Google Play services and not by this app and can therefore not be blocked by blocking this app
+ Downloads are performed by the download manager and not by this app and can therefore not be blocked by blocking this app
+ Apply rules and conditions
+ Conditions
+ Allow Wi-Fi when screen is on
+ Allow mobile when screen is on
+ R
+ Block when roaming
+ Allow in lockdown mode
+ Filter related
+ Access attempts
+ Access rules take precedence over other rules
+ Options
+ Notify internet access attempts
+
+ Logging or filtering is not enabled
+ Logging and filtering are enabled
+ Configure
+
+ Enable logging of blocked addresses only
+ Enable filtering to log allowed addresses too
+ Enable access notifications for newly logged addresses
+ These settings are global settings that apply to all apps
+ Filtering is also required to allow or block individual addresses
+ Enabling logging (less) or filtering (more) might increase battery usage and might affect network speed
+
+ Rate
+ Allow
+ Block
+ Allow Wi-Fi
+ Block Wi-Fi
+ Allow mobile
+ Block mobile
+ root
+ mediaserver
+ GPS daemon
+ DNS daemon
+ nobody
+ Don\'t ask again
+
+ Whois %1$s
+ Port %1$d
+ Copy
+
+ Pro features
+ The following pro features are available:
+ View blocked traffic log
+ Filter network traffic
+ New app notifications
+ Network speed graph notification
+ Appearance (theme, colors)
+ All above pro features
+ Support development
+ Buy
+ Enabled
+ Unavailable
+ Tap on a title for more information
+ Challenge
+ Response
+ This is a pro feature
+
+ A monthly subscriptions of 1 or 2 euros (excluding local taxes) will activate all pro features.
+ You can cancel or manage a subscription via the subscriptions tab in the Play store app.
+
+
+
+ - teal/orange
+ - blue/orange
+ - purple/red
+ - amber/blue
+ - orange/grey
+ - green
+
+
+
+ - teal
+ - blue
+ - purple
+ - amber
+ - orange
+ - green
+
+
+
+ - Verbose
+ - Debug
+ - Info
+ - Warning
+ - Error
+
+
+
+ - 2
+ - 3
+ - 4
+ - 5
+ - 6
+
+
+
+ - UDP
+ - TCP
+
+
+
+ - 17
+ - 6
+
+
+ ef46f813d2c8a064d72c936b9b96d1cccc989378
+
diff --git a/NetGuard/app/src/main/res/values/styles.xml b/NetGuard/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..2732b1e
--- /dev/null
+++ b/NetGuard/app/src/main/res/values/styles.xml
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/xml-v14/preferences.xml b/NetGuard/app/src/main/res/xml-v14/preferences.xml
new file mode 100644
index 0000000..606e385
--- /dev/null
+++ b/NetGuard/app/src/main/res/xml-v14/preferences.xml
@@ -0,0 +1,381 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/xml-v21/preferences.xml b/NetGuard/app/src/main/res/xml-v21/preferences.xml
new file mode 100644
index 0000000..5ababb1
--- /dev/null
+++ b/NetGuard/app/src/main/res/xml-v21/preferences.xml
@@ -0,0 +1,381 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/xml/network_security_config.xml b/NetGuard/app/src/main/res/xml/network_security_config.xml
new file mode 100644
index 0000000..05c4256
--- /dev/null
+++ b/NetGuard/app/src/main/res/xml/network_security_config.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/xml/predefined.xml b/NetGuard/app/src/main/res/xml/predefined.xml
new file mode 100644
index 0000000..2a90f6a
--- /dev/null
+++ b/NetGuard/app/src/main/res/xml/predefined.xml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/xml/shortcuts.xml b/NetGuard/app/src/main/res/xml/shortcuts.xml
new file mode 100644
index 0000000..9b9cc53
--- /dev/null
+++ b/NetGuard/app/src/main/res/xml/shortcuts.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NetGuard/app/src/main/res/xml/widgetlockdown.xml b/NetGuard/app/src/main/res/xml/widgetlockdown.xml
new file mode 100644
index 0000000..2301200
--- /dev/null
+++ b/NetGuard/app/src/main/res/xml/widgetlockdown.xml
@@ -0,0 +1,8 @@
+
+
\ No newline at end of file
diff --git a/NetGuard/app/src/main/res/xml/widgetmain.xml b/NetGuard/app/src/main/res/xml/widgetmain.xml
new file mode 100644
index 0000000..87598a0
--- /dev/null
+++ b/NetGuard/app/src/main/res/xml/widgetmain.xml
@@ -0,0 +1,8 @@
+
+
\ No newline at end of file
diff --git a/NetGuard/build.gradle b/NetGuard/build.gradle
new file mode 100644
index 0000000..aaabb1d
--- /dev/null
+++ b/NetGuard/build.gradle
@@ -0,0 +1,42 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ google()
+ jcenter()
+ }
+ dependencies {
+ // http://tools.android.com/tech-docs/new-build-system/gradle-experimental
+ // https://bintray.com/android/android-tools/com.android.tools.build.gradle-experimental/view
+ // https://bintray.com/android/android-tools/com.google.gms.google-services/view
+ classpath 'com.android.tools.build:gradle:7.3.1'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ mavenCentral()
+ maven {
+ url 'https://maven.google.com'
+ }
+ }
+}
+
+subprojects {
+ project.configurations.all {
+ resolutionStrategy.eachDependency { details ->
+ if (details.requested.group == 'com.android.support'
+ && !details.requested.name.contains('multidex')) {
+ details.useVersion "27.1.1"
+ }
+ }
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/NetGuard/gradle.properties b/NetGuard/gradle.properties
new file mode 100644
index 0000000..09e5d31
--- /dev/null
+++ b/NetGuard/gradle.properties
@@ -0,0 +1,24 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+org.gradle.jvmargs=-Xmx500m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+
+# http://android-developers.googleblog.com/2017/08/next-generation-dex-compiler-now-in.html
+android.enableD8=true
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/NetGuard/gradle/wrapper/gradle-wrapper.jar b/NetGuard/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
Binary files /dev/null and b/NetGuard/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/NetGuard/gradle/wrapper/gradle-wrapper.properties b/NetGuard/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..a0fd81f
--- /dev/null
+++ b/NetGuard/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Thu Dec 03 08:28:04 CET 2020
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
diff --git a/NetGuard/gradlew b/NetGuard/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/NetGuard/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/NetGuard/gradlew.bat b/NetGuard/gradlew.bat
new file mode 100644
index 0000000..aec9973
--- /dev/null
+++ b/NetGuard/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/NetGuard/playstore/PLAY-es.md b/NetGuard/playstore/PLAY-es.md
new file mode 100644
index 0000000..97df9f0
--- /dev/null
+++ b/NetGuard/playstore/PLAY-es.md
@@ -0,0 +1,63 @@
+Play store
+==========
+
+Title
+-----
+NetGuard - cortafuegos sin root
+
+
+Short description
+-----------------
+Una forma simple de bloquear el acceso a Internet por aplicación
+
+
+Long description
+----------------
+NetGuard proporciona formas simples y avanzadas de bloquear el acceso a Internet - No requiere root.
+
+Las aplicaciones y direcciones, permiten o denegan individualmente el acceso a tu Wi-Fi y/o conexión móvil.
+
+Bloquear el acceso a Internet ayuda a:
+
+• reducir tu uso de datos
+• ahorrar tu batería
+• incrementar tu privacidad
+
+Características:
+
+• Simple de usar
+• No requiere root
+• 100% código abierto
+• No calling home
+• Sin seguimiento o análisis integrado
+• Desarrollado y soportado activamente
+• Soporta Android 5.0 o superior
+• Soporta IPv4/IPv6, TCP/UDP
+• Soporta anclaje a red (tethering)
+• Soporta múltiples dispositivos de usuarios
+• (Opcional) permite con la pantalla encendida
+• (Opcional) bloquea con roaming
+• (Opcional) bloquea aplicaciones del sistema
+• (Opcional) notifica cuando una aplicación accede a Internet
+• (Opcional) registra el uso de la red por aplicación por dirección
+• Apariencia material design con tema claro y oscuro
+
+Características de pago (PRO):
+
+• Registra todo el tráfico saliente; busca y filtra intentos de acceso; exporta archivos PCAP para analizar el tráfico
+• Permite/bloquea direcciones individuales por aplicación
+• Nueva aplicación de notificaciones; configura NetGuard directamente en la notificación
+• Muestra un gráfico de velocidad de red en una notificación en la barra de estado
+• Selecciona entre 5 temas adicionales en versiones claras y oscuras
+
+No existe otro cortafuegos sin-root que ofrezca todas estas características.
+
+Si tienes preguntas o problemas, puedes enviar un correo electrónico a marcel+netguard@faircode.eu
+
+Si te gusta ayudar a personas con menor fluidez de Inglés, puedes ayudar a traducir NetGuard en tu idioma: https://crowdin.com/project/netguard/
+
+Si te gusta probar las nuevas características, puedes participar en el programa de prueba: https://play.google.com/apps/testing/eu.faircode.netguard
+
+Todos los permisos requeridos se detallan aquí: https://github.com/M66B/NetGuard/blob/master/FAQ.md#FAQ42
+
+El código fuente está disponible aquí: https://github.com/M66B/NetGuard
diff --git a/NetGuard/playstore/PLAY-hi.md b/NetGuard/playstore/PLAY-hi.md
new file mode 100644
index 0000000..d7717cc
--- /dev/null
+++ b/NetGuard/playstore/PLAY-hi.md
@@ -0,0 +1,63 @@
+Play store
+==========
+
+Title
+-----
+NetGuard - कोई रूट फ़ायरवॉल
+
+
+Short description
+-----------------
+आवेदन के अनुसार इंटरनेट के लिए उपयोग ब्लॉक करने के लिए एक आसान तरीका
+
+
+Long description
+----------------
+कोई जड़ आवश्यक - NetGuard इंटरनेट के लिए उपयोग ब्लॉक करने के लिए सरल और उन्नत तरीके सुझाता है।
+
+आवेदन और पतों को व्यक्तिगत रूप से अनुमति या अपने वाई-फाई और / या मोबाइल कनेक्शन के लिए उपयोग से इनकार किया जा सकता है।
+
+इंटरनेट का उपयोग रोकने में मदद कर सकते हैं:
+
+• अपने डेटा के उपयोग को कम
+• अपनी बैटरी बचाने
+• आपकी गोपनीयता वृद्धि
+
+विशेषताएं:
+
+• सरल का उपयोग करने के लिए
+• आवश्यक नहीं जड़
+• 100% खुला स्रोत
+• कोई बुला घर
+• कोई ट्रैकिंग या एनालिटिक्स सक्रिय रूप से विकसित और समर्थित
+• एंड्रॉयड 5.0 और
+• बाद में समर्थित
+• आईपीवी 4 / IPv6 टीसीपी / यूडीपी समर्थित
+• Tethering समर्थित
+• एकाधिक डिवाइस उपयोगकर्ताओं समर्थित
+• वैकल्पिक रूप से
+• वैकल्पिक खंड पर जब स्क्रीन अनुमति देते हैं जब घूम
+• वैकल्पिक ब्लॉक सिस्टम अनुप्रयोगों वैकल्पिक
+• सूचित करें जब एक आवेदन प्रकाश और अंधेरे विषय के साथ प्रति पते
+• सामग्री डिजाइन विषय आवेदन के अनुसार इंटरनेट
+• वैकल्पिक रूप से रिकॉर्ड नेटवर्क उपयोग पहुँचता
+
+प्रो सुविधाएँ:
+
+• सभी निवर्तमान यातायात लॉग; खोज और उपयोग प्रयास को फिल्टर; यातायात का विश्लेषण करने के लिए निर्यात PCAP फ़ाइलों
+• अनुमति दें / ब्लॉक आवेदन के अनुसार अलग-अलग पतों
+• नई आवेदन सूचनाएं; एक स्थिति पट्टी अधिसूचना में अधिसूचना
+• प्रदर्शन नेटवर्क की गति ग्राफ से सीधे NetGuard कॉन्फ़िगर
+• दोनों प्रकाश और अंधेरे संस्करण में पांच अतिरिक्त विषयों में से चयन करें
+
+वहाँ कोई अन्य कोई रूट इन सभी सुविधाओं की पेशकश फ़ायरवॉल है।
+
+आप एक प्रश्न या समस्या है, तो आप marcel+netguard@faircode.eu~~V को एक ई-मेल भेज सकते हैं
+
+आप लोगों को अंग्रेजी में धाराप्रवाह कम में मदद करना चाहते हैं, तो आप मदद कर सकते हैं अपनी भाषा में अनुवाद कर NetGuard: https://crowdin.com/project/netguard/
+
+आप नई सुविधाओं का परीक्षण करना चाहते हैं, तो आप परीक्षण कार्यक्रम में भाग ले सकते हैं: https://play.google.com/apps/testing/eu.faircode.netguard
+
+सभी आवश्यक अनुमतियों यहाँ वर्णित हैं: https://github.com/M66B/NetGuard/blob/master/FAQ.md#FAQ42
+
+स्रोत कोड यहाँ उपलब्ध है: https://github.com/M66B/NetGuard
diff --git a/NetGuard/playstore/PLAY-ro.md b/NetGuard/playstore/PLAY-ro.md
new file mode 100644
index 0000000..679ed33
--- /dev/null
+++ b/NetGuard/playstore/PLAY-ro.md
@@ -0,0 +1,63 @@
+Play store
+==========
+
+Title
+-----
+NetGuard - firewall fara root
+
+
+Short description
+-----------------
+Un mod simplu de a bloca accesul aplicatiilor la internet
+
+
+Long description
+----------------
+NetGuard ofera modalitati simple si avansate de a bloca accesul la internet, ce nu necesita acces root.
+
+Accesul aplicatiilor la conexiunile Wi-Fi si/sau mobile poate fi permis sau blocat atat la nivel individual cat si la nivel de adresa.
+
+Blocarea accesului la internet poate ajuta la:
+
+• reducerea consumului de date mobile
+• reducerea consumului bateriei
+• protejarea mai buna a intimitatii
+
+Caracteristici:
+
+• Simplu de utilizat
+• Nu necesita acces root
+• 100% software cu sursa deschisa
+• Nu transmite datele nicaieri
+• Nu urmareste activitatea si nici nu o analizeaza
+• Dezvoltare si asistenta continuua
+• Suporta Android 5.0 si ulterior
+• Suporta IPv4/IPv6 TCP/UDP
+• Suporta partajarea conexiunii
+• Suporta utilizatori multiplii
+• Optional permite cand ecranul este pornit
+• Optional blocheaza in roaming
+• Optional blocheaza aplicatiile de sistem
+• Optional notifica la accesarea internetului
+• Optional inregistreaza utilizarea conexiunii per aplicatie si per adresa
+• Design Material cu tema deschisa si inchisa
+
+Caracteristici PRO:
+
+• Jurnal de trafic; cauta si filtreaza lista de accesari; exporta fisiere PCAP pentru analiza traficului
+• Permite/blocheaza accesul per aplicatie si per domeniu
+• Notificare aplicatie noua instalata; configureaza NetGuard direct din notificare
+• Grafic viteza conexiune intr-o notificare
+• Alege din cele 5 teme aditionale atat in versiune deschisa cat si inchisa
+
+Nu există nici un alt firewall, ce nu necesita root, care sa ofere toate aceste caracteristici.
+
+Pentru intrebari sau probleme puteti trimite un email la marcel+netguard@faircode.eu
+
+Daca vrei sa ii ajuti pe cei ce nu vorbesc limba engleza, poti ajuta la traducerea NetGuard in limba ta materna: https://crowdin.com/project/netguard/
+
+Daca doriti sa testati caracteristile in dezvoltare ale aplicatiei, va puteti alatura programului de testare: https://play.google.com/apps/testing/eu.faircode.netguard
+
+Toate permisiunile necesare sunt detaliate aici: https://github.com/M66B/NetGuard/blob/master/FAQ.md#FAQ42
+
+Codul sursa este disponibil aici: https://github.com/M66B/NetGuard
diff --git a/NetGuard/playstore/PLAY-ta.md b/NetGuard/playstore/PLAY-ta.md
new file mode 100644
index 0000000..c2fde89
--- /dev/null
+++ b/NetGuard/playstore/PLAY-ta.md
@@ -0,0 +1,63 @@
+Play store
+==========
+
+Title
+-----
+NetGuard - எந்த ரூட் ஃபயர்வால்
+
+
+Short description
+-----------------
+விண்ணப்ப ஒன்றுக்கு இணைய அணுகலை தடுக்க ஒரு எளிய வழி
+
+
+Long description
+----------------
+எந்த ரூட் தேவை - NetGuard இணைய அணுகலை தடுக்க எளிய மற்றும் மேம்பட்ட வழிகளை வழங்குகிறது.
+
+பயன்பாடுகள் மற்றும் முகவரிகள் தனித்தனியாக அனுமதி அல்லது உங்கள் Wi-Fi மற்றும் / அல்லது மொபைல் இணைப்பு அனுமதி மறுக்கப்பட்டது முடியும்.
+
+இணைய அணுகல் தடுப்பதை உதவ முடியும்:
+
+• உங்கள் தரவு பயன்பாட்டைக் குறைப்பதற்காக
+• உங்கள் பேட்டரி சேமிக்க
+• உங்கள் தனியுரிமை அதிகரிக்க
+
+அம்சங்கள்:
+
+• எளிய
+• இல்லை ரூட் தேவையான
+• 100% திறந்த மூல
+• இல்லை அழைப்பு வீட்டில்
+• இல்லை கண்காணிப்பு அல்லது பகுப்பாய்வு
+• தீவிரமாக அபிவிருத்தி மற்றும் ஆதரவு
+• அண்ட்ராய்டு 5.0 மற்றும் பின்னர் ஆதரவு
+• IPv4 / IPv6 TCP / UDP ஆதரவு
+• இணைப்புமுறை ஆதரவு
+• பல சாதனம் பயனர்கள் ஆதரவு பயன்படுத்த
+• விருப்பமாக
+• விருப்பமாக தொகுதி கணினி பயன்பாடுகள் ஒரு பயன்பாடு ஒளி மற்றும் இருண்ட தீம் முகவரியை
+• பொருள் வடிவமைப்பு தீம் ஒன்றுக்கு பயன்பாடு ஒன்றுக்கு இணைய
+• விருப்பமாக சாதனை நெட்வொர்க் பயன்பாடு அணுகும் போது அறிவிக்குமாறு
+• விருப்பமாக ரோமிங் போது
+• விருப்பமாக தொகுதி போது திரையில் அனுமதிக்க
+
+ப்ரோ அம்சங்கள்:
+
+• அனைத்து வெளிச்செல்லும் போக்குவரத்து பதிவு; தேடல் மற்றும் அணுகல் முயற்சிகள் வடிகட்ட; ஏற்றுமதி PCAP கோப்புகளை போக்குவரத்து / தொகுதி பயன்பாடு ஒன்றுக்கு தனிப்பட்ட முகவரிகள்
+• புதிய விண்ணப்ப அறிவிப்புகளை ஆய்வு செய்ய
+• அனுமதி; ஒரு நிலைப் பட்டி அறிவிப்பை அறிவிப்பு
+• காட்சி நெட்வொர்க் வேகம் வரைபடம் இருந்து நேரடியாக NetGuard கட்டமைக்க
+• ஒளி மற்றும் இருண்ட பதிப்பு இரண்டு ஐந்து கூடுதல் கருப்பொருள்கள் இருந்து தேர்வு
+
+இந்த அம்சங்களை வழங்கும் எந்த வேறு எந்த ரூட் ஃபயர்வால் உள்ளது.
+
+நீங்கள் ஒரு கேள்வி அல்லது பிரச்சனை இருந்தால், நீங்கள் marcel+netguard@faircode.eu~~V ஒரு மின்னஞ்சல் அனுப்ப முடியும்
+
+நீங்கள் ஆங்கிலத்தில் மக்கள் குறைவாக சரளமாக உதவ விரும்பினால், நீங்கள் உங்கள் மொழியில் NetGuard மொழிபெயர்க்க உதவ முடியும்: https://crowdin.com/project/netguard/
+
+நீங்கள் புதிய அம்சங்களை சோதிக்க விரும்பினால், நீங்கள் சோதனை திட்டம் பங்கேற்க முடியும்: https://play.google.com/apps/testing/eu.faircode.netguard
+
+அனைத்து தேவையான அனுமதிகள் இங்கு விவரிக்கப்பட்டுள்ளன: https://github.com/M66B/NetGuard/blob/master/FAQ.md#FAQ42
+
+மூல குறியீடு இங்கே கிடைக்கும்: https://github.com/M66B/NetGuard
diff --git a/NetGuard/playstore/PLAY.md b/NetGuard/playstore/PLAY.md
new file mode 100644
index 0000000..e87649e
--- /dev/null
+++ b/NetGuard/playstore/PLAY.md
@@ -0,0 +1,63 @@
+Play store
+==========
+
+Title
+-----
+NetGuard - no-root firewall
+
+
+Short description
+-----------------
+A simple way to block access to the internet per application
+
+
+Long description
+----------------
+NetGuard provides simple and advanced ways to block access to the internet - no root required.
+
+Applications and addresses can individually be allowed or denied access to your Wi-Fi and/or mobile connection.
+
+Blocking access to the internet can help:
+
+• reduce your data usage
+• save your battery
+• increase your privacy
+
+Features:
+
+• Simple to use
+• No root required
+• 100% open source
+• No calling home
+• No tracking or analytics
+• Actively developed and supported
+• Android 5.0 and later supported
+• IPv4/IPv6 TCP/UDP supported
+• Tethering supported
+• Multiple device users supported
+• Optionally allow when screen on
+• Optionally block when roaming
+• Optionally block system applications
+• Optionally notify when an application accesses the internet
+• Optionally record network usage per application per address
+• Material design theme with light and dark theme
+
+PRO features:
+
+• Log all outgoing traffic; search and filter access attempts; export PCAP files to analyze traffic
+• Allow/block individual addresses per application
+• New application notifications; configure NetGuard directly from the notification
+• Display network speed graph in a status bar notification
+• Select from five additional themes in both light and dark version
+
+There is no other no-root firewall offering all these features.
+
+If you have a question or problem, you can send an e-mail to marcel+netguard@faircode.eu
+
+If you like to help people less fluent in English, you can help translate NetGuard in your language: https://crowdin.com/project/netguard/
+
+If you like to test new features, you can participate in the test program: https://play.google.com/apps/testing/eu.faircode.netguard
+
+All required permissions are described here: https://github.com/M66B/NetGuard/blob/master/FAQ.md#FAQ42
+
+The source code is available here: https://github.com/M66B/NetGuard
diff --git a/NetGuard/playstore/play.png b/NetGuard/playstore/play.png
new file mode 100644
index 0000000..44ee237
Binary files /dev/null and b/NetGuard/playstore/play.png differ
diff --git a/NetGuard/playstore/play.xcf b/NetGuard/playstore/play.xcf
new file mode 100644
index 0000000..ca3b9fc
Binary files /dev/null and b/NetGuard/playstore/play.xcf differ
diff --git a/NetGuard/screenshots/01-main.png b/NetGuard/screenshots/01-main.png
new file mode 100755
index 0000000..9496393
Binary files /dev/null and b/NetGuard/screenshots/01-main.png differ
diff --git a/NetGuard/screenshots/02-main-details.png b/NetGuard/screenshots/02-main-details.png
new file mode 100755
index 0000000..3cd9a6c
Binary files /dev/null and b/NetGuard/screenshots/02-main-details.png differ
diff --git a/NetGuard/screenshots/03-main-access.png b/NetGuard/screenshots/03-main-access.png
new file mode 100755
index 0000000..369306e
Binary files /dev/null and b/NetGuard/screenshots/03-main-access.png differ
diff --git a/NetGuard/screenshots/04-main-legend.png b/NetGuard/screenshots/04-main-legend.png
new file mode 100755
index 0000000..1efafe6
Binary files /dev/null and b/NetGuard/screenshots/04-main-legend.png differ
diff --git a/NetGuard/screenshots/05-main-filter.png b/NetGuard/screenshots/05-main-filter.png
new file mode 100755
index 0000000..b7a5179
Binary files /dev/null and b/NetGuard/screenshots/05-main-filter.png differ
diff --git a/NetGuard/screenshots/06-main-sort.png b/NetGuard/screenshots/06-main-sort.png
new file mode 100755
index 0000000..56cb751
Binary files /dev/null and b/NetGuard/screenshots/06-main-sort.png differ
diff --git a/NetGuard/screenshots/07-main-menu.png b/NetGuard/screenshots/07-main-menu.png
new file mode 100755
index 0000000..49d31c6
Binary files /dev/null and b/NetGuard/screenshots/07-main-menu.png differ
diff --git a/NetGuard/screenshots/08-notifications.png b/NetGuard/screenshots/08-notifications.png
new file mode 100755
index 0000000..cc30f24
Binary files /dev/null and b/NetGuard/screenshots/08-notifications.png differ
diff --git a/NetGuard/screenshots/101-main.png b/NetGuard/screenshots/101-main.png
new file mode 100644
index 0000000..7149f43
Binary files /dev/null and b/NetGuard/screenshots/101-main.png differ
diff --git a/NetGuard/screenshots/102-main-details.png b/NetGuard/screenshots/102-main-details.png
new file mode 100644
index 0000000..182bccd
Binary files /dev/null and b/NetGuard/screenshots/102-main-details.png differ
diff --git a/NetGuard/screenshots/103-main-access.png b/NetGuard/screenshots/103-main-access.png
new file mode 100644
index 0000000..bbb4294
Binary files /dev/null and b/NetGuard/screenshots/103-main-access.png differ
diff --git a/NetGuard/screenshots/104-main-legend.png b/NetGuard/screenshots/104-main-legend.png
new file mode 100644
index 0000000..194ee86
Binary files /dev/null and b/NetGuard/screenshots/104-main-legend.png differ
diff --git a/NetGuard/screenshots/105-main-filter.png b/NetGuard/screenshots/105-main-filter.png
new file mode 100644
index 0000000..3ff1e09
Binary files /dev/null and b/NetGuard/screenshots/105-main-filter.png differ
diff --git a/NetGuard/screenshots/106-main-sort.png b/NetGuard/screenshots/106-main-sort.png
new file mode 100644
index 0000000..e18dda9
Binary files /dev/null and b/NetGuard/screenshots/106-main-sort.png differ
diff --git a/NetGuard/screenshots/107-main-menu.png b/NetGuard/screenshots/107-main-menu.png
new file mode 100644
index 0000000..2a1eb94
Binary files /dev/null and b/NetGuard/screenshots/107-main-menu.png differ
diff --git a/NetGuard/screenshots/108-notifications.png b/NetGuard/screenshots/108-notifications.png
new file mode 100644
index 0000000..a99c914
Binary files /dev/null and b/NetGuard/screenshots/108-notifications.png differ
diff --git a/NetGuard/screenshots/120-traffic-log.png b/NetGuard/screenshots/120-traffic-log.png
new file mode 100644
index 0000000..1277f9a
Binary files /dev/null and b/NetGuard/screenshots/120-traffic-log.png differ
diff --git a/NetGuard/screenshots/121-traffic-filter.png b/NetGuard/screenshots/121-traffic-filter.png
new file mode 100644
index 0000000..3351930
Binary files /dev/null and b/NetGuard/screenshots/121-traffic-filter.png differ
diff --git a/NetGuard/screenshots/122-traffic-menu.png b/NetGuard/screenshots/122-traffic-menu.png
new file mode 100644
index 0000000..e8b64c8
Binary files /dev/null and b/NetGuard/screenshots/122-traffic-menu.png differ
diff --git a/NetGuard/screenshots/123-traffic-popup.png b/NetGuard/screenshots/123-traffic-popup.png
new file mode 100644
index 0000000..8034951
Binary files /dev/null and b/NetGuard/screenshots/123-traffic-popup.png differ
diff --git a/NetGuard/screenshots/130-settings-default.png b/NetGuard/screenshots/130-settings-default.png
new file mode 100644
index 0000000..26d8a86
Binary files /dev/null and b/NetGuard/screenshots/130-settings-default.png differ
diff --git a/NetGuard/screenshots/131-settings-options.png b/NetGuard/screenshots/131-settings-options.png
new file mode 100644
index 0000000..e74ffa7
Binary files /dev/null and b/NetGuard/screenshots/131-settings-options.png differ
diff --git a/NetGuard/screenshots/132-settings-network.png b/NetGuard/screenshots/132-settings-network.png
new file mode 100644
index 0000000..f5d594d
Binary files /dev/null and b/NetGuard/screenshots/132-settings-network.png differ
diff --git a/NetGuard/screenshots/133-settings-advanced.png b/NetGuard/screenshots/133-settings-advanced.png
new file mode 100644
index 0000000..fc2fe7f
Binary files /dev/null and b/NetGuard/screenshots/133-settings-advanced.png differ
diff --git a/NetGuard/screenshots/134-settings-speed.png b/NetGuard/screenshots/134-settings-speed.png
new file mode 100644
index 0000000..532cec0
Binary files /dev/null and b/NetGuard/screenshots/134-settings-speed.png differ
diff --git a/NetGuard/screenshots/135-settings-add-port.png b/NetGuard/screenshots/135-settings-add-port.png
new file mode 100644
index 0000000..2d1afd8
Binary files /dev/null and b/NetGuard/screenshots/135-settings-add-port.png differ
diff --git a/NetGuard/screenshots/136-settings-ports.png b/NetGuard/screenshots/136-settings-ports.png
new file mode 100644
index 0000000..6b86369
Binary files /dev/null and b/NetGuard/screenshots/136-settings-ports.png differ
diff --git a/NetGuard/screenshots/150-theme.png b/NetGuard/screenshots/150-theme.png
new file mode 100644
index 0000000..9696367
Binary files /dev/null and b/NetGuard/screenshots/150-theme.png differ
diff --git a/NetGuard/screenshots/151-theme.png b/NetGuard/screenshots/151-theme.png
new file mode 100644
index 0000000..a15d03d
Binary files /dev/null and b/NetGuard/screenshots/151-theme.png differ
diff --git a/NetGuard/screenshots/152-theme.png b/NetGuard/screenshots/152-theme.png
new file mode 100644
index 0000000..57df133
Binary files /dev/null and b/NetGuard/screenshots/152-theme.png differ
diff --git a/NetGuard/screenshots/153-theme.png b/NetGuard/screenshots/153-theme.png
new file mode 100644
index 0000000..6bc83ac
Binary files /dev/null and b/NetGuard/screenshots/153-theme.png differ
diff --git a/NetGuard/screenshots/154-theme.png b/NetGuard/screenshots/154-theme.png
new file mode 100644
index 0000000..88aff40
Binary files /dev/null and b/NetGuard/screenshots/154-theme.png differ
diff --git a/NetGuard/screenshots/155-theme.png b/NetGuard/screenshots/155-theme.png
new file mode 100644
index 0000000..d5e2990
Binary files /dev/null and b/NetGuard/screenshots/155-theme.png differ
diff --git a/NetGuard/screenshots/156-theme.png b/NetGuard/screenshots/156-theme.png
new file mode 100644
index 0000000..1e6145d
Binary files /dev/null and b/NetGuard/screenshots/156-theme.png differ
diff --git a/NetGuard/screenshots/157-theme.png b/NetGuard/screenshots/157-theme.png
new file mode 100644
index 0000000..c670c11
Binary files /dev/null and b/NetGuard/screenshots/157-theme.png differ
diff --git a/NetGuard/screenshots/158-theme.png b/NetGuard/screenshots/158-theme.png
new file mode 100644
index 0000000..9dc821c
Binary files /dev/null and b/NetGuard/screenshots/158-theme.png differ
diff --git a/NetGuard/screenshots/159-theme.png b/NetGuard/screenshots/159-theme.png
new file mode 100644
index 0000000..1efd0a7
Binary files /dev/null and b/NetGuard/screenshots/159-theme.png differ
diff --git a/NetGuard/screenshots/160-theme.png b/NetGuard/screenshots/160-theme.png
new file mode 100644
index 0000000..517de6e
Binary files /dev/null and b/NetGuard/screenshots/160-theme.png differ
diff --git a/NetGuard/screenshots/20-traffic-log.png b/NetGuard/screenshots/20-traffic-log.png
new file mode 100755
index 0000000..c931812
Binary files /dev/null and b/NetGuard/screenshots/20-traffic-log.png differ
diff --git a/NetGuard/screenshots/21-traffic-filter.png b/NetGuard/screenshots/21-traffic-filter.png
new file mode 100755
index 0000000..557a9bd
Binary files /dev/null and b/NetGuard/screenshots/21-traffic-filter.png differ
diff --git a/NetGuard/screenshots/22-traffic-menu.png b/NetGuard/screenshots/22-traffic-menu.png
new file mode 100755
index 0000000..6ecaf5e
Binary files /dev/null and b/NetGuard/screenshots/22-traffic-menu.png differ
diff --git a/NetGuard/screenshots/23-traffic-popup.png b/NetGuard/screenshots/23-traffic-popup.png
new file mode 100755
index 0000000..1b78cfd
Binary files /dev/null and b/NetGuard/screenshots/23-traffic-popup.png differ
diff --git a/NetGuard/screenshots/30-settings-default.png b/NetGuard/screenshots/30-settings-default.png
new file mode 100755
index 0000000..ae70f9a
Binary files /dev/null and b/NetGuard/screenshots/30-settings-default.png differ
diff --git a/NetGuard/screenshots/31-settings-options.png b/NetGuard/screenshots/31-settings-options.png
new file mode 100755
index 0000000..23c868e
Binary files /dev/null and b/NetGuard/screenshots/31-settings-options.png differ
diff --git a/NetGuard/screenshots/32-settings-network.png b/NetGuard/screenshots/32-settings-network.png
new file mode 100755
index 0000000..ab2bea8
Binary files /dev/null and b/NetGuard/screenshots/32-settings-network.png differ
diff --git a/NetGuard/screenshots/33-settings-advanced.png b/NetGuard/screenshots/33-settings-advanced.png
new file mode 100755
index 0000000..2fb3242
Binary files /dev/null and b/NetGuard/screenshots/33-settings-advanced.png differ
diff --git a/NetGuard/screenshots/34-settings-speed.png b/NetGuard/screenshots/34-settings-speed.png
new file mode 100755
index 0000000..c3229cb
Binary files /dev/null and b/NetGuard/screenshots/34-settings-speed.png differ
diff --git a/NetGuard/screenshots/35-settings-add-port.png b/NetGuard/screenshots/35-settings-add-port.png
new file mode 100755
index 0000000..70ca308
Binary files /dev/null and b/NetGuard/screenshots/35-settings-add-port.png differ
diff --git a/NetGuard/screenshots/36-settings-ports.png b/NetGuard/screenshots/36-settings-ports.png
new file mode 100755
index 0000000..78e0a90
Binary files /dev/null and b/NetGuard/screenshots/36-settings-ports.png differ
diff --git a/NetGuard/screenshots/50-theme.png b/NetGuard/screenshots/50-theme.png
new file mode 100755
index 0000000..70b9b1f
Binary files /dev/null and b/NetGuard/screenshots/50-theme.png differ
diff --git a/NetGuard/screenshots/51-theme.png b/NetGuard/screenshots/51-theme.png
new file mode 100755
index 0000000..1b451e8
Binary files /dev/null and b/NetGuard/screenshots/51-theme.png differ
diff --git a/NetGuard/screenshots/52-theme.png b/NetGuard/screenshots/52-theme.png
new file mode 100755
index 0000000..52a15b8
Binary files /dev/null and b/NetGuard/screenshots/52-theme.png differ
diff --git a/NetGuard/screenshots/53-theme.png b/NetGuard/screenshots/53-theme.png
new file mode 100755
index 0000000..d42ec71
Binary files /dev/null and b/NetGuard/screenshots/53-theme.png differ
diff --git a/NetGuard/screenshots/54-theme.png b/NetGuard/screenshots/54-theme.png
new file mode 100755
index 0000000..179487e
Binary files /dev/null and b/NetGuard/screenshots/54-theme.png differ
diff --git a/NetGuard/screenshots/55-theme.png b/NetGuard/screenshots/55-theme.png
new file mode 100755
index 0000000..f76cad2
Binary files /dev/null and b/NetGuard/screenshots/55-theme.png differ
diff --git a/NetGuard/screenshots/56-theme.png b/NetGuard/screenshots/56-theme.png
new file mode 100755
index 0000000..ec04d6c
Binary files /dev/null and b/NetGuard/screenshots/56-theme.png differ
diff --git a/NetGuard/screenshots/57-theme.png b/NetGuard/screenshots/57-theme.png
new file mode 100755
index 0000000..63fa1fe
Binary files /dev/null and b/NetGuard/screenshots/57-theme.png differ
diff --git a/NetGuard/screenshots/58-theme.png b/NetGuard/screenshots/58-theme.png
new file mode 100755
index 0000000..c129eb2
Binary files /dev/null and b/NetGuard/screenshots/58-theme.png differ
diff --git a/NetGuard/screenshots/59-theme.png b/NetGuard/screenshots/59-theme.png
new file mode 100755
index 0000000..883941f
Binary files /dev/null and b/NetGuard/screenshots/59-theme.png differ
diff --git a/NetGuard/screenshots/60-theme.png b/NetGuard/screenshots/60-theme.png
new file mode 100755
index 0000000..78cde87
Binary files /dev/null and b/NetGuard/screenshots/60-theme.png differ
diff --git a/NetGuard/settings.gradle b/NetGuard/settings.gradle
new file mode 100644
index 0000000..e7b4def
--- /dev/null
+++ b/NetGuard/settings.gradle
@@ -0,0 +1 @@
+include ':app'
diff --git a/NetGuard/tools/Crowdin-Android-Importer.patch b/NetGuard/tools/Crowdin-Android-Importer.patch
new file mode 100644
index 0000000..e0eeebd
--- /dev/null
+++ b/NetGuard/tools/Crowdin-Android-Importer.patch
@@ -0,0 +1,29 @@
+diff --git a/crowdin.py b/crowdin.py
+old mode 100755
+new mode 100644
+diff --git a/helper.py b/helper.py
+index d3a57c9..7ef7d14 100644
+--- a/helper.py
++++ b/helper.py
+@@ -109,8 +109,12 @@ def GetResDirectory(path):
+
+
+ def GetTargetStringsXml(targetResDirectory, langCode):
+- country = langCode[0:2]
+- variant = langCode[3:]
++ if langCode == 'fil':
++ country = 'fil'
++ variant = ''
++ else:
++ country = langCode[0:2]
++ variant = langCode[3:]
+ if variant is not None and len(variant) > 0:
+ variant = "-r" + variant
+
+@@ -127,4 +131,4 @@ def IsSingleFolderUpdate(path):
+ def IsDefaultStringsXml(path):
+ if "res/values/strings.xml" in path:
+ return True
+- return False
+\ No newline at end of file
++ return False
diff --git a/NetGuard/tools/TCP_state_diagram.jpg b/NetGuard/tools/TCP_state_diagram.jpg
new file mode 100644
index 0000000..2e8576a
Binary files /dev/null and b/NetGuard/tools/TCP_state_diagram.jpg differ
diff --git a/NetGuard/tools/addr2line.sh b/NetGuard/tools/addr2line.sh
new file mode 100644
index 0000000..240db4f
--- /dev/null
+++ b/NetGuard/tools/addr2line.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+addr2line=/media/marcel/C720/android-ndk-r10e/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-addr2line
+lib=./app/build/intermediates/cmake/debug/obj/arm64-v8a/libnetguard.so
+addr2line -C -f -e $lib $1
diff --git a/NetGuard/tools/checkprefs.sh b/NetGuard/tools/checkprefs.sh
new file mode 100644
index 0000000..fa2d940
--- /dev/null
+++ b/NetGuard/tools/checkprefs.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+#apt-get install meld
+meld app/src/main/res/xml-v14/preferences.xml app/src/main/res/xml-v21/preferences.xml &
diff --git a/NetGuard/tools/strings.sh b/NetGuard/tools/strings.sh
new file mode 100644
index 0000000..49b918d
--- /dev/null
+++ b/NetGuard/tools/strings.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+grep -RIl "\Backup '
+#grep -RIl "\Options '
+#grep -RIl "\Defaults '
+
+#grep -RIl "\Do not apply the roaming rules when the SIM and mobile network country are the same '
+
+#grep -RIl "\