mirror of
				https://codeberg.org/slatian/service.echoip-slatecave.git
				synced 2025-11-04 10:38:58 +01:00 
			
		
		
		
	Make clippy happy
Mostly cleaning up type system crimes from when I was still learning rust: * Abuse of `match` and loops * Non-use of helper functions (`is_empty`, `is_none`) * Use of borrowed owned types (`&String`) * Implementing `Into` instead of `From`
This commit is contained in:
		@@ -73,14 +73,14 @@ impl Default for DnsConfig {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Into<Protocol> for DnsProtocol {
 | 
			
		||||
	fn into(self) -> Protocol {
 | 
			
		||||
		match self {
 | 
			
		||||
			Self::Udp   => Protocol::Udp,
 | 
			
		||||
			Self::Tcp   => Protocol::Tcp,
 | 
			
		||||
			Self::Tls   => Protocol::Tls,
 | 
			
		||||
			Self::Https => Protocol::Https,
 | 
			
		||||
			Self::Quic  => Protocol::Quic,
 | 
			
		||||
impl From<DnsProtocol> for Protocol {
 | 
			
		||||
	fn from(value: DnsProtocol) -> Self {
 | 
			
		||||
		match value {
 | 
			
		||||
			DnsProtocol::Udp   => Protocol::Udp,
 | 
			
		||||
			DnsProtocol::Tcp   => Protocol::Tcp,
 | 
			
		||||
			DnsProtocol::Tls   => Protocol::Tls,
 | 
			
		||||
			DnsProtocol::Https => Protocol::Https,
 | 
			
		||||
			DnsProtocol::Quic  => Protocol::Quic,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								src/geoip.rs
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								src/geoip.rs
									
									
									
									
									
								
							@@ -4,7 +4,6 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
use log::{info,warn,error};
 | 
			
		||||
use maxminddb;
 | 
			
		||||
use maxminddb::geoip2;
 | 
			
		||||
 | 
			
		||||
use parking_lot::RwLock;
 | 
			
		||||
@@ -56,7 +55,7 @@ pub struct MMDBCarrier {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub trait QueryLocation {
 | 
			
		||||
	fn query_location_for_ip(&self, address: &IpAddr, laguages: &Vec<&String>) -> Option<LocationResult>;
 | 
			
		||||
	fn query_location_for_ip(&self, address: &IpAddr, laguages: &[&str]) -> Option<LocationResult>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub trait QueryAsn {
 | 
			
		||||
@@ -67,12 +66,12 @@ pub trait QueryAsn {
 | 
			
		||||
 | 
			
		||||
pub fn extract_localized_name(
 | 
			
		||||
names: &Option<BTreeMap<&str, &str>>,
 | 
			
		||||
	languages: &Vec<&String>)
 | 
			
		||||
	languages: &[&str])
 | 
			
		||||
-> Option<String> {
 | 
			
		||||
	match names {
 | 
			
		||||
		Some(names) => {
 | 
			
		||||
			for language in languages {
 | 
			
		||||
				if let Some(name) = names.get(language.as_str()){
 | 
			
		||||
				if let Some(name) = names.get(language){
 | 
			
		||||
					return Some(name.to_string())
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
@@ -82,7 +81,7 @@ names: &Option<BTreeMap<&str, &str>>,
 | 
			
		||||
	}	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn geoip2_city_to_named_location(item: geoip2::city::City, languages: &Vec<&String>) -> NamedLocation {
 | 
			
		||||
pub fn geoip2_city_to_named_location(item: geoip2::city::City, languages: &[&str]) -> NamedLocation {
 | 
			
		||||
	NamedLocation {
 | 
			
		||||
		iso_code: None,
 | 
			
		||||
		geoname_id: item.geoname_id,
 | 
			
		||||
@@ -90,7 +89,7 @@ pub fn geoip2_city_to_named_location(item: geoip2::city::City, languages: &Vec<&
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn geoip2_continent_to_named_location(item: geoip2::country::Continent, languages: &Vec<&String>) -> NamedLocation {
 | 
			
		||||
pub fn geoip2_continent_to_named_location(item: geoip2::country::Continent, languages: &[&str]) -> NamedLocation {
 | 
			
		||||
	NamedLocation {
 | 
			
		||||
		iso_code: item.code.map(ToString::to_string),
 | 
			
		||||
		geoname_id: item.geoname_id,
 | 
			
		||||
@@ -98,7 +97,7 @@ pub fn geoip2_continent_to_named_location(item: geoip2::country::Continent, lang
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn geoip2_country_to_named_location(item: geoip2::country::Country, languages: &Vec<&String>) -> NamedLocation {
 | 
			
		||||
pub fn geoip2_country_to_named_location(item: geoip2::country::Country, languages: &[&str]) -> NamedLocation {
 | 
			
		||||
	NamedLocation {
 | 
			
		||||
		iso_code: item.iso_code.map(ToString::to_string),
 | 
			
		||||
		geoname_id: item.geoname_id,
 | 
			
		||||
@@ -106,7 +105,7 @@ pub fn geoip2_country_to_named_location(item: geoip2::country::Country, language
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn geoip2_represented_country_to_named_location(item: geoip2::country::RepresentedCountry, languages: &Vec<&String>) -> NamedLocation {
 | 
			
		||||
pub fn geoip2_represented_country_to_named_location(item: geoip2::country::RepresentedCountry, languages: &[&str]) -> NamedLocation {
 | 
			
		||||
	NamedLocation {
 | 
			
		||||
		iso_code: item.iso_code.map(ToString::to_string),
 | 
			
		||||
		geoname_id: item.geoname_id,
 | 
			
		||||
@@ -114,7 +113,7 @@ pub fn geoip2_represented_country_to_named_location(item: geoip2::country::Repre
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn geoip2_subdivision_to_named_location(item: geoip2::city::Subdivision, languages: &Vec<&String>) -> NamedLocation {
 | 
			
		||||
pub fn geoip2_subdivision_to_named_location(item: geoip2::city::Subdivision, languages: &[&str]) -> NamedLocation {
 | 
			
		||||
	NamedLocation {
 | 
			
		||||
		iso_code: item.iso_code.map(ToString::to_string),
 | 
			
		||||
		geoname_id: item.geoname_id,
 | 
			
		||||
@@ -148,7 +147,7 @@ impl QueryAsn for MMDBCarrier {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl QueryLocation for MMDBCarrier {
 | 
			
		||||
	fn query_location_for_ip(&self, address: &IpAddr, languages: &Vec<&String>) -> Option<LocationResult> {
 | 
			
		||||
	fn query_location_for_ip(&self, address: &IpAddr, languages: &[&str]) -> Option<LocationResult> {
 | 
			
		||||
		let mmdb = self.mmdb.read();
 | 
			
		||||
		match &*mmdb {
 | 
			
		||||
			Some(mmdb) => {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								src/idna.rs
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								src/idna.rs
									
									
									
									
									
								
							@@ -14,7 +14,7 @@ pub enum NameType {
 | 
			
		||||
	#[default]
 | 
			
		||||
	Ascii,
 | 
			
		||||
	Unicode,
 | 
			
		||||
	IDN,
 | 
			
		||||
	Idn,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Note, that the
 | 
			
		||||
@@ -32,8 +32,8 @@ pub struct IdnaName {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl IdnaName {
 | 
			
		||||
	pub fn from_string(s: &String) -> Self {
 | 
			
		||||
		if s == "" {
 | 
			
		||||
	pub fn from_str(s: &str) -> Self {
 | 
			
		||||
		if s.is_empty() {
 | 
			
		||||
			return Default::default();
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
@@ -41,17 +41,17 @@ impl IdnaName {
 | 
			
		||||
		let unicode: String;
 | 
			
		||||
		let decoder_error;
 | 
			
		||||
		if s.starts_with("xn--") && s.is_ascii() {
 | 
			
		||||
			original_was = NameType::IDN;
 | 
			
		||||
			original_was = NameType::Idn;
 | 
			
		||||
			let (uc, ures) = idna::domain_to_unicode(s);
 | 
			
		||||
			unicode = uc;
 | 
			
		||||
			decoder_error = ures.map_or_else(|e| Some(e.to_string()), |_| None);
 | 
			
		||||
		} else {
 | 
			
		||||
			unicode = s.clone();
 | 
			
		||||
			unicode = s.to_owned();
 | 
			
		||||
			decoder_error = None;
 | 
			
		||||
		};
 | 
			
		||||
		let (idn, encoder_error) = match idna::domain_to_ascii(s) {
 | 
			
		||||
			Ok(idn) => {
 | 
			
		||||
				if &idn != s || original_was == NameType::IDN {
 | 
			
		||||
				if idn != s || original_was == NameType::Idn {
 | 
			
		||||
					(Some(idn), None)
 | 
			
		||||
				} else {
 | 
			
		||||
					original_was = NameType::Ascii;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										74
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										74
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -1,3 +1,7 @@
 | 
			
		||||
 | 
			
		||||
#![allow(clippy::redundant_field_names)]
 | 
			
		||||
#![allow(clippy::needless_return)]
 | 
			
		||||
 | 
			
		||||
use axum::{
 | 
			
		||||
	body::Body,
 | 
			
		||||
	extract::{
 | 
			
		||||
@@ -61,7 +65,7 @@ use crate::idna::IdnaName;
 | 
			
		||||
use crate::simple_dns::DnsLookupResult;
 | 
			
		||||
use crate::settings::*;
 | 
			
		||||
use crate::view::View;
 | 
			
		||||
use crate::ipinfo::{AddressCast,AddressInfo,AddressScope};
 | 
			
		||||
use crate::ipinfo::{AddressInfo,AddressScope};
 | 
			
		||||
 | 
			
		||||
type TemplatingEngine = HumusEngine<View,QuerySettings,ResponseFormat>;
 | 
			
		||||
 | 
			
		||||
@@ -133,7 +137,7 @@ struct CliArgs {
 | 
			
		||||
	static_location: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn match_domain_hidden_list(domain: &String, hidden_list: &Vec<String>) -> bool {
 | 
			
		||||
fn match_domain_hidden_list(domain: &str, hidden_list: &Vec<String>) -> bool {
 | 
			
		||||
	let name = domain.trim_end_matches(".");
 | 
			
		||||
	for suffix in hidden_list {
 | 
			
		||||
		if name.ends_with(suffix) {
 | 
			
		||||
@@ -265,7 +269,7 @@ async fn main() {
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	dns_resolver_selectables.sort_by(|a,b| b.weight.cmp(&a.weight));
 | 
			
		||||
	let default_resolver = dns_resolver_selectables.get(0)
 | 
			
		||||
	let default_resolver = dns_resolver_selectables.first()
 | 
			
		||||
		.map(|s| s.id.clone() )
 | 
			
		||||
		.unwrap_or("none".into());
 | 
			
		||||
	let derived_config = DerivedConfiguration {
 | 
			
		||||
@@ -286,7 +290,7 @@ async fn main() {
 | 
			
		||||
			}
 | 
			
		||||
		};
 | 
			
		||||
		loop {
 | 
			
		||||
			if None == signal_stream.recv().await { return; }
 | 
			
		||||
			if signal_stream.recv().await.is_none() { return; }
 | 
			
		||||
			info!("Received signal USR1, reloading geoip databses!");
 | 
			
		||||
			signal_usr1_handlers_state.location_db.reload_database().ok();
 | 
			
		||||
			signal_usr1_handlers_state.asn_db.reload_database().ok();
 | 
			
		||||
@@ -436,10 +440,8 @@ async fn handle_default_route(
 | 
			
		||||
		&state,
 | 
			
		||||
	).await;
 | 
			
		||||
 | 
			
		||||
	let user_agent: Option<String> = match user_agent_header {
 | 
			
		||||
		Some(TypedHeader(user_agent)) => Some(user_agent.to_string()),
 | 
			
		||||
		None => None,
 | 
			
		||||
	};
 | 
			
		||||
	let user_agent: Option<String> = user_agent_header
 | 
			
		||||
		.map(|TypedHeader(user_agent)| user_agent.to_string());
 | 
			
		||||
 | 
			
		||||
	state.templating_engine.render_view(
 | 
			
		||||
		&settings,
 | 
			
		||||
@@ -466,7 +468,7 @@ async fn handle_search_request(
 | 
			
		||||
 | 
			
		||||
	//If someone asked for an asn, give an asn answer
 | 
			
		||||
	if let Some(asn_cap) = ASN_REGEX.captures(&search_query) {
 | 
			
		||||
		if let Some(asn) = asn_cap.get(1).map_or(None, |m| m.as_str().parse::<u32>().ok()) {
 | 
			
		||||
		if let Some(asn) = asn_cap.get(1).and_then(|m| m.as_str().parse::<u32>().ok()) {
 | 
			
		||||
			// Render a dummy template that can at least link to other pages
 | 
			
		||||
			let state = Arc::clone(&arc_state);
 | 
			
		||||
			return state.templating_engine.render_view(
 | 
			
		||||
@@ -571,7 +573,7 @@ async fn handle_ip_request(
 | 
			
		||||
 | 
			
		||||
async fn get_ip_result(
 | 
			
		||||
	address: &IpAddr,
 | 
			
		||||
	lang: &String,
 | 
			
		||||
	lang: &str,
 | 
			
		||||
	dns_resolver_name: &Arc<str>,
 | 
			
		||||
	dns_disable_self_lookup: bool,
 | 
			
		||||
	client_ip: &IpAddr,
 | 
			
		||||
@@ -580,34 +582,36 @@ async fn get_ip_result(
 | 
			
		||||
 | 
			
		||||
	let mut reverse_dns_disabled_for_privacy = false;
 | 
			
		||||
	
 | 
			
		||||
	if state.config.dns.allow_reverse_lookup {
 | 
			
		||||
		if address == client_ip && dns_disable_self_lookup {
 | 
			
		||||
			reverse_dns_disabled_for_privacy = true;
 | 
			
		||||
		}
 | 
			
		||||
	if state.config.dns.allow_reverse_lookup &&
 | 
			
		||||
		address == client_ip &&
 | 
			
		||||
		dns_disable_self_lookup
 | 
			
		||||
	{
 | 
			
		||||
		reverse_dns_disabled_for_privacy = true;
 | 
			
		||||
	}
 | 
			
		||||
		
 | 
			
		||||
	let ip_info = AddressInfo::new(&address);
 | 
			
		||||
	let ip_info = AddressInfo::new(address);
 | 
			
		||||
 | 
			
		||||
	if !(ip_info.scope == AddressScope::Global || ip_info.scope == AddressScope::Shared) || ip_info.cast != AddressCast::Unicast {
 | 
			
		||||
		if !((ip_info.scope == AddressScope::Private || ip_info.scope == AddressScope::LinkLocal) && state.config.server.allow_private_ip_lookup) {
 | 
			
		||||
			return IpResult {
 | 
			
		||||
				address: *address,
 | 
			
		||||
				hostname: None,
 | 
			
		||||
				asn: None,
 | 
			
		||||
				location: None,
 | 
			
		||||
				ip_info: ip_info,
 | 
			
		||||
				used_dns_resolver: None,
 | 
			
		||||
				reverse_dns_disabled_for_privacy: reverse_dns_disabled_for_privacy,
 | 
			
		||||
			}
 | 
			
		||||
	// Return dummy result if:
 | 
			
		||||
	//
 | 
			
		||||
	// The address falls into a private range and lookup of private addresses is not allowed.
 | 
			
		||||
	if (!state.config.server.allow_private_ip_lookup) && (ip_info.scope == AddressScope::Private || ip_info.scope == AddressScope::LinkLocal) {
 | 
			
		||||
		return IpResult {
 | 
			
		||||
			address: *address,
 | 
			
		||||
			hostname: None,
 | 
			
		||||
			asn: None,
 | 
			
		||||
			location: None,
 | 
			
		||||
			ip_info: ip_info,
 | 
			
		||||
			used_dns_resolver: None,
 | 
			
		||||
			reverse_dns_disabled_for_privacy: reverse_dns_disabled_for_privacy,
 | 
			
		||||
		}
 | 
			
		||||
	} 
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// do reverse lookup
 | 
			
		||||
	let mut hostname: Option<String> = None;
 | 
			
		||||
	let mut used_dns_resolver: Option<Arc<str>> = None;
 | 
			
		||||
	if state.config.dns.allow_reverse_lookup && !reverse_dns_disabled_for_privacy {
 | 
			
		||||
		if let Some(dns_resolver) = &state.dns_resolvers.get(dns_resolver_name) {
 | 
			
		||||
			hostname = simple_dns::reverse_lookup(&dns_resolver, &address).await;
 | 
			
		||||
			hostname = simple_dns::reverse_lookup(dns_resolver, address).await;
 | 
			
		||||
			used_dns_resolver = Some(dns_resolver_name.clone());
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -618,12 +622,12 @@ async fn get_ip_result(
 | 
			
		||||
	// location lookup
 | 
			
		||||
	let location_result = state.location_db.query_location_for_ip(
 | 
			
		||||
		address,
 | 
			
		||||
		&vec![lang, &"en".to_string()]
 | 
			
		||||
		&[lang, "en"]
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	// filter reverse lookup
 | 
			
		||||
	if let Some(name) = &hostname {
 | 
			
		||||
		if match_domain_hidden_list(&name, &state.config.dns.hidden_suffixes) {
 | 
			
		||||
		if match_domain_hidden_list(name, &state.config.dns.hidden_suffixes) {
 | 
			
		||||
			hostname = None;
 | 
			
		||||
			used_dns_resolver = None;
 | 
			
		||||
		}
 | 
			
		||||
@@ -672,21 +676,21 @@ async fn handle_dig_request(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async fn get_dig_result(
 | 
			
		||||
	dig_query:         &String,
 | 
			
		||||
	dig_query:         &str,
 | 
			
		||||
	dns_resolver_name: &Arc<str>,
 | 
			
		||||
	state:             &ServiceSharedState,
 | 
			
		||||
	do_full_lookup:     bool,
 | 
			
		||||
) -> DigResult {
 | 
			
		||||
	let name = &dig_query.trim().trim_end_matches(".").to_string();
 | 
			
		||||
	let idna_name = IdnaName::from_string(&name);
 | 
			
		||||
	let idna_name = IdnaName::from_str(name);
 | 
			
		||||
	if let Some(dns_resolver) = state.dns_resolvers.get(dns_resolver_name) {
 | 
			
		||||
		if let Ok(domain_name) = Name::from_str_relaxed(name.to_owned()+".") {
 | 
			
		||||
			if match_domain_hidden_list(&name, &state.config.dns.hidden_suffixes) {
 | 
			
		||||
			if match_domain_hidden_list(name, &state.config.dns.hidden_suffixes) {
 | 
			
		||||
				// Try to hide the fact that we didn't do dns resolution at all
 | 
			
		||||
				// We resolve example.org as basic avoidance of timing sidechannels.
 | 
			
		||||
				// WARNING: this timing sidechannel avoidance is very crude.
 | 
			
		||||
				simple_dns::lookup(
 | 
			
		||||
							&dns_resolver,
 | 
			
		||||
							dns_resolver,
 | 
			
		||||
							&Name::from_ascii("example.org.").expect("Static Dummy Name"),
 | 
			
		||||
							do_full_lookup).await;
 | 
			
		||||
				return DigResult {
 | 
			
		||||
@@ -698,7 +702,7 @@ async fn get_dig_result(
 | 
			
		||||
			} else {
 | 
			
		||||
				return DigResult {
 | 
			
		||||
					records: simple_dns::lookup(
 | 
			
		||||
						&dns_resolver,
 | 
			
		||||
						dns_resolver,
 | 
			
		||||
						&domain_name,
 | 
			
		||||
						do_full_lookup).await,
 | 
			
		||||
					idn: idna_name,
 | 
			
		||||
 
 | 
			
		||||
@@ -80,7 +80,7 @@ pub async fn reverse_lookup(
 | 
			
		||||
	let revese_res = resolver.reverse_lookup(*address);
 | 
			
		||||
	match revese_res.await {
 | 
			
		||||
		Ok(lookup) => {
 | 
			
		||||
			for name in lookup {
 | 
			
		||||
			if let Some(name) = lookup.iter().next() {
 | 
			
		||||
				return Some(name.to_string())
 | 
			
		||||
			}
 | 
			
		||||
			None
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user