refactor: WEBIRC gateways and +G censor rules are named structs (WebircGateway/CensorRule) instead of positional tuples — self-documenting field access, no (_, g, _) index guessing; extends the OperBlock pattern
This commit is contained in:
parent
c4456cf002
commit
235c747c03
4 changed files with 35 additions and 13 deletions
|
|
@ -42,6 +42,24 @@ pub struct OperBlock {
|
||||||
pub fingerprint: Option<String>,
|
pub fingerprint: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A trusted WEBIRC gateway: after presenting `password` it may rewrite a client's
|
||||||
|
/// real host + IP. `ipmask` (empty = any) restricts which source addresses may use
|
||||||
|
/// this block.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct WebircGateway {
|
||||||
|
pub password: String,
|
||||||
|
pub name: String,
|
||||||
|
pub ipmask: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A +G censor rule: substitute `find` -> `replace` in channel text; an empty
|
||||||
|
/// `replace` blocks the message instead of rewriting it.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CensorRule {
|
||||||
|
pub find: String,
|
||||||
|
pub replace: String,
|
||||||
|
}
|
||||||
|
|
||||||
/// Config for the `antimixedutf8` module (blocks mixed-script look-alike spam).
|
/// Config for the `antimixedutf8` module (blocks mixed-script look-alike spam).
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AntiMixedCfg {
|
pub struct AntiMixedCfg {
|
||||||
|
|
@ -90,7 +108,7 @@ pub struct Config {
|
||||||
pub bind_server: Vec<String>, // server-to-server link listeners (repeatable)
|
pub bind_server: Vec<String>, // server-to-server link listeners (repeatable)
|
||||||
pub links: Vec<LinkBlock>, // peers we accept / dial
|
pub links: Vec<LinkBlock>, // peers we accept / dial
|
||||||
pub conf_path: String, // where this was loaded from (for REHASH)
|
pub conf_path: String, // where this was loaded from (for REHASH)
|
||||||
pub censor: Vec<(String, String)>, // +G bad words: (find, replace); empty replace = block
|
pub censor: Vec<CensorRule>, // +G bad words (empty replace = block)
|
||||||
pub amu: AntiMixedCfg, // antimixedutf8 module config
|
pub amu: AntiMixedCfg, // antimixedutf8 module config
|
||||||
pub resolve_hosts: bool, // reverse-DNS clients on connect (default on)
|
pub resolve_hosts: bool, // reverse-DNS clients on connect (default on)
|
||||||
pub use_resolved_host: bool, // put the resolved hostname in the hostmask (default on)
|
pub use_resolved_host: bool, // put the resolved hostname in the hostmask (default on)
|
||||||
|
|
@ -98,7 +116,7 @@ pub struct Config {
|
||||||
pub dnsbl_action: String, // mark | kline | gline | zline (on a hit)
|
pub dnsbl_action: String, // mark | kline | gline | zline (on a hit)
|
||||||
pub dnsbl_reason: String, // ban reason for a DNSBL hit
|
pub dnsbl_reason: String, // ban reason for a DNSBL hit
|
||||||
pub sasl_server: String, // linked services server that handles SASL ("" = none)
|
pub sasl_server: String, // linked services server that handles SASL ("" = none)
|
||||||
pub webirc: Vec<(String, String, String)>, // web gateways: (password, name, ip-mask)
|
pub webirc: Vec<WebircGateway>, // trusted web gateways
|
||||||
/// Every `key = value` line, captured raw so modules read their own settings
|
/// Every `key = value` line, captured raw so modules read their own settings
|
||||||
/// via `Server::conf*` — no per-module field bloats this struct or `Server`.
|
/// via `Server::conf*` — no per-module field bloats this struct or `Server`.
|
||||||
pub raw: HashMap<String, Vec<String>>,
|
pub raw: HashMap<String, Vec<String>>,
|
||||||
|
|
@ -235,7 +253,7 @@ impl Config {
|
||||||
let mut it = v.splitn(2, char::is_whitespace);
|
let mut it = v.splitn(2, char::is_whitespace);
|
||||||
if let Some(find) = it.next().filter(|f| !f.is_empty()) {
|
if let Some(find) = it.next().filter(|f| !f.is_empty()) {
|
||||||
let replace = it.next().unwrap_or("").trim().to_string();
|
let replace = it.next().unwrap_or("").trim().to_string();
|
||||||
c.censor.push((find.to_string(), replace));
|
c.censor.push(CensorRule { find: find.to_string(), replace });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"antimixedutf8" | "amu" => {
|
"antimixedutf8" | "amu" => {
|
||||||
|
|
@ -291,7 +309,11 @@ impl Config {
|
||||||
if let Some(pass) = it.next() {
|
if let Some(pass) = it.next() {
|
||||||
let gw = it.next().unwrap_or("webirc").to_string();
|
let gw = it.next().unwrap_or("webirc").to_string();
|
||||||
let mask = it.next().unwrap_or("").to_string();
|
let mask = it.next().unwrap_or("").to_string();
|
||||||
c.webirc.push((pass.to_string(), gw, mask));
|
c.webirc.push(WebircGateway {
|
||||||
|
password: pass.to_string(),
|
||||||
|
name: gw,
|
||||||
|
ipmask: mask,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
||||||
|
|
@ -105,16 +105,16 @@ fn ci_replace(hay: &str, find: &str, rep: &str) -> String {
|
||||||
|
|
||||||
/// +G censor: replace each configured bad word in `body`. Returns `None` when a
|
/// +G censor: replace each configured bad word in `body`. Returns `None` when a
|
||||||
/// matched word has an empty replacement (⇒ the message must be blocked).
|
/// matched word has an empty replacement (⇒ the message must be blocked).
|
||||||
fn apply_censor(body: &str, censor: &[(String, String)]) -> Option<String> {
|
fn apply_censor(body: &str, censor: &[crate::config::CensorRule]) -> Option<String> {
|
||||||
let mut out = body.to_string();
|
let mut out = body.to_string();
|
||||||
for (find, replace) in censor {
|
for rule in censor {
|
||||||
if find.is_empty() || !ci_contains(&out, find) {
|
if rule.find.is_empty() || !ci_contains(&out, &rule.find) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if replace.is_empty() {
|
if rule.replace.is_empty() {
|
||||||
return None; // no replacement ⇒ block
|
return None; // no replacement ⇒ block
|
||||||
}
|
}
|
||||||
out = ci_replace(&out, find, replace);
|
out = ci_replace(&out, &rule.find, &rule.replace);
|
||||||
}
|
}
|
||||||
Some(out)
|
Some(out)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,8 +102,8 @@ impl Command for WebIrc {
|
||||||
let Some(gw) = s
|
let Some(gw) = s
|
||||||
.webirc
|
.webirc
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(p, _, mask)| p == pass && (mask.is_empty() || glob_match(mask, &from)))
|
.find(|g| g.password == *pass && (g.ipmask.is_empty() || glob_match(&g.ipmask, &from)))
|
||||||
.map(|(_, g, _)| g.clone())
|
.map(|g| g.name.clone())
|
||||||
else {
|
else {
|
||||||
s.notice_star(uid, "WEBIRC: invalid credentials");
|
s.notice_star(uid, "WEBIRC: invalid credentials");
|
||||||
return CmdResult::Fail;
|
return CmdResult::Fail;
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,7 @@ pub struct Server {
|
||||||
pub xlines: Vec<XLine>, // server bans (KLINE/GLINE/ZLINE)
|
pub xlines: Vec<XLine>, // server bans (KLINE/GLINE/ZLINE)
|
||||||
pub mode_sudo: bool, // SAMODE/SAKICK: bypass rank checks
|
pub mode_sudo: bool, // SAMODE/SAKICK: bypass rank checks
|
||||||
pub in_redirect: bool, // +L: guards against redirect loops
|
pub in_redirect: bool, // +L: guards against redirect loops
|
||||||
pub censor: Vec<(String, String)>, // +G bad words: (find, replace)
|
pub censor: Vec<crate::config::CensorRule>, // +G bad words
|
||||||
pub amu: crate::config::AntiMixedCfg, // antimixedutf8 module config
|
pub amu: crate::config::AntiMixedCfg, // antimixedutf8 module config
|
||||||
pub resolve_hosts: bool, // reverse-DNS clients on connect
|
pub resolve_hosts: bool, // reverse-DNS clients on connect
|
||||||
pub use_resolved_host: bool, // apply the resolved name to the hostmask
|
pub use_resolved_host: bool, // apply the resolved name to the hostmask
|
||||||
|
|
@ -157,7 +157,7 @@ pub struct Server {
|
||||||
pub dnsbl_action: String, // mark | kline | gline | zline
|
pub dnsbl_action: String, // mark | kline | gline | zline
|
||||||
pub dnsbl_reason: String, // ban reason on a DNSBL hit
|
pub dnsbl_reason: String, // ban reason on a DNSBL hit
|
||||||
pub sasl_server: String, // services server that handles SASL
|
pub sasl_server: String, // services server that handles SASL
|
||||||
pub webirc: Vec<(String, String, String)>, // web gateways: (password, name, ip-mask)
|
pub webirc: Vec<crate::config::WebircGateway>, // trusted web gateways
|
||||||
/// Every `key = value` line from the config, so each module reads its own
|
/// Every `key = value` line from the config, so each module reads its own
|
||||||
/// settings via [`Server::conf`] / [`conf_all`] / [`conf_bool`] / [`conf_num`]
|
/// settings via [`Server::conf`] / [`conf_all`] / [`conf_bool`] / [`conf_num`]
|
||||||
/// — no per-module field lives on this struct (module-per-file rule).
|
/// — no per-module field lives on this struct (module-per-file rule).
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue