Cap FORBID and vhost LIST output so a huge list can't overflow the operator's receive queue
All checks were successful
CI / check (push) Successful in 5m25s

This commit is contained in:
Jean Chevronnet 2026-07-20 20:44:15 +00:00
parent 8b45d386c6
commit aa270e061e
No known key found for this signature in database
9 changed files with 24 additions and 8 deletions

View file

@ -280,6 +280,10 @@ pub fn chanmode_takes_param(m: char, adding: bool) -> bool {
// mask or value. Fallback before the ircd's live prefix set is learned.
pub const STATUS_MODES: &str = "qaohv";
/// Max entries a service prints for a LIST before truncating, so a huge list
/// can't exceed the client's receive queue and disconnect the operator.
pub const LIST_CAP: usize = 200;
/// How a channel mode consumes its parameter, from the ircd's `CAPAB CHANMODES`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ChanModeKind {

View file

@ -1365,5 +1365,6 @@
"Added \u0002{count}\u0002 channels to your auto-join list.": "\u0002{count}\u0002 Kanäle zu deiner Auto-Join-Liste hinzugefügt.",
"Unknown AJOIN command \u0002{other}\u0002. Use \u0002ADD\u0002, \u0002ADDALL\u0002, \u0002DEL\u0002 or \u0002LIST\u0002.": "Unbekannter AJOIN-Befehl \u0002{other}\u0002. Nutze \u0002ADD\u0002, \u0002ADDALL\u0002, \u0002DEL\u0002 oder \u0002LIST\u0002.",
"Or confirm in one click: {link}": "Oder bestätige mit einem Klick: {link}",
"Confirm now": "Jetzt bestätigen"
"Confirm now": "Jetzt bestätigen",
"… and \u0002{more}\u0002 more; showing the first {cap}.": "… und \u0002{more}\u0002 weitere; die ersten {cap} werden angezeigt."
}

View file

@ -1365,5 +1365,6 @@
"Added \u0002{count}\u0002 channels to your auto-join list.": "\u0002{count}\u0002 canales agregados a tu lista de auto-unión.",
"Unknown AJOIN command \u0002{other}\u0002. Use \u0002ADD\u0002, \u0002ADDALL\u0002, \u0002DEL\u0002 or \u0002LIST\u0002.": "Comando AJOIN desconocido \u0002{other}\u0002. Usá \u0002ADD\u0002, \u0002ADDALL\u0002, \u0002DEL\u0002 o \u0002LIST\u0002.",
"Or confirm in one click: {link}": "O confirmá con un clic: {link}",
"Confirm now": "Confirmar ahora"
"Confirm now": "Confirmar ahora",
"… and \u0002{more}\u0002 more; showing the first {cap}.": "… y \u0002{more}\u0002 más; mostrando los primeros {cap}."
}

View file

@ -1365,5 +1365,6 @@
"Added \u0002{count}\u0002 channels to your auto-join list.": "\u0002{count}\u0002 canales añadidos a tu lista de auto-unión.",
"Unknown AJOIN command \u0002{other}\u0002. Use \u0002ADD\u0002, \u0002ADDALL\u0002, \u0002DEL\u0002 or \u0002LIST\u0002.": "Comando AJOIN desconocido \u0002{other}\u0002. Usa \u0002ADD\u0002, \u0002ADDALL\u0002, \u0002DEL\u0002 o \u0002LIST\u0002.",
"Or confirm in one click: {link}": "O confirma con un clic: {link}",
"Confirm now": "Confirmar ahora"
"Confirm now": "Confirmar ahora",
"… and \u0002{more}\u0002 more; showing the first {cap}.": "… y \u0002{more}\u0002 más; mostrando los primeros {cap}."
}

View file

@ -1365,5 +1365,6 @@
"Added \u0002{count}\u0002 channels to your auto-join list.": "\u0002{count}\u0002 salons ajoutés à votre liste d'auto-join.",
"Unknown AJOIN command \u0002{other}\u0002. Use \u0002ADD\u0002, \u0002ADDALL\u0002, \u0002DEL\u0002 or \u0002LIST\u0002.": "Commande AJOIN inconnue \u0002{other}\u0002. Utilisez \u0002ADD\u0002, \u0002ADDALL\u0002, \u0002DEL\u0002 ou \u0002LIST\u0002.",
"Or confirm in one click: {link}": "Ou confirmez en un clic : {link}",
"Confirm now": "Confirmer maintenant"
"Confirm now": "Confirmer maintenant",
"… and \u0002{more}\u0002 more; showing the first {cap}.": "… et \u0002{more}\u0002 de plus ; affichage des {cap} premiers."
}

View file

@ -1365,5 +1365,6 @@
"Added \u0002{count}\u0002 channels to your auto-join list.": "\u0002{count}\u0002 canais adicionados à sua lista de auto-entrada.",
"Unknown AJOIN command \u0002{other}\u0002. Use \u0002ADD\u0002, \u0002ADDALL\u0002, \u0002DEL\u0002 or \u0002LIST\u0002.": "Comando AJOIN desconhecido \u0002{other}\u0002. Use \u0002ADD\u0002, \u0002ADDALL\u0002, \u0002DEL\u0002 ou \u0002LIST\u0002.",
"Or confirm in one click: {link}": "Ou confirme com um clique: {link}",
"Confirm now": "Confirmar agora"
"Confirm now": "Confirmar agora",
"… and \u0002{more}\u0002 more; showing the first {cap}.": "… e mais \u0002{more}\u0002; mostrando os primeiros {cap}."
}

View file

@ -1365,5 +1365,6 @@
"Added \u0002{count}\u0002 channels to your auto-join list.": "\u0002{count}\u0002 canais adicionados à sua lista de auto-entrada.",
"Unknown AJOIN command \u0002{other}\u0002. Use \u0002ADD\u0002, \u0002ADDALL\u0002, \u0002DEL\u0002 or \u0002LIST\u0002.": "Comando AJOIN desconhecido \u0002{other}\u0002. Use \u0002ADD\u0002, \u0002ADDALL\u0002, \u0002DEL\u0002 ou \u0002LIST\u0002.",
"Or confirm in one click: {link}": "Ou confirme com um clique: {link}",
"Confirm now": "Confirmar agora"
"Confirm now": "Confirmar agora",
"… and \u0002{more}\u0002 more; showing the first {cap}.": "… e mais \u0002{more}\u0002; a mostrar os primeiros {cap}."
}

View file

@ -11,8 +11,11 @@ pub fn handle(me: &str, from: &Sender, ctx: &mut ServiceCtx, db: &dyn Store) {
return;
}
ctx.notice(me, from.uid, t!(ctx, "Assigned vhosts ({count}):", count = vhosts.len()));
for v in &vhosts {
for v in vhosts.iter().take(echo_api::LIST_CAP) {
let temp = if v.expires.is_some() { t!(ctx, ", temporary") } else { String::new() };
ctx.notice(me, from.uid, t!(ctx, " \x02{account}\x02 — {host} (by {setter}{temp})", account = v.account, host = v.host, setter = v.setter, temp = temp));
}
if vhosts.len() > echo_api::LIST_CAP {
ctx.notice(me, from.uid, t!(ctx, "… and \x02{more}\x02 more; showing the first {cap}.", more = vhosts.len() - echo_api::LIST_CAP, cap = echo_api::LIST_CAP));
}
}

View file

@ -45,9 +45,12 @@ pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, db:
return;
}
ctx.notice(me, from.uid, "Registration bans:");
for f in &forbids {
for f in forbids.iter().take(echo_api::LIST_CAP) {
ctx.notice(me, from.uid, t!(ctx, " [{kind}] \x02{mask}\x02 by {setter} ({when}) — {reason}", kind = f.kind.wire(), mask = f.mask, setter = f.setter, when = human_time(f.ts), reason = f.reason));
}
if forbids.len() > echo_api::LIST_CAP {
ctx.notice(me, from.uid, t!(ctx, "… and \x02{more}\x02 more; showing the first {cap}.", more = forbids.len() - echo_api::LIST_CAP, cap = echo_api::LIST_CAP));
}
}
_ => ctx.notice(me, from.uid, "Syntax: FORBID ADD <NICK|CHAN|EMAIL> <mask> <reason> | DEL <NICK|CHAN|EMAIL> <mask> | LIST"),
}