aidoku/helpers/
cfemail.rs

1//! Handles Cloudflare email protection.
2use crate::imports::html::Element;
3
4extern crate alloc;
5use alloc::string::String;
6
7/// Parses `data-cfemail` attribute and returns the email address.
8///
9/// # Examples
10/// ```
11/// use aidoku::helpers::cfemail::parse_cfemail;
12/// assert_eq!(
13///     parse_cfemail("98d1fcf7f4f5d8ebecfdea"),
14///     "Idolm@ster",
15/// );
16/// ```
17pub fn parse_cfemail<T: AsRef<str>>(data: T) -> String {
18	let data = data.as_ref();
19	if let Ok(key) = u32::from_str_radix(&data[0..2], 16) {
20		let mut email = String::with_capacity(data.len() / 2 - 1);
21		let mut n = 2;
22
23		while n < data.len() {
24			if let Ok(chrcode) = u32::from_str_radix(&data[n..n + 2], 16) {
25				let chrcode = chrcode ^ key;
26				email.push(char::from_u32(chrcode).unwrap_or_default());
27			}
28			n += 2;
29		}
30		email
31	} else {
32		"[email protected]".into()
33	}
34}
35
36/// Replaces all `[email protected]` elements with their contents in-place.
37pub fn decode_cfemail(html: &Element) {
38	let Some(elements) = html.select(".__cf_email__") else {
39		return;
40	};
41	for mut elem in elements {
42		let email = parse_cfemail(elem.attr("data-cfemail").unwrap_or_default());
43		elem.set_text(email).ok();
44	}
45}