|  |  | @ -17,8 +17,6 @@ pub fn routes() -> Vec<Route> { | 
			
		
	
		
			
				
					|  |  |  |     routes![icon] | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | const FALLBACK_ICON: &[u8; 344] = include_bytes!("../static/fallback-icon.png"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | const ALLOWED_CHARS: &str = "_-."; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | static CLIENT: Lazy<Client> = Lazy::new(|| { | 
			
		
	
	
		
			
				
					|  |  | @ -52,15 +50,15 @@ fn is_valid_domain(domain: &str) -> bool { | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | #[get("/<domain>/icon.png")] | 
			
		
	
		
			
				
					|  |  |  | fn icon(domain: String) -> Cached<Content<Vec<u8>>> { | 
			
		
	
		
			
				
					|  |  |  |     let icon_type = ContentType::new("image", "x-icon"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | fn icon(domain: String) -> Option<Cached<Content<Vec<u8>>>> { | 
			
		
	
		
			
				
					|  |  |  |     if !is_valid_domain(&domain) { | 
			
		
	
		
			
				
					|  |  |  |         warn!("Invalid domain: {:#?}", domain); | 
			
		
	
		
			
				
					|  |  |  |         return Cached::long(Content(icon_type, FALLBACK_ICON.to_vec())); | 
			
		
	
		
			
				
					|  |  |  |         return None; | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     Cached::long(Content(icon_type, get_icon(&domain))) | 
			
		
	
		
			
				
					|  |  |  |     get_icon(&domain).map(|icon| { | 
			
		
	
		
			
				
					|  |  |  |         Cached::long(Content(ContentType::new("image", "x-icon"), icon)) | 
			
		
	
		
			
				
					|  |  |  |     }) | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | /// TODO: This is extracted from IpAddr::is_global, which is unstable:
 | 
			
		
	
	
		
			
				
					|  |  | @ -190,39 +188,39 @@ fn check_icon_domain_is_blacklisted(domain: &str) -> bool { | 
			
		
	
		
			
				
					|  |  |  |     is_blacklisted | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | fn get_icon(domain: &str) -> Vec<u8> { | 
			
		
	
		
			
				
					|  |  |  | fn get_icon(domain: &str) -> Option<Vec<u8>> { | 
			
		
	
		
			
				
					|  |  |  |     let path = format!("{}/{}.png", CONFIG.icon_cache_folder(), domain); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // Check for expiration of negatively cached copy
 | 
			
		
	
		
			
				
					|  |  |  |     if icon_is_negcached(&path) { | 
			
		
	
		
			
				
					|  |  |  |         return None; | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     if let Some(icon) = get_cached_icon(&path) { | 
			
		
	
		
			
				
					|  |  |  |         return icon; | 
			
		
	
		
			
				
					|  |  |  |         return Some(icon); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     if CONFIG.disable_icon_download() { | 
			
		
	
		
			
				
					|  |  |  |         return FALLBACK_ICON.to_vec(); | 
			
		
	
		
			
				
					|  |  |  |         return None; | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // Get the icon, or fallback in case of error
 | 
			
		
	
		
			
				
					|  |  |  |     // Get the icon, or None in case of error
 | 
			
		
	
		
			
				
					|  |  |  |     match download_icon(&domain) { | 
			
		
	
		
			
				
					|  |  |  |         Ok(icon) => { | 
			
		
	
		
			
				
					|  |  |  |             save_icon(&path, &icon); | 
			
		
	
		
			
				
					|  |  |  |             icon | 
			
		
	
		
			
				
					|  |  |  |             Some(icon) | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |         Err(e) => { | 
			
		
	
		
			
				
					|  |  |  |             error!("Error downloading icon: {:?}", e); | 
			
		
	
		
			
				
					|  |  |  |             let miss_indicator = path + ".miss"; | 
			
		
	
		
			
				
					|  |  |  |             let empty_icon = Vec::new(); | 
			
		
	
		
			
				
					|  |  |  |             save_icon(&miss_indicator, &empty_icon); | 
			
		
	
		
			
				
					|  |  |  |             FALLBACK_ICON.to_vec() | 
			
		
	
		
			
				
					|  |  |  |             None | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | fn get_cached_icon(path: &str) -> Option<Vec<u8>> { | 
			
		
	
		
			
				
					|  |  |  |     // Check for expiration of negatively cached copy
 | 
			
		
	
		
			
				
					|  |  |  |     if icon_is_negcached(path) { | 
			
		
	
		
			
				
					|  |  |  |         return Some(FALLBACK_ICON.to_vec()); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     // Check for expiration of successfully cached copy
 | 
			
		
	
		
			
				
					|  |  |  |     if icon_is_expired(path) { | 
			
		
	
		
			
				
					|  |  |  |         return None; | 
			
		
	
	
		
			
				
					|  |  | 
 |