<data android:mimeType="text/*" />
</intent-filter>
+ <!-- Process intents for MHT archives. -->
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.BROWSABLE" />
+ <category android:name="android.intent.category.DEFAULT" />
+
+ <data android:scheme="file" />
+ <data android:scheme="content" />
+
+ <data android:host="*" />
+
+ <!-- This pattern matches any file that starts with a `/`, has at least one character, followed by any number of other characters, terminating with `.mht`. -->
+ <data android:pathPattern="/.*\.mht" />
+ <data android:mimeType="*/*" />
+ </intent-filter>
+
<!-- Process web search intents. -->
<intent-filter>
<action android:name="android.intent.action.WEB_SEARCH" />
<h3><img class="title" src="../shared_images/open_in_browser_blue_dark.png"> Nutzung von Proxies</h3>
<p>Trotz ihrer Einschränkungen können Proxies unter bestimmen Umständen durchaus nützlich sein.
- <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> und <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+ <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> und <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
existieren Android-Apps, die die einfache Nutzung dieser Proxy-Netzwerke ermöglichen.
Wird die Nutzung dieser Proxy-Netzwerke in Privacy Browser aktiviert, wird die App-Leiste mit einem hellblauen statt hellgrauen Hintergrund versehen.
Da der Datenverkehr in solchen Fällen jedoch über mehrere Proxy-Knoten geleitet wird,
<h3><img class="title" src="../shared_images/open_in_browser_blue_light.png"> Nutzung von Proxies</h3>
<p>Trotz ihrer Einschränkungen können Proxies unter bestimmen Umständen durchaus nützlich sein.
- <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> und <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+ <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> und <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
existieren Android-Apps, die die einfache Nutzung dieser Proxy-Netzwerke ermöglichen.
Wird die Nutzung dieser Proxy-Netzwerke in Privacy Browser aktiviert, wird die App-Leiste mit einem hellblauen statt hellgrauen Hintergrund versehen.
Da der Datenverkehr in solchen Fällen jedoch über mehrere Proxy-Knoten geleitet wird,
<h3><img class="title" src="../shared_images/open_in_browser_blue_dark.png"> Using Proxies</h3>
<p>Despite their limitations, proxies can be useful in some circumstances.
- <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+ <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
have Android apps that make it easy to use their proxy networks. When proxying is turned on in Privacy Browser, the app bar will have a light blue background instead of the default light grey.
Because traffic is being routed through several proxy nodes, using a layered proxy is often much slower than connecting directly to the internet.</p>
<h3><img class="title" src="../shared_images/open_in_browser_blue_light.png"> Using Proxies</h3>
<p>Despite their limitations, proxies can be useful in some circumstances.
- <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+ <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
have Android apps that make it easy to use their proxy networks. When proxying is turned on in Privacy Browser, the app bar will have a light blue background instead of the default light grey.
Because traffic is being routed through several proxy nodes, using a layered proxy is often much slower than connecting directly to the internet.</p>
<h3><img class="title" src="../shared_images/open_in_browser_blue_dark.png"> Uso de Proxis</h3>
<p>A pesar de sus limitaciones, los proxis pueden ser útiles en algunas circunstancias.
- <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> e <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+ <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> e <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
tienen aplicaciones Android que facilitan el uso de sus redes de proxy. Cuando se activa el proxy en Navegador Privado,
la barra de aplicaciones tendrá un fondo azul claro en lugar del gris claro predeterminado.
Debido a que el tráfico está siendo enrutado a través de varios nodos proxy, usar un proxy en capas es a menudo mucho más lento que conectarse directamente a Internet.</p>
<h3><img class="title" src="../shared_images/open_in_browser_blue_light.png"> Uso de Proxis</h3>
<p>A pesar de sus limitaciones, los proxis pueden ser útiles en algunas circunstancias.
- <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> e <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+ <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> e <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
tienen aplicaciones Android que facilitan el uso de sus redes de proxy. Cuando se activa el proxy en Navegador Privado,
la barra de aplicaciones tendrá un fondo azul claro en lugar del gris claro predeterminado.
Debido a que el tráfico está siendo enrutado a través de varios nodos proxy, usar un proxy en capas es a menudo mucho más lento que conectarse directamente a Internet.</p>
<h3><img class="title" src="../shared_images/open_in_browser_blue_dark.png"> Utiliser des Proxies</h3>
<p>Malgré leurs limites, les proxies peuvent être utiles dans certaines circonstances.
- <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> et <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+ <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> et <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
ont des applications Android qui facilitent l'utilisation de leurs réseaux proxy.
Lorsque le proxy est activé dans Privacy Browser, la barre d'application aura un fond bleu clair au lieu du gris clair par défaut.
Étant donné que le trafic est acheminé via plusieurs nœuds proxy, l'utilisation d'un proxy en couches est souvent beaucoup plus lente que la connexion directe à Internet.</p>
<h3><img class="title" src="../shared_images/open_in_browser_blue_light.png"> Utiliser des Proxies</h3>
<p>Malgré leurs limites, les proxies peuvent être utiles dans certaines circonstances.
- <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> et <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+ <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> et <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
ont des applications Android qui facilitent l'utilisation de leurs réseaux proxy.
Lorsque le proxy est activé dans Privacy Browser, la barre d'application aura un fond bleu clair au lieu du gris clair par défaut.
Étant donné que le trafic est acheminé via plusieurs nœuds proxy, l'utilisation d'un proxy en couches est souvent beaucoup plus lente que la connexion directe à Internet.</p>
</head>
<body>
- <h3><img class="title" src="../shared_images/vpn_key_blue_dark.png"> Proxies and Their Limits</h3>
+ <h3><img class="title" src="../shared_images/vpn_key_blue_dark.png"> I Proxy e i loro limiti</h3>
<p>Esistono due categorie generali di cattivi soggetti che vogliono violare la privacy del web:
governi maliziosi con accesso agli ISP (Internet Service Providers) e mega corporations che gestiscono social network e agenzie pubblicitarie.
- Proxies like TOR (The Onion Router) and I2P (the Invisible Internet Project) are useful in protecting privacy from malicious governments (which spy on traffic in transit)
- but not from mega corporations (which embed malicious code on web servers).</p>
+ Proxy come TOR (The Onion Router) e I2P (Invisible Internet Project) sono utili per la protezione della privacy da governi maliziosi (che spiano il traffico in transito)
+ ma non dalle mega corporations (che inseriscono codice malizioso sui web server).</p>
<h3><img class="title" src="../shared_images/language_blue_dark.png"> Governi Maliziosi</h3>
<p>I governi malizionsi spesso spiano i loro cittadini per punire il dissenso o le attività di difesa dei diritti umani.
Solitamente, o gestiscono loro stessi gli ISP locali oppure li obbligano a rivelare informazioni mostrando tutti gli indirizzi IP visitati da ciascun utente.
- Layered proxies are designed to defeat this infringement of privacy by encrypting the traffic from a user’s device and routing it through multiple servers on the internet
- before sending it on to the final destination.
- This means that no individual ISP, server, or website, can know both the <a href="https://ipleak.net">IP address of the user’s device</a> and the IP address of the final web server.
- Malicious governments and the ISPs they control cannot tell which web servers a user is accessing, although they can tell that the user is using a layered proxy service.
- In some parts of the world, using proxies could be construed as an evidence of illegal behavior (“If you didn’t have anything to hide you wouldn’t be encrypting your traffic”)
- and users could be punished because governments assume they are doing something that is prohibited. Thus, proxies can be helpful, but they aren’t a panacea.</p>
+ I proxy a strati sono progettati per sconfiggere questa violazione di privacy crittografando il traffico dal dispositivo dell'utente e instradandolo attraverso server multipli su internet
+ prima di inviarlo alla destinazione finale.
+ Questo significa che nessun ISP individuale, server, o sito web,
+ può conoscere sia l'<a href="https://ipleak.net">indirizzo IP del dispositivo dell'utente</a> che l'indirizzo IP del web server finale.
+ I governi maliziosi e gli ISP che controllano, non possono conoscere i web server ai quali l'utente sta accedendo, sebbene sappiano che l'utente sta utilizzando un servizio di proxy a strati.
+ In alcune parti del mondo l'utilizzo di proxy può essere consideraro come evidenza di un comportamento illegale (“Se non hai nulla da nascondere non crittograferesti il tuo traffico”)
+ e gli utenti potrebbero essere perseguiti perchè il loro governo potrebbe assumere che stiano facendo qualcosa di proibito.
+ Per questo motivo i proxy possono essere utili ma non sono la soluzione di tutti i mali.</p>
<h3><img class="title" src="../shared_images/language_blue_dark.png"> Mega corporations</h3>
<p>Quando un utente si connette a un web server, il server può vedere l'indirizzo IP dell'utente.
Nonostante non sia una scienza esatta, è possibile convertire l'IP in indirizzi fisici con <a href="https://www.whatismyip.com/">discreta accuratezza</a>.
- Small web servers typically rely on IP addresses to identify the location of the users visiting their site. Proxies are a good solution to mask the user’s location from these servers.
+ I piccoli web servers solitamente si basano sull'indirizzo IP per identificare la posizione degli utenti che accedono al loro sito.
+ I Proxy sono una buona soluzione per mascherare la posizione dell'utente a questi server.
Le mega corporations proprietarie di social media e agenzie pubblicitarie utilizzano però un intero profilo di informazioni con lo scopo di tracciare gli utenti sui dispositivi e sgli indirizzi IP.
Questi profili utilizzano molte tecniche diverse per l'identificazione degli utenti, tra cui JavaScript, cookie, ID traccianti,
e <a href="https://panopticlick.eff.org/">impronta digitale dei browser</a>.
<p>Viene tracciato ogni sito visitato, ogni acquisto effettuato, ogni carta di credito utilizzata, ogni indirizzo di spedizione, i metadati GPS di ogni immagine che viene caricata su internet.
Viene costruito il profilo per età, sesso, stato civile, indirizzo, appartenenza politica, religione, situazione familiare, animali domestici, e tutto ciò su cui possono mettere le mani.
Le corporations acquistano anche i database delle transazioni con carta di credito effettuate nei negozi, per poter tracciare anche le abitudini di acquisto off-line degli utenti nei loro profili.
- Because they already have much more accurate address information about a user than an IP address discloses, proxies provides no real privacy protection against mega corporations.</p>
+ Poichè hanno già informazioni molto più accurate sull'utente rispetto a quelle fornite dall'indirizzo IP, i proxy non forniscono alcuna vera protezione della privacy contro le mega corporations.</p>
<p>La miglior protezione per la privacy contro le mega corporations è quella di navigare con JavaScript disabilitato, seguita dal bloccare gli annunci pubblicitari,
disabilitare i cookie e il DOM storage, e utilizzare un browser di cui è difficile avere l'impronta digitale.</p>
- <h3><img class="title" src="../shared_images/open_in_browser_blue_dark.png"> Using Proxies</h3>
+ <h3><img class="title" src="../shared_images/open_in_browser_blue_dark.png"> L'utilizzo di Proxy</h3>
- <p>Despite their limitations, proxies can be useful in some circumstances.
- <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
- have Android apps that make it easy to use their proxy networks. When proxying is turned on in Privacy Browser, the app bar will have a light blue background instead of the default light grey.
- Because traffic is being routed through several proxy nodes, using a layered proxy is often much slower than connecting directly to the internet.</p>
+ <p>Nonostante i loro limiti, i proxy possono essere utili in alcune circostanze.
+ <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> e <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
+ hanno app per Android che facilitano l'utilizzo delle loro reti proxy.
+ Quando si abilita il proxy in Privacy Browser la barra dell'app bar avrà una colorazione dello sfondo azzurra, rispetto a quella grigia di default.
+ Dal momento che il traffico è instradato attraverso diversi nodi proxy, l'utilizzo di un proxy a strati è spesso molto più lento di una connessione diretta a internet.</p>
<img class="center" src="images/tor.png">
<h3><img class="title" src="../shared_images/file_download_blue_dark.png"> Download di File con Tor</h3>
- <p>When Orbot is operating in proxy mode, browsing the internet using Privacy Browser will be routed through the proxy, but file downloads will not.
- This is because Privacy Browser uses Android’s builtin download manager to download files, which doesn’t have a proxy option.
- Users who want to download files via Orbot need to enable its VPN mode. There is currently no way to download files through I2P.</p>
+ <p>Quando Orbot sta funzionando in modalità proxy, la navigazione su internet con Privacy Browser è instradata attraverso il proxy, ma il download di file no.
+ Questo perchè Privacy Browser utilizza il download manager nativo di Android per lo scaricamento dei file, e questo non ha l'opzione proxy.
+ Gli utenti che vogliono scaricare i file via Orbot devono quindi abilitare la sua modalità VPN. Attualmente non c'è ancora la possibilità di scaricare file con I2P.</p>
<img class="center" src="../shared_images/vpn_mode.png">
</body>
</head>
<body>
- <h3><img class="title" src="../shared_images/vpn_key_blue_light.png"> Proxies and Their Limits</h3>
+ <h3><img class="title" src="../shared_images/vpn_key_blue_light.png"> I Proxy e i loro limiti</h3>
<p>Esistono due categorie generali di cattivi soggetti che vogliono violare la privacy del web:
governi maliziosi con accesso agli ISP (Internet Service Providers) e mega corporations che gestiscono social network e agenzie pubblicitarie.
- Proxies like TOR (The Onion Router) and I2P (the Invisible Internet Project) are useful in protecting privacy from malicious governments (which spy on traffic in transit)
- but not from mega corporations (which embed malicious code on web servers).</p>
+ Proxy come TOR (The Onion Router) e I2P (Invisible Internet Project) sono utili per la protezione della privacy da governi maliziosi (che spiano il traffico in transito)
+ ma non dalle mega corporations (che inseriscono codice malizioso sui web server).</p>
<h3><img class="title" src="../shared_images/language_blue_light.png"> Governi Maliziosi</h3>
<p>I governi malizionsi spesso spiano i loro cittadini per punire il dissenso o le attività di difesa dei diritti umani.
Solitamente, o gestiscono loro stessi gli ISP locali oppure li obbligano a rivelare informazioni mostrando tutti gli indirizzi IP visitati da ciascun utente.
- Layered proxies are designed to defeat this infringement of privacy by encrypting the traffic from a user’s device and routing it through multiple servers on the internet
- before sending it on to the final destination.
- This means that no individual ISP, server, or website, can know both the <a href="https://ipleak.net">IP address of the user’s device</a> and the IP address of the final web server.
- Malicious governments and the ISPs they control cannot tell which web servers a user is accessing, although they can tell that the user is using a layered proxy service.
- In some parts of the world, using proxies could be construed as an evidence of illegal behavior (“If you didn’t have anything to hide you wouldn’t be encrypting your traffic”)
- and users could be punished because governments assume they are doing something that is prohibited. Thus, proxies can be helpful, but they aren’t a panacea.</p>
+ I proxy a strati sono progettati per sconfiggere questa violazione di privacy crittografando il traffico dal dispositivo dell'utente e instradandolo attraverso server multipli su internet
+ prima di inviarlo alla destinazione finale.
+ Questo significa che nessun ISP individuale, server, o sito web,
+ può conoscere sia l'<a href="https://ipleak.net">indirizzo IP del dispositivo dell'utente</a> che l'indirizzo IP del web server finale.
+ I governi maliziosi e gli ISP che controllano, non possono conoscere i web server ai quali l'utente sta accedendo, sebbene sappiano che l'utente sta utilizzando un servizio di proxy a strati.
+ In alcune parti del mondo l'utilizzo di proxy può essere consideraro come evidenza di un comportamento illegale (“Se non hai nulla da nascondere non crittograferesti il tuo traffico”)
+ e gli utenti potrebbero essere perseguiti perchè il loro governo potrebbe assumere che stiano facendo qualcosa di proibito.
+ Per questo motivo i proxy possono essere utili ma non sono la soluzione di tutti i mali.</p>
<h3><img class="title" src="../shared_images/language_blue_light.png"> Mega corporations</h3>
<p>Quando un utente si connette a un web server, il server può vedere l'indirizzo IP dell'utente.
Nonostante non sia una scienza esatta, è possibile convertire l'IP in indirizzi fisici con <a href="https://www.whatismyip.com/">discreta accuratezza</a>.
- Small web servers typically rely on IP addresses to identify the location of the users visiting their site. Proxies are a good solution to mask the user’s location from these servers.
+ I piccoli web servers solitamente si basano sull'indirizzo IP per identificare la posizione degli utenti che accedono al loro sito.
+ I Proxy sono una buona soluzione per mascherare la posizione dell'utente a questi server.
Le mega corporations proprietarie di social media e agenzie pubblicitarie utilizzano però un intero profilo di informazioni con lo scopo di tracciare gli utenti sui dispositivi e sgli indirizzi IP.
Questi profili utilizzano molte tecniche diverse per l'identificazione degli utenti, tra cui JavaScript, cookie, ID traccianti,
e <a href="https://panopticlick.eff.org/">impronta digitale dei browser</a>.
<p>Viene tracciato ogni sito visitato, ogni acquisto effettuato, ogni carta di credito utilizzata, ogni indirizzo di spedizione, i metadati GPS di ogni immagine che viene caricata su internet.
Viene costruito il profilo per età, sesso, stato civile, indirizzo, appartenenza politica, religione, situazione familiare, animali domestici, e tutto ciò su cui possono mettere le mani.
Le corporations acquistano anche i database delle transazioni con carta di credito effettuate nei negozi, per poter tracciare anche le abitudini di acquisto off-line degli utenti nei loro profili.
- Because they already have much more accurate address information about a user than an IP address discloses, proxies provides no real privacy protection against mega corporations.</p>
+ Poichè hanno già informazioni molto più accurate sull'utente rispetto a quelle fornite dall'indirizzo IP, i proxy non forniscono alcuna vera protezione della privacy contro le mega corporations.</p>
<p>La miglior protezione per la privacy contro le mega corporations è quella di navigare con JavaScript disabilitato, seguita dal bloccare gli annunci pubblicitari,
disabilitare i cookie e il DOM storage, e utilizzare un browser di cui è difficile avere l'impronta digitale.</p>
- <h3><img class="title" src="../shared_images/open_in_browser_blue_light.png"> Using Proxies</h3>
+ <h3><img class="title" src="../shared_images/open_in_browser_blue_light.png"> L'utilizzo di Proxy</h3>
- <p>Despite their limitations, proxies can be useful in some circumstances.
- <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
- have Android apps that make it easy to use their proxy networks. When proxying is turned on in Privacy Browser, the app bar will have a light blue background instead of the default light grey.
- Because traffic is being routed through several proxy nodes, using a layered proxy is often much slower than connecting directly to the internet.</p>
+ <p>Nonostante i loro limiti, i proxy possono essere utili in alcune circostanze.
+ <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> e <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
+ hanno app per Android che facilitano l'utilizzo delle loro reti proxy.
+ Quando si abilita il proxy in Privacy Browser la barra dell'app bar avrà una colorazione dello sfondo azzurra, rispetto a quella grigia di default.
+ Dal momento che il traffico è instradato attraverso diversi nodi proxy, l'utilizzo di un proxy a strati è spesso molto più lento di una connessione diretta a internet.</p>
<img class="center" src="images/tor.png">
<h3><img class="title" src="../shared_images/file_download_blue_light.png"> Download di File con Tor</h3>
- <p>When Orbot is operating in proxy mode, browsing the internet using Privacy Browser will be routed through the proxy, but file downloads will not.
- This is because Privacy Browser uses Android’s builtin download manager to download files, which doesn’t have a proxy option.
- Users who want to download files via Orbot need to enable its VPN mode. There is currently no way to download files through I2P.</p>
+ <p>Quando Orbot sta funzionando in modalità proxy, la navigazione su internet con Privacy Browser è instradata attraverso il proxy, ma il download di file no.
+ Questo perchè Privacy Browser utilizza il download manager nativo di Android per lo scaricamento dei file, e questo non ha l'opzione proxy.
+ Gli utenti che vogliono scaricare i file via Orbot devono quindi abilitare la sua modalità VPN. Attualmente non c'è ancora la possibilità di scaricare file con I2P.</p>
<img class="center" src="../shared_images/vpn_mode.png">
</body>
<h3><img class="title" src="../shared_images/open_in_browser_blue_dark.png"> Using Proxies</h3>
<p>Despite their limitations, proxies can be useful in some circumstances.
- <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+ <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
have Android apps that make it easy to use their proxy networks. When proxying is turned on in Privacy Browser, the app bar will have a light blue background instead of the default light grey.
Because traffic is being routed through several proxy nodes, using a layered proxy is often much slower than connecting directly to the internet.</p>
<h3><img class="title" src="../shared_images/open_in_browser_blue_light.png"> Using Proxies</h3>
<p>Despite their limitations, proxies can be useful in some circumstances.
- <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+ <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
have Android apps that make it easy to use their proxy networks. When proxying is turned on in Privacy Browser, the app bar will have a light blue background instead of the default light grey.
Because traffic is being routed through several proxy nodes, using a layered proxy is often much slower than connecting directly to the internet.</p>
<h3><img class="title" src="../shared_images/open_in_browser_blue_dark.png"> Using Proxies</h3>
<p>Despite their limitations, proxies can be useful in some circumstances.
- <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+ <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
have Android apps that make it easy to use their proxy networks. When proxying is turned on in Privacy Browser, the app bar will have a light blue background instead of the default light grey.
Because traffic is being routed through several proxy nodes, using a layered proxy is often much slower than connecting directly to the internet.</p>
<h3><img class="title" src="../shared_images/open_in_browser_blue_light.png"> Using Proxies</h3>
<p>Despite their limitations, proxies can be useful in some circumstances.
- <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+ <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
have Android apps that make it easy to use their proxy networks. When proxying is turned on in Privacy Browser, the app bar will have a light blue background instead of the default light grey.
Because traffic is being routed through several proxy nodes, using a layered proxy is often much slower than connecting directly to the internet.</p>
// Set the content view.
setContentView(R.layout.import_export_coordinatorlayout);
- // Use the `SupportActionBar` from `android.support.v7.app.ActionBar` until the minimum API is >= 21.
+ // Set the support action bar.
Toolbar toolbar = findViewById(R.id.import_export_toolbar);
setSupportActionBar(toolbar);
// Display the home arrow on the support action bar.
actionBar.setDisplayHomeAsUpEnabled(true);
- // Find out if we are running KitKat
+ // Find out if the system is running KitKat
boolean runningKitKat = (Build.VERSION.SDK_INT == 19);
// Find out if OpenKeychain is installed.
// Check if the user has previously denied the storage permission.
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { // Show a dialog explaining the request first.
// Instantiate the storage permission alert dialog.
- DialogFragment storagePermissionDialogFragment = new StoragePermissionDialog();
+ DialogFragment storagePermissionDialogFragment = StoragePermissionDialog.displayDialog(0);
// Show the storage permission alert dialog. The permission will be requested when the dialog is closed.
storagePermissionDialogFragment.show(getSupportFragmentManager(), getString(R.string.storage_permission));
}
@Override
- public void onCloseStoragePermissionDialog() {
+ public void onCloseStoragePermissionDialog(int type) {
// Request the write external storage permission. The import/export will be run when it finishes.
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
}
// Check if the user has previously denied the storage permission.
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { // Show a dialog explaining the request first.
// Instantiate the storage permission alert dialog.
- DialogFragment storagePermissionDialogFragment = new StoragePermissionDialog();
+ DialogFragment storagePermissionDialogFragment = StoragePermissionDialog.displayDialog(0);
// Show the storage permission alert dialog. The permission will be requested when the dialog is closed.
storagePermissionDialogFragment.show(getSupportFragmentManager(), getString(R.string.storage_permission));
}
@Override
- public void onCloseStoragePermissionDialog() {
+ public void onCloseStoragePermissionDialog(int type) {
// Request the write external storage permission. The logcat will be saved when it finishes.
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
}
import com.stoutner.privacybrowser.dialogs.HttpAuthenticationDialog;
import com.stoutner.privacybrowser.dialogs.ProxyNotInstalledDialog;
import com.stoutner.privacybrowser.dialogs.PinnedMismatchDialog;
-import com.stoutner.privacybrowser.dialogs.SaveWebpageImageDialog;
+import com.stoutner.privacybrowser.dialogs.SaveWebpageDialog;
import com.stoutner.privacybrowser.dialogs.SslCertificateErrorDialog;
import com.stoutner.privacybrowser.dialogs.StoragePermissionDialog;
import com.stoutner.privacybrowser.dialogs.UrlHistoryDialog;
// AppCompatActivity from android.support.v7.app.AppCompatActivity must be used to have access to the SupportActionBar until the minimum API is >= 21.
public class MainWebViewActivity extends AppCompatActivity implements CreateBookmarkDialog.CreateBookmarkListener, CreateBookmarkFolderDialog.CreateBookmarkFolderListener,
DownloadFileDialog.DownloadFileListener, DownloadImageDialog.DownloadImageListener, DownloadLocationPermissionDialog.DownloadLocationPermissionDialogListener, EditBookmarkDialog.EditBookmarkListener,
- EditBookmarkFolderDialog.EditBookmarkFolderListener, FontSizeDialog.UpdateFontSizeListener, NavigationView.OnNavigationItemSelectedListener, PinnedMismatchDialog.PinnedMismatchListener, PopulateBlocklists.PopulateBlocklistsListener, SaveWebpageImageDialog.SaveWebpageImageListener,
- StoragePermissionDialog.StoragePermissionDialogListener, UrlHistoryDialog.NavigateHistoryListener, WebViewTabFragment.NewTabListener {
+ EditBookmarkFolderDialog.EditBookmarkFolderListener, FontSizeDialog.UpdateFontSizeListener, NavigationView.OnNavigationItemSelectedListener, PinnedMismatchDialog.PinnedMismatchListener,
+ PopulateBlocklists.PopulateBlocklistsListener, SaveWebpageDialog.SaveWebpageListener, StoragePermissionDialog.StoragePermissionDialogListener, UrlHistoryDialog.NavigateHistoryListener,
+ WebViewTabFragment.NewTabListener {
// `orbotStatus` is public static so it can be accessed from `OrbotProxyHelper`. It is also used in `onCreate()`, `onResume()`, and `applyProxy()`.
public static String orbotStatus = "unknown";
// Start activity for result request codes.
private final int FILE_UPLOAD_REQUEST_CODE = 0;
- public final static int BROWSE_SAVE_WEBPAGE_IMAGE_REQUEST_CODE = 1;
+ public final static int BROWSE_SAVE_WEBPAGE_REQUEST_CODE = 1;
// The current WebView is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, `onRestart()`, `onCreateContextMenu()`, `findPreviousOnPage()`,
// `downloadImageUrl` is used in `onCreateContextMenu()` and `onRequestPermissionResult()`.
private String downloadImageUrl;
- // The save website image file path string is used in `onSaveWebpageImage()` and `onRequestPermissionResult()`
- private String saveWebsiteImageFilePath;
+ // The save webpage file path string is used in `onSaveWebpageImage()` and `onRequestPermissionResult()`
+ private String saveWebpageFilePath;
// The permission result request codes are used in `onCreateContextMenu()`, `onCloseDownloadLocationPermissionDialog()`, `onRequestPermissionResult()`, `onSaveWebpageImage()`,
// `onCloseStoragePermissionDialog()`, and `initializeWebView()`.
- private final int DOWNLOAD_FILE_REQUEST_CODE = 1;
- private final int DOWNLOAD_IMAGE_REQUEST_CODE = 2;
+ private final int DOWNLOAD_FILE_REQUEST_CODE = 0;
+ private final int DOWNLOAD_IMAGE_REQUEST_CODE = 1;
+ private final int SAVE_WEBPAGE_ARCHIVE_REQUEST_CODE = 2;
private final int SAVE_WEBPAGE_IMAGE_REQUEST_CODE = 3;
@Override
// Consume the event.
return true;
+ case R.id.save_as_archive:
+ // Instantiate the save webpage archive dialog.
+ DialogFragment saveWebpageArchiveDialogFragment = SaveWebpageDialog.saveWebpage(SaveWebpageDialog.ARCHIVE);
+
+ // Show the save webpage archive dialog.
+ saveWebpageArchiveDialogFragment.show(getSupportFragmentManager(), getString(R.string.save_webpage));
+
+ // Consume the event.
+ return true;
+
case R.id.save_as_image:
// Instantiate the save webpage image dialog.
- DialogFragment saveWebpageImageDialogFragment = new SaveWebpageImageDialog();
+ DialogFragment saveWebpageImageDialogFragment = SaveWebpageDialog.saveWebpage(SaveWebpageDialog.IMAGE);
// Show the save webpage image dialog.
- saveWebpageImageDialogFragment.show(getSupportFragmentManager(), getString(R.string.save_as_image));
+ saveWebpageImageDialogFragment.show(getSupportFragmentManager(), getString(R.string.save_webpage));
// Consume the event.
return true;
downloadImageUrl = "";
break;
+ case SAVE_WEBPAGE_ARCHIVE_REQUEST_CODE:
+ // Check to see if the storage permission was granted. If the dialog was canceled the grant results will be empty.
+ if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) { // The storage permission was granted.
+ // Save the webpage archive.
+ currentWebView.saveWebArchive(saveWebpageFilePath);
+ } else {
+ // Display an error snackbar.
+ Snackbar.make(currentWebView, getString(R.string.cannot_use_location), Snackbar.LENGTH_LONG).show();
+ }
+
+ // Reset the save webpage file path.
+ saveWebpageFilePath = "";
+ break;
+
case SAVE_WEBPAGE_IMAGE_REQUEST_CODE:
- // Check to see if the storage permission was granted. If the dialog was canceled the grant result will be empty.
+ // Check to see if the storage permission was granted. If the dialog was canceled the grant results will be empty.
if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) { // The storage permission was granted.
// Save the webpage image.
- new SaveWebpageImage(this, currentWebView).execute(saveWebsiteImageFilePath);
+ new SaveWebpageImage(this, currentWebView).execute(saveWebpageFilePath);
} else { // The storage permission was not granted.
// Display an error snackbar.
Snackbar.make(currentWebView, getString(R.string.cannot_use_location), Snackbar.LENGTH_LONG).show();
}
- // Reset the save website image file path.
- saveWebsiteImageFilePath = "";
+ // Reset the save webpage file path.
+ saveWebpageFilePath = "";
break;
}
}
}
break;
- case BROWSE_SAVE_WEBPAGE_IMAGE_REQUEST_CODE:
+ case BROWSE_SAVE_WEBPAGE_REQUEST_CODE:
// Don't do anything if the user pressed back from the file picker.
if (resultCode == Activity.RESULT_OK) {
// Get a handle for the save dialog fragment.
- DialogFragment saveWebpageImageDialogFragment= (DialogFragment) getSupportFragmentManager().findFragmentByTag(getString(R.string.save_as_image));
+ DialogFragment saveWebpageDialogFragment= (DialogFragment) getSupportFragmentManager().findFragmentByTag(getString(R.string.save_webpage));
// Only update the file name if the dialog still exists.
- if (saveWebpageImageDialogFragment != null) {
- // Get a handle for the save webpage image dialog.
- Dialog saveWebpageImageDialog = saveWebpageImageDialogFragment.getDialog();
+ if (saveWebpageDialogFragment != null) {
+ // Get a handle for the save webpage dialog.
+ Dialog saveWebpageDialog = saveWebpageDialogFragment.getDialog();
// Remove the incorrect lint warning below that the dialog might be null.
- assert saveWebpageImageDialog != null;
+ assert saveWebpageDialog != null;
// Get a handle for the file name edit text.
- EditText fileNameEditText = saveWebpageImageDialog.findViewById(R.id.file_name_edittext);
+ EditText fileNameEditText = saveWebpageDialog.findViewById(R.id.file_name_edittext);
// Instantiate the file name helper.
FileNameHelper fileNameHelper = new FileNameHelper();
}
@Override
- public void onSaveWebpageImage(DialogFragment dialogFragment) {
+ public void onSaveWebpage(int saveType, DialogFragment dialogFragment) {
// Get the dialog.
Dialog dialog = dialogFragment.getDialog();
EditText fileNameEditText = dialog.findViewById(R.id.file_name_edittext);
// Get the file path string.
- saveWebsiteImageFilePath = fileNameEditText.getText().toString();
+ saveWebpageFilePath = fileNameEditText.getText().toString();
// Check to see if the storage permission is needed.
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { // The storage permission has been granted.
- // Save the webpage image.
- new SaveWebpageImage(this, currentWebView).execute(saveWebsiteImageFilePath);
+ //Save the webpage according to the save type.
+ switch (saveType) {
+ case SaveWebpageDialog.ARCHIVE:
+ // Save the webpage archive.
+ currentWebView.saveWebArchive(saveWebpageFilePath);
+ break;
+
+ case SaveWebpageDialog.IMAGE:
+ // Save the webpage image.
+ new SaveWebpageImage(this, currentWebView).execute(saveWebpageFilePath);
+ break;
+ }
} else { // The storage permission has not been granted.
// Get the external private directory `File`.
File externalPrivateDirectoryFile = getExternalFilesDir(null);
String externalPrivateDirectory = externalPrivateDirectoryFile.toString();
// Check to see if the file path is in the external private directory.
- if (saveWebsiteImageFilePath.startsWith(externalPrivateDirectory)) { // The file path is in the external private directory.
- // Save the webpage image.
- new SaveWebpageImage(this, currentWebView).execute(saveWebsiteImageFilePath);
+ if (saveWebpageFilePath.startsWith(externalPrivateDirectory)) { // The file path is in the external private directory.
+ //Save the webpage according to the save type.
+ switch (saveType) {
+ case SaveWebpageDialog.ARCHIVE:
+ // Save the webpage archive.
+ currentWebView.saveWebArchive(saveWebpageFilePath);
+ break;
+
+ case SaveWebpageDialog.IMAGE:
+ // Save the webpage image.
+ new SaveWebpageImage(this, currentWebView).execute(saveWebpageFilePath);
+ break;
+ }
} else { // The file path is in a public directory.
// Check if the user has previously denied the storage permission.
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { // Show a dialog explaining the request first.
// Instantiate the storage permission alert dialog.
- DialogFragment storagePermissionDialogFragment = new StoragePermissionDialog();
+ DialogFragment storagePermissionDialogFragment = StoragePermissionDialog.displayDialog(saveType);
// Show the storage permission alert dialog. The permission will be requested when the dialog is closed.
storagePermissionDialogFragment.show(getSupportFragmentManager(), getString(R.string.storage_permission));
} else { // Show the permission request directly.
- // Request the write external storage permission. The webpage image will be saved when it finishes.
- ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, SAVE_WEBPAGE_IMAGE_REQUEST_CODE);
+ switch (saveType) {
+ case SaveWebpageDialog.ARCHIVE:
+ // Request the write external storage permission. The webpage archive will be saved when it finishes.
+ ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, SAVE_WEBPAGE_ARCHIVE_REQUEST_CODE);
+ break;
+
+ case SaveWebpageDialog.IMAGE:
+ // Request the write external storage permission. The webpage image will be saved when it finishes.
+ ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, SAVE_WEBPAGE_IMAGE_REQUEST_CODE);
+ break;
+ }
}
}
}
}
@Override
- public void onCloseStoragePermissionDialog() {
- // Request the write external storage permission. The webpage image will be saved when it finishes.
- ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, SAVE_WEBPAGE_IMAGE_REQUEST_CODE);
+ public void onCloseStoragePermissionDialog(int saveType) {
+ switch (saveType) {
+ case SaveWebpageDialog.ARCHIVE:
+ // Request the write external storage permission. The webpage archive will be saved when it finishes.
+ ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, SAVE_WEBPAGE_ARCHIVE_REQUEST_CODE);
+ break;
+
+ case SaveWebpageDialog.IMAGE:
+ // Request the write external storage permission. The webpage image will be saved when it finishes.
+ ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, SAVE_WEBPAGE_IMAGE_REQUEST_CODE);
+ break;
+ }
}
private void applyAppSettings() {
--- /dev/null
+/*
+ * Copyright © 2019 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+ *
+ * Privacy Browser 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.
+ *
+ * Privacy Browser 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 Privacy Browser. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.stoutner.privacybrowser.dialogs;
+
+import android.Manifest;
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Environment;
+import android.provider.DocumentsContract;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.DialogFragment;
+import androidx.preference.PreferenceManager;
+
+import com.stoutner.privacybrowser.R;
+import com.stoutner.privacybrowser.activities.MainWebViewActivity;
+
+public class SaveWebpageDialog extends DialogFragment {
+ // Define the save type constants.
+ public static final int ARCHIVE = 0;
+ public static final int IMAGE = 1;
+
+ // Define the save webpage listener.
+ private SaveWebpageListener saveWebpageListener;
+
+ // The public interface is used to send information back to the parent activity.
+ public interface SaveWebpageListener {
+ void onSaveWebpage(int saveType, DialogFragment dialogFragment);
+ }
+
+ @Override
+ public void onAttach(@NonNull Context context) {
+ // Run the default commands.
+ super.onAttach(context);
+
+ // Get a handle for the save webpage listener from the launching context.
+ saveWebpageListener = (SaveWebpageListener) context;
+ }
+
+ public static SaveWebpageDialog saveWebpage(int saveType) {
+ // Create an arguments bundle.
+ Bundle argumentsBundle = new Bundle();
+
+ // Store the save type in the bundle.
+ argumentsBundle.putInt("save_type", saveType);
+
+ // Create a new instance of the save webpage dialog.
+ SaveWebpageDialog saveWebpageDialog = new SaveWebpageDialog();
+
+ // Add the arguments bundle to the new dialog.
+ saveWebpageDialog.setArguments(argumentsBundle);
+
+ // Return the new dialog.
+ return saveWebpageDialog;
+ }
+
+ // `@SuppressLing("InflateParams")` removes the warning about using null as the parent view group when inflating the alert dialog.
+ @SuppressLint("InflateParams")
+ @Override
+ @NonNull
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ // Get a handle for the arguments.
+ Bundle arguments = getArguments();
+
+ // Remove the incorrect lint warning that the arguments might be null.
+ assert arguments != null;
+
+ // Get the save type.
+ int saveType = arguments.getInt("save_type");
+
+ // Get a handle for the activity and the context.
+ Activity activity = getActivity();
+ Context context = getContext();
+
+ // Remove the incorrect lint warnings below that the activity and context might be null.
+ assert activity != null;
+ assert context != null;
+
+ // Get a handle for the shared preferences.
+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
+
+ // Get the screenshot and theme preferences.
+ boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
+ boolean allowScreenshots = sharedPreferences.getBoolean("allow_screenshots", false);
+
+ // Use an alert dialog builder to create the alert dialog.
+ AlertDialog.Builder dialogBuilder;
+
+ // Set the style and icon according to the theme.
+ if (darkTheme) {
+ // Set the style.
+ dialogBuilder = new AlertDialog.Builder(activity, R.style.PrivacyBrowserAlertDialogDark);
+
+ // Set the icon according to the save type.
+ switch (saveType) {
+ case ARCHIVE:
+ dialogBuilder.setIcon(R.drawable.dom_storage_cleared_dark);
+ break;
+
+ case IMAGE:
+ dialogBuilder.setIcon(R.drawable.images_enabled_dark);
+ break;
+ }
+ } else {
+ // Set the style.
+ dialogBuilder = new AlertDialog.Builder(activity, R.style.PrivacyBrowserAlertDialogLight);
+
+ // Set the icon according to the save type.
+ switch (saveType) {
+ case ARCHIVE:
+ dialogBuilder.setIcon(R.drawable.dom_storage_cleared_light);
+ break;
+
+ case IMAGE:
+ dialogBuilder.setIcon(R.drawable.images_enabled_light);
+ break;
+ }
+ }
+
+ // Set the title according to the type.
+ switch (saveType) {
+ case ARCHIVE:
+ dialogBuilder.setTitle(R.string.save_archive);
+ break;
+
+ case IMAGE:
+ dialogBuilder.setTitle(R.string.save_image);
+ break;
+ }
+
+ // Set the view. The parent view is null because it will be assigned by the alert dialog.
+ dialogBuilder.setView(activity.getLayoutInflater().inflate(R.layout.save_dialog, null));
+
+ // Set the cancel button listener. Using `null` as the listener closes the dialog without doing anything else.
+ dialogBuilder.setNegativeButton(R.string.cancel, null);
+
+ // Set the save button listener.
+ dialogBuilder.setPositiveButton(R.string.save, (DialogInterface dialog, int which) -> {
+ // Return the dialog fragment to the parent activity.
+ saveWebpageListener.onSaveWebpage(saveType, this);
+ });
+
+ // Create an alert dialog from the builder.
+ AlertDialog alertDialog = dialogBuilder.create();
+
+ // Remove the incorrect lint warning below that `getWindow()` might be null.
+ assert alertDialog.getWindow() != null;
+
+ // Disable screenshots if not allowed.
+ if (!allowScreenshots) {
+ alertDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
+ }
+
+ // The alert dialog must be shown before items in the layout can be modified.
+ alertDialog.show();
+
+ // Get handles for the layout items.
+ EditText fileNameEditText = alertDialog.findViewById(R.id.file_name_edittext);
+ Button browseButton = alertDialog.findViewById(R.id.browse_button);
+ TextView storagePermissionTextView = alertDialog.findViewById(R.id.storage_permission_textview);
+ Button saveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
+
+ // Create a default file name string.
+ String defaultFileName = "";
+
+ // Set the default file name according to the type.
+ switch (saveType) {
+ case ARCHIVE:
+ defaultFileName = getString(R.string.webpage_mht);
+ break;
+
+ case IMAGE:
+ defaultFileName = getString(R.string.webpage_png);
+ break;
+ }
+
+ // Create a string for the default file path.
+ String defaultFilePath;
+
+ // Set the default file path according to the storage permission state.
+ if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { // The storage permission has been granted.
+ // Set the default file path to use the external public directory.
+ defaultFilePath = Environment.getExternalStorageDirectory() + "/" + defaultFileName;
+ } else { // The storage permission has not been granted.
+ // Set the default file path to use the external private directory.
+ defaultFilePath = context.getExternalFilesDir(null) + "/" + defaultFileName;
+ }
+
+ // Display the default file path.
+ fileNameEditText.setText(defaultFilePath);
+
+ // Update the status of the save button when the file name changes.
+ fileNameEditText.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 s) {
+ // // Enable the save button if a file name exists.
+ saveButton.setEnabled(!fileNameEditText.getText().toString().isEmpty());
+ }
+ });
+
+ // Handle clicks on the browse button.
+ browseButton.setOnClickListener((View view) -> {
+ // Create the file picker intent.
+ Intent browseIntent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+
+ // Set the intent MIME type to include all files so that everything is visible.
+ browseIntent.setType("*/*");
+
+ // Set the initial file name according to the type.
+ switch (saveType) {
+ case ARCHIVE:
+ browseIntent.putExtra(Intent.EXTRA_TITLE, getString(R.string.webpage_mht));
+ break;
+
+ case IMAGE:
+ browseIntent.putExtra(Intent.EXTRA_TITLE, getString(R.string.webpage_png));
+ break;
+ }
+
+ // Set the initial directory if the minimum API >= 26.
+ if (Build.VERSION.SDK_INT >= 26) {
+ browseIntent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.getExternalStorageDirectory());
+ }
+
+ // Request a file that can be opened.
+ browseIntent.addCategory(Intent.CATEGORY_OPENABLE);
+
+ // Start the file picker. This must be started under `activity` so that the request code is returned correctly.
+ activity.startActivityForResult(browseIntent, MainWebViewActivity.BROWSE_SAVE_WEBPAGE_REQUEST_CODE);
+ });
+
+ // Hide the storage permission text view on API < 23 as permissions on older devices are automatically granted.
+ if (Build.VERSION.SDK_INT < 23) {
+ storagePermissionTextView.setVisibility(View.GONE);
+ }
+
+ // Return the alert dialog.
+ return alertDialog;
+ }
+}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright © 2019 Soren Stoutner <soren@stoutner.com>.
- *
- * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
- *
- * Privacy Browser 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.
- *
- * Privacy Browser 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 Privacy Browser. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.stoutner.privacybrowser.dialogs;
-
-import android.Manifest;
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Environment;
-import android.provider.DocumentsContract;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.core.content.ContextCompat;
-import androidx.fragment.app.DialogFragment;
-import androidx.preference.PreferenceManager;
-
-import com.stoutner.privacybrowser.R;
-import com.stoutner.privacybrowser.activities.MainWebViewActivity;
-
-public class SaveWebpageImageDialog extends DialogFragment {
- // Define the save webpage image listener.
- private SaveWebpageImageListener saveWebpageImageListener;
-
- // The public interface is used to send information back to the parent activity.
- public interface SaveWebpageImageListener {
- void onSaveWebpageImage(DialogFragment dialogFragment);
- }
-
- @Override
- public void onAttach(@NonNull Context context) {
- // Run the default commands.
- super.onAttach(context);
-
- // Get a handle for the save webpage image listener from the launching context.
- saveWebpageImageListener = (SaveWebpageImageListener) context;
- }
-
- // `@SuppressLing("InflateParams")` removes the warning about using null as the parent view group when inflating the alert dialog.
- @SuppressLint("InflateParams")
- @Override
- @NonNull
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- // Get a handle for the activity and the context.
- Activity activity = getActivity();
- Context context = getContext();
-
- // Remove the incorrect lint warnings below that the activity and context might be null.
- assert activity != null;
- assert context != null;
-
- // Get a handle for the shared preferences.
- SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
-
- // Get the screenshot and theme preferences.
- boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
- boolean allowScreenshots = sharedPreferences.getBoolean("allow_screenshots", false);
-
- // Use an alert dialog builder to create the alert dialog.
- AlertDialog.Builder dialogBuilder;
-
- // Set the style and icon according to the theme.
- if (darkTheme) {
- dialogBuilder = new AlertDialog.Builder(activity, R.style.PrivacyBrowserAlertDialogDark);
- dialogBuilder.setIcon(R.drawable.images_enabled_dark);
- } else {
- dialogBuilder = new AlertDialog.Builder(activity, R.style.PrivacyBrowserAlertDialogLight);
- dialogBuilder.setIcon(R.drawable.images_enabled_light);
- }
-
- // Set the title.
- dialogBuilder.setTitle(R.string.save_image);
-
- // Set the view. The parent view is null because it will be assigned by the alert dialog.
- dialogBuilder.setView(activity.getLayoutInflater().inflate(R.layout.save_dialog, null));
-
- // Set the cancel button listener. Using `null` as the listener closes the dialog without doing anything else.
- dialogBuilder.setNegativeButton(R.string.cancel, null);
-
- // Set the save button listener.
- dialogBuilder.setPositiveButton(R.string.save, (DialogInterface dialog, int which) -> {
- // Return the dialog fragment to the parent activity.
- saveWebpageImageListener.onSaveWebpageImage(this);
- });
-
- // Create an alert dialog from the builder.
- AlertDialog alertDialog = dialogBuilder.create();
-
- // Remove the incorrect lint warning below that `getWindow()` might be null.
- assert alertDialog.getWindow() != null;
-
- // Disable screenshots if not allowed.
- if (!allowScreenshots) {
- alertDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
- }
-
- // The alert dialog must be shown before items in the layout can be modified.
- alertDialog.show();
-
- // Get handles for the layout items.
- EditText fileNameEditText = alertDialog.findViewById(R.id.file_name_edittext);
- Button browseButton = alertDialog.findViewById(R.id.browse_button);
- TextView storagePermissionTextView = alertDialog.findViewById(R.id.storage_permission_textview);
- Button saveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
-
- // Create a string for the default file path.
- String defaultFilePath;
-
- // Set the default file path according to the storage permission state.
- if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { // The storage permission has been granted.
- // Set the default file path to use the external public directory.
- defaultFilePath = Environment.getExternalStorageDirectory() + "/" + getString(R.string.webpage_png);
- } else { // The storage permission has not been granted.
- // Set the default file path to use the external private directory.
- defaultFilePath = context.getExternalFilesDir(null) + "/" + getString(R.string.webpage_png);
- }
-
- // Display the default file path.
- fileNameEditText.setText(defaultFilePath);
-
- // Update the status of the save button when the file name changes.
- fileNameEditText.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 s) {
- // // Enable the save button if a file name exists.
- saveButton.setEnabled(!fileNameEditText.getText().toString().isEmpty());
- }
- });
-
- // Handle clicks on the browse button.
- browseButton.setOnClickListener((View view) -> {
- // Create the file picker intent.
- Intent browseIntent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
-
- // Set the intent MIME type to include all files so that everything is visible.
- browseIntent.setType("*/*");
-
- // Set the initial file name.
- browseIntent.putExtra(Intent.EXTRA_TITLE, getString(R.string.webpage_png));
-
- // Set the initial directory if the minimum API >= 26.
- if (Build.VERSION.SDK_INT >= 26) {
- browseIntent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.getExternalStorageDirectory());
- }
-
- // Request a file that can be opened.
- browseIntent.addCategory(Intent.CATEGORY_OPENABLE);
-
- // Start the file picker. This must be started under `activity` so that the request code is returned correctly.
- activity.startActivityForResult(browseIntent, MainWebViewActivity.BROWSE_SAVE_WEBPAGE_IMAGE_REQUEST_CODE);
- });
-
- // Hide the storage permission text view on API < 23 as permissions on older devices are automatically granted.
- if (Build.VERSION.SDK_INT < 23) {
- storagePermissionTextView.setVisibility(View.GONE);
- }
-
- // Return the alert dialog.
- return alertDialog;
- }
-}
\ No newline at end of file
// The public interface is used to send information back to the parent activity.
public interface StoragePermissionDialogListener {
- void onCloseStoragePermissionDialog();
+ void onCloseStoragePermissionDialog(int saveType);
}
@Override
storagePermissionDialogListener = (StoragePermissionDialogListener) context;
}
+ public static StoragePermissionDialog displayDialog(int saveType) {
+ // Create an arguments bundle.
+ Bundle argumentsBundle = new Bundle();
+
+ // Store the save type in the bundle.
+ argumentsBundle.putInt("save_type", saveType);
+
+ // Create a new instance of the storage permission dialog.
+ StoragePermissionDialog storagePermissionDialog = new StoragePermissionDialog();
+
+ // Add the arguments bundle to the new dialog.
+ storagePermissionDialog.setArguments(argumentsBundle);
+
+ // Return the new dialog.
+ return storagePermissionDialog;
+ }
+
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- // Use a builder to create the alert dialog.
- AlertDialog.Builder dialogBuilder;
+ // Get a handle for the arguments.
+ Bundle arguments = getArguments();
+
+ // Remove the incorrect lint warning that the arguments might be null.
+ assert arguments != null;
+
+ // Get the save type.
+ int saveType = arguments.getInt("save_type");
// Get a handle for the shared preferences.
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
boolean allowScreenshots = sharedPreferences.getBoolean("allow_screenshots", false);
+ // Use a builder to create the alert dialog.
+ AlertDialog.Builder dialogBuilder;
+
// Set the style and the icon according to the theme.
if (darkTheme) {
dialogBuilder = new AlertDialog.Builder(getActivity(), R.style.PrivacyBrowserAlertDialogDark);
// Set the text.
dialogBuilder.setMessage(R.string.storage_permission_message);
- // Set an `onClick` listener on the negative button.
+ // Set an listener on the OK button.
dialogBuilder.setNegativeButton(R.string.ok, (DialogInterface dialog, int which) -> {
// Inform the parent activity that the dialog was closed.
- storagePermissionDialogListener.onCloseStoragePermissionDialog();
+ storagePermissionDialogListener.onCloseStoragePermissionDialog(saveType);
});
// Create an alert dialog from the builder.
alertDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
- // `onCreateDialog()` requires the return of an `AlertDialog`.
+ // Return the alert dialog.
return alertDialog;
}
}
\ No newline at end of file
-<!-- `import_export_dark.xml` comes from the Android Material icon set, where it is called `import_export`. It is released under the Apache License 2.0. -->
+<!-- This drawable comes from the Android Material icon set, where it is called `import_export`. It is released under the Apache License 2.0. -->
<!-- `tools:ignore="VectorRaster"` removes the lint warning about `android:autoMirrored="true"` not applying to API < 21. -->
<vector
<!-- A hard coded color must be used until API >= 21. Then `@color` may be used. -->
<path
- android:fillColor="#FFE0E0E0"
+ android:fillColor="#FF1E88E5"
android:pathData="M9,3L5,6.99h3L8,14h2L10,6.99h3L9,3zM16,17.01L16,10h-2v7.01h-3L15,21l4,-3.99h-3z" />
-</vector>
+</vector>
\ No newline at end of file
-<!-- `import_export_light.xml` comes from the Android Material icon set, where it is called `import_export`. It is released under the Apache License 2.0. -->
+<!-- This drawable comes from the Android Material icon set, where it is called `import_export`. It is released under the Apache License 2.0. -->
<!-- `tools:ignore="VectorRaster"` removes the lint warning about `android:autoMirrored="true"` not applying to API < 21. -->
<vector
<!-- A hard coded color must be used until API >= 21. Then `@color` may be used. -->
<path
- android:fillColor="#FF000000"
+ android:fillColor="#FF1565C0"
android:pathData="M9,3L5,6.99h3L8,14h2L10,6.99h3L9,3zM16,17.01L16,10h-2v7.01h-3L15,21l4,-3.99h-3z" />
-</vector>
+</vector>
\ No newline at end of file
android:id="@+id/font_size"
android:title="@string/font_size"
android:orderInCategory="1070"
- app:showAsAction="never" >
- </item>
+ app:showAsAction="never" />
<item
android:id="@+id/find_on_page"
app:showAsAction="never" />
<item
- android:id="@+id/save_as_image"
- android:title="@string/save_as_image"
+ android:id="@+id/save"
+ android:title="@string/save"
android:orderInCategory="1100"
- app:showAsAction="never" />
+ app:showAsAction="never" >
+
+ <menu>
+ <item
+ android:id="@+id/save_as_archive"
+ android:title="@string/save_as_archive"
+ android:orderInCategory="1101"
+ app:showAsAction="never" />
+
+ <item
+ android:id="@+id/save_as_image"
+ android:title="@string/save_as_image"
+ android:orderInCategory="1102"
+ app:showAsAction="never" />
+ </menu>
+ </item>
<item
android:id="@+id/add_to_homescreen"
<string name="find_on_page">Auf Seite finden</string>
<string name="print">Drucken</string>
<string name="privacy_browser_web_page">Privacy Browser-Website</string>
- <string name="save_as_image">Als Grafik speichern</string>
+ <string name="save">Speichern</string>
+ <string name="save_as_image">Als Grafik speichern</string>
<string name="view_source">Quelltext anzeigen</string>
<string name="add_to_home_screen">Zur Startseite hinzufügen</string>
<string name="share">Teilen</string>
<string name="edit_folder">Ordner bearbeiten</string>
<string name="move_to_folder">In Ordner verschieben</string>
<string name="move">Verschieben</string>
- <string name="save">Speichern</string>
<!-- Bookmarks Contextual App Bar. -->
<string name="selected">Ausgewählt:</string> <!--This is a plural adjective.-->
<string name="i2p_not_installed_title">I2P ist nicht installiert</string>
<string name="i2p_not_installed_message">Der I2P-Proxy kann erst nach Installation der I2P-App genutzt werden.</string>
<string name="waiting_for_orbot">Warte auf die Verbindung zum Orbot-Proxy.</string>
+ <string name="custom_proxy_invalid">Die benutzerdefinierte Proxy-URL ist ungültig.</string>
+ <string name="socks_proxies_do_not_work_on_kitkat">SOCKS-Proxies funktionieren nicht unter Android KitKat.</string>
<!-- About Activity. -->
<string name="about_privacy_browser">Über Privacy Browser</string>
<item>I2P</item>
<item>Benutzerdefiniert</item>
</string-array>
+ <string name="no_proxy_enabled">Keiner - direkte Verbindung zum Internet.</string>
+ <string name="tor_enabled">Tor - Verbidnung über socks://localhost:9050.</string>
+ <string name="tor_enabled_kitkat">Tor - Verbidnung über http://localhost:8118.</string>
+ <string name="i2p_enabled">I2P - Verbindung über http://localhost:4444.</string>
<string name="custom_proxy">Benutzerdefinierter Proxy</string>
+ <string name="proxy_custom_url">Benutzerdefinierte Proxy-URL</string>
<string name="full_screen">Vollbild-Modus</string>
<string name="full_screen_browsing_mode">Vollbild-Browser-Modus</string>
<string name="full_screen_browsing_mode_summary">Doppel-Tippen, um zwischen normalem und Vollbild-Modus umzuschalten.</string>
<string name="find_on_page">Buscar en página</string>
<string name="print">Imprimir</string>
<string name="privacy_browser_web_page">Página web de Navegador Privado</string>
- <string name="save_as_image">Guardar como imagen</string>
+ <string name="save">Guardar</string>
+ <string name="save_as_image">Guardar como imagen</string>
<string name="add_to_home_screen">Añadir a la ventana de inicio</string>
<string name="view_source">Ver la fuente</string>
<string name="share">Compartir</string>
<string name="edit_folder">Editar carpeta</string>
<string name="move_to_folder">Mover a carpeta</string>
<string name="move">Mover</string>
- <string name="save">Guardar</string>
<!-- Bookmarks Contextual App Bar. -->
<string name="selected">Seleccionados:</string> <!--This is a plural adjective.-->
<string name="i2p_not_installed_title">I2P No Instalado</string>
<string name="i2p_not_installed_message">El proxy a través de I2P no funcionará a menos que la aplicación I2P esté instalada.</string>
<string name="waiting_for_orbot">Esperando a que Orbot se conecte.</string>
+ <string name="custom_proxy_invalid">La URL del proxy personalizado no es válida.</string>
+ <string name="socks_proxies_do_not_work_on_kitkat">SOCKS proxies do not work on Android KitKat.</string>
<!-- About Activity. -->
<string name="about_privacy_browser">Acerca de Navegador Privado</string>
<item>Yahoo - Javascript habilitado</item>
<item>Personalizado</item>
</string-array>
+ <string name="no_proxy_enabled">Ninguno - conectar directamente a Internet.</string>
+ <string name="tor_enabled">Tor - conectar a través de socks://localhost:9050.</string>
+ <string name="tor_enabled_kitkat">Tor - conectar a través de http://localhost:8118.</string>
+ <string name="i2p_enabled">I2P - conectar a través de http://localhost:4444.</string>
<string name="search_custom_url">URL personalizado de búsqueda</string>
<string name="custom_url">URL personalizado</string>
+ <string name="proxy_custom_url">URL personalizada del proxy</string>
<string name="proxy">Proxy</string>
<string name="proxy_none">Ninguno</string>
<string name="proxy_tor">Tor</string>
<string name="find_on_page">Chercher sur la page</string>
<string name="print">Imprimer</string>
<string name="privacy_browser_web_page">Site Web de Privacy Browser</string>
- <string name="save_as_image">Sauvergarder comme image</string>
+ <string name="save">Sauvegarder</string>
+ <string name="save_as_image">Sauvergarder comme image</string>
<string name="add_to_home_screen">Ajouter à l\'écran d\'accueil</string>
<string name="view_source">Voir Source</string>
<string name="share">Partager</string>
<string name="edit_folder">Editer dossier</string>
<string name="move_to_folder">Déplacer vers dossier</string>
<string name="move">Déplacer</string>
- <string name="save">Sauvegarder</string>
<!-- Bookmarks Contextual App Bar. -->
<string name="selected">Selectionnés :</string> <!--This is a plural adjective.-->
<string name="i2p_not_installed_title">I2P non installé</string>
<string name="i2p_not_installed_message">Le proxy via I2P ne fonctionnera que si l\'application I2P est installée.</string>
<string name="waiting_for_orbot">En attente de la connexion d\'Orbot.</string>
+ <string name="custom_proxy_invalid">L\'URL du proxy personnalisé n\'est pas valide.</string>
+ <string name="socks_proxies_do_not_work_on_kitkat">Les proxys de type SOCKS ne fonctionnent pas sur Android KitKat.</string>
<!-- About Activity. -->
<string name="about_privacy_browser">À propos</string>
<item>I2P</item>
<item>Personnalisé</item>
</string-array>
+ <string name="no_proxy_enabled">Aucun - Connectez-vous directement à Internet.</string>
+ <string name="tor_enabled">Tor - Connectez-vous via socks://localhost:9050.</string>
+ <string name="tor_enabled_kitkat">Tor - Connectez-vous via http://localhost:8118.</string>
+ <string name="i2p_enabled">I2P - Connectez-vous via http://localhost:4444.</string>
<string name="custom_proxy">Proxy personnalisé</string>
+ <string name="proxy_custom_url">URL personnalisée du proxy</string>
<string name="full_screen">Plein écran</string>
<string name="full_screen_browsing_mode">Navigation plein écran</string>
<string name="full_screen_browsing_mode_summary">Appuyez deux fois pour basculer en mode de navigation en plein écran.</string>
<string name="find_on_page">Cerca nella pagina</string>
<string name="print">Stampa</string>
<string name="privacy_browser_web_page">Pagina web di Privacy Browser</string>
- <string name="save_as_image">Salva come Immagine</string>
+ <string name="save">Salva</string>
+ <string name="save_as_image">Salva come Immagine</string>
<string name="add_to_home_screen">Aggiungi collegamento</string>
<string name="view_source">Visualizza sorgente</string>
<string name="share">Condividi</string>
<string name="edit_folder">Modifica Cartella</string>
<string name="move_to_folder">Sposta nella Cartella</string>
<string name="move">Sposta</string>
- <string name="save">Salva</string>
<!-- Bookmarks Contextual App Bar. -->
<string name="selected">Selezionato:</string> <!--This is a plural adjective.-->
<string name="overview">Descrizione</string>
<string name="local_storage">Archiviazione Locale</string>
<string name="ssl_certificates">Certificati SSL</string>
+ <string name="proxies">Proxy</string>
<string name="tracking_ids">Tracciamento utenti</string>
<!-- Download Location -->
Nel caso in cui il permesso sia negato sarà utilizzata la cartella di download dell\'applicazione.</string>
<string name="ok">OK</string>
- <!-- Orbot. -->
+ <!-- Proxy. -->
+ <string name="orbot_not_installed_title">Orbot Non Installato</string>
+ <string name="orbot_not_installed_message">Il Proxy con Orbot non funziona se non è installata la app Orbot.</string>
+ <string name="i2p_not_installed_title">I2P Non Installato</string>
+ <string name="i2p_not_installed_message">Il Proxy con I2P non funziona se non è installata la app I2P.</string>
<string name="waiting_for_orbot">In attesa della connessione di Orbot.</string>
+ <string name="custom_proxy_invalid">La URL del proxy personalizzato non è valida.</string>
+ <string name="socks_proxies_do_not_work_on_kitkat">I proxy SOCKS non funzionano con Android KitKat.</string>
<!-- About Activity. -->
<string name="about_privacy_browser">Informazioni su Privacy Browser</string>
<string name="webview_provider">Provider di WebView:</string>
<string name="webview_version">Versione di WebView:</string>
<string name="orbot">Orbot:</string>
+ <string name="i2p">I2P:</string>
<string name="openkeychain">OpenKeychain:</string>
<string name="easylist_label">EasyList:</string>
<string name="easyprivacy_label">EasyPrivacy:</string>
</string-array>
<string name="search_custom_url">Ricerca personalizzata</string>
<string name="custom_url">URL Personalizzata</string>
+ <string name="proxy">Proxy</string>
+ <string name="proxy_none">Nessuno</string>
+ <string name="proxy_tor">Tor</string>
+ <string name="proxy_i2p">I2P</string>
+ <string name="proxy_custom">Personalizzato</string>
+ <string-array name="proxy_entries">
+ <item>Nessuno</item>
+ <item>Tor</item>
+ <item>I2P</item>
+ <item>Personalizzato</item>
+ </string-array>
+ <string name="no_proxy_enabled">Nessuno - connessione diretta a internet.</string>
+ <string name="tor_enabled">Tor - connessione con socks://localhost:9050.</string>
+ <string name="tor_enabled_kitkat">Tor - connessione con http://localhost:8118.</string>
+ <string name="i2p_enabled">I2P - connessione con http://localhost:4444.</string>
+ <string name="custom_proxy">Proxy personalizzato</string>
+ <string name="proxy_custom_url">URL personalizzata del Proxy</string>
<string name="full_screen">Schermo intero</string>
<string name="full_screen_browsing_mode">Navigazione a schermo intero</string>
<string name="full_screen_browsing_mode_summary">Toccare due volte per avviare la navigazione a schermo intero.</string>
<string name="find_on_page">Найти на странице</string>
<string name="print">Печать</string>
<string name="privacy_browser_web_page">Privacy Browser веб-страница</string>
- <string name="save_as_image">Сохранить как изображение</string>
+ <string name="save">Сохранить</string>
+ <string name="save_as_image">Сохранить как изображение</string>
<string name="add_to_home_screen">Добавить на главный экран</string>
<string name="view_source">Просмотр исходного кода</string>
<string name="share">Поделиться</string>
<string name="edit_folder">Изменить папку</string>
<string name="move_to_folder">Переместить в папку</string>
<string name="move">Переместить</string>
- <string name="save">Сохранить</string>
<!-- Bookmarks Contextual App Bar. -->
<string name="selected">выбраны:</string> <!--This is a plural adjective.-->
<string name="i2p_not_installed_title">I2P не установлен</string>
<string name="i2p_not_installed_message">Прокси через I2P работать не будет, если приложение I2P не установлено.</string>
<string name="waiting_for_orbot">Ожидание подключения Orbot.</string>
+ <string name="custom_proxy_invalid">URL пользовательского прокси недействителен.</string>
+ <string name="socks_proxies_do_not_work_on_kitkat">SOCKS-прокси не работает на Android KitKat.</string>
<!-- About Activity. -->
<string name="about_privacy_browser">О Privacy Browser</string>
<item>I2P</item>
<item>Пользовательский</item>
</string-array>
+ <string name="no_proxy_enabled">Нет - подключиться к интернету напрямую.</string>
+ <string name="tor_enabled">Tor - connect through socks://localhost:9050.</string>
+ <string name="tor_enabled_kitkat">Tor - подключиться через http://localhost:8118.</string>
+ <string name="i2p_enabled">I2P - подключиться через http://localhost:4444.</string>
<string name="custom_proxy">Пользовательский прокси</string>
+ <string name="proxy_custom_url">URL пользовательского прокси</string>
<string name="full_screen">Во весь экран</string>
<string name="full_screen_browsing_mode">Полноэкранный режим просмотра</string>
<string name="full_screen_browsing_mode_summary">Двойное касание переключает режим просмотра.</string>
<string name="find_on_page">Sayfada bul</string>
<string name="print">Yazdır</string>
<string name="privacy_browser_web_page">Privacy Browser Web Sayfası</string>
- <string name="save_as_image">Resmi farklı kaydet</string>
+ <string name="save">Kaydet</string>
+ <string name="save_as_image">Resmi farklı kaydet</string>
<string name="add_to_home_screen">Ana ekrana ekle</string>
<string name="view_source">Kaynağı görüntüle</string>
<string name="share">Paylaş</string>
<string name="edit_folder">Klasörü düzenle</string>
<string name="move_to_folder">Klasöre taşı</string>
<string name="move">Taşı</string>
- <string name="save">Kaydet</string>
<!-- Bookmarks Contextual App Bar. -->
<string name="selected">Seçili:</string> <!--This is a plural adjective.-->
<string name="find_on_page">Find on Page</string>
<string name="print">Print</string>
<string name="privacy_browser_web_page">Privacy Browser Web Page</string>
- <string name="save_as_image">Save as Image</string>
+ <string name="save">Save</string>
+ <string name="save_as_archive">Save as Archive</string>
+ <string name="save_as_image">Save as Image</string>
<string name="add_to_home_screen">Add to Home Screen</string>
<string name="view_source">View Source</string>
<string name="share">Share</string>
<string name="previous">Previous</string>
<string name="next">Next</string>
- <!-- Save Webpage as Image. -->
+ <!-- Save Webpage. -->
+ <string name="save_webpage">Save Webpage</string>
+ <string name="save_archive">Save Archive</string>
<string name="save_image">Save Image</string>
+ <string name="webpage_mht">Webpage.mht</string>
<string name="webpage_png">Webpage.png</string>
<string name="saving_image">Saving image…</string>
<string name="image_saved">Image saved.</string>
<string name="edit_folder">Edit Folder</string>
<string name="move_to_folder">Move to Folder</string>
<string name="move">Move</string>
- <string name="save">Save</string>
<!-- Bookmarks Contextual App Bar. -->
<string name="selected">Selected:</string> <!--This is a plural adjective.-->
</string-array>
<string name="no_proxy_enabled">None - connect directly to the internet.</string>
<string name="tor_enabled">Tor - connect through socks://localhost:9050.</string>
- <string name="tor_enabled_kitkat">Tor - connect through http://localhost:8118</string>
+ <string name="tor_enabled_kitkat">Tor - connect through http://localhost:8118.</string>
<string name="i2p_enabled">I2P - connect through http://localhost:4444.</string>
<string name="custom_proxy">Custom proxy</string>
<string name="proxy_custom_url">Proxy custom URL</string>