From 96fd2b4338ea6dd9520605b2ef290e38ef044f1f Mon Sep 17 00:00:00 2001 From: Soren Stoutner Date: Tue, 27 Dec 2022 13:30:44 -0700 Subject: [PATCH] Update the file name when the URL changes in SaveDialog. https://redmine.stoutner.com/issues/781 --- app/src/main/assets/de/about_licenses.html | 18 +- app/src/main/assets/en/about_licenses.html | 18 +- app/src/main/assets/es/about_licenses.html | 18 +- app/src/main/assets/fr/about_licenses.html | 18 +- app/src/main/assets/it/about_licenses.html | 18 +- .../main/assets/pt-rBR/about_licenses.html | 46 +-- .../main/assets/pt-rBR/about_permissions.html | 2 +- .../main/assets/pt-rBR/guide_interface.html | 3 +- app/src/main/assets/ru/about_licenses.html | 18 +- app/src/main/assets/tr/about_licenses.html | 18 +- .../activities/MainWebViewActivity.java | 11 +- .../coroutines/PrepareSaveDialogCoroutine.kt | 169 +----------- .../privacybrowser/dialogs/SaveDialog.kt | 21 +- .../helpers/GetUrlSizeHelper.kt | 97 ------- .../helpers/SanitizeUrlHelper.kt | 8 +- .../privacybrowser/helpers/UrlHelper.kt | 261 ++++++++++++++++++ 16 files changed, 376 insertions(+), 368 deletions(-) delete mode 100644 app/src/main/java/com/stoutner/privacybrowser/helpers/GetUrlSizeHelper.kt create mode 100644 app/src/main/java/com/stoutner/privacybrowser/helpers/UrlHelper.kt diff --git a/app/src/main/assets/de/about_licenses.html b/app/src/main/assets/de/about_licenses.html index 3d6411eb..9e404c05 100644 --- a/app/src/main/assets/de/about_licenses.html +++ b/app/src/main/assets/de/about_licenses.html @@ -64,36 +64,36 @@

Icons:

- are derived from security and language, which are part of the Android Material icon set and are released under the + are derived from security and language, which are part of the Android Material icon set and are released under the Apache License 2.0. The full text of the license is below. Modifications copyright 2016 Soren Stoutner. The resulting images are released under the GPLv3+ license.

is derived from elements of folder and exit_to_app, - which are part of the Android Material icon set + which are part of the Android Material icon set and are released under the Apache License 2.0. Modifications copyright 2017, 2022 Soren Stoutner. The resulting image is released under the GPLv3+ license.

is derived from elements of bookmark and create_new_folder, which are part of the - Android Material icon set and are released under the Apache License 2.0. + Android Material icon set and are released under the Apache License 2.0. Modifications copyright 2017, 2022 Soren Stoutner. The resulting image is released under the GPLv3+ license.

ist abgeleitet von create_new_folder, - das Teil des Android Material icon set unter der Apache Lizenz 2.0 veröffentlicht wird. + das Teil des Android Material icon set unter der Apache Lizenz 2.0 veröffentlicht wird. Änderungen Copyright 2017, 2022 Soren Stoutner. Die resultierende Grafik wird unter der GPLv3+ Lizenz veröffentlicht.

ist abgeleitet von exit_to_app, - das Teil des Android Material icon set unter der Apache Lizenz 2.0 veröffentlicht wird. + das Teil des Android Material icon set unter der Apache Lizenz 2.0 veröffentlicht wird. Änderungen Copyright 2017, 2022 Soren Stoutner. Die resultierende Grafik wird unter der GPLv3+ Lizenz veröffentlicht.

ist abgeleitet von compare, - das Teil des Android Material icon set unter der Apache Lizenz 2.0 veröffentlicht wird. + das Teil des Android Material icon set unter der Apache Lizenz 2.0 veröffentlicht wird. Änderungen Copyright 2017, 2022 Soren Stoutner. Die resultierende Grafik wird unter der GPLv3+ Lizenz veröffentlicht.

-

ist abgeleitet von sort, das Teil des Android Material icon set +

ist abgeleitet von sort, das Teil des Android Material icon set unter der Apache Lizenz 2.0 veröffentlicht wird. Änderungen Copyright 2019, 2022 Soren Stoutner. Die resultierende Grafik wird unter der GPLv3+ Lizenz veröffentlicht.

ist abgeleitet von push_pin_selected, - das Teil des Android Material icon set unter der Apache Lizenz 2.0 veröffentlicht wird. + das Teil des Android Material icon set unter der Apache Lizenz 2.0 veröffentlicht wird. Änderungen Copyright 2019-2020, 2022 Soren Stoutner. Die resultierende Grafik wird unter der GPLv3+ Lizenz veröffentlicht.

cookie was created by Google. @@ -104,7 +104,7 @@ welches unter der AGPLv3+ Lizenz veröffentlicht wird. Den gesamte Text dieser Lizenz finden Sie unterhalb. Das Bild ist ein unverändertes Exzerpt zur Darstellung von Layout-Informationen wie Farbe, Größe und Rahmen. Es ist in Privacy Browser unter Beachtung der Bestimmungen von Sektion 13 der Lizenz enthalten.

-

The following icons come from the Android Material icon set, +

The following icons come from the Android Material icon set, which is released under the Apache License 2.0. They are unchanged except for layout information like color and size. Some of them have been renamed to match their use in the code. The original icons and names are shown below.

add.

diff --git a/app/src/main/assets/en/about_licenses.html b/app/src/main/assets/en/about_licenses.html index 5814f18d..e1528674 100644 --- a/app/src/main/assets/en/about_licenses.html +++ b/app/src/main/assets/en/about_licenses.html @@ -61,36 +61,36 @@

Icons

- are derived from security and language, which are part of the Android Material icon set and are released under the + are derived from security and language, which are part of the Android Material icon set and are released under the Apache License 2.0. The full text of the license is below. Modifications copyright 2016 Soren Stoutner. The resulting images are released under the GPLv3+ license.

is derived from elements of folder and exit_to_app, - which are part of the Android Material icon set + which are part of the Android Material icon set and are released under the Apache License 2.0. Modifications copyright 2017, 2022 Soren Stoutner. The resulting image is released under the GPLv3+ license.

is derived from elements of bookmark and create_new_folder, which are part of the - Android Material icon set and are released under the Apache License 2.0. + Android Material icon set and are released under the Apache License 2.0. Modifications copyright 2017, 2022 Soren Stoutner. The resulting image is released under the GPLv3+ license.

is derived from create_new_folder, - which is part of the Android Material icon set and is released under the Apache License 2.0. + which is part of the Android Material icon set and is released under the Apache License 2.0. Modifications copyright 2017, 2022 Soren Stoutner. The resulting image is released under the GPLv3+ license.

is derived from exit_to_app, - which is part of the Android Material icon set and is released under the Apache License 2.0. + which is part of the Android Material icon set and is released under the Apache License 2.0. Modifications copyright 2017, 2022 Soren Stoutner. The resulting image is released under the GPLv3+ license.

is derived from compare, - which is part of the Android Material icon set and is released under the Apache License 2.0. + which is part of the Android Material icon set and is released under the Apache License 2.0. Modifications copyright 2017, 2022 Soren Stoutner. The resulting image is released under the GPLv3+ license.

-

is derived from sort, which is part of the Android Material icon set +

is derived from sort, which is part of the Android Material icon set and is released under the Apache License 2.0. Modifications copyright 2019, 2022 Soren Stoutner. The resulting image is released under the GPLv3+ license.

is derived from push_pin_selected, - which is part of the Android Material icon set and is released under the Apache License 2.0. + which is part of the Android Material icon set and is released under the Apache License 2.0. Modifications copyright 2019-2020, 2022 Soren Stoutner. The resulting image is released under the GPLv3+ license.

cookie was created by Google. @@ -100,7 +100,7 @@ Mastodon project, which is released under the AGPLv3+ license. The full text of the license is below. The image is unchanged except for layout information like color, size, and margin. It is included in Privacy Browser under the provisions in section 13 of the license.

-

The following icons come from the Android Material icon set, +

The following icons come from the Android Material icon set, which is released under the Apache License 2.0. They are unchanged except for layout information like color and size. Some of them have been renamed to match their use in the code. The original icons and names are shown below.

add.

diff --git a/app/src/main/assets/es/about_licenses.html b/app/src/main/assets/es/about_licenses.html index 01188b45..15f85cdd 100644 --- a/app/src/main/assets/es/about_licenses.html +++ b/app/src/main/assets/es/about_licenses.html @@ -63,35 +63,35 @@

Iconos

- derivan de security y de language, que son parte del conjunto de iconos Android Material y son liberados bajo la + derivan de security y de language, que son parte del conjunto de iconos Android Material y son liberados bajo la Licencia Apache 2.0. El texto completo de la licencia se encuentra debajo. Copyright de modificaciones 2016 Soren Stoutner. Las imágenes resultantes se liberan bajo la licencia GPLv3+.

deriva de elementos de folder y exit_to_app, que son parte del - conjunto de iconos Android Material y son liberados bajo la Licencia Apache 2.0. + conjunto de iconos Android Material y son liberados bajo la Licencia Apache 2.0. Copyright de modificaciones 2017, 2022 Soren Stoutner. La imagen resultante se libera bajo la licencia GPLv3+.

deriva de elementos de bookmark y create_new_folder, que son parte del - conjunto de iconos Android Material y son liberados bajo la Licencia Apache 2.0. + conjunto de iconos Android Material y son liberados bajo la Licencia Apache 2.0. Copyright de modificaciones 2017, 2022 Soren Stoutner. La imagen resultante se libera bajo la licencia GPLv3+.

deriva de create_new_folder, - que es parte del conjunto de iconos Android Material y es liberado bajo la Licencia Apache 2.0. + que es parte del conjunto de iconos Android Material y es liberado bajo la Licencia Apache 2.0. Copyright de modificaciones 2017, 2022 Soren Stoutner. La imagen resultante se libera bajo la licencia GPLv3+.

deriva de exit_to_app, - que es parte del conjunto de iconos Android Material y es liberado bajo la Licencia Apache 2.0. + que es parte del conjunto de iconos Android Material y es liberado bajo la Licencia Apache 2.0. Copyright de modificaciones 2017, 2022 Soren Stoutner. La imagen resultante se libera bajo la licencia GPLv3+.

deriva de compare, - que es parte del conjunto de iconos Android Material y es liberado bajo la Licencia Apache 2.0. + que es parte del conjunto de iconos Android Material y es liberado bajo la Licencia Apache 2.0. Copyright de modificaciones 2017, 2022 Soren Stoutner. La imagen resultante se libera bajo la licencia GPLv3+.

-

deriva de sort, que es parte del conjunto de iconos Android Material +

deriva de sort, que es parte del conjunto de iconos Android Material y es liberado bajo la Licencia Apache 2.0. Copyright de modificaciones 2019, 2022 Soren Stoutner. La imagen resultante se libera bajo la licencia GPLv3+.

deriva de push_pin_selected, - que es parte del conjunto de iconos Android Material y es liberado bajo la Licencia Apache 2.0. + que es parte del conjunto de iconos Android Material y es liberado bajo la Licencia Apache 2.0. Copyright de modificaciones 2019-2020, 2022 Soren Stoutner. La imagen resultante se libera bajo la licencia GPLv3+.

cookie fue creado por Google. @@ -103,7 +103,7 @@ que se libera bajo la licencia AGPLv3+. El texto completo de la licencia está abajo. La imagen no ha cambiado excepto por la información de diseño como el color, el tamaño y el margen. Está incluida en el Navegador de Privacidad bajo las disposiciones de la sección 13 de la licencia.

-

Los siguientes iconos proceden de conjunto de iconos Android Material, +

Los siguientes iconos proceden de conjunto de iconos Android Material, el cual es liberado bajo la licencia Apache 2.0. Están sin cambios, excepto por la información de diseño como el color y el tamaño. Algunos de ellos se han renombrado para que coincida con su uso en el código. Los iconos y los nombres originales se muestran a continuación.

diff --git a/app/src/main/assets/fr/about_licenses.html b/app/src/main/assets/fr/about_licenses.html index 615ce34c..a18cb1bc 100644 --- a/app/src/main/assets/fr/about_licenses.html +++ b/app/src/main/assets/fr/about_licenses.html @@ -63,37 +63,37 @@

Icônes

sont dérivés de - security et de language, qui font partie de l'ensemble d'icônes Matériel Android et sont publiés sous la + security et de language, qui font partie de l'ensemble d'icônes Matériel Android et sont publiés sous la Licence Apache 2.0. Le texte complet de la licence est ci-dessous. Modifications copyright 2016 Soren Stoutner. Les images résultantes sont publiées sous la licence GPLv3+.

est dérivé des éléments folder et exit_to_app, - qui font partie de l'ensemble d'icônes Matériel Android + qui font partie de l'ensemble d'icônes Matériel Android et sont publiés sous Licence Apache 2.0. Modifications copyright 2017, 2022 Soren Stoutner. L'image résultante est publiée sous la licence GPLv3+.

est dérivé des éléments bookmark et create_new_folder, qui font partie de - l'ensemble d'icônes Matériel Android et sont publiés sous Licence Apache 2.0. + l'ensemble d'icônes Matériel Android et sont publiés sous Licence Apache 2.0. Modifications copyright 2017, 2022 Soren Stoutner. L'image résultante est publiée sous la licence GPLv3+.

est dérivée de l'élément create_new_folder, - qui fait partie de l'ensemble d'icônes Matériel Android et sont publiés sous Licence Apache 2.0. + qui fait partie de l'ensemble d'icônes Matériel Android et sont publiés sous Licence Apache 2.0. Modifications copyright 2017, 2022 Soren Stoutner. L'image résultante est publiée sous la licence GPLv3+.

est dérivée de l'élément exit_to_app, qui fait partie de - l'ensemble d'icônes Matériel Android et sont publiés sous Licence Apache 2.0. + l'ensemble d'icônes Matériel Android et sont publiés sous Licence Apache 2.0. Modifications copyright 2017, 2022 Soren Stoutner. L'image résultante est publiée sous la licence GPLv3+.

est dérivée de l'élément compare, - qui fait partie de l'ensemble d'icônes Matériel Android et sont publiés sous Licence Apache 2.0. + qui fait partie de l'ensemble d'icônes Matériel Android et sont publiés sous Licence Apache 2.0. Modifications copyright 2017, 2022 Soren Stoutner. L'image résultante est publiée sous la licence GPLv3+.

est dérivée de l'élément sort, - qui fait partie de l'ensemble d'icônes Matériel Android et sont publiés sous Licence Apache 2.0. + qui fait partie de l'ensemble d'icônes Matériel Android et sont publiés sous Licence Apache 2.0. Modifications copyright 2019, 2022 Soren Stoutner. L'image résultante est publiée sous la licence GPLv3+.

est dérivée de l'élément push_pin_selected, - qui fait partie de l'ensemble d'icônes Matériel Android et sont publiés sous Licence Apache 2.0. + qui fait partie de l'ensemble d'icônes Matériel Android et sont publiés sous Licence Apache 2.0. Modifications copyright 2019-2020, 2022 Soren Stoutner. L'image résultante est publiée sous la licence GPLv3+.

cookie a été créé par Google. @@ -105,7 +105,7 @@ qui est publié sous la licence AGPLv3+. Le texte complet de la licence est ci-dessous. L'image reste inchangée à l'exception des informations de mise en page telles que la couleur, la taille et la marge. Il est inclus dans Privacy Browser conformément aux dispositions de la section 13 de la licence.

-

Les icônes suivantes proviennent de l'ensemble d'icônes Matériel Android, +

Les icônes suivantes proviennent de l'ensemble d'icônes Matériel Android, qui est publié sous la Licence Apache 2.0. Ils sont inchangés sauf pour les informations de mise en page comme la couleur et la taille. Certains d'entre eux ont été renommés pour correspondre à leur utilisation dans le code. Les icônes et les noms d'origine sont indiqués ci-dessous.

diff --git a/app/src/main/assets/it/about_licenses.html b/app/src/main/assets/it/about_licenses.html index daf85928..ea88771a 100644 --- a/app/src/main/assets/it/about_licenses.html +++ b/app/src/main/assets/it/about_licenses.html @@ -68,36 +68,36 @@

Icone

- sono state derivate da security e language, che fanno parte dell'Android Material icon set e sono state rilasciate sotto + sono state derivate da security e language, che fanno parte dell'Android Material icon set e sono state rilasciate sotto Licenza Apache 2.0. Il testo completo della Licenza è riportato di seguito. Copyright delle modifiche 2016 Soren Stoutner. Le immagini risultanti sono rilasciate sotto Licenza GPLv3+.

è stata derivata da elementi di folder e di exit_to_app, che fanno parte - dell'Android Material icon set e sono state rilasciate sotto Licenza Apache 2.0. + dell'Android Material icon set e sono state rilasciate sotto Licenza Apache 2.0. Copyright delle modifiche 2017, 2020 Soren Stoutner. L'immagine risultante è rilasciata sotto Licenza GPLv3+.

è stata derivata da elementi di bookmark e di create_new_folder, che fanno parte - dell'Android Material icon set e sono state rilasciate sotto Licenza Apache 2.0. + dell'Android Material icon set e sono state rilasciate sotto Licenza Apache 2.0. Copyright delle modifiche 2017, 2020 Soren Stoutner. L'immagine risultante è rilasciata sotto Licenza GPLv3+.

è stata derivata da create_new_folder, - che fa parte dell'Android Material icon set ed è stata rilasciata sotto Licenza Apache 2.0. + che fa parte dell'Android Material icon set ed è stata rilasciata sotto Licenza Apache 2.0. Copyright delle modifiche 2017, 2020 Soren Stoutner. L'immagine risultante è rilasciata sotto Licenza GPLv3+.

è stata derivata da exit_to_app, - che fa parte dell'Android Material icon set ed è stata rilasciata sotto Licenza Apache 2.0. + che fa parte dell'Android Material icon set ed è stata rilasciata sotto Licenza Apache 2.0. Copyright delle modifiche 2017, 2020 Soren Stoutner. L'immagine risultante è rilasciata sotto Licenza GPLv3+.

è stata derivata da compare, - che fa parte dell'Android Material icon set ed è stata rilasciata sotto Licenza Apache 2.0. + che fa parte dell'Android Material icon set ed è stata rilasciata sotto Licenza Apache 2.0. Copyright delle modifiche 2017, 2020 Soren Stoutner. L'immagine risultante è rilasciata sotto Licenza GPLv3+.

è stata derivata da sort, - che fa parte dell'Android Material icon set ed è stata rilasciata sotto Licenza Apache 2.0. + che fa parte dell'Android Material icon set ed è stata rilasciata sotto Licenza Apache 2.0. Copyright delle modifiche 2019, 2020 Soren Stoutner. L'immagine risultante è rilasciata sotto Licenza GPLv3+.

è stata derivata da push_pin_selected, - che fa parte dell'Android Material icon set ed è stata rilasciata sotto Licenza Apache 2.0. + che fa parte dell'Android Material icon set ed è stata rilasciata sotto Licenza Apache 2.0. Copyright delle modifiche 2019-2020, 2020 Soren Stoutner. L'immagine risultante è rilasciata sotto Licenza GPLv3+.

cookie è stata creata da Google. @@ -107,7 +107,7 @@ progetto Mastodon, che è rilasciato sotto licenza AGPLv3+. Il testo completo della licenza è riportato qui sotto. L'immagine non è stata modificata ad eccezione del layout come il colore, le dimensioni, i bordi. E' inclusa in Privacy Browser in accordo con quanto indicato nella sezione 13 della licenza.

-

Le seguenti icone derivano dall'Android Material icon set, +

Le seguenti icone derivano dall'Android Material icon set, che è rilasciato sotto Licenza Apache 2.0. Non sono state modificatae ad eccezione del colore e della dimensione. Alcune sono state rinominate per coerenza con il tipo di utilizzo all'interno del codice. Le icone con i loro nomi originali sono riportate di seguito.

diff --git a/app/src/main/assets/pt-rBR/about_licenses.html b/app/src/main/assets/pt-rBR/about_licenses.html index 61a9e660..04be0d6f 100644 --- a/app/src/main/assets/pt-rBR/about_licenses.html +++ b/app/src/main/assets/pt-rBR/about_licenses.html @@ -63,38 +63,38 @@

Icons

- are derived from security and language, which are part of the Android Material icon set and are released under the + are derived from security and language, which are part of the Android Material icon set and are released under the Apache License 2.0. The full text of the license is below. Modifications copyright 2016 Soren Stoutner. The resulting images are released under the GPLv3+ license.

is derived from elements of folder and exit_to_app, - which are part of the Android Material icon set + which are part of the Android Material icon set and are released under the Apache License 2.0. Modifications copyright 2017, 2022 Soren Stoutner. The resulting image is released under the GPLv3+ license.

is derived from elements of bookmark and create_new_folder, which are part of the - Android Material icon set and are released under the Apache License 2.0. + Android Material icon set and are released under the Apache License 2.0. Modifications copyright 2017, 2022 Soren Stoutner. The resulting image is released under the GPLv3+ license.

-

is derived from create_new_folder, - which is part of the Android Material icon set and is released under the Apache License 2.0. - Modifications copyright 2017, 2022 Soren Stoutner. - The resulting image is released under the GPLv3+ license.

-

is derived from exit_to_app, - which is part of the Android Material icon set and is released under the Apache License 2.0. - Modifications copyright 2017, 2022 Soren Stoutner. - The resulting image is released under the GPLv3+ license.

-

is derived from compare, - which is part of the Android Material icon set and is released under the Apache License 2.0. - Modifications copyright 2017, 2022 Soren Stoutner. - The resulting image is released under the GPLv3+ license.

-

is derived from sort, which is part of the Android Material icon set - and is released under the Apache License 2.0. Modifications copyright 2019, 2022 Soren Stoutner. - The resulting image is released under the GPLv3+ license.

-

is derived from push_pin_selected, - which is part of the Android Material icon set and is released under the Apache License 2.0. - Modifications copyright 2019-2020, 2022 Soren Stoutner. - The resulting image is released under the GPLv3+ license.

+

é deridado de create_new_folder, + que faz parte do conjunto de ícones do Android Material é lançado sob a Licença Apache 2.0. + Direitos autorais das modificações 2017, 2022 Soren Stoutner. + A imagem resultante é liberada sob a licença GPLv3+.

+

é deridado de exit_to_app, + que faz parte do conjunto de ícones do Android Material é lançado sob a Licença Apache 2.0. + Direitos autorais das modificações 2017, 2022 Soren Stoutner. + A imagem resultante é liberada sob a licença GPLv3+.

+

é deridado de compare, + que faz parte do conjunto de ícones do Android Material é lançado sob a Licença Apache 2.0. + Direitos autorais das modificações 2017, 2022 Soren Stoutner. + A imagem resultante é liberada sob a licença GPLv3+.

+

é deridado de sort, que faz parte do conjunto de ícones do Android Material + é lançado sob a Licença Apache 2.0. Direitos autorais das modificações 2019, 2022 Soren Stoutner. + A imagem resultante é liberada sob a licença GPLv3+.

+

é deridado de push_pin_selected, + que faz parte do conjunto de ícones do Android Material é lançado sob a Licença Apache 2.0. + Direitos autorais das modificações 2019-2020, 2022 Soren Stoutner. + A imagem resultante é liberada sob a licença GPLv3+.

cookie was created by Google. It is released under the Apache License 2.0 and can be downloaded from Material Design Icons. It is unchanged except for layout information like color and size.

@@ -102,7 +102,7 @@ Mastodon project, which is released under the AGPLv3+ license. The full text of the license is below. The image is unchanged except for layout information like color, size, and margin. It is included in Privacy Browser under the provisions in section 13 of the license.

-

The following icons come from the Android Material icon set, +

The following icons come from the Android Material icon set, which is released under the Apache License 2.0. They are unchanged except for layout information like color and size. Some of them have been renamed to match their use in the code. The original icons and names are shown below.

add.

diff --git a/app/src/main/assets/pt-rBR/about_permissions.html b/app/src/main/assets/pt-rBR/about_permissions.html index c54fd029..aa9b9a98 100644 --- a/app/src/main/assets/pt-rBR/about_permissions.html +++ b/app/src/main/assets/pt-rBR/about_permissions.html @@ -39,6 +39,6 @@

com.stoutner.privacybrowser.standard.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION

-

Automatically added to all apps targeting API >= 33 (Android 13) to prevent other apps from connecting to dynamic receivers without explicit permission.

+

Adicionado automaticamente a todos os aplicativos direcionados à API >= 33 (Android 13) para impedir que outros aplicativos se conectem a receptores dinâmicos sem permissão explícita.

diff --git a/app/src/main/assets/pt-rBR/guide_interface.html b/app/src/main/assets/pt-rBR/guide_interface.html index 094c0c7c..8be37261 100644 --- a/app/src/main/assets/pt-rBR/guide_interface.html +++ b/app/src/main/assets/pt-rBR/guide_interface.html @@ -36,7 +36,8 @@ the drawer may be opened by long-pressing on the edge of the screen until the drawer peaks out and then swiping it open. Sometimes it can be difficult to get the bookmarks drawer to reliably peak on devices with curved edges, so it is also possible to open the bookmarks drawer from the options menu.

-

Tapping on a bookmark opens it in the current tab. Long-pressing on a bookmark opens it in a new tab and long-pressing on a folder opens all the bookmarks it directly contains in new tabs. +

Tocar em um marcador o abre na guia atual. + Pressionar longamente um marcador abre-o em uma nova guia e pressionar longamente uma pasta abre todos os favoritos que ela contém diretamente em novas guias. Tapping the top floating action button in the bookmarks drawer opens the bookmarks activity, where bookmarks can be edited and reorganized.

diff --git a/app/src/main/assets/ru/about_licenses.html b/app/src/main/assets/ru/about_licenses.html index bae60d8e..4d458836 100644 --- a/app/src/main/assets/ru/about_licenses.html +++ b/app/src/main/assets/ru/about_licenses.html @@ -61,36 +61,36 @@

Иконки

- являются производными от security и language, которые являются частью Android Material icon set и выпущены под + являются производными от security и language, которые являются частью Android Material icon set и выпущены под Apache License 2.0. Полный текст лицензии приведен ниже. Модификации авторских прав 2016 Soren Stoutner. Полученные изображения выпущены под лицензией GPLv3+.

являются производными от folder и exit_to_app, которые являются частью - Android Material icon set и выпущены под Apache License 2.0. + Android Material icon set и выпущены под Apache License 2.0. Модификации авторских прав 2017, 2022 Soren Stoutner. Полученные изображения выпущены под лицензией GPLv3+.

являются производными от bookmark и create_new_folder, которые являются частью - Android Material icon set и выпущены под Apache License 2.0. + Android Material icon set и выпущены под Apache License 2.0. Модификации авторских прав 2017, 2022 Soren Stoutner. Полученные изображения выпущены под лицензией GPLv3+.

являются производными от create_new_folder, которые являются частью - Android Material icon set и выпущены под Apache License 2.0. + Android Material icon set и выпущены под Apache License 2.0. Модификации авторских прав 2017, 2022 Soren Stoutner. Полученные изображения выпущены под лицензией GPLv3+.

являются производными от exit_to_app, - которые являются частью Android Material icon set и выпущены под Apache License 2.0. + которые являются частью Android Material icon set и выпущены под Apache License 2.0. Модификации авторских прав 2017, 2022 Soren Stoutner. Полученные изображения выпущены под лицензией GPLv3+.

являются производными от compare, - которые являются частью Android Material icon set и выпущены под Apache License 2.0. + которые являются частью Android Material icon set и выпущены под Apache License 2.0. Модификации авторских прав 2017, 2022 Soren Stoutner. Полученные изображения выпущены под лицензией GPLv3+.

являются производными от sort, - которые являются частью Android Material icon set и выпущены под Apache License 2.0. + которые являются частью Android Material icon set и выпущены под Apache License 2.0. Модификации авторских прав 2019, 2022 Soren Stoutner. Полученные изображения выпущены под лицензией GPLv3+.

являются производными от push_pin_selected, - которые являются частью Android Material icon set и выпущены под Apache License 2.0. + которые являются частью Android Material icon set и выпущены под Apache License 2.0. Модификации авторских прав 2019-2020, 2022 Soren Stoutner. Полученные изображения выпущены под лицензией GPLv3+.

cookie были созданы Google. @@ -100,7 +100,7 @@ проекта Mastodon, который выпускается под лицензией AGPLv3+. Полный текст лицензии приведен ниже. Изображение не было изменено, за исключением информации о верстке, в том числе цвет, размеры и отступы. В соответствии с положениями раздела 13 лицензии оно включено в Privacy Browser.

-

Следующие значки взяты изAndroid Material icon set, +

Следующие значки взяты изAndroid Material icon set, которые выпущены под Apache License 2.0. Они неизменны, за исключением такой информации, как цвет и размер. Некоторые из них были переименованы в соответствии с их использованием в коде. Оригинальные значки и имена показаны ниже.

add.

diff --git a/app/src/main/assets/tr/about_licenses.html b/app/src/main/assets/tr/about_licenses.html index 13946d99..5137d942 100644 --- a/app/src/main/assets/tr/about_licenses.html +++ b/app/src/main/assets/tr/about_licenses.html @@ -63,35 +63,35 @@

Simgeler

Apache License 2.0 altında yayınlanan ve - Android Material simge setinin bir parçası olan security ve language'den elde edilmiştir. + Android Material simge setinin bir parçası olan security ve language'den elde edilmiştir. Lisansın tüm metni aşağıdadır. Değişikliklerin telif hakkı 2016 Soren Stoutner. Ortaya çıkan görüntüler GPLv3+ lisansı altında yayınlandı.

Apache License 2.0 altında yayınlanan ve - Android Material simge setinin bir parçası olan folder ve exit_to_app elementlerinden elde edilmiştir. + Android Material simge setinin bir parçası olan folder ve exit_to_app elementlerinden elde edilmiştir. Değişikliklerin telif hakkı 2017, 2022 Soren Stoutner. Ortaya çıkan görüntü GPLv3+ lisansı altında yayınlandı.

Apache License 2.0 altında yayınlanan ve - Android Material simge setinin bir parçası olan bookmarks ve create_new_folder elementlerinden elde edilmiştir. + Android Material simge setinin bir parçası olan bookmarks ve create_new_folder elementlerinden elde edilmiştir. Değişikliklerin telif hakkı 2017, 2022 Soren Stoutner. Ortaya çıkan görüntü GPLv3+ lisansı altında yayınlandı.

Apache License 2.0 altında yayınlanan ve - Android Material simge setinin bir parçası olan create_new_folder'dan elde edilmiştir. + Android Material simge setinin bir parçası olan create_new_folder'dan elde edilmiştir. Değişikliklerin telif hakkı 2017, 2022 Soren Stoutner. Ortaya çıkan görüntü GPLv3+ lisansı altında yayınlandı.

Apache License 2.0 altında yayınlanan ve - Android Material simge setinin bir parçası olan exit_to_app'ten elde edilmiştir. + Android Material simge setinin bir parçası olan exit_to_app'ten elde edilmiştir. Değişikliklerin telif hakkı 2017, 2022 Soren Stoutner. Ortaya çıkan görüntü GPLv3+ lisansı altında yayınlandı.

Apache License 2.0 altında yayınlanan ve - Android Material simge setinin bir parçası olan compare'den elde edilmiştir. + Android Material simge setinin bir parçası olan compare'den elde edilmiştir. Değişikliklerin telif hakkı 2017, 2022 Soren Stoutner. Ortaya çıkan görüntü GPLv3+ lisansı altında yayınlandı.

Apache License 2.0 altında yayınlanan ve - Android Material simge setinin bir parçası olan sort'dan elde edilmiştir. + Android Material simge setinin bir parçası olan sort'dan elde edilmiştir. Değişikliklerin telif hakkı 2019, 2022 Soren Stoutner. Ortaya çıkan görüntü GPLv3+ lisansı altında yayınlandı.

Apache License 2.0 altında yayınlanan ve - Android Material simge setinin bir parçası olan push_pin_selected'dan elde edilmiştir. + Android Material simge setinin bir parçası olan push_pin_selected'dan elde edilmiştir. Değişikliklerin telif hakkı 2019-2020, 2022 Soren Stoutner. Ortaya çıkan görüntü GPLv3+ lisansı altında yayınlandı.

cookie Google tarafından oluşturuldu. @@ -101,7 +101,7 @@ Mastodon project, which is released under the AGPLv3+ license. The full text of the license is below. The image is unchanged except for layout information like color, size, and margin. It is included in Privacy Browser under the provisions in section 13 of the license.

-

Aşağıdaki simgeler Apache License 2.0 altında yayınlanan Android Material +

Aşağıdaki simgeler Apache License 2.0 altında yayınlanan Android Material simge setinden gelmektedir. Renk ve ebat gibi düzen bilgileri dışında herhangi bir değişiklik yapılmamıştır. Bazıları koddaki kullanımlarıyla uygun olacak şekilde yeniden adlandırıldı. Orijinal simgeler ve adlar aşağıda gösterilmiştir.

add.

diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java index 46be93ad..d3e352b6 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java @@ -153,6 +153,7 @@ import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper; import com.stoutner.privacybrowser.helpers.DomainsDatabaseHelper; import com.stoutner.privacybrowser.helpers.ProxyHelper; import com.stoutner.privacybrowser.helpers.SanitizeUrlHelper; +import com.stoutner.privacybrowser.helpers.UrlHelper; import com.stoutner.privacybrowser.views.NestedScrollWebView; import java.io.ByteArrayInputStream; @@ -263,7 +264,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook private BookmarksDatabaseHelper bookmarksDatabaseHelper; private DomainsDatabaseHelper domainsDatabaseHelper; private ProxyHelper proxyHelper; - private SanitizeUrlHelper sanitizeUrlHelper; // Declare the class variables private boolean bookmarksDrawerPinned; @@ -608,7 +608,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook bookmarksDatabaseHelper = new BookmarksDatabaseHelper(this); domainsDatabaseHelper = new DomainsDatabaseHelper(this); proxyHelper = new ProxyHelper(); - sanitizeUrlHelper = new SanitizeUrlHelper(); // Update the bookmarks drawer pinned image view. updateBookmarksDrawerPinnedImageView(); @@ -4371,11 +4370,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook private String sanitizeUrl(String url) { // Sanitize tracking queries. if (sanitizeTrackingQueries) - url = sanitizeUrlHelper.sanitizeTrackingQueries(url); + url = SanitizeUrlHelper.sanitizeTrackingQueries(url); // Sanitize AMP redirects. if (sanitizeAmpRedirects) - url = sanitizeUrlHelper.sanitizeAmpRedirects(url); + url = SanitizeUrlHelper.sanitizeAmpRedirects(url); // Return the sanitized URL. return url; @@ -5140,10 +5139,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook } // Get the file name from the content disposition. - String fileNameString = PrepareSaveDialogCoroutine.getFileNameFromHeaders(this, contentDisposition, mimetype, downloadUrl); + String fileNameString = UrlHelper.getFileName(this, contentDisposition, mimetype, downloadUrl); // Instantiate the save dialog. - DialogFragment saveDialogFragment = SaveDialog.saveUrl(downloadUrl, formattedFileSizeString, fileNameString, userAgent, + DialogFragment saveDialogFragment = SaveDialog.saveUrl(downloadUrl, fileNameString, formattedFileSizeString, userAgent, nestedScrollWebView.getAcceptCookies()); // Try to show the dialog. The download listener continues to function even when the WebView is paused. Attempting to display a dialog in that state leads to a crash. diff --git a/app/src/main/java/com/stoutner/privacybrowser/coroutines/PrepareSaveDialogCoroutine.kt b/app/src/main/java/com/stoutner/privacybrowser/coroutines/PrepareSaveDialogCoroutine.kt index 1af03207..200e0492 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/coroutines/PrepareSaveDialogCoroutine.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/coroutines/PrepareSaveDialogCoroutine.kt @@ -20,9 +20,6 @@ package com.stoutner.privacybrowser.coroutines import android.content.Context -import android.net.Uri -import android.webkit.CookieManager -import android.webkit.MimeTypeMap import androidx.fragment.app.DialogFragment import androidx.fragment.app.FragmentManager @@ -31,16 +28,14 @@ import com.stoutner.privacybrowser.R import com.stoutner.privacybrowser.activities.MainWebViewActivity import com.stoutner.privacybrowser.dataclasses.PendingDialogDataClass import com.stoutner.privacybrowser.dialogs.SaveDialog -import com.stoutner.privacybrowser.helpers.ProxyHelper +import com.stoutner.privacybrowser.helpers.UrlHelper + import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.lang.Exception -import java.net.HttpURLConnection -import java.net.URL -import java.text.NumberFormat object PrepareSaveDialogCoroutine { @JvmStatic @@ -49,108 +44,13 @@ object PrepareSaveDialogCoroutine { CoroutineScope(Dispatchers.Main).launch { // Make the network requests on the IO thread. withContext(Dispatchers.IO) { - // Define the strings. - var formattedFileSize: String - var fileNameString: String - - // Populate the file size and name strings. - if (urlString.startsWith("data:")) { // The URL contains the entire data of an image. - // Remove `data:` from the beginning of the URL. - val urlWithoutData = urlString.substring(5) - - // Get the URL MIME type, which ends with a `;`. - val urlMimeType = urlWithoutData.substring(0, urlWithoutData.indexOf(";")) - - // Get the Base64 data, which begins after a `,`. - val base64DataString = urlWithoutData.substring(urlWithoutData.indexOf(",") + 1) - - // Calculate the file size of the data URL. Each Base64 character represents 6 bits. - formattedFileSize = NumberFormat.getInstance().format(base64DataString.length * 3L / 4) + " " + context.getString(R.string.bytes) - - // Set the file name according to the MIME type. - fileNameString = context.getString(R.string.file) + "." + MimeTypeMap.getSingleton().getExtensionFromMimeType(urlMimeType) - } else { // The URL refers to the location of the data. - // Initialize the formatted file size string. - formattedFileSize = context.getString(R.string.unknown_size) - - // Because everything relating to requesting data from a webserver can throw errors, the entire section must catch exceptions. - try { - // Convert the URL string to a URL. - val url = URL(urlString) - - // Instantiate the proxy helper. - val proxyHelper = ProxyHelper() - - // Get the current proxy. - val proxy = proxyHelper.getCurrentProxy(context) - - // Open a connection to the URL. No data is actually sent at this point. - val httpUrlConnection = url.openConnection(proxy) as HttpURLConnection - - // Add the user agent to the header property. - httpUrlConnection.setRequestProperty("User-Agent", userAgent) - - // Add the cookies if they are enabled. - if (cookiesEnabled) { - // Get the cookies for the current domain. - val cookiesString = CookieManager.getInstance().getCookie(url.toString()) - - // Add the cookies if they are not null. - if (cookiesString != null) - httpUrlConnection.setRequestProperty("Cookie", cookiesString) - } - - // The actual network request is in a `try` bracket so that `disconnect()` is run in the `finally` section even if an error is encountered in the main block. - try { - // Get the status code. This initiates a network connection. - val responseCode = httpUrlConnection.responseCode - - // Check the response code. - if (responseCode >= 400) { // The response code is an error message. - // Set the formatted file size to indicate a bad URL. - formattedFileSize = context.getString(R.string.invalid_url) - - // Set the file name according to the URL. - fileNameString = getFileNameFromUrl(context, urlString, null) - } else { // The response code is not an error message. - // Get the headers. - val contentLengthString = httpUrlConnection.getHeaderField("Content-Length") - val contentDispositionString = httpUrlConnection.getHeaderField("Content-Disposition") - var contentTypeString = httpUrlConnection.contentType - - // Remove anything after the MIME type in the content type string. - if (contentTypeString.contains(";")) - contentTypeString = contentTypeString.substring(0, contentTypeString.indexOf(";")) - - // Only process the content length string if it isn't null. - if (contentLengthString != null) { - // Convert the content length string to a long. - val fileSize = contentLengthString.toLong() - - // Format the file size. - formattedFileSize = NumberFormat.getInstance().format(fileSize) + " " + context.getString(R.string.bytes) - } - - // Get the file name string from the content disposition. - fileNameString = getFileNameFromHeaders(context, contentDispositionString, contentTypeString, urlString) - } - } finally { - // Disconnect the HTTP URL connection. - httpUrlConnection.disconnect() - } - } catch (exception: Exception) { - // Set the formatted file size to indicate a bad URL. - formattedFileSize = context.getString(R.string.invalid_url) - - // Set the file name according to the URL. - fileNameString = getFileNameFromUrl(context, urlString, null) - } - } + // Get the file name and size. + val fileNameAndSize = UrlHelper.getNameAndSize(context, urlString, userAgent, cookiesEnabled) // Display the dialog on the main thread. withContext(Dispatchers.Main) { // Instantiate the save dialog. - val saveDialogFragment: DialogFragment = SaveDialog.saveUrl(urlString, formattedFileSize, fileNameString, userAgent, cookiesEnabled) + val saveDialogFragment: DialogFragment = SaveDialog.saveUrl(urlString, fileNameAndSize.first, fileNameAndSize.second, userAgent, cookiesEnabled) // Try to show the dialog. Sometimes the window is not active. try { @@ -164,63 +64,4 @@ object PrepareSaveDialogCoroutine { } } } - - // Content dispositions can contain other text besides the file name, and they can be in any order. - // Elements are separated by semicolons. Sometimes the file names are contained in quotes. - @JvmStatic - fun getFileNameFromHeaders(context: Context, contentDispositionString: String?, contentTypeString: String?, urlString: String): String { - // Define a file name string. - var fileNameString: String - - // Only process the content disposition string if it isn't null. - if (contentDispositionString != null) { // The content disposition is not null. - // Check to see if the content disposition contains a file name. - if (contentDispositionString.contains("filename=")) { // The content disposition contains a filename. - // Get the part of the content disposition after `filename=`. - fileNameString = contentDispositionString.substring(contentDispositionString.indexOf("filename=") + 9) - - // Remove any `;` and anything after it. This removes any entries after the filename. - if (fileNameString.contains(";")) - fileNameString = fileNameString.substring(0, fileNameString.indexOf(";") - 1) - - // Remove any `"` at the beginning of the string. - if (fileNameString.startsWith("\"")) - fileNameString = fileNameString.substring(1) - - // Remove any `"` at the end of the string. - if (fileNameString.endsWith("\"")) - fileNameString = fileNameString.substring(0, fileNameString.length - 1) - } else { // The headers contain no useful information. - // Get the file name string from the URL. - fileNameString = getFileNameFromUrl(context, urlString, contentTypeString) - } - } else { // The content disposition is null. - // Get the file name string from the URL. - fileNameString = getFileNameFromUrl(context, urlString, contentTypeString) - } - - // Return the file name string. - return fileNameString - } - - private fun getFileNameFromUrl(context: Context, urlString: String, contentTypeString: String?): String { - // Convert the URL string to a URI. - val uri = Uri.parse(urlString) - - // Get the last path segment. - var lastPathSegment = uri.lastPathSegment - - // Use a default file name if the last path segment is null. - if (lastPathSegment == null) { - // Set the last path segment to be the generic file name. - lastPathSegment = context.getString(R.string.file) - - // Add a file extension if it can be detected. - if (MimeTypeMap.getSingleton().hasMimeType(contentTypeString)) - lastPathSegment = lastPathSegment + "." + MimeTypeMap.getSingleton().getExtensionFromMimeType(contentTypeString) - } - - // Return the last path segment as the file name. - return lastPathSegment - } } diff --git a/app/src/main/java/com/stoutner/privacybrowser/dialogs/SaveDialog.kt b/app/src/main/java/com/stoutner/privacybrowser/dialogs/SaveDialog.kt index 63a6eaa3..2f7868e9 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/dialogs/SaveDialog.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/dialogs/SaveDialog.kt @@ -35,15 +35,13 @@ import androidx.fragment.app.DialogFragment import androidx.preference.PreferenceManager import com.stoutner.privacybrowser.R -import com.stoutner.privacybrowser.helpers.GetUrlSizeHelper +import com.stoutner.privacybrowser.helpers.UrlHelper import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import java.net.URL - // Define the class constants. private const val URL_STRING = "url_string" private const val FILE_SIZE_STRING = "file_size_string" @@ -71,14 +69,14 @@ class SaveDialog : DialogFragment() { companion object { // `@JvmStatic` will no longer be required once all the code has transitioned to Kotlin. @JvmStatic - fun saveUrl(urlString: String, fileSizeString: String, fileNameString: String, userAgentString: String, cookiesEnabled: Boolean): SaveDialog { + fun saveUrl(urlString: String, fileNameString: String, fileSizeString: String, userAgentString: String, cookiesEnabled: Boolean): SaveDialog { // Create an arguments bundle. val argumentsBundle = Bundle() // Store the arguments in the bundle. argumentsBundle.putString(URL_STRING, urlString) - argumentsBundle.putString(FILE_SIZE_STRING, fileSizeString) argumentsBundle.putString(FILE_NAME_STRING, fileNameString) + argumentsBundle.putString(FILE_SIZE_STRING, fileSizeString) argumentsBundle.putString(USER_AGENT_STRING, userAgentString) argumentsBundle.putBoolean(COOKIES_ENABLED, cookiesEnabled) @@ -96,8 +94,8 @@ class SaveDialog : DialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { // Get the arguments from the bundle. val originalUrlString = requireArguments().getString(URL_STRING)!! + var fileNameString = requireArguments().getString(FILE_NAME_STRING)!! val fileSizeString = requireArguments().getString(FILE_SIZE_STRING)!! - val fileNameString = requireArguments().getString(FILE_NAME_STRING)!! val userAgentString = requireArguments().getString(USER_AGENT_STRING)!! val cookiesEnabled = requireArguments().getBoolean(COOKIES_ENABLED) @@ -181,16 +179,19 @@ class SaveDialog : DialogFragment() { CoroutineScope(Dispatchers.Main).launch { // Create a URL size string. - var urlSize: String + var fileNameAndSize: Pair // Get the URL size on the IO thread. withContext(Dispatchers.IO) { - // Get the URL size. - urlSize = GetUrlSizeHelper.getUrl(requireContext(), URL(urlToSave), userAgentString, cookiesEnabled) + // Get the updated file name and size. + fileNameAndSize = UrlHelper.getNameAndSize(requireContext(), urlToSave, userAgentString, cookiesEnabled) + + // Save the updated file name. + fileNameString = fileNameAndSize.first } // Display the updated URL. - fileSizeTextView.text = urlSize + fileSizeTextView.text = fileNameAndSize.second } } }) diff --git a/app/src/main/java/com/stoutner/privacybrowser/helpers/GetUrlSizeHelper.kt b/app/src/main/java/com/stoutner/privacybrowser/helpers/GetUrlSizeHelper.kt deleted file mode 100644 index 6c3b3f87..00000000 --- a/app/src/main/java/com/stoutner/privacybrowser/helpers/GetUrlSizeHelper.kt +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2020-2022 Soren Stoutner . - * - * This file is part of Privacy Browser Android . - * - * Privacy Browser Android 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 Android 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 Android. If not, see . - */ - -package com.stoutner.privacybrowser.helpers - -import android.content.Context -import android.webkit.CookieManager - -import com.stoutner.privacybrowser.R - -import java.lang.Exception -import java.net.HttpURLConnection -import java.net.URL -import java.text.NumberFormat - -object GetUrlSizeHelper { - fun getUrl(context: Context, url: URL, userAgent: String, cookiesEnabled: Boolean): String { - // Initialize the formatted file size string. - var formattedFileSize = context.getString(R.string.unknown_size) - - // Because everything relating to requesting data from a webserver can throw errors, the entire section must catch exceptions. - try { - // Instantiate the proxy helper. - val proxyHelper = ProxyHelper() - - // Get the current proxy. - val proxy = proxyHelper.getCurrentProxy(context) - - // Open a connection to the URL. No data is actually sent at this point. - val httpUrlConnection = url.openConnection(proxy) as HttpURLConnection - - // Add the user agent to the header property. - httpUrlConnection.setRequestProperty("User-Agent", userAgent) - - // Add the cookies if they are enabled. - if (cookiesEnabled) { - // Get the cookies for the current domain. - val cookiesString = CookieManager.getInstance().getCookie(url.toString()) - - // Only add the cookies if they are not null. - if (cookiesString != null) { - // Add the cookies to the header property. - httpUrlConnection.setRequestProperty("Cookie", cookiesString) - } - } - - // The actual network request is in a `try` bracket so that `disconnect()` is run in the `finally` section even if an error is encountered in the main block. - try { - // Get the status code. This initiates a network connection. - val responseCode = httpUrlConnection.responseCode - - // Check the response code. - if (responseCode >= 400) { // The response code is an error message. - // Set the formatted file size to indicate a bad URL. - formattedFileSize = context.getString(R.string.invalid_url) - } else { // The response code is not an error message. - // Get the content length header. - val contentLengthString = httpUrlConnection.getHeaderField("Content-Length") - - // Only process the content length string if it isn't null. - if (contentLengthString != null) { - // Convert the content length string to a long. - val fileSize = contentLengthString.toLong() - - // Format the file size. - formattedFileSize = NumberFormat.getInstance().format(fileSize) + " " + context.getString(R.string.bytes) - } - } - } finally { - // Disconnect the HTTP URL connection. - httpUrlConnection.disconnect() - } - } catch (exception: Exception) { - // Set the formatted file size to indicate a bad URL. - formattedFileSize = context.getString(R.string.invalid_url) - } - - // Return the formatted file size. - return formattedFileSize - } -} diff --git a/app/src/main/java/com/stoutner/privacybrowser/helpers/SanitizeUrlHelper.kt b/app/src/main/java/com/stoutner/privacybrowser/helpers/SanitizeUrlHelper.kt index 7e4ad981..370eae96 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/helpers/SanitizeUrlHelper.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/helpers/SanitizeUrlHelper.kt @@ -1,5 +1,5 @@ /* - * Copyright ©2022 Soren Stoutner . + * Copyright 2022 Soren Stoutner . * * This file is part of Privacy Browser Android . * @@ -48,7 +48,8 @@ private val trackingQueriesList = listOf( "yclid=" // Yandex Click ID. ) -class SanitizeUrlHelper { +object SanitizeUrlHelper { + @JvmStatic fun sanitizeTrackingQueries(inputUrl: String): String { // Make a copy of the input URL so that it can be modified. var url = inputUrl @@ -69,6 +70,7 @@ class SanitizeUrlHelper { return url } + @JvmStatic fun sanitizeAmpRedirects(inputUrl: String): String { // Make a copy of the input URL so that it can be modified. var url = inputUrl @@ -82,4 +84,4 @@ class SanitizeUrlHelper { // Return the sanitized URL. return url } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/stoutner/privacybrowser/helpers/UrlHelper.kt b/app/src/main/java/com/stoutner/privacybrowser/helpers/UrlHelper.kt new file mode 100644 index 00000000..e51b2c0b --- /dev/null +++ b/app/src/main/java/com/stoutner/privacybrowser/helpers/UrlHelper.kt @@ -0,0 +1,261 @@ +/* + * Copyright 2020-2022 Soren Stoutner . + * + * This file is part of Privacy Browser Android . + * + * Privacy Browser Android 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 Android 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 Android. If not, see . + */ + +package com.stoutner.privacybrowser.helpers + +import android.content.Context +import android.net.Uri +import android.webkit.CookieManager +import android.webkit.MimeTypeMap + +import com.stoutner.privacybrowser.R + +import java.lang.Exception +import java.net.HttpURLConnection +import java.net.URL +import java.text.NumberFormat + +object UrlHelper { + // Content dispositions can contain other text besides the file name, and they can be in any order. + // Elements are separated by semicolons. Sometimes the file names are contained in quotes. + @JvmStatic + fun getFileName(context: Context, contentDispositionString: String?, contentTypeString: String?, urlString: String): String { + // Define a file name string. + var fileNameString: String + + // Only process the content disposition string if it isn't null. + if (contentDispositionString != null) { // The content disposition is not null. + // Check to see if the content disposition contains a file name. + if (contentDispositionString.contains("filename=")) { // The content disposition contains a filename. + // Get the part of the content disposition after `filename=`. + fileNameString = contentDispositionString.substring(contentDispositionString.indexOf("filename=") + 9) + + // Remove any `;` and anything after it. This removes any entries after the filename. + if (fileNameString.contains(";")) + fileNameString = fileNameString.substring(0, fileNameString.indexOf(";") - 1) + + // Remove any `"` at the beginning of the string. + if (fileNameString.startsWith("\"")) + fileNameString = fileNameString.substring(1) + + // Remove any `"` at the end of the string. + if (fileNameString.endsWith("\"")) + fileNameString = fileNameString.substring(0, fileNameString.length - 1) + } else { // The headers contain no useful information. + // Get the file name string from the URL. + fileNameString = getFileNameFromUrl(context, urlString, contentTypeString) + } + } else { // The content disposition is null. + // Get the file name string from the URL. + fileNameString = getFileNameFromUrl(context, urlString, contentTypeString) + } + + // Return the file name string. + return fileNameString + } + + private fun getFileNameFromUrl(context: Context, urlString: String, contentTypeString: String?): String { + // Convert the URL string to a URI. + val uri = Uri.parse(urlString) + + // Get the last path segment. + var lastPathSegment = uri.lastPathSegment + + // Use a default file name if the last path segment is null. + if (lastPathSegment == null) { + // Set the last path segment to be the generic file name. + lastPathSegment = context.getString(R.string.file) + + // Add a file extension if it can be detected. + if (MimeTypeMap.getSingleton().hasMimeType(contentTypeString)) + lastPathSegment = lastPathSegment + "." + MimeTypeMap.getSingleton().getExtensionFromMimeType(contentTypeString) + } + + // Return the last path segment as the file name. + return lastPathSegment + } + + fun getNameAndSize(context: Context, urlString: String, userAgent: String, cookiesEnabled: Boolean): Pair { + // Define the strings. + var fileNameString: String + var formattedFileSize: String + + // Populate the file size and name strings. + if (urlString.startsWith("data:")) { // The URL contains the entire data of an image. + // Remove `data:` from the beginning of the URL. + val urlWithoutData = urlString.substring(5) + + // Get the URL MIME type, which ends with a `;`. + val urlMimeType = urlWithoutData.substring(0, urlWithoutData.indexOf(";")) + + // Get the Base64 data, which begins after a `,`. + val base64DataString = urlWithoutData.substring(urlWithoutData.indexOf(",") + 1) + + // Calculate the file size of the data URL. Each Base64 character represents 6 bits. + formattedFileSize = NumberFormat.getInstance().format(base64DataString.length * 3L / 4) + " " + context.getString(R.string.bytes) + + // Set the file name according to the MIME type. + fileNameString = context.getString(R.string.file) + "." + MimeTypeMap.getSingleton().getExtensionFromMimeType(urlMimeType) + } else { // The URL refers to the location of the data. + // Initialize the formatted file size string. + formattedFileSize = context.getString(R.string.unknown_size) + + // Because everything relating to requesting data from a webserver can throw errors, the entire section must catch exceptions. + try { + // Convert the URL string to a URL. + val url = URL(urlString) + + // Instantiate the proxy helper. + val proxyHelper = ProxyHelper() + + // Get the current proxy. + val proxy = proxyHelper.getCurrentProxy(context) + + // Open a connection to the URL. No data is actually sent at this point. + val httpUrlConnection = url.openConnection(proxy) as HttpURLConnection + + // Add the user agent to the header property. + httpUrlConnection.setRequestProperty("User-Agent", userAgent) + + // Add the cookies if they are enabled. + if (cookiesEnabled) { + // Get the cookies for the current domain. + val cookiesString = CookieManager.getInstance().getCookie(url.toString()) + + // Add the cookies if they are not null. + if (cookiesString != null) + httpUrlConnection.setRequestProperty("Cookie", cookiesString) + } + + // The actual network request is in a `try` bracket so that `disconnect()` is run in the `finally` section even if an error is encountered in the main block. + try { + // Get the status code. This initiates a network connection. + val responseCode = httpUrlConnection.responseCode + + // Check the response code. + if (responseCode >= 400) { // The response code is an error message. + // Set the formatted file size to indicate a bad URL. + formattedFileSize = context.getString(R.string.invalid_url) + + // Set the file name according to the URL. + fileNameString = getFileNameFromUrl(context, urlString, null) + } else { // The response code is not an error message. + // Get the headers. + val contentLengthString = httpUrlConnection.getHeaderField("Content-Length") + val contentDispositionString = httpUrlConnection.getHeaderField("Content-Disposition") + var contentTypeString = httpUrlConnection.contentType + + // Remove anything after the MIME type in the content type string. + if (contentTypeString.contains(";")) + contentTypeString = contentTypeString.substring(0, contentTypeString.indexOf(";")) + + // Only process the content length string if it isn't null. + if (contentLengthString != null) { + // Convert the content length string to a long. + val fileSize = contentLengthString.toLong() + + // Format the file size. + formattedFileSize = NumberFormat.getInstance().format(fileSize) + " " + context.getString(R.string.bytes) + } + + // Get the file name string from the content disposition. + fileNameString = getFileName(context, contentDispositionString, contentTypeString, urlString) + } + } finally { + // Disconnect the HTTP URL connection. + httpUrlConnection.disconnect() + } + } catch (exception: Exception) { + // Set the formatted file size to indicate a bad URL. + formattedFileSize = context.getString(R.string.invalid_url) + + // Set the file name according to the URL. + fileNameString = getFileNameFromUrl(context, urlString, null) + } + } + + // Return the file name and size. + return Pair(fileNameString, formattedFileSize) + } + + fun getSize(context: Context, url: URL, userAgent: String, cookiesEnabled: Boolean): String { + // Initialize the formatted file size string. + var formattedFileSize = context.getString(R.string.unknown_size) + + // Because everything relating to requesting data from a webserver can throw errors, the entire section must catch exceptions. + try { + // Instantiate the proxy helper. + val proxyHelper = ProxyHelper() + + // Get the current proxy. + val proxy = proxyHelper.getCurrentProxy(context) + + // Open a connection to the URL. No data is actually sent at this point. + val httpUrlConnection = url.openConnection(proxy) as HttpURLConnection + + // Add the user agent to the header property. + httpUrlConnection.setRequestProperty("User-Agent", userAgent) + + // Add the cookies if they are enabled. + if (cookiesEnabled) { + // Get the cookies for the current domain. + val cookiesString = CookieManager.getInstance().getCookie(url.toString()) + + // Only add the cookies if they are not null. + if (cookiesString != null) { + // Add the cookies to the header property. + httpUrlConnection.setRequestProperty("Cookie", cookiesString) + } + } + + // The actual network request is in a `try` bracket so that `disconnect()` is run in the `finally` section even if an error is encountered in the main block. + try { + // Get the status code. This initiates a network connection. + val responseCode = httpUrlConnection.responseCode + + // Check the response code. + if (responseCode >= 400) { // The response code is an error message. + // Set the formatted file size to indicate a bad URL. + formattedFileSize = context.getString(R.string.invalid_url) + } else { // The response code is not an error message. + // Get the content length header. + val contentLengthString = httpUrlConnection.getHeaderField("Content-Length") + + // Only process the content length string if it isn't null. + if (contentLengthString != null) { + // Convert the content length string to a long. + val fileSize = contentLengthString.toLong() + + // Format the file size. + formattedFileSize = NumberFormat.getInstance().format(fileSize) + " " + context.getString(R.string.bytes) + } + } + } finally { + // Disconnect the HTTP URL connection. + httpUrlConnection.disconnect() + } + } catch (exception: Exception) { + // Set the formatted file size to indicate a bad URL. + formattedFileSize = context.getString(R.string.invalid_url) + } + + // Return the formatted file size. + return formattedFileSize + } +} -- 2.45.2