From 65288278137cbb2820d91a18b6dc6225dd2f981d Mon Sep 17 00:00:00 2001 From: Rafael Mardojai CM Date: Wed, 20 Mar 2024 15:54:35 -0500 Subject: [PATCH] backend: scraper: Add support for data urls on favicons Fixes #69 --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + src/backend/scraper.rs | 34 +++++++++++++++++++++++++--------- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d510c2f..02a4caa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -596,6 +596,12 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "data-url" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" + [[package]] name = "derive_more" version = "0.99.17" @@ -2438,6 +2444,7 @@ name = "share-preview" version = "0.4.0" dependencies = [ "async-std", + "data-url", "gettext-rs", "gtk-macros", "gtk4", diff --git a/Cargo.toml b/Cargo.toml index 67d782d..2c51c1c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ gtk = { package = "gtk4", version = "0.7", features = ["v4_10"] } gtk-macros = "0.3" once_cell = "1.5" url = "2.2" +data-url = "0.3" scraper = "0.12" surf = "2.2" async-std = "1.12" diff --git a/src/backend/scraper.rs b/src/backend/scraper.rs index 9697e10..d3f0460 100644 --- a/src/backend/scraper.rs +++ b/src/backend/scraper.rs @@ -6,6 +6,7 @@ use std::{ fmt::{Display, Formatter, Result as FmtResult} }; +use data_url::DataUrl; use url::{Url, ParseError}; use scraper::{Html, Selector, element_ref::ElementRef}; @@ -159,16 +160,31 @@ async fn get_favicon(url: &Url, html_icons: Vec) -> Option { } for icon in icons.iter() { - if let Ok(mut resp) = CLIENT.get(&icon).await { - if resp.status().is_success() { - if let Ok(bytes) = resp.body_bytes().await { - let image = Image::new(icon.to_string()); - image.size.set(Some(bytes.len())); - image.bytes.replace(Some(bytes)); - return Some(image); - }; + match icon.scheme() { + "file" | "http" | "https" => { + if let Ok(mut resp) = CLIENT.get(&icon).await { + if resp.status().is_success() { + if let Ok(bytes) = resp.body_bytes().await { + let image = Image::new(icon.to_string()); + image.size.set(Some(bytes.len())); + image.bytes.replace(Some(bytes)); + return Some(image); + }; + } + } } - }; + "data" => { + if let Ok(data) = DataUrl::process(icon.as_str()) { + if let Ok((body, _fragment)) = data.decode_to_vec() { + let image = Image::new(icon.to_string()); + image.size.set(Some(body.len())); + image.bytes.replace(Some(body)); + return Some(image); + } + } + } + _ => () + } } None