diff options
| author | Fuwn <[email protected]> | 2025-06-07 13:34:17 +0000 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2025-06-07 13:34:17 +0000 |
| commit | 22bce5a842dc365a5a18644d0fbdcc75e6aa5d5e (patch) | |
| tree | 17f02d84656a586e826fae5c2802644a045e6b13 /src | |
| parent | chore: Bump version patch (diff) | |
| download | september-22bce5a842dc365a5a18644d0fbdcc75e6aa5d5e.tar.xz september-22bce5a842dc365a5a18644d0fbdcc75e6aa5d5e.zip | |
feat!: Overhaul KEEP_GEMINI configuration option
Diffstat (limited to 'src')
| -rw-r--r-- | src/html.rs | 51 | ||||
| -rw-r--r-- | src/response.rs | 49 | ||||
| -rw-r--r-- | src/url.rs | 42 |
3 files changed, 71 insertions, 71 deletions
diff --git a/src/html.rs b/src/html.rs index c0425df..341286c 100644 --- a/src/html.rs +++ b/src/html.rs @@ -1,16 +1,21 @@ use { + crate::url::matches_pattern, germ::ast::Node, std::{env::var, fmt::Write}, url::Url, }; fn link_from_host_href(url: &Url, href: &str) -> Option<String> { - Some(format!( - "gemini://{}{}{}", - url.domain()?, - { if href.starts_with('/') { "" } else { "/" } }, - href - )) + if href.starts_with("/proxy/") { + Some(format!("gemini://{}", href.replace("/proxy/", ""))) + } else { + Some(format!( + "gemini://{}{}{}", + url.domain()?, + { if href.starts_with('/') { "" } else { "/" } }, + href + )) + } } fn safe(text: &str) -> String { @@ -181,30 +186,26 @@ pub fn from_gemini( } } - if let Ok(keeps) = var("KEEP_GEMINI_EXACT") { - let mut keeps = keeps.split(','); + if let Ok(keeps) = var("KEEP_GEMINI") { + let patterns = keeps.split(',').collect::<Vec<_>>(); if (href.starts_with('/') || !href.contains("://")) && !surface { let temporary_href = link_from_host_href(url, &href)?; + let should_exclude = patterns + .iter() + .filter(|p| p.starts_with('!')) + .any(|p| matches_pattern(&p[1..], &temporary_href)); - if keeps.any(|k| k == &*temporary_href) { - href = temporary_href; - } - } - } - - if let Ok(keeps) = var("KEEP_GEMINI_DOMAIN") { - let host = if let Some(host) = url.host() { - host.to_string() - } else { - return None; - }; + if !should_exclude { + let should_include = patterns + .iter() + .filter(|p| !p.starts_with('!')) + .any(|p| matches_pattern(p, &temporary_href)); - if (href.starts_with('/') - || !href.contains("://") && keeps.split(',').any(|k| k == &*host)) - && !surface - { - href = link_from_host_href(url, &href)?; + if should_include { + href = temporary_href; + } + } } } diff --git a/src/response.rs b/src/response.rs index 1a68b08..68c1690 100644 --- a/src/response.rs +++ b/src/response.rs @@ -1,7 +1,7 @@ pub mod configuration; use { - crate::url::from_path as url_from_path, + crate::url::{from_path as url_from_path, matches_pattern}, actix_web::{Error, HttpResponse}, std::{env::var, fmt::Write, time::Instant}, }; @@ -262,8 +262,8 @@ pub async fn default( if let Ok(plain_texts) = var("PLAIN_TEXT_ROUTE") { if plain_texts.split(',').any(|r| { - path_matches_pattern(r, http_request.path()) - || path_matches_pattern(r, http_request.path().trim_end_matches('/')) + matches_pattern(r, http_request.path()) + || matches_pattern(r, http_request.path().trim_end_matches('/')) }) { return Ok(HttpResponse::Ok().body( response.content().as_ref().map_or_else(String::default, String::clone), @@ -277,46 +277,3 @@ pub async fn default( .body(html_context), ) } - -fn path_matches_pattern(pattern: &str, path: &str) -> bool { - if !pattern.contains('*') { - return path == pattern; - } - - let parts: Vec<&str> = pattern.split('*').collect(); - let mut position = if pattern.starts_with('*') { - 0 - } else { - let first = parts.first().unwrap(); - - if !path.starts_with(first) { - return false; - } - - first.len() - }; - - let mid_end = parts.len().saturating_sub(1); - - for part in &parts[1..mid_end] { - if part.is_empty() { - continue; - } - - if let Some(found) = path[position..].find(part) { - position += found + part.len(); - } else { - return false; - } - } - - if !pattern.ends_with('*') { - let last = parts.last().unwrap(); - - if !path[position..].ends_with(last) { - return false; - } - } - - true -} @@ -57,3 +57,45 @@ pub fn from_path( ) }) } + +pub fn matches_pattern(pattern: &str, path: &str) -> bool { + if !pattern.contains('*') { + return path == pattern; + } + + let parts: Vec<&str> = pattern.split('*').collect(); + let mut position = if pattern.starts_with('*') { + 0 + } else { + let first = parts.first().unwrap(); + + if !path.starts_with(first) { + return false; + } + + first.len() + }; + let before_last = parts.len().saturating_sub(1); + + for part in &parts[1..before_last] { + if part.is_empty() { + continue; + } + + if let Some(found) = path[position..].find(part) { + position += found + part.len(); + } else { + return false; + } + } + + if !pattern.ends_with('*') { + let last = parts.last().unwrap(); + + if !path[position..].ends_with(last) { + return false; + } + } + + true +} |