feat: add base64 encoded email protection (#110)

main
Óscar 2 years ago committed by GitHub
commit 6dc6e51ea8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -208,6 +208,14 @@ menu = [
# The RSS icon will be shown if (1) it's enabled and (2) the following variable is set to true.
feed_icon = true
# Email address for footer's social section.
# Protect against spambots:
# 1. Use base64 for email (convert at https://www.base64encode.org/ or `printf 'your@email.com' | base64`).
# 2. Or, set 'encode_plaintext_email' to true for auto-encoding (only protects on site, not in public repos).
email = "bWFpbEBleGFtcGxlLmNvbQ==" # base64 encoded version of "mail@example.com"
# Decoding requires ~400 bytes of JavaScript. If JS is disabled, the email won't be displayed.
encode_plaintext_email = true # Setting is ignored if email is already encoded.
# The icons available can be found in "social_icons" in the "static" folder.
socials = [
{ name = "github", url = "https://github.com/welpo/", icon = "github" },

@ -1,18 +1,23 @@
+++
title = "Sense JavaScript obligatori"
date = 2023-01-06
updated = 2023-08-02
updated = 2023-08-18
description = "JavaScript només s'utilitza quan HTML i CSS no són suficients."
[taxonomies]
tags = ["funcionalitat", "tutorial"]
[extra]
footnote_backlinks = true
+++
Aquest tema no requereix JavaScript obligatori. Opcionalment, pot carregar una quantitat mínima per afegir algunes característiques que són impossibles d'aconseguir amb HTML i CSS.
## Opcions habilitades globalment
L'**interruptor de mode clar/fosc** pot habilitar-se configurant `theme_switcher = true` a la secció `[extra]` del teu `config.toml` (~900 bytes de JavaScript).
- L'**interruptor de mode clar/fosc** pot habilitar-se configurant `theme_switcher = true` a la secció `[extra]` del teu `config.toml` (~900 bytes de JavaScript).
- **Decodificació del correu** (~400 bytes). Per protegir el teu lloc correu dels [robots de correu brossa](https://ca.wikipedia.org/wiki/Robot_de_correu_brossa), pots configurar `encode_plaintext_email = true`. Si el teu lloc web està en un repositori públic, per a una protecció millorada, considera configurar el teu `email` com una cadena codificada en base64[^1] directament (per exemple: `email = "bWFpbEBleGFtcGxlLmNvbQ=="`).
## Configuracions que es poden habilitar tant globalment com en publicacions individuals
@ -28,3 +33,7 @@ Per habilitar aquestes configuracions globalment, afegeix-les a la secció `[ext
- [**Comentaris**](@/blog/comments.ca.md). giscus (2 KB), utterances (1 KB), Hyvor Talk (~800 bytes) o Isso (1KB) es poden habilitar globalment configurant `enabled_for_all_posts = true` a la secció apropiada del teu fitxer `config.toml` (`[extra.giscus]`, `[extra.utterances]`, `[extra.hyvortalk]` o `[extra.isso]`). Per habilitar comentaris en publicacions individuals, configura el nom del sistema `= true` (per exemple, `hyvortalk = true`) al front matter del post.
A part d'això, és un tema ràpid amb HTML i CSS que funciona sense JavaScript. Just com hauria de ser (la majoria de) la web :-)
<hr>
[^1]: Per codificar el teu correu en base64 pots utilitzar [eines en línia](https://www.base64encode.org/) o, al terminal, executa: `printf 'mail@example.com' | base64`.

@ -1,18 +1,23 @@
+++
title = "Sin JavaScript obligatorio"
date = 2023-01-06
updated = 2023-08-02
updated = 2023-08-18
description = "JavaScript solo se utiliza cuando HTML y CSS no son suficientes."
[taxonomies]
tags = ["funcionalidad", "tutorial"]
[extra]
footnote_backlinks = true
+++
Este tema no tiene JavaScript obligatorio. Opcionalmente, puede cargar una cantidad mínima para agregar algunas características que son imposibles de lograr con HTML y CSS.
## Opciones habilitadas globalmente
El **interruptor de modo claro/oscuro** puede habilitarse configurando `theme_switcher = true` en la sección `[extra]` de tu `config.toml` (~900 bytes de JavaScript).
- El **interruptor de modo claro/oscuro** puede habilitarse configurando `theme_switcher = true` en la sección `[extra]` de tu `config.toml` (~900 bytes de JavaScript).
- **Decodificación de correo electrónico** (~400 bytes). Para protegerte contra los bots que escanean tu correo electrónico desde tu sitio web, puedes configurar `encode_plaintext_email = true`. Si tu sitio está en un repositorio público, para una protección extra, considera configurar tu `email` como una cadena codificada en base64[^1] directamente.
## Configuraciones que pueden habilitarse tanto globalmente como en publicaciones individuales
@ -27,3 +32,7 @@ Para habilitar estas configuraciones globalmente, añádelas en la sección `[ex
- [**Comentarios**](@/blog/comments.es.md). giscus (2 KB), utterances (1 KB), Hyvor Talk (~800 bytes) o Isso (1KB) se pueden habilitar globalmente configurando `enabled_for_all_posts = true` en el apartado apropiado de tu archivo `config.toml` (`[extra.giscus]`, `[extra.utterances]`, `[extra.hyvortalk]` o `[extra.isso]`). Para habilitar comentarios en publicaciones individuales, configura el nombre del sistema `= true` (por ejemplo, `hyvortalk = true`) en el front matter del post.
Aparte de eso, es un tema rápido con HTML y CSS que funciona con JavaScript deshabilitado. Justo como debería ser (en su mayoría) la web :-)
<hr>
[^1]: Para codificar tu correo en base64 puedes usar [herramientas en línea](https://www.base64encode.org/) o, en tu terminal, ejecuta: `printf '

@ -1,18 +1,23 @@
+++
title = "No mandatory JavaScript"
date = 2023-01-06
updated = 2023-08-02
updated = 2023-08-18
description = "JavaScript is only used when HTML and CSS aren't enough."
[taxonomies]
tags = ["showcase", "tutorial"]
[extra]
footnote_backlinks = true
+++
This theme has no mandatory JavaScript. Optionally, it can load a minimal amount to add some features that are impossible to achieve with HTML and CSS.
## Globally enabled settings
The **light/dark mode switch** can be enabled by setting `theme_switcher = true` in the `[extra]` section of your `config.toml` (~900 bytes of JavaScript).
- The **light/dark mode switch** can be enabled by setting `theme_switcher = true` in the `[extra]` section of your `config.toml` (~900 bytes of JavaScript).
- **E-mail decoding** (~400 bytes). To protect against spambots scraping your e-mail from your website, you can set `encode_plaintext_email = true`. If your site is on a public repository, for extra protection, consider setting your `email` as a base64-encoded string[^1] directly.
## Settings that can be enabled globally and for individual posts
@ -27,3 +32,7 @@ To enable these settings globally, add them in the `[extra]` section of your `co
- [**Comments**](@/blog/comments.md). giscus (2 KB), utterances (1 KB), Hyvor Talk (~800 bytes) or Isso (1KB) can be globally enabled by setting `enabled_for_all_posts = true` in the right section of your `config.toml` (i.e. `[extra.giscus]`, `[extra.utterances]`, `[extra.hyvortalk]` or `[extra.isso]`). To enable comments on individual posts, set the name of the system `= true` (e.g. `hyvortalk = true`) in the post's front matter.
Other than that, it's a fast theme with HTML and CSS which works with JavaScript disabled. Just the way (most of) the web should be :-)
<hr>
[^1]: To encode your email in base64 you can use [online tools](https://www.base64encode.org/) or, on your terminal, run: `printf 'mail@example.com' | base64`.

@ -0,0 +1,44 @@
(function () {
'use strict';
// Utility function: Base64 Decoding.
function decodeBase64(encodedString) {
try {
// Can't use atob() directly because it doesn't support non-ascii characters.
// And non-ascii characters are allowed in email addresses and domains.
// See https://en.wikipedia.org/wiki/Email_address#Internationalization
// Code below adapted from Jackie Han: https://stackoverflow.com/a/64752311
const byteString = atob(encodedString);
// Convert byteString to an array of char codes.
const charCodes = [...byteString].map(char => char.charCodeAt(0));
// Use TypedArray.prototype.set() to copy the char codes into a Uint8Array.
const bytes = new Uint8Array(charCodes.length);
bytes.set(charCodes);
const decoder = new TextDecoder("utf-8");
return decoder.decode(bytes);
} catch (e) {
console.error("Failed to decode Base64 string: ", e);
return null;
}
}
// Utility function: Update href of an element with a decoded email.
function updateEmailHref(element) {
const encodedEmail = element.getAttribute('data-encoded-email');
const decodedEmail = decodeBase64(encodedEmail);
if (decodedEmail) {
element.setAttribute('href', `mailto:${decodedEmail}`);
} else {
// If the decoding fails, hide the email link.
element.style.display = 'none';
}
}
// Fetch and process email elements with the "data-encoded-email" attribute.
const encodedEmailElements = document.querySelectorAll('[data-encoded-email]');
encodedEmailElements.forEach(updateEmailHref);
})();

@ -0,0 +1 @@
!function(){"use strict";document.querySelectorAll("[data-encoded-email]").forEach(function(e){var t=function(e){try{var t=[...atob(e)].map(e=>e.charCodeAt(0)),r=new Uint8Array(t.length);return r.set(t),new TextDecoder("utf-8").decode(r)}catch(e){return console.error("Failed to decode Base64 string: ",e),null}}(e.getAttribute("data-encoded-email"));t?e.setAttribute("href","mailto:"+t):e.style.display="none"})}();

@ -10,6 +10,34 @@
</a>
</li>
{%- endif -%}
{# Mail icon #}
{%- if config.extra.email -%}
{%- set email_already_encoded = (config.extra.email is not containing("@")) -%}
{%- set email_needs_decoding = email_already_encoded or config.extra.encode_plaintext_email -%}
{%- if email_already_encoded -%}
{%- set encoded_email = config.extra.email -%}
{# Verify the pre-encoded e-mail is valid (i.e. contains an '@') #}
{%- set decoded_email = encoded_email | base64_decode -%}
{%- if '@' not in decoded_email -%}
{{ throw(message="ERROR: The provided e-mail appears to be base64-encoded, but does not decode to a valid e-mail address.")}}
{%- endif -%}
{%- elif config.extra.encode_plaintext_email -%}
{%- set encoded_email = config.extra.email | base64_encode -%}
{%- endif -%}
<li class="{% if email_needs_decoding %}js{% endif %}">
{%- if email_needs_decoding -%}
<a rel="noopener noreferrer" target="_blank" class="nav-links no-hover-padding social" href="#" data-encoded-email="{{ encoded_email | safe }}">
{%- else -%}
<a rel="noopener noreferrer" target="_blank" class="nav-links no-hover-padding social" href="mailto:{{ config.extra.email | safe }}">
{%- endif -%}
<img alt="email" title="email" src="{{ get_url(path='social_icons/email.svg') }}">
</a>
</li>
{%- endif -%}
{% for social in config.extra.socials %}
<li>
<a rel="noopener noreferrer me" target="_blank" class="nav-links no-hover-padding social" href={{ social.url | safe }}>
@ -24,4 +52,9 @@
<small>{%- if lang != config.default_language %} {{ trans(key="powered_by" | safe, lang=lang) }} {% else %} Powered by {% endif %} <a href="https://www.getzola.org" target="_blank">Zola</a> {%- if lang != config.default_language %} {{ trans(key="and" | safe, lang=lang) }} {% else %} & {% endif %} <a href="https://github.com/welpo/tabi" target="_blank">tabi</a></small>
</div>
</section>
{# Load the decoding script if email is encoded #}
{%- if email_needs_decoding -%}
<script src="{{ get_url(path='js/decodeMail.min.js') }}" async></script>
{%- endif -%}
</footer>

Loading…
Cancel
Save