From f407dbfeabc99b2a48c42ea05176e3aff8432a14 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Tue, 28 Aug 2018 21:40:57 -0400 Subject: slacktopic.pl: only change topic if the update is a security fix --- slacktopic.pl | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/slacktopic.pl b/slacktopic.pl index e45d094..4471584 100644 --- a/slacktopic.pl +++ b/slacktopic.pl @@ -13,8 +13,11 @@ # and extract the new date from it. # - Extract the old date from the current /topic. # - If the /topic has an old date, and if it's different from the new -# date, update the /topic (really, get ChanServ to do it). Only the date -# (inside []) is changed, all the other stuff is left as-is. +# date, retrieve the full ChangeLog entry (up to the first "+----..." line), +# check for the string "(* Security fix *)" or similar. If nothing +# found, it's not a security update, so don't update the topic. +# - If it needs updating, update the /topic (really, get ChanServ to do # it). +# Only the date (inside []) is changed, all the other stuff is left as-is. # Assumptions made: # - Every new ChangeLog entry is a security fix. This is almost @@ -286,6 +289,9 @@ sub finish_update { return; } + # Make sure this is a security fix update. + return unless is_security_update(); + # Ask ChanServ to change the topic for us. We don't need +o in # the channel, so long as we're logged in to services and have +t. logmsg("ChangeLog updated [$new_date], asking ChanServ to update topic"); @@ -319,5 +325,48 @@ sub exec_update { 0); # last arg is unused } +# Return true if the first ChangeLog entry is a security update. Unlike +# the regular check-for-update that happens periodically, this one blocks +# for up to $cmd_timeout seconds. The updates only happen every few days, +# I don't see this as a real problem that needs extra complexity to solve. +sub is_security_update { + debugmsg("is_security_update() called"); + + my $result = 0; + my $lines = 0; + + # Too bad we couldn't have kept the TCP connection open + # from the previous run of curl. + open my $pipe, + "curl --silent --no-buffer --max-time $cmd_timeout $changelog_url|"; + + # Read lines until we hit "(* Security fix *)" or the separator that + # ends the entry. Unfortunately, even with --no-buffer, we get a lot + # more data than we need (no harm done, just wastes a bit of bandwidth). + while(<$pipe>) { + $lines++; + + # Allow Pat some typos (case insensitive, variable spacing). + if(/\(\*\s*security\s+fix\s*\*\)/i) { + $result = 1; + last; + } elsif(/^\+-+\+/) { # Separator between entries. + last; + } + } + + my $curl_exit = (close $pipe) >> 8; + + # 23 is "error writing output" (from curl man page), this is expected + # when we close the read pipe. If we get any other error, it's worth + # complaining about. + if($curl_exit != 23) { + errmsg("curl exited with unexpected status: $curl_exit"); + } + + debugmsg("read $lines lines from ChangeLog, returning $result"); + return $result; +} + ### main() init(); -- cgit v1.2.3