mirror of
https://codeberg.org/slatian/service.echoip-slatecave.git
synced 2025-07-17 14:33:27 +02:00
Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
35c71aba64 | |||
d79d949d65 | |||
b3f94b0d90 | |||
96207f3960 | |||
cd7a7fbe05 | |||
aaecdb84bb | |||
b08c98376c | |||
51877fc4c3 | |||
396bbdb348 | |||
a582c74d18 | |||
e8a21ac95f | |||
d706e7c614 | |||
0bffa0fd96 | |||
fb0ce1dc0b | |||
a67631fa9b | |||
636e10f786 | |||
0076db531a |
986
Cargo.lock
generated
986
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
25
Cargo.toml
25
Cargo.toml
@ -1,30 +1,31 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "echoip-slatecave"
|
name = "echoip-slatecave"
|
||||||
version = "1.2.0"
|
version = "1.2.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Slatian <baschdel@disroot.org>"]
|
authors = ["Slatian <baschdel@disroot.org>"]
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lib-humus = { version="0.1", features=["axum-view+cookie"], git="https://codeberg.org/slatian/lib-humus.git" }
|
lib-humus = { version="0.2", features=["axum-view+cookie"], git="https://codeberg.org/slatian/lib-humus.git" }
|
||||||
|
|
||||||
axum = { version = "0.6", features = ["macros", "headers"] }
|
axum = { version = "0.7", features = ["macros"] }
|
||||||
axum-extra = { version = "0.7", features = ["cookie"] }
|
axum-extra = { version = "0.9", features = ["cookie", "typed-header"] }
|
||||||
axum-client-ip = "0.4"
|
axum-client-ip = "0.5"
|
||||||
clap = { version = "4", features = ["derive"] }
|
clap = { version = "4", features = ["derive"] }
|
||||||
governor = "0.5"
|
governor = "0.6"
|
||||||
idna = "0.3"
|
idna = "0.4"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
parking_lot = "0.12"
|
parking_lot = "0.12"
|
||||||
regex = "1.7"
|
regex = "1.10"
|
||||||
serde = { version = "1", features = ["derive","rc"] }
|
serde = { version = "1", features = ["derive","rc"] }
|
||||||
tokio = { version = "1", features = ["macros","signal"] }
|
tokio = { version = "1", features = ["macros","signal"] }
|
||||||
tera = "1"
|
tera = "1"
|
||||||
toml = "0.7"
|
toml = "0.8"
|
||||||
tower = "0.4"
|
tower = "0.4"
|
||||||
tower-http = { version = "0.4", features = ["fs"] }
|
tower-http = { version = "0.5", features = ["fs"] }
|
||||||
trust-dns-proto = "0.22"
|
hickory-proto = "0.24"
|
||||||
trust-dns-resolver = { version = "0.22", features = ["dns-over-rustls","dns-over-https","dns-over-quic"] }
|
hickory-resolver = { version = "0.24", features = ["dns-over-rustls","dns-over-https","dns-over-quic","native-certs"] }
|
||||||
maxminddb = "0.23"
|
maxminddb = "0.23"
|
||||||
mime = "0.3"
|
mime = "0.3"
|
||||||
|
http = "1.0"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use serde::{Deserialize,Serialize};
|
use serde::{Deserialize,Serialize};
|
||||||
use trust_dns_resolver::config::Protocol;
|
use hickory_resolver::config::Protocol;
|
||||||
|
use hickory_resolver::config::ResolverConfig as HickoryResolverConfig;
|
||||||
|
use hickory_resolver::config::NameServerConfig;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@ -43,8 +45,8 @@ pub struct DnsResolverConfig {
|
|||||||
pub tls_dns_name: Option<Arc<str>>,
|
pub tls_dns_name: Option<Arc<str>>,
|
||||||
#[serde(skip_serializing)] //Don't leak our bind address to the outside
|
#[serde(skip_serializing)] //Don't leak our bind address to the outside
|
||||||
pub bind_address: Option<SocketAddr>,
|
pub bind_address: Option<SocketAddr>,
|
||||||
#[serde(default="default_true")]
|
#[serde(default="default_true", alias="trust_nx_responses")]
|
||||||
pub trust_nx_responses: bool,
|
pub trust_negative_responses: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zero() -> i32 {
|
fn zero() -> i32 {
|
||||||
@ -86,14 +88,14 @@ impl Into<Protocol> for DnsProtocol {
|
|||||||
impl DnsResolverConfig {
|
impl DnsResolverConfig {
|
||||||
pub fn to_trust_resolver_config(
|
pub fn to_trust_resolver_config(
|
||||||
&self
|
&self
|
||||||
) -> trust_dns_resolver::config::ResolverConfig {
|
) -> HickoryResolverConfig {
|
||||||
let mut resolver = trust_dns_resolver::config::ResolverConfig::new();
|
let mut resolver = HickoryResolverConfig::new();
|
||||||
for server in &self.servers {
|
for server in &self.servers {
|
||||||
resolver.add_name_server(trust_dns_resolver::config::NameServerConfig{
|
resolver.add_name_server(NameServerConfig{
|
||||||
socket_addr: *server,
|
socket_addr: *server,
|
||||||
protocol: self.protocol.clone().into(),
|
protocol: self.protocol.clone().into(),
|
||||||
tls_dns_name: self.tls_dns_name.clone().map(|s| s.to_string()),
|
tls_dns_name: self.tls_dns_name.clone().map(|s| s.to_string()),
|
||||||
trust_nx_responses: self.trust_nx_responses,
|
trust_negative_responses: self.trust_negative_responses,
|
||||||
tls_config: None,
|
tls_config: None,
|
||||||
bind_addr: self.bind_address,
|
bind_addr: self.bind_address,
|
||||||
});
|
});
|
||||||
|
43
src/main.rs
43
src/main.rs
@ -1,28 +1,29 @@
|
|||||||
use axum::{
|
use axum::{
|
||||||
|
body::Body,
|
||||||
extract::{
|
extract::{
|
||||||
self,
|
self,
|
||||||
Query,
|
Query,
|
||||||
State,
|
State,
|
||||||
Extension,
|
Extension,
|
||||||
},
|
},
|
||||||
headers,
|
|
||||||
http::Request,
|
|
||||||
handler::Handler,
|
handler::Handler,
|
||||||
|
http::Request,
|
||||||
middleware::{self, Next},
|
middleware::{self, Next},
|
||||||
response::Response,
|
response::Response,
|
||||||
Router,
|
Router,
|
||||||
routing::get,
|
routing::get,
|
||||||
TypedHeader,
|
|
||||||
};
|
};
|
||||||
use axum_client_ip::SecureClientIp;
|
use axum_client_ip::SecureClientIp;
|
||||||
|
use axum_extra::headers;
|
||||||
|
use axum_extra::TypedHeader;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde::{Deserialize,Serialize};
|
use serde::{Deserialize,Serialize};
|
||||||
use tower::ServiceBuilder;
|
use tower::ServiceBuilder;
|
||||||
use tower_http::services::ServeDir;
|
use tower_http::services::ServeDir;
|
||||||
use trust_dns_resolver::Name;
|
use hickory_resolver::Name;
|
||||||
use trust_dns_resolver::TokioAsyncResolver;
|
use hickory_resolver::TokioAsyncResolver;
|
||||||
|
|
||||||
use tokio::signal::unix::{
|
use tokio::signal::unix::{
|
||||||
signal,
|
signal,
|
||||||
@ -228,7 +229,7 @@ async fn main() {
|
|||||||
let resolver = TokioAsyncResolver::tokio(
|
let resolver = TokioAsyncResolver::tokio(
|
||||||
resolver_config.to_trust_resolver_config(),
|
resolver_config.to_trust_resolver_config(),
|
||||||
Default::default()
|
Default::default()
|
||||||
).unwrap();
|
);
|
||||||
dns_resolver_map.insert(key.clone(), resolver);
|
dns_resolver_map.insert(key.clone(), resolver);
|
||||||
dns_resolver_selectables.push(Selectable {
|
dns_resolver_selectables.push(Selectable {
|
||||||
id: key.clone(),
|
id: key.clone(),
|
||||||
@ -311,21 +312,21 @@ async fn main() {
|
|||||||
|
|
||||||
println!("Starting Server on {} ...",listen_on);
|
println!("Starting Server on {} ...",listen_on);
|
||||||
|
|
||||||
axum::Server::bind(&listen_on)
|
let listener = tokio::net::TcpListener::bind(&listen_on).await.unwrap();
|
||||||
.serve(app.into_make_service_with_connect_info::<std::net::SocketAddr>())
|
axum::serve(listener, app.into_make_service_with_connect_info::<std::net::SocketAddr>())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn settings_query_middleware<B>(
|
async fn settings_query_middleware(
|
||||||
Query(query): Query<SettingsQuery>,
|
Query(query): Query<SettingsQuery>,
|
||||||
Extension(config): Extension<config::EchoIpServiceConfig>,
|
Extension(config): Extension<config::EchoIpServiceConfig>,
|
||||||
Extension(derived_config): Extension<DerivedConfiguration>,
|
Extension(derived_config): Extension<DerivedConfiguration>,
|
||||||
cookie_header: Option<TypedHeader<headers::Cookie>>,
|
cookie_header: Option<TypedHeader<headers::Cookie>>,
|
||||||
user_agent_header: Option<TypedHeader<headers::UserAgent>>,
|
user_agent_header: Option<TypedHeader<headers::UserAgent>>,
|
||||||
mut req: Request<B>,
|
mut req: Request<Body>,
|
||||||
next: Next<B>
|
next: Next
|
||||||
) -> Response {
|
) -> Response {
|
||||||
let mut format = query.format;
|
let mut format = query.format;
|
||||||
let mut dns_resolver_id = derived_config.default_resolver;
|
let mut dns_resolver_id = derived_config.default_resolver;
|
||||||
@ -369,7 +370,7 @@ async fn not_found_handler(
|
|||||||
state.templating_engine.render_view(
|
state.templating_engine.render_view(
|
||||||
&settings,
|
&settings,
|
||||||
View::NotFound,
|
View::NotFound,
|
||||||
).await
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn hello_world_handler(
|
async fn hello_world_handler(
|
||||||
@ -382,9 +383,9 @@ async fn hello_world_handler(
|
|||||||
&settings,
|
&settings,
|
||||||
View::Message{
|
View::Message{
|
||||||
title: "Hey There!".to_string(),
|
title: "Hey There!".to_string(),
|
||||||
message: "You,You are an awesome Creature!".to_string()
|
message: "You are an awesome Creature!".to_string()
|
||||||
},
|
},
|
||||||
).await
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -428,7 +429,7 @@ async fn handle_default_route(
|
|||||||
result: result,
|
result: result,
|
||||||
user_agent: user_agent,
|
user_agent: user_agent,
|
||||||
}
|
}
|
||||||
).await
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -455,7 +456,7 @@ async fn handle_search_request(
|
|||||||
return state.templating_engine.render_view(
|
return state.templating_engine.render_view(
|
||||||
&settings,
|
&settings,
|
||||||
View::Asn{asn: asn},
|
View::Asn{asn: asn},
|
||||||
).await
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,7 +495,7 @@ async fn handle_dns_resolver_route(
|
|||||||
state.templating_engine.render_view(
|
state.templating_engine.render_view(
|
||||||
&settings,
|
&settings,
|
||||||
View::DnsResolverList,
|
View::DnsResolverList,
|
||||||
).await
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -508,12 +509,12 @@ async fn handle_dns_resolver_route_with_path(
|
|||||||
state.templating_engine.render_view(
|
state.templating_engine.render_view(
|
||||||
&settings,
|
&settings,
|
||||||
View::DnsResolver{ config: resolver.clone() },
|
View::DnsResolver{ config: resolver.clone() },
|
||||||
).await
|
)
|
||||||
} else {
|
} else {
|
||||||
state.templating_engine.render_view(
|
state.templating_engine.render_view(
|
||||||
&settings,
|
&settings,
|
||||||
View::NotFound,
|
View::NotFound,
|
||||||
).await
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,7 +546,7 @@ async fn handle_ip_request(
|
|||||||
state.templating_engine.render_view(
|
state.templating_engine.render_view(
|
||||||
&settings,
|
&settings,
|
||||||
View::Ip{result: result}
|
View::Ip{result: result}
|
||||||
).await
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_ip_result(
|
async fn get_ip_result(
|
||||||
@ -634,7 +635,7 @@ async fn handle_dig_request(
|
|||||||
state.templating_engine.render_view(
|
state.templating_engine.render_view(
|
||||||
&settings,
|
&settings,
|
||||||
View::Dig{ query: dig_query, result: dig_result}
|
View::Dig{ query: dig_query, result: dig_result}
|
||||||
).await
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use axum_client_ip::SecureClientIp;
|
use axum_client_ip::SecureClientIp;
|
||||||
use axum::{
|
use axum::{
|
||||||
|
body::Body,
|
||||||
extract::Extension,
|
extract::Extension,
|
||||||
http::{
|
http::{
|
||||||
Request,
|
Request,
|
||||||
@ -40,11 +41,11 @@ pub fn build_rate_limiting_state(
|
|||||||
Extension(arc_limiter)
|
Extension(arc_limiter)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn rate_limit_middleware<B>(
|
pub async fn rate_limit_middleware(
|
||||||
SecureClientIp(address): SecureClientIp,
|
SecureClientIp(address): SecureClientIp,
|
||||||
Extension(arc_limiter): Extension<Arc<SimpleRateLimiter<IpAddr>>>,
|
Extension(arc_limiter): Extension<Arc<SimpleRateLimiter<IpAddr>>>,
|
||||||
req: Request<B>,
|
req: Request<Body>,
|
||||||
next: Next<B>
|
next: Next
|
||||||
) -> Response {
|
) -> Response {
|
||||||
let limiter = Arc::clone(&arc_limiter);
|
let limiter = Arc::clone(&arc_limiter);
|
||||||
|
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
/*
|
|
||||||
* This module wraps the trust_dns_resolver library
|
|
||||||
* to generate results thaat are ready for serializing
|
|
||||||
* or templating.
|
|
||||||
* It does not aim to be reusable for any other purpose,
|
|
||||||
* the trust_dns_resolver library already does that.
|
|
||||||
*/
|
|
||||||
|
|
||||||
use trust_dns_proto::op::response_code::ResponseCode;
|
//! This module wraps the hickory_resolver library
|
||||||
use trust_dns_proto::rr::{
|
//! to generate results thaat are ready for serializing
|
||||||
|
//! or templating.
|
||||||
|
//! It does not aim to be reusable for any other purpose,
|
||||||
|
//! the hickory_resolver library already does that.
|
||||||
|
|
||||||
|
use hickory_proto::op::response_code::ResponseCode;
|
||||||
|
use hickory_proto::rr::{
|
||||||
RData,
|
RData,
|
||||||
record_type::RecordType,
|
record_type::RecordType,
|
||||||
};
|
};
|
||||||
use trust_dns_resolver::{
|
use hickory_resolver::{
|
||||||
error::ResolveError,
|
error::ResolveError,
|
||||||
error::ResolveErrorKind,
|
error::ResolveErrorKind,
|
||||||
lookup::Lookup,
|
lookup::Lookup,
|
||||||
@ -121,9 +120,9 @@ pub fn set_default_if_none<T>(opt_vec: &mut Option<Vec<T>>) {
|
|||||||
|
|
||||||
pub fn add_record_to_lookup_result(result: &mut DnsLookupResult, record: &RData){
|
pub fn add_record_to_lookup_result(result: &mut DnsLookupResult, record: &RData){
|
||||||
match record {
|
match record {
|
||||||
RData::AAAA(address) => opush(&mut result.aaaa, std::net::IpAddr::V6(*address)),
|
RData::AAAA(aaaa) => opush(&mut result.aaaa, std::net::IpAddr::V6(aaaa.0)),
|
||||||
RData::ANAME(aname) => opush(&mut result.aname, aname.to_string()),
|
RData::ANAME(aname) => opush(&mut result.aname, aname.to_string()),
|
||||||
RData::A(address) => opush(&mut result.a, std::net::IpAddr::V4(*address)),
|
RData::A(a) => opush(&mut result.a, std::net::IpAddr::V4(a.0)),
|
||||||
RData::CAA(caa) => opush(&mut result.caa, caa.to_string()),
|
RData::CAA(caa) => opush(&mut result.caa, caa.to_string()),
|
||||||
RData::CNAME(cname) => opush(&mut result.cname, cname.to_string()),
|
RData::CNAME(cname) => opush(&mut result.cname, cname.to_string()),
|
||||||
RData::MX(mx) => opush(&mut result.mx, MxRecord{
|
RData::MX(mx) => opush(&mut result.mx, MxRecord{
|
||||||
|
@ -51,10 +51,10 @@ impl HumusView<QuerySettings, ResponseFormat> for View {
|
|||||||
|
|
||||||
fn get_cookie_header(&self, settings: &QuerySettings) -> Option<String> {
|
fn get_cookie_header(&self, settings: &QuerySettings) -> Option<String> {
|
||||||
Some(
|
Some(
|
||||||
Cookie::build("dns_resolver",settings.dns_resolver_id.to_string())
|
Cookie::build(Cookie::new("dns_resolver",settings.dns_resolver_id.to_string()))
|
||||||
.path("/")
|
.path("/")
|
||||||
.same_site(cookie::SameSite::Strict)
|
.same_site(cookie::SameSite::Strict)
|
||||||
.finish()
|
.build()
|
||||||
.to_string()
|
.to_string()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,11 @@
|
|||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<nav>
|
<nav>
|
||||||
<a href="{{ extra.base_url }}" class="sitename">{{extra.site_name|default(value="echoip")}}</a>
|
<a href="{{ extra.base_url }}" class="sitename">
|
||||||
|
{%- if extra.display_icon -%}
|
||||||
|
<img src="{{extra.display_icon}}" alt="">
|
||||||
|
{%- endif -%}
|
||||||
|
{{extra.site_name|default(value="echoip")}}</a>
|
||||||
<form class="search" method="GET" action="{{ extra.base_url }}">
|
<form class="search" method="GET" action="{{ extra.base_url }}">
|
||||||
<input type="search" name="query" autocomplete="on" maxlength="260"
|
<input type="search" name="query" autocomplete="on" maxlength="260"
|
||||||
title="Search for an IP-Adress, Domain-Name, or ASN."
|
title="Search for an IP-Adress, Domain-Name, or ASN."
|
||||||
|
@ -8,10 +8,14 @@ base_url="http://localhost:3000"
|
|||||||
stylesheet = "/style.css"
|
stylesheet = "/style.css"
|
||||||
|
|
||||||
# URL to and mimetype of your favicon
|
# URL to and mimetype of your favicon
|
||||||
# favicon = ""
|
favicon = "/icon_64.png"
|
||||||
# favicon_mimetype = "image/png"
|
favicon_mimetype = "image/png"
|
||||||
|
# favicon_mimetype = "image/svg+xml"
|
||||||
# favicon_mimetype = "image/jpeg"
|
# favicon_mimetype = "image/jpeg"
|
||||||
|
|
||||||
|
# Icon to display next to the title
|
||||||
|
display_icon = "/icon_64.png"
|
||||||
|
|
||||||
# URLs to look up v4 and v6 addresses explicitly
|
# URLs to look up v4 and v6 addresses explicitly
|
||||||
# If you have not configured them, comment them out, the button will stay hidden
|
# If you have not configured them, comment them out, the button will stay hidden
|
||||||
v4_url="http://v4.localhost:3000/"
|
v4_url="http://v4.localhost:3000/"
|
||||||
|
@ -16,12 +16,13 @@
|
|||||||
{% macro domain_name_links(name) %}
|
{% macro domain_name_links(name) %}
|
||||||
<p>Look up <code>{{name}}</code></p>
|
<p>Look up <code>{{name}}</code></p>
|
||||||
<ul class="link-list">
|
<ul class="link-list">
|
||||||
<li><a target="_blank" href="https://www.shodan.io/domain/{{ name }}">… on shodan.io <small>(limited query's per day, wants an account)</small></a></li>
|
<li><a target="_blank" href="https://www.shodan.io/domain/{{ name | urlencode_strict }}">… on shodan.io <small>(limited query's per day, wants an account)</small></a></li>
|
||||||
<li><a target="_blank" href="https://search.censys.io/search?resource=hosts&sort=RELEVANCE&per_page=25&virtual_hosts=EXCLUDE&q={{ name }}">… on search.censys.io <small>(10 query's per day, wants an account)</small></a></li>
|
<li><a target="_blank" href="https://search.censys.io/search?resource=hosts&sort=RELEVANCE&per_page=25&virtual_hosts=EXCLUDE&q={{ name | urlencode_strict }}">… on search.censys.io <small>(10 query's per day, wants an account)</small></a></li>
|
||||||
<li><a target="_blank" href="https://www.virustotal.com/gui/domain/{{ name }}">… on virustotal.com</a></li>
|
<li><a target="_blank" href="https://www.virustotal.com/gui/domain/{{ name | urlencode_strict }}">… on virustotal.com</a></li>
|
||||||
<li><a target="_blank" href="https://observatory.mozilla.org/analyze/{{ name }}">… on the Mozilla Observatory (http and tls checks)</a></li>
|
<li><a target="_blank" href="https://observatory.mozilla.org/analyze/{{ name | urlencode_strict }}">… on the Mozilla Observatory (http and tls checks)</a></li>
|
||||||
<li><a target="_blank" href="https://internet.nl/site/{{ name }}">… on the Internet.nl Website test</a></li>
|
<li><a target="_blank" href="https://internet.nl/site/{{ name | urlencode_strict }}">… on the Internet.nl Website test</a></li>
|
||||||
<li><a target="_blank" href="https://client.rdap.org/?type=domain&object={{ name }}">… on client.rdap.org <small>(a modern whois, make sure to allow xhr to 3rd parties)</small></a></li>
|
<li><a target="_blank" href="https://client.rdap.org/?type=domain&object={{ name | urlencode_strict }}">… on client.rdap.org <small>(a modern whois, make sure to allow xhr to 3rd parties)</small></a></li>
|
||||||
|
<li><a target="_blank" href="https://crt.sh/?Identity={{ name | urlencode_strict }}&match==">… on crt.sh <small>(Certificate Transparancy Monitor)</small></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
{% endmacro domain_name_links %}
|
{% endmacro domain_name_links %}
|
||||||
|
|
||||||
|
50
templates/static/icon.svg
Normal file
50
templates/static/icon.svg
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="48"
|
||||||
|
height="48"
|
||||||
|
viewBox="0 0 48 48"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient8">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#fb9a00;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop8" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#884f00;stop-opacity:1;"
|
||||||
|
offset="0.49966338"
|
||||||
|
id="stop10" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#be8700;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop9" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
xlink:href="#linearGradient8"
|
||||||
|
id="linearGradient9"
|
||||||
|
x1="10.202637"
|
||||||
|
y1="35.241699"
|
||||||
|
x2="39.21582"
|
||||||
|
y2="12.833984"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
id="path2"
|
||||||
|
style="fill:url(#linearGradient9);fill-opacity:1;stroke-width:3.15427;stroke-linejoin:round;paint-order:stroke markers fill"
|
||||||
|
d="m 2,7 v 33.767595 l 1.586,0.0021 L 8.299716,45.41681 12.826,40.767584 H 46 V 7 Z" />
|
||||||
|
<path
|
||||||
|
id="rect1"
|
||||||
|
style="fill:#111111;stroke-width:3;stroke-linejoin:round;paint-order:stroke markers fill"
|
||||||
|
d="M 3 8 L 3 40 L 4.0019531 40 L 4 40.001953 L 8.2792969 44.205078 L 12.412109 40 L 45 40 L 45 8 L 3 8 z M 35.671875 11.712891 L 39.357422 11.712891 L 39.357422 36.287109 L 35.671875 36.287109 L 35.671875 17.033203 L 31.494141 21.363281 L 28.839844 18.804688 C 31.107109 16.462871 35.671875 11.712891 35.671875 11.712891 z M 8.6425781 21.542969 L 12.328125 21.542969 L 12.328125 25.228516 L 8.6425781 25.228516 L 8.6425781 21.542969 z M 20.927734 21.542969 L 24.615234 21.542969 L 24.615234 25.228516 L 20.927734 25.228516 L 20.927734 21.542969 z M 8.6425781 32.599609 L 12.328125 32.599609 L 12.328125 36.287109 L 8.6425781 36.287109 L 8.6425781 32.599609 z M 20.927734 32.599609 L 24.615234 32.599609 L 24.615234 36.287109 L 20.927734 36.287109 L 20.927734 32.599609 z " />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
BIN
templates/static/icon_128.png
Normal file
BIN
templates/static/icon_128.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
BIN
templates/static/icon_32.png
Normal file
BIN
templates/static/icon_32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 950 B |
BIN
templates/static/icon_64.png
Normal file
BIN
templates/static/icon_64.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
@ -599,3 +599,10 @@ form.search {
|
|||||||
background: var(--button-bg);
|
background: var(--button-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Custom icon style for sitename*/
|
||||||
|
|
||||||
|
.sitename > img {
|
||||||
|
height: 1.2em;
|
||||||
|
padding: 0 0.3ch;
|
||||||
|
margin-bottom: -.2em;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user