summaryrefslogtreecommitdiffstats
path: root/lib/ASM
diff options
context:
space:
mode:
authorLibravatarJanik Kleinhoff <ilbelkyr@shalture.org>2016-03-13 16:27:49 +0000
committerLibravatarJanik Kleinhoff <ilbelkyr@shalture.org>2016-03-13 16:27:49 +0000
commitfbb00b1778c9a58180e8fa960f2a57a79b5ea760 (patch)
tree463408e99085ad98c35fe5f51281bf2667cc89dc /lib/ASM
parent2638f623e8405ffad402e258bdba4f90cf7228de (diff)
BOOM GOES THE XML
This likely introduces twenty new bugs, but on the other hand it avoids twenty thousand other issues (most of them relating to XML::Simple doing the utterly wrong things all the time and configuration merely mitigating the issues, rather than fixing the core problem) so chances are it's more than worth it. We check if there's shiny new JSON-based config in place already; if not, we try to load XML config and convert it to the new format. The old config files are left untouched in case we fucked up somehow.
Diffstat (limited to 'lib/ASM')
-rw-r--r--lib/ASM/Commander.pm40
-rw-r--r--lib/ASM/Config.pm110
-rw-r--r--lib/ASM/Event.pm2
-rw-r--r--lib/ASM/XML.pm70
4 files changed, 131 insertions, 91 deletions
diff --git a/lib/ASM/Commander.pm b/lib/ASM/Commander.pm
index 1fd92d1..7037755 100644
--- a/lib/ASM/Commander.pm
+++ b/lib/ASM/Commander.pm
@@ -377,7 +377,7 @@ sub cmd_monitor2 {
my $chan = lc $+{chan};
my $switch = lc $+{switch};
$::channels->{channel}->{$chan}->{monitor} = $switch;
- ASM::XML->writeChannels();
+ ASM::Config->writeChannels();
$conn->privmsg($event->replyto, "Monitor flag for $chan set to $switch");
}
@@ -397,10 +397,10 @@ sub cmd_suppress {
$conn->schedule($duration, sub {
if (($::channels->{channel}{$chan}{suppress} // 0) - 10 <= time) {
# we needn't actually delete this here, but doing so
- # avoids cluttering the XML
+ # avoids cluttering the config
delete $::channels->{channel}{$chan}{suppress};
$conn->privmsg($event->replyto, "Unsuppressed $chan");
- ASM::XML->writeChannels();
+ ASM::Config->writeChannels();
}
});
$conn->privmsg($event->replyto, "Suppressing alerts from $chan for $minutes minutes.");
@@ -433,7 +433,7 @@ sub cmd_silence2 {
my $chan = lc $+{chan};
my $switch = lc $+{switch};
$::channels->{channel}->{$chan}->{silence} = $switch;
- ASM::XML->writeChannels();
+ ASM::Config->writeChannels();
$conn->privmsg($event->replyto, "Silence flag for $chan set to $switch");
}
@@ -592,7 +592,7 @@ sub cmd_user_add {
return;
}
$::users->{person}->{$nick} = { 'flags' => $flags };
- ASM::XML->writeUsers();
+ ASM::Config->writeUsers();
$conn->privmsg($event->replyto, "Flags for NickServ account $nick set to $flags");
}
@@ -651,7 +651,7 @@ sub cmd_user_flags2 {
$o_Htgroup->save();
}
$::users->{person}->{$nick}->{flags} = $flags;
- ASM::XML->writeUsers();
+ ASM::Config->writeUsers();
$conn->privmsg($event->replyto, "Flags for $nick set to $flags");
}
@@ -665,7 +665,7 @@ sub cmd_user_del {
return $conn->privmsg($event->replyto, "Users with the 'd' flag are untouchable. Edit the config file manually.");
}
delete($::users->{person}->{$nick});
- ASM::XML->writeUsers();
+ ASM::Config->writeUsers();
use Apache::Htpasswd; use Apache::Htgroup;
my $o_Htpasswd = new Apache::Htpasswd({passwdFile => $::settings->{web}->{userfile}, UseMD5 => 1});
my $o_Htgroup = new Apache::Htgroup($::settings->{web}->{groupfile});
@@ -697,7 +697,7 @@ sub cmd_target {
my @tmphl = @{$::channels->{channel}->{$chan}->{msgs}->{$level}};
push(@tmphl, $nick);
$::channels->{channel}->{$chan}->{msgs}->{$level} = \@tmphl;
- ASM::XML->writeChannels();
+ ASM::Config->writeChannels();
$conn->privmsg($event->replyto, "$nick added to $level risk messages for $chan");
}
@@ -717,7 +717,7 @@ sub cmd_detarget {
@ppl = grep { lc $_ ne $nick } @ppl;
$::channels->{channel}->{$chan}->{msgs}->{$risk} = \@ppl;
}
- ASM::XML->writeChannels();
+ ASM::Config->writeChannels();
$conn->privmsg($event->replyto, "$nick removed from targets for $chan");
}
@@ -778,7 +778,7 @@ sub cmd_hilight {
push(@tmphl, $nick);
}
$::channels->{channel}->{$chan}->{hilights}->{$level} = \@tmphl;
- ASM::XML->writeChannels();
+ ASM::Config->writeChannels();
$conn->privmsg($event->replyto, ASM::Util->commaAndify(@nicks) . " added to $level risk hilights for $chan");
}
@@ -798,7 +798,7 @@ sub cmd_dehilight {
@ppl = grep { !(lc $_ ~~ @nicks) } @ppl;
$::channels->{channel}->{$chan}->{hilights}->{$risk} = \@ppl;
}
- ASM::XML->writeChannels();
+ ASM::Config->writeChannels();
$conn->privmsg($event->replyto, "Removing hilights for " . ASM::Util->commaAndify(@nicks) . " in $chan");
}
@@ -808,14 +808,14 @@ sub cmd_join {
my $chan = lc $+{chan};
unless (defined($::channels->{channel}->{$chan})) {
$::channels->{channel}->{$chan} = { monitor => "yes", silence => "no" };
- ASM::XML->writeChannels();
+ ASM::Config->writeChannels();
}
$conn->join($chan);
my @autojoins = @{$::settings->{autojoins}};
if (!grep { $chan eq lc $_ } @autojoins) {
@autojoins = (@autojoins, $chan);
$::settings->{autojoins} = \@autojoins;
- ASM::XML->writeSettings();
+ ASM::Config->writeSettings();
}
}
@@ -827,7 +827,7 @@ sub cmd_part {
my @autojoins = @{$::settings->{autojoins}};
@autojoins = grep { lc $_ ne $chan } @autojoins;
$::settings->{autojoins} = \@autojoins;
- ASM::XML->writeSettings();
+ ASM::Config->writeSettings();
}
sub cmd_sl {
@@ -852,7 +852,7 @@ sub cmd_ev {
sub cmd_rehash {
my ($conn, $event) = @_;
- ASM::XML->readXML();
+ ASM::Config->readConfig();
$conn->privmsg($event->replyto, 'config files were re-read');
}
@@ -871,7 +871,7 @@ sub cmd_restrict {
$::restrictions->{$+{type} . 's'}->{$+{type}}->{$who}->{$+{restriction}} = $+{restriction};
$conn->privmsg($event->replyto, "Added $+{restriction} restriction for $+{type} $who");
}
- ASM::XML->writeRestrictions();
+ ASM::Config->writeRestrictions();
}
sub cmd_ops {
@@ -950,7 +950,7 @@ sub cmd_blacklist {
use String::CRC32;
my $id = sprintf("%08x", crc32($string));
$::blacklist->{string}->{$id} = { "content" => $string, "type" => "string", "setby" => $event->nick, "settime" => strftime('%F', gmtime) };
- ASM::XML->writeBlacklist();
+ ASM::Config->writeBlacklist();
$conn->privmsg($event->replyto, "$string blacklisted with id $id, please use ;blreason $id reasonGoesHere to set a reason");
}
@@ -960,7 +960,7 @@ sub cmd_blacklistpcre {
use String::CRC32;
my $id = sprintf("%08x", crc32($+{string}));
$::blacklist->{string}->{$id} = { "content" => $+{string}, "type" => "pcre", "setby" => $event->nick, "settime" => strftime('%F', gmtime) };
- ASM::XML->writeBlacklist();
+ ASM::Config->writeBlacklist();
$conn->privmsg($event->replyto, "$+{string} blacklisted with id $id, please use ;blreason $id reasonGoesHere to set a reason");
}
@@ -970,7 +970,7 @@ sub cmd_unblacklist {
if (defined($::blacklist->{string}->{$+{id}})) {
delete $::blacklist->{string}->{$+{id}};
$conn->privmsg($event->replyto, "blacklist id $+{id} removed");
- ASM::XML->writeBlacklist();
+ ASM::Config->writeBlacklist();
} else {
$conn->privmsg($event->replyto, "invalid id");
}
@@ -1014,7 +1014,7 @@ sub cmd_blreason {
if (defined($::blacklist->{string}->{$+{id}})) {
$::blacklist->{string}->{$+{id}}->{reason} = $+{reason};
$conn->privmsg($event->replyto, "Reason set");
- ASM::XML->writeBlacklist();
+ ASM::Config->writeBlacklist();
} else {
$conn->privmsg($event->replyto, "ID is invalid");
}
diff --git a/lib/ASM/Config.pm b/lib/ASM/Config.pm
new file mode 100644
index 0000000..de0bb21
--- /dev/null
+++ b/lib/ASM/Config.pm
@@ -0,0 +1,110 @@
+package ASM::Config;
+no autovivification;
+use warnings;
+use strict;
+use feature 'state';
+
+use XML::Simple qw(:strict);
+use JSON;
+use IO::All;
+no if $] >= 5.017011, warnings => 'experimental::smartmatch';
+
+our $json = JSON->new->utf8->pretty->canonical;
+
+sub serialize {
+ return $json->encode(@_);
+}
+sub deserialize {
+ return $json->decode(@_);
+}
+
+sub readXML {
+ my ( $p ) = $::cset;
+ my @fchan = ( 'event', keys %::RISKS );
+ my $xs1 = XML::Simple->new( KeyAttr => ['id'], Cache => [ qw/memcopy/ ]);
+ $::settings = $xs1->XMLin( "$p/settings.xml", ForceArray => ['host'],
+ 'GroupTags' => { altnicks => 'altnick', server => 'host',
+ autojoins => 'autojoin' });
+ $::channels = $xs1->XMLin( "$p/channels.xml", ForceArray => \@fchan );
+ $::users = $xs1->XMLin( "$p/users.xml", ForceArray => 'person');
+ $::mysql = $xs1->XMLin( "$p/mysql.xml", ForceArray => ['ident', 'geco'],
+ 'GroupTags' => { ignoredidents => 'ident', ignoredgecos => 'geco' });
+ $::dnsbl = $xs1->XMLin( "$p/dnsbl.xml", ForceArray => []);
+ $::rules = $xs1->XMLin( "$p/rules.xml", ForceArray => []);
+ $::restrictions = $xs1->XMLin( "$p/restrictions.xml", ForceArray => ['host', 'nick', 'account']);
+ $::blacklist = $xs1->XMLin( "$p/blacklist.xml", ForceArray => 'string');
+}
+
+sub readConfig {
+ if (!-e "$::cset/settings.json") {
+ state $in_readconfig = 0;
+ die "Unexpected readConfig recursion" if $in_readconfig++;
+ readXML();
+ writeConfig();
+ readConfig();
+ }
+ else {
+ $::settings = deserialize(io->file("$::cset/settings.json")->all);
+ $::channels = deserialize(io->file("$::cset/channels.json")->all);
+ $::users = deserialize(io->file("$::cset/users.json")->all);
+ $::mysql = deserialize(io->file("$::cset/mysql.json")->all);
+ $::dnsbl = deserialize(io->file("$::cset/dnsbl.json")->all);
+ $::rules = deserialize(io->file("$::cset/rules.json")->all);
+ $::restrictions = deserialize(io->file("$::cset/restrictions.json")->all);
+ $::blacklist = deserialize(io->file("$::cset/blacklist.json")->all);
+ }
+}
+
+sub writeConfig {
+ writeMysql();
+ writeChannels();
+ writeUsers();
+ writeSettings();
+ writeRestrictions();
+ writeBlacklist();
+ writeDnsbl();
+ writeRules();
+}
+
+sub writeMysql {
+ $::settingschanged=1;
+ serialize($::mysql) > io->file("$::cset/mysql.json");
+}
+
+sub writeRules {
+ $::settingschanged=1;
+ serialize($::rules) > io->file("$::cset/rules.json");
+}
+
+sub writeDnsbl {
+ $::settingschanged=1;
+ serialize($::dnsbl) > io->file("$::cset/dnsbl.json");
+}
+
+sub writeChannels {
+ $::settingschanged=1;
+ serialize($::channels) > io("$::cset/channels.json");
+}
+
+sub writeUsers {
+ $::settingschanged=1;
+ serialize($::users) > io("$::cset/users.json");
+}
+
+sub writeSettings {
+ $::settingschanged=1;
+ serialize($::settings) > io("$::cset/settings.json");
+}
+
+sub writeRestrictions {
+ $::settingschanged=1;
+ serialize($::restrictions) > io("$::cset/restrictions.json");
+}
+
+sub writeBlacklist {
+ $::settingschanged=1;
+ serialize($::blacklist) > io("$::cset/blacklist.json");
+}
+
+return 1;
+# vim: ts=2:sts=2:sw=2:expandtab
diff --git a/lib/ASM/Event.pm b/lib/ASM/Event.pm
index 005a9d3..1b2a4a2 100644
--- a/lib/ASM/Event.pm
+++ b/lib/ASM/Event.pm
@@ -87,7 +87,7 @@ sub on_pong
$::settingschanged = 0;
} else {
$conn->privmsg($::settings->{masterchan}, "Config files changed, auto rehash triggered. Check console for possible errors.");
- ASM::XML->readXML();
+ ASM::Config->readConfig();
}
}
if ($lag > 1) {
diff --git a/lib/ASM/XML.pm b/lib/ASM/XML.pm
deleted file mode 100644
index 7588699..0000000
--- a/lib/ASM/XML.pm
+++ /dev/null
@@ -1,70 +0,0 @@
-package ASM::XML;
-no autovivification;
-use warnings;
-use strict;
-
-use XML::Simple qw(:strict);
-use IO::All;
-no if $] >= 5.017011, warnings => 'experimental::smartmatch';
-
-$::xs1 = XML::Simple->new( KeyAttr => ['id'], Cache => [ qw/memcopy/ ]);
-
-sub readXML {
- my ( $p ) = $::cset;
- my @fchan = ( 'event', keys %::RISKS );
- $::settings = $::xs1->XMLin( "$p/settings.xml", ForceArray => ['host'],
- 'GroupTags' => { altnicks => 'altnick', server => 'host',
- autojoins => 'autojoin' });
- $::channels = $::xs1->XMLin( "$p/channels.xml", ForceArray => \@fchan );
- $::users = $::xs1->XMLin( "$p/users.xml", ForceArray => 'person');
- $::mysql = $::xs1->XMLin( "$p/mysql.xml", ForceArray => ['ident', 'geco'],
- 'GroupTags' => { ignoredidents => 'ident', ignoredgecos => 'geco' });
- $::dnsbl = $::xs1->XMLin( "$p/dnsbl.xml", ForceArray => []);
- $::rules = $::xs1->XMLin( "$p/rules.xml", ForceArray => []);
- $::restrictions = $::xs1->XMLin( "$p/restrictions.xml", ForceArray => ['host', 'nick', 'account']);
- $::blacklist = $::xs1->XMLin( "$p/blacklist.xml", ForceArray => 'string');
-}
-
-sub writeXML {
- writeSettings();
- writeChannels();
- writeUsers();
- writeRestrictions();
- writeBlacklist();
- writeMysql();
-}
-
-sub writeMysql {
- $::settingschanged=1;
- $::xs1->XMLout($::mysql, RootName => 'mysql', KeyAttr => ['id']) > io("$::cset/mysql.xml");
-}
-
-sub writeChannels {
- $::settingschanged=1;
- $::xs1->XMLout($::channels, RootName => 'channels', KeyAttr => ['id'], NumericEscape => 2) > io("$::cset/channels.xml");
-}
-
-sub writeUsers {
- $::settingschanged=1;
- $::xs1->XMLout($::users, RootName => 'people', KeyAttr => ['id']) > io("$::cset/users.xml");
-}
-
-sub writeSettings {
- $::settingschanged=1;
- $::xs1->XMLout($::settings, RootName => 'settings',
- GroupTags => { altnicks => 'altnick', server => 'host', autojoins => 'autojoin' }, NoAttr => 1) > io("$::cset/settings.xml");
-}
-
-sub writeRestrictions {
- $::settingschanged=1;
- $::xs1->XMLout($::restrictions, RootName => 'restrictions', KeyAttr => ['id'],
- GroupTags => { hosts => "host", nicks => "nick", accounts => "account"}) > io("$::cset/restrictions.xml");
-}
-
-sub writeBlacklist {
- $::settingschanged=1;
- $::xs1->XMLout($::blacklist, RootName => 'blacklist', KeyAttr => ['id'], NumericEscape => 2) > io("$::cset/blacklist.xml");
-}
-
-return 1;
-# vim: ts=2:sts=2:sw=2:expandtab