use SrSv::Unreal::Tokens qw( :tokens );
use SrSv::Unreal::Base64 qw(itob64);
use SrSv::IRCd::State qw(synced $ircd_ready %IRCd_capabilities);
-use SrSv::IRCd::IO qw(ircsend ircsendimm);
+use SrSv::IRCd::IO qw(ircsend ircsendimm );
use SrSv::IRCd::Event qw(addhandler);
use SrSv::IRCd::Validate qw(valid_nick);
use SrSv::RunLevel 'main_shutdown';
-
+use SrSv::IRCd::Send;
# FIXME
BEGIN { *SJB64 = \&ircd::SJB64 }
$agent = lc $agent; $chan = lc $chan;
if($agents{$agent} and $agents{$agent}{CHANS} and $agents{$agent}{CHANS}{$chan}) {
+ print "$agent is in $chan\n";
return 1;
} else {
return 0;
}
$agents{lc $nick}{PARMS} = [ @_ ];
-
$host = main_conf_local unless $host;
+=cut
+# Unreal specific version
ircsend("@{[TOK_NICK]} $nick 1 $time $ident $host ".
(SJB64 ? itob64(main_conf_numeric) : main_conf_local).
" 1 $modes * :$gecos");
-
+=cut
+ ircd::agent_doconn ($nick, $ident, $host, $modes, $gecos);
+ #$host = main_conf_local unless $host;
+ #ircsend($tkn{NICK}[$tkn]." $nick 1 $time $ident $host ".
+ # (SJB64 ? itob64(main_conf_numeric) : main_conf_local).
+ # " 1 $modes * :$gecos");
+
+=cut
+# Unreal specific again -.-
foreach my $chan (@chans) {
- ircsend(":$nick @{[TOK_JOIN]} $chan");
+ ircsend(":$nick ".$tkn{JOIN}[$tkn]." $chan");
# If we tracked chanmodes for agents, that would go here as well.
}
+=cut
}
sub agent_quit($$) {
return undef;
}
-sub agent_join($$) {
- my ($agent, $chan) = @_;
-
- if($agents{lc $agent}) {
- $agents{lc $agent}{CHANS}{lc $chan} = 1;
- ircsend(":$agent @{[TOK_JOIN]} $chan");
- } else {
- if($ircd_ready) {
- print "Tried to make nonexistent agent ($agent) join channel ($chan)" if DEBUG;
- } else {
- print "Deferred join: $agent $chan\n" if DEBUG;
- push @defer_join, "$agent $chan";
- }
- }
-}
sub agent_part($$$) {
my ($agent, $chan, $reason) = @_;
-
delete($agents{lc $agent}{CHANS}{lc $chan});
- ircsend(":$agent @{[TOK_PART]} $chan :$reason");
+ ircd::agent_dopart ($agent, $chan, $reason);
}
sub set_agent_umode($$) {
ircsend(":$src @{[TOK_UMODE2]} $modes");
}
-
+sub agent_join($$) {
+ my ($agent, $chan) = @_;
+ ircd::agent_dojoin($agent,$chan);
+}
sub agent_sync() {
foreach my $j (@defer_join) {
print "Processing join: $j\n" if DEBUG;
my ($agent, $chan) = split(/ /, $j);
- agent_join($agent, $chan);
+ if($agents{lc $agent}) {
+ $agents{lc $agent}{CHANS}{lc $chan} = 1;
+ agent_join($agents{lc $agent}, $chan);
+ } else {
+ if($ircd_ready) {
+ print "Tried to make nonexistent agent ($agent) join channel ($chan)" if DEBUG;
+ } else {
+ print "Deferred join: $agent $chan\n" if DEBUG;
+ push @defer_join, "$agent $chan";
+ }
+ }
}
undef(@defer_join);
}
$sync = 0;
$wf = $_[3];
}
-
$message = {
CLASS => 'IRCD',
TYPE => $_[0],
use strict;
use Exporter 'import';
-BEGIN { our @EXPORT_OK = qw(ircd_connect ircd_disconnect ircsendimm ircsend ircd_flush_queue) }
+BEGIN { our @EXPORT_OK = qw(ircd_connect ircd_disconnect ircsendimm ircsend ircd_flush_queue ) }
use constant {
NL => "\015\012",
use Errno ':POSIX';
use Event;
-
+use SrSv::Conf 'main';
use SrSv::Process::InParent qw(irc_connect ircsend ircsendimm ircd_flush_queue);
use SrSv::Process::Worker qw(ima_worker);
use SrSv::Debug;
-../Unreal/Parse.pm
\ No newline at end of file
+../Insp/Parse.pm
\ No newline at end of file
-../Unreal/Send.pm
\ No newline at end of file
+../Insp/Send.pm
\ No newline at end of file
SYNCED: {
foreach my $s (keys(%servers)) {
my $state = get_server_state($s);
-
- print "Server: $s State: $state\n" if DEBUG();
-
+ print "Server:d $s State: $state\n" if DEBUG();
if(!$state) {
$synced = 0;
last SYNCED;
--- /dev/null
+# This file is part of SurrealServices.
+#
+# SurrealServices is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# SurrealServices is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with SurrealServices; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+package SrSv::IRCd::Parse;
+
+use strict;
+
+use Exporter 'import';
+# parse_sjoin shouldn't get used anywhere else, as we never produce SJOINs
+# parse_tkl however is used for loopbacks.
+BEGIN { our @EXPORT_OK = qw(parse_line parse_tkl parse_addline) }
+
+# FIXME
+BEGIN { *SJB64 = \&ircd::SJB64; *CLK = \&ircd::CLK; *NICKIP = \&ircd::NICKIP; }
+
+use SrSv::Conf 'main';
+
+use SrSv::Debug;
+use SrSv::IRCd::State qw($ircline $remoteserv create_server get_server_children set_server_state get_server_state %IRCd_capabilities);
+use SrSv::IRCd::Queue qw(queue_size);
+use SrSv::IRCd::IO qw( ircsend ircsendimm);
+use SrSv::IRCd::Send qw (getRevUuid getUuid setRevUuid setUuid);
+use SrSv::Unreal::Modes qw(%opmodes);
+
+# Unreal uses its own modified base64 for everything except NICKIP
+use SrSv::Unreal::Base64 qw(b64toi itob64);
+use SrSv::User '/./';
+# Unreal uses unmodified base64 for NICKIP.
+# Consider private implementation,
+# tho MIME's is probably faster
+use MIME::Base64;
+use Data::Dumper;
+# FIXME
+use constant {
+ # Wait For
+ WF_NONE => 0,
+ WF_NICK => 1,
+ WF_CHAN => 2,
+ WF_ALL => 3,
+};
+
+use SrSv::Shared qw(@servernum);
+
+our %cmdhash;
+
+sub parse_line($) {
+ my ($in) = @_;
+ if (!$in) {
+ return;
+ }
+ my $cmd;
+
+ if($in =~ /^(?:@|:)(\S+) (\S+)/) {
+ $cmd = $2;
+ }
+ elsif ($in =~ /^(\S+)/) {
+ $cmd = $1;
+ }
+ my $sub = $cmdhash{$cmd};
+ unless (defined($sub)) {
+ print "Bailing out from $ircline:$cmd for lack of cmdhash\n" if DEBUG();
+ return undef();
+ }
+ my ($event, $src, $dst, $wf, @args) = &$sub($in);
+ unless (defined($event)) {
+ print "Bailing out from $ircline:$cmd for lack of event\n" if DEBUG;
+ return undef();
+ }
+ #return unless defined $event;
+
+ my (@recipients, @out);
+ if(defined($dst)) {
+ #$args[$dst] = lc $args[$dst];
+ @recipients = split(/\,/, $args[$dst]);
+ }
+ #if(defined($src)) { $args[$src] = lc $args[$src]; }
+
+ if(@recipients > 1) {
+ foreach my $rcpt (@recipients) {
+ $args[$dst] = $rcpt;
+ push @out, [$event, $src, $dst, $wf, [@args]];
+ }
+ } else {
+ @out = [$event, $src, $dst, $wf, [@args]];
+ }
+
+ return @out;
+}
+#parse_fjoin($server, $channel, $ts, $modes, @nicks, @status)
+sub parse_fjoin ($$$$$$) {
+ my ($server, $channel, $ts, $modes, $idsr, $statusref) = @_;
+ my @status = @$statusref;
+ my @ids = @$idsr;
+ my $i = 0;
+ my @users;
+ foreach my $id (@ids) {
+ my $op = 0;
+ my @ops = split ("",$status[$i]);
+ foreach my $prefix (@ops) {
+ $op |= $opmodes{$prefix};
+ }
+ my $user = {ID => $id, __OP=>$op};
+ get_user_nick ($user);
+ push @users, $user;
+ $i++;
+ }
+ return ($server, $channel, $ts, $modes, undef, \@users, undef, undef, undef); #bans etc are got from FMODE..
+}
+sub parse_sjoin($$$$) {
+ my ($server, $ts, $cn, $parms) = @_;
+ my (@users, @bans, @excepts, @invex, @blobs, $blobs, $chmodes, $chmodeparms);
+
+ $server = '' unless $server;
+
+ if($parms =~ /^:(.*)/) {
+ $blobs = $1;
+ } else {
+ ($chmodes, $blobs) = split(/ :/, $parms, 2);
+ ($chmodes, $chmodeparms) = split(/ /, $chmodes, 2);
+ }
+ @blobs = split(/ /, $blobs);
+
+ foreach my $x (@blobs) {
+ if($x =~ /^(\&|\"|\')(.*)$/) {
+ my $type;
+ push @bans, $2 if $1 eq '&';
+ push @excepts, $2 if $1 eq '"';
+ push @invex, $2 if $1 eq "\'";
+ } else {
+ $x =~ /^([*~@%+]*)(.*)$/;
+ my ($prefixes, $nick) = ($1, $2);
+ my @prefixes = split(//, $prefixes);
+ my $op = 0;
+ foreach my $prefix (@prefixes) {
+ $op |= $opmodes{q} if ($prefix eq '*');
+ $op |= $opmodes{a} if ($prefix eq '~');
+ $op |= $opmodes{o} if ($prefix eq '@');
+ $op |= $opmodes{h} if ($prefix eq '%');
+ $op |= $opmodes{v} if ($prefix eq '+');
+ }
+
+ push @users, { NICK => $nick, __OP => $op };
+ }
+ }
+
+ return ($server, $cn, $ts, $chmodes, $chmodeparms, \@users, \@bans, \@excepts, \@invex);
+}
+sub parse_addline ($) {
+ my ($line) = @_;
+ #return ($type, +1, $ident, $host, $setter, $expire, $time, $reason);
+ #>> 47 :583AAAAAA ADDLINE G test@testie inspircd.erry.omg 1308118489 0 :hi
+ my ($setter, undef, $type, $mask, $server, $time, $expiry, $reason) = split (/ /, $line, 7);
+ $reason =~ /:(.*)/;
+ $reason = $1;
+ $setter =~ /:(.*)/;
+ $setter = $1;
+ my @masks = split (/@/,$mask, 1);
+ my $ident = $masks[0];
+ my $host = $masks[1];
+ #return ($type, +1, $ident, $host, $setter, $expire, $time, $reason);
+ return ($type, +1, $ident, $host, $setter, $expiry, $time, $reason);
+}
+sub parse_tkl ($) {
+ my ($in) = @_;
+ # This function is intended to accept ALL tkl types,
+ # tho maybe not parse all of them in the first version.
+
+ # Discard first token, 'TKL'
+ my (undef, $sign, $type, $params) = split(/ /, $in, 4);
+
+ # Yes, TKL types are case sensitive!
+ # also be aware (and this applies to the net.pm generator functions too)
+ # This implementation may appear naiive, but Unreal assumes that, for a given
+ # TKL type, that all parameters are non-null.
+ # Thus, if any parameters ARE null, Unreal WILL segfault.
+ ## Update: this problem may have been fixed since Unreal 3.2.2 or so.
+ if ($type eq 'G' or $type eq 'Z' or $type eq 's' or $type eq 'Q') {
+ # format is
+ # TKL + type ident host setter expiretime settime :reason
+ # TKL - type ident host setter
+ # for Q, ident is always '*' or 'h' (Services HOLDs)
+ if ($sign eq '+') {
+ my ($ident, $host, $setter, $expire, $time, $reason) = split(/ /, $params, 6);
+
+ $reason =~ s/^\://;
+ return ($type, +1, $ident, $host, $setter, $expire, $time, $reason);
+ }
+ elsif($sign eq '-') {
+ my ($ident, $host, $setter) = split(/ /, $params, 3);
+ return ($type, -1, $ident, $host, $setter);
+ }
+ }
+ elsif($type eq 'F') {
+ # TKL + F cpnNPq b saturn!attitude@netadmin.SCnet.ops 0 1099959668 86400 Possible_mIRC_DNS_exploit :\/dns (\d+\.){3}\d
+ # TKL + F u g saturn!attitude@saturn.netadmin.SCnet.ops 0 1102273855 604800 sploogatheunbreakable:_Excessively_offensive_behavior,_ban_evasion. :.*!imleetnig@.*\.dsl\.mindspring\.com
+ # TKL - F u Z tabris!northman@tabris.netadmin.SCnet.ops 0 0 :do_not!use@mask
+ if ($sign eq '+') {
+ my ($target, $action, $setter, $expire, $time, $bantime, $reason, $mask) = split(/ /, $params, 8);
+ $mask =~ s/^\://;
+ return ($type, +1, $target, $action, $setter, $expire, $time, $bantime, $reason, $mask);
+ }
+ elsif($sign eq '-') {
+ my ($target, $action, $setter, $expire, $time, $mask) = split(/ /, $params, 6);
+ $mask =~ s/^\://;
+ return ($type, -1, $target, $action, $setter, $mask);
+ }
+ }
+}
+
+sub PING($) {
+ my ($event, $src, $dst, @args);
+ $_[0] =~ /^(?:8|PING) :(\S+)$/;
+ # ($event, $src, $dst, $args)
+ return ('PING', undef, undef, WF_NONE, $1);
+}
+sub UID ($) {
+ #:583 UID 583AAAAAJ 1307703236 erry__ localhost localhost errietta 127.0.0.1 1307703241 + :errietta
+ $_[0] =~ /^(:\S+) UID (\S+) (\d+) (\S+) (\S+) (\S+) (\S+) (\S+) (\d+) (\S+) :(.*)$/;
+ my ($server, $uid, $stamp, $nick, $host, $vhost, $ident, $IP, $ts, $modes, $gecos) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);
+ ircd::setRevUuid ($uid, $nick);
+ ircd::setUuid ($nick, $uid);
+ my $user = { NICK => $nick, ID => $uid };
+ return ('NICKCONN', undef, undef, WF_NICK, $user, 0, $ts, $ident, $host, $server, $stamp, $modes, $vhost, $gecos,
+ join('.', unpack('C4', MIME::Base64::decode($IP))));
+}
+sub EOS($) {
+ my $event;
+ print "EOS\n";
+ if ($_[1] != "ENDBURST") {
+ $_[0] =~ /^(@|:)(\S+) (?:EOS|ES)/; # Sometimes there's extra crap on the end?
+ my $server;
+ if ($1 eq '@') {
+ $server = $servernum[b64toi($2)];
+ }
+ else {
+ $server = $2;
+ }
+ print "SERVER $server\n";
+ set_server_state($server, 1);
+ return undef() unless get_server_state($remoteserv);
+ if($server eq $remoteserv) { $event = 'SEOS' } else { $event = 'EOS' }
+ print "Ok. we had EOS\n";
+ return ($event, undef, undef, WF_ALL, $server);
+ }
+ else {
+ print "wot\n";
+ $_[0] =~ /^:(\S+) ENDBURST/;
+ my $server = $1;
+ set_server_state($server, 1);
+ print "server $server remote $remoteserv\n";
+ return undef() unless get_server_state($remoteserv);
+ print "This be it! Got endbrust!\n";
+ return ("ENDBURST", undef, undef, WF_ALL, $1);
+ }
+}
+
+sub SERVER($) {
+ #ircd::debug($_[0]) if $debug;
+
+ if($_[0] =~ /^(?:SERVER|\') (\S+) (\S+) :(U[0-9]+)-([A-Za-z0-9]+)-([0-9]+) (.*)$/) {
+ # SERVER test-tab.surrealchat.net 1 :U2307-FhinXeOoZEmM-200 SurrealChat
+ # cmd, servername, hopCount, U<protocol>-<buildflags>-<numeric> infoLine
+ $remoteserv = $1;
+ create_server($1);
+ $servernum[$5] = $1;
+
+ return ('SERVER', undef, undef, WF_ALL, undef, $1, $2, $6, $5, $3, $4);
+ # src, serverName, numHops, infoLine, serverNumeric, protocolVersion, buildFlags
+ }
+ elsif($_[0] =~ /^(:|@)(\S+) (?:SERVER|\') (\S+) (\d+) (\d+) :(.*)$/) {
+ # @38 SERVER test-hermes.surrealchat.net 2 100 :SurrealChat
+ # source, cmd, new server, hopCount, serverNumeric, infoLine
+ my ($numeric, $name);
+ if ($1 eq '@') {
+ $name = $servernum[b64toi($2)];
+ }
+ else {
+ $name = $2;
+ }
+ create_server($3, $name);
+ $servernum[$5] = $3;
+
+ return ('SERVER', undef, undef, WF_ALL, $name, $3, $4, $6, $5);
+ # src, serverName, numHops, infoLine, serverNumeric
+ }
+ if($_[0] =~ /^(?:SERVER|\') (\S+) (\S+) :(.*)$/) {
+ $remoteserv = $1;
+ create_server($1);
+ return ('SERVER', undef, undef, WF_ALL, undef, $1, $2, $3);
+ # src, serverName, numHops, infoLine
+ }
+ elsif($_[0] =~ /^:(\S+) (?:SERVER|\') (\S+) (\d+) :(.*)$/) {
+ # source, new server, hop count, description
+ create_server($2, $1);
+ return ('SERVER', undef, undef, WF_ALL, $1, $2, $3, $4);
+ # src, serverName, numHops, infoLine
+ }
+ elsif ($_[0] =~ /SERVER (\S+) (\S+) (\d+) (\S+) :(.*)$/) {
+ #SERVER inspircd.erry.omg mypass 0 583 :erry World
+ #SERVER servername password hopcount SID :Server Desc
+ $remoteserv = $4;
+ create_server ($4);
+ #since from now on we'll be getting commands as sent from the SID it's much wiser to keep that than the name.
+ return ("SERVER", undef, undef, WF_ALL, undef, $1, $3, $5, $4);
+ }
+}
+
+sub SQUIT($) {
+ if($_[0] =~ /^(?:SQUIT|-) (\S+) :(.*)$/) {
+ my $list = [get_server_children($1)];
+ set_server_state($1, undef());
+ return ('SQUIT', undef, undef, WF_ALL, undef, $list, $2);
+ }
+ elsif($_[0] =~ /^(:|@)(\S+) (?:SQUIT|-) (\S+) :(.*)$/) {
+ my $name;
+ if ($1 eq '@') {
+ $name = $servernum[b64toi($2)];
+ }
+ else {
+ $name = $2;
+ }
+ my $list = [get_server_children($3)];
+ set_server_state($3, undef());
+ return ('SQUIT', undef, undef, WF_ALL, $name, $list, $4);
+ }
+}
+
+sub NETINFO($) {
+ $_[0] =~ /^(?:NETINFO|AO) (\S+) (\S+) (\S+) (\S+) (\S+) (\S+) (\S+) :(.*)$/;
+ return ('NETINFO', undef, undef, WF_NONE, $1, $2, $3, $4, $5, $6, $7, $8);
+}
+
+sub PROTOCTL($) {
+ $_[0] =~ /^PROTOCTL (.*)$/;
+ return ('PROTOCTL', undef, undef, WF_NONE, $1);
+}
+
+sub JOIN($) {
+ $_[0] =~ /^:(\S+) (?:C|JOIN) (\S+)$/;
+ my $user = { ID => $1 };
+ get_user_nick ($user);
+ return ('JOIN', undef, 1, WF_CHAN, $user, $2);
+}
+
+sub FJOIN ($) {
+ #>> 13 :97K FJOIN #erry 1307879417 +nt :o,97KAAAAAA ,97KAAAAAB
+ $_[0] =~ m"^(:\S+) FJOIN (\S+) (\d+) (\S+) (.*)$";
+ my ($server, $channel, $ts, $modes, $userstring) = ($1, $2, $3, $4, $5);
+ my @users = split (" ", $userstring);
+ my (@ids, @status);
+ foreach my $user (@users) {
+ my @params = split (",",$user);
+ push (@status, $params[0]);
+ push (@ids, $params[1]);
+ }
+ return ('SJOIN', undef, undef, WF_CHAN, parse_fjoin($server, $channel, $ts, $modes, \@ids, \@status));
+}
+sub SJOIN($) {
+ if ($_[0] =~ /^(?:\~|SJOIN) (\S+) (\S+) (.*)$/) {
+ my ($ts, $cn, $payload) = ($1, $2, $3);
+ if ($ts =~ s/^!//) {
+ $ts = b64toi($ts);
+ }
+ return ('SJOIN', undef, undef, WF_CHAN, parse_sjoin($remoteserv, $ts, $cn, $payload));
+ }
+ elsif($_[0] =~ /^(@|:)(\S+) (?:\~|SJOIN) (\S+) (\S+) (.*)$/) {
+ my ($server, $ts, $cn, $payload) = ($2, $3, $4, $5);
+ if ($1 eq '@') {
+ $server = $servernum[b64toi($2)];
+ }
+ else {
+ $server = $2;
+ }
+ if ($ts =~ s/^!//) {
+ $ts = b64toi($ts);
+ }
+ return ('SJOIN', undef, undef, WF_CHAN, parse_sjoin($server, $ts, $cn, $payload));
+ }
+}
+
+sub PART($) {
+ my $user;
+
+ if($_[0] =~ /^:(\S+) (?:D|PART) (\S+) :(.*)$/) {
+ $user = {ID => $1};
+ get_user_nick ($user);
+ return ('PART', undef, 0, WF_CHAN, $user, $2, $3);
+ }
+ elsif($_[0] =~ /^:(\S+) (?:D|PART) (\S+)$/) {
+ $user = {ID => $1};
+ return ('PART', undef, 0, WF_CHAN, $user, $2, undef);
+ }
+}
+sub FMODE($) {
+ #:583AAAAAR FMODE #erry 1308214721 +ib test!*@* When any mode in the channel is set.
+ #:583 FMODE #erry 1308214721 +b test1!*@* At server connect. Note that the rest of the channel modes are not there but rather at FJOIN. So this will only have bans and the like.
+ if($_[0] =~ /^:(\S+) FMODE (#\S+) (\d+) (\S+) ?(.*)$/) {
+ my $id = $1;
+ my $user = {ID => $id};
+ get_user_nick ($user);
+ return ('MODE', undef, 1, WF_ALL, $user, $2, $4, $5);
+ }
+}
+sub MODE($) {
+ my $user;
+
+ if($_[0] =~ /^(@|:)(\S+) (?:G|MODE) (#\S+) (\S+) (.*)(?: \d+)?$/) {
+ my $name;
+ if ($1 eq '@') {
+ $name = $servernum[b64toi($2)];
+ $user = {NICK => $name};
+ }
+ else {
+ $name = $2;
+ $user = { ID=>$name};
+ get_user_nick ($user);
+ }
+ return ('MODE', undef, 1, WF_ALL, $user, $3, $4, $5);
+ }
+ elsif($_[0] =~ /^:(\S+) (?:G|MODE) (\S+) :(\S+)$/) {
+ # We shouldn't ever get this, as UMODE2 is preferred
+ $user = { ID => $1 };
+ get_user_nick ($user);
+ return ('UMODE', 0, 0, WF_ALL, $user, $3);
+ }
+
+}
+
+sub MESSAGE($) {
+ my ($event, @args);
+ if($_[0] =~ /^(@|:)(\S+) (?:\!|PRIVMSG) (\S+) :(.*)$/) {
+
+ my ($name, $srcUser, $dstUser) ;
+ if ($1 eq '@') {
+ $name = $servernum[b64toi($2)];
+ $srcUser = {NICK=>$name};
+ }
+ else {
+ $name = $2;
+ $srcUser = {ID=>$name};
+ unless (get_user_nick ($srcUser)) {
+ $srcUser = {NICK=>$name};
+ get_user_id ($name);
+ }
+ }
+ my $dest = $3;
+ $dstUser = {ID=>$dest};
+ unless (get_user_nick ($dstUser)) {
+ $dstUser = {NICK=>$dest};
+ }
+ print Dumper ($srcUser);
+ print Dumper ($dstUser);
+ $event = 'PRIVMSG'; @args = ($srcUser, $dstUser, $4);
+ }
+ elsif($_[0] =~ /^(@|:)(\S+) (?:B|NOTICE) (\S+) :(.*)$/) {
+ my $name;
+ if ($1 eq '@') {
+ $name = $servernum[b64toi($2)];
+ }
+ else {
+ $name = $2;
+ }
+ $event = 'NOTICE'; @args = ($name, $3, $4);
+ }
+ $args[1] =~ s/\@${main_conf{local}}.*//io;
+
+ if(queue_size > 50 and $event eq 'PRIVMSG' and $args[1] !~ /^#/ and $args[2] =~ /^\w/) {
+ ircd::notice($args[1], $args[0], "It looks like the system is busy. You don't need to do your command again, just hold on a minute...");
+ }
+
+ return ($event, 0, 1, WF_ALL, @args);
+}
+
+sub AWAY($) {
+ if($_[0] =~ /^:(\S+) (?:6|AWAY) :(.*)$/) {
+ my $user = {ID=>$1};
+ get_user_nick($user);
+ return ('AWAY', undef, undef, WF_ALL, $user, $2);
+ }
+ elsif($_[0] =~ /^:(\S+) (?:6|AWAY)$/) {
+ my $user = {ID => $1};
+ get_user_nick ($user);
+ return ('BACK', undef, undef, WF_ALL, $user);
+ }
+}
+
+sub NICK($) {
+ my ($event, @args);
+ #:97KAAAAAA NICK erry_ 1307878528
+ if($_[0] =~ /^:(\S+) (?:NICK|\&) (\S+) :?(\S+)$/) {
+ my $user = {ID => $1};
+ get_user_nick ($user);
+ ircd::setRevUuid ($1, $2);
+ ircd::setUuid ($2, $1);
+ return ('NICKCHANGE', undef, undef, WF_NICK, $user, $2, $3);
+ }
+}
+
+sub QUIT($) {
+ $_[0] =~ /^:(\S+) (?:QUIT|\,) :(.*)$/;
+ my $user = {ID=>$1};
+ get_user_nick ($1);
+ return ('QUIT', 0, undef, WF_NICK, $user, $2);
+}
+
+sub KILL($) {
+#:tabris KILL ProxyBotW :tabris.netadmin.SCnet.ops!tabris (test.)
+#:ProxyBotW!bopm@ircop.SCnet.ops QUIT :Killed (tabris (test.))
+ $_[0] =~ /^(@|:)(\S+) (?:KILL|\.) (\S+) :(\S+) \((.*)\)$/;
+ my $name;
+ if ($1 eq '@') {
+ $name = $servernum[b64toi($2)];
+ }
+ else {
+ $name = $2;
+ }
+ my $user = {ID => $name};
+ unless (get_user_nick ($user)) {
+ $user = {NICK => $name};
+ get_user_id ($user);
+ }
+ return ('KILL', 0, 1, WF_NICK, $user, $3, $4, $5);
+}
+
+sub KICK($) {
+#:tabris KICK #diagnostics SurrealBot :i know you don't like this. but it's for science!
+ $_[0] =~ /^(@|:)(\S+) (?:KICK|H) (\S+) (\S+) :(.*)$/;
+ # source, chan, target, reason
+ #$src = 0; #$dst = 2;
+ my $name;
+ if ($1 eq '@') {
+ $name = $servernum[b64toi($2)];
+ }
+ else {
+ $name = $2;
+ }
+ my $user = {ID => $name};
+ unless (get_user_nick ($user)) {
+ $user = {NICK => $name};
+ get_user_id ($user);
+ }
+ return ('KICK', 0, undef, WF_CHAN, $user, $3, $4, $5);
+}
+
+sub HOST($) {
+ if($_[0] =~ /^:(\S+) (?:CHGHOST|AL) (\S+) (\S+)$/) {
+ #:Agent CHGHOST tabris tabris.netadmin.SCnet.ops
+ return ('CHGHOST', 0, 1, WF_CHAN, $1, $2, $3);
+ #setter, target, vhost
+ }
+ elsif($_[0] =~ /^:(\S+) (?:SETHOST|AA) (\S+)$/) {
+ #:tabris SETHOST tabris.netadmin.SCnet.ops
+ return ('CHGHOST', 0, 1, WF_CHAN, $1, $1, $2);
+ }
+
+ elsif ($_[0] =~ /^:(?:\S* )?302 (\S+) :(\S+?)\*?=[+-].*?\@(.*)/) {
+ #:serebii.razorville.co.uk 302 leif :Jesture=+~Jesture00@buzz-3F604D09.sympatico.ca
+ return ('CHGHOST', 0, 1, WF_CHAN, $1, $2, $3);
+ }
+}
+
+
+sub USERIP($) {
+ $_[0] =~ /^:(?:\S* )?340 (\S+) :(\S+?)\*?=[+-].*?\@((?:\.|\d)*)/;
+ return ('USERIP', 0, 1, WF_CHAN, $1, $2, $3);
+}
+
+sub IDENT($) {
+ if($_[0] =~ /^:(\S+) (?:CHGIDENT|AL) (\S+) (\S+)$/) {
+ return ('CHGIDENT', 0, 1, WF_ALL, $1, $2, $3);
+ #setter, target, IDENT
+ }
+ elsif($_[0] =~ /^:(\S+) (?:SETIDENT|AD) (\S+)$/) {
+ return ('CHGIDENT', 0, 1, WF_ALL, $1, $1, $2);
+ #setter, target, ident
+ }
+}
+
+
+sub TOPIC($) {
+ if ($_[0] =~ /^:(\S+) TOPIC (\S+) :(.*)$/) {
+ #:583AAAAAF TOPIC #erry :Welcome to erry(world|net). Have a cookie.
+ my $setter = { ID => $1 };
+ get_user_nick ($setter);
+ return ('TOPIC', 0, 1, WF_ALL, $setter, $2, $setter, 0, $3);
+ }
+}
+
+sub UMODE($) {
+#:tabris | +oghaANWt
+ $_[0] =~ /^:(\S+) (?:UMODE2|\|) (\S+)$/;
+ # src, umodes
+ # a note, not all umodes are passed
+ # +s, +O, and +t are not passed. possibly others
+ # also not all umodes do we care about.
+ # umodes we need care about:
+ # oper modes: hoaACN,O oper-only modes: HSq
+ # regular modes: rxB,izV (V is only somewhat, as the ircd
+ # does the conversions from NOTICE to PRIVSMG for us).
+
+ # Yes, I'm changing the event type on this
+ # It's better called UMODE, and easily emulated
+ # on IRCds with only MODE.
+ return ('UMODE', 0, 0, WF_ALL, $1, $2);
+}
+sub OPERTYPE ($) {
+ #:583AAAAAB OPERTYPE SuperNetAdmin
+ #Every OPERTYPE will get +o, so it's safe to assume they're opers,
+ #even if we don't give them privs (either in inspircd or srsv)
+ $_[0] =~ /^:(\S+) OPERTYPE (\S+)$/;
+ my $user = { ID => $1 };
+ print Dumper ($user);
+ get_user_nick ($user);
+ return ("OPERUP", 0, 0, WF_ALL, $user);
+}
+sub SVSMODE($) {
+#:tabris | +oghaANWt
+ $_[0] =~ /^:(\S+) (?:SVS2?MODE|n|v) (\S+) (\S+)$/;
+ # src, umodes
+ # a note, not all umodes are passed
+ # +s, +O, and +t are not passed. possibly others
+ # also not all umodes do we care about.
+ # umodes we need care about:
+ # oper modes: hoaACN,O oper-only modes: HSq
+ # regular modes: rxB,izV (V is only somewhat, as the ircd
+ # does the conversions from NOTICE to PRIVSMG for us).
+
+ return ('UMODE', 0, 0, WF_ALL, $2, $3);
+}
+
+sub WHOIS($) {
+# :tab WHOIS ConnectServ :ConnectServ
+ if($_[0] =~ /^:(\S+) (?:WHOIS|\#) (\S+)$/) {
+ return ('WHOIS', 0, undef, WF_NONE, $1, $2);
+ }
+ elsif($_[0] =~ /^:(\S+) (?:WHOIS|\#) (\S+) :(\S+)$/) {
+ return ('WHOIS', 0, undef, WF_NONE, $1, $3);
+ }
+}
+
+sub TSCTL($) {
+ $_[0] =~ /^:(\S+) (?:TSCTL|AW) alltime$/;
+ ircsend(":$main_conf{local} NOTICE $1 *** Server=$main_conf{local} TSTime=".
+ time." time()=".time." TSOffset=0");
+ return;
+}
+
+sub VERSION($) {
+ $_[0] =~ /^:(\S+) (?:VERSION|\+).*$/;
+ return ('VERSION', 0, undef, WF_NONE, $1);
+}
+
+sub TKL($) {
+ if ($_[0] =~ /^(@|:)(\S+) (?:TKL|BD) (.*)$/) {
+ # We discard the source anyway.
+ #my $server;
+ #if ($1 eq '@') {
+ # $server = $servernum[b64toi($2)];
+ #}
+ #else {
+ # $server = $2;
+ #}
+ return ('TKL', undef, undef, WF_NONE, parse_tkl("TKL $3"));
+ }
+ elsif ($_[0] =~ /^(?:TKL|BD) (.*)$/) {
+ return ('TKL', undef, undef, WF_NONE, parse_tkl("TKL $1"));
+ }
+}
+
+sub SNOTICE($) {
+ $_[0] =~ /^(@|:)(\S+) (SENDSNO|Ss|SMO|AU) ([A-Za-z]) :(.*)$/;
+ #@servernumeric Ss snomask :message
+ my $name;
+ if ($1 eq '@') {
+ $name = $servernum[b64toi($2)];
+ }
+ else {
+ $name = $2;
+ }
+ my $event;
+ $event = 'SENDSNO' if(($3 eq 'SENDSNO' or $3 eq 'Ss'));
+ $event = 'SMO' if(($3 eq 'SMO' or $3 eq 'AU'));
+ return ($event, 0, undef, WF_NONE, $name, $4, $5);
+}
+
+sub GLOBOPS($) {
+ $_[0] =~ /^(@|:)(\S+) (?:GLOBOPS|\]) :(.*)$/;
+ #@servernumeric [ :message
+ my $name;
+ if ($1 eq '@') {
+ $name = $servernum[b64toi($2)];
+ }
+ else {
+ $name = $2;
+ }
+ return ('GLOBOPS', 0, undef, WF_NONE, $name, $3);
+}
+
+sub ISUPPORT($) {
+ $_[0] =~ /^:(\S+) (?:105|005) (\S+) (.+) :are supported by this server$/;
+ # :test-tab.surrealchat.net 105 services.SC.net CMDS=KNOCK,MAP,DCCALLOW,USERIP :are supported by this server
+ foreach my $token (split(/\s+/, $3)) {
+ my ($key, $value) = split('=', $token);
+ $IRCd_capabilities{$key} = ($value ? $value : 1);
+ }
+}
+
+sub STATS($) {
+ $_[0] =~ /^:(\S+) (?:STATS|2) (\S) :(.+)$/;
+ return ('STATS', undef, undef, WF_NONE, $1, $2, $3)
+}
+
+BEGIN {
+ %cmdhash = (
+ PING => \&PING,
+ '8' => \&PING,
+
+ EOS => \&EOS,
+ ES => \&EOS,
+ ENDBURST => \&EOS,
+ SERVER => \&SERVER,
+ "\'" => \&SERVER,
+
+ SQUIT => \&SQUIT,
+ '-' => \&SQUIT,
+
+ NETINFO => \&NETINFO,
+ AO => \&NETINFO,
+
+ PROTOCTL => \&PROTOCTL,
+
+ JOIN => \&JOIN,
+ C => \&JOIN,
+
+ PART => \&PART,
+ D => \&PART,
+
+ SJOIN => \&SJOIN,
+ '~' => \&SJOIN,
+ FJOIN => \&FJOIN,
+ FMODE => \&FMODE,
+ MODE => \&MODE,
+ G => \&MODE,
+
+ PRIVMSG => \&MESSAGE,
+ '!' => \&MESSAGE,
+ NOTICE => \&MESSAGE,
+ B => \&MESSAGE,
+
+ AWAY => \&AWAY,
+ '6' => \&AWAY,
+
+ NICK => \&NICK,
+ '&' => \&NICK,
+
+ QUIT => \&QUIT,
+ ',' => \&QUIT,
+
+ KILL => \&KILL,
+ '.' => \&KILL,
+
+ KICK => \&KICK,
+ H => \&KICK,
+
+ CHGHOST => \&HOST,
+ AL => \&HOST,
+ SETHOST => \&HOST,
+ AA => \&HOST,
+ '302' => \&HOST,
+
+ '340' => \&USERIP,
+
+ CHGIDENT => \&IDENT,
+ AZ => \&IDENT,
+ SETIDENT => \&IDENT,
+ AD => \&IDENT,
+
+ TOPIC => \&TOPIC,
+ ')' => \&TOPIC,
+
+ UMODE2 => \&UMODE,
+ '|' => \&UMODE,
+
+ TSCTL => \&TSCTL,
+ AW => \&TSCTL,
+
+ VERSION => \&VERSION,
+ '+' => \&VERSION,
+
+ TKL => \&TKL,
+ BD => \&TKL,
+
+ WHOIS => \&WHOIS,
+ '#' => \&WHOIS,
+
+ SENDSNO => \&SNOTICE,
+ Ss => \&SNOTICE,
+
+ SMO => \&SNOTICE,
+ AU => \&SNOTICE,
+
+ GLOBOPS => \&GLOBOPS,
+ ']' => \&GLOBOPS,
+
+ '105' => \&ISUPPORT,
+ '005' => \&ISUPPORT,
+
+ SVSMODE => \&SVSMODE,
+ 'n' => \&SVSMODE,
+ SVS2MODE => \&SVSMODE,
+ 'v' => \&SVSMODE,
+
+ STATS => \&STATS,
+ '2' => \&STATS,
+ UID => \&UID,
+ OPERTYPE => \&OPERTYPE,
+ );
+}
+
+1;
--- /dev/null
+# This file is part of SurrealServices.
+#
+# SurrealServices is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# SurrealServices is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with SurrealServices; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+package ircd;
+
+use strict;
+use IO::Socket::INET;
+use Event;
+use Carp;
+use MIME::Base64;
+use Data::Dumper;
+use SrSv::Conf 'main';
+use SrSv::Insp::UUID;
+use SrSv::Debug;
+use SrSv::Log;
+use Exporter 'import';
+our @EXPORT = qw (agent_doconn getRevUuid getUuid setRevUuid setUuid);
+# FIXME
+use constant {
+ MAXBUFLEN => 510,
+
+# These appear to match the implementations I've seen, but are unspecified in the RFCs.
+# They may vary by implementation.
+ NICKLEN => 30, # some ircds are different. hyperion is 16.
+ IDENTLEN => 10, # Sometimes 8 or 9.
+ # hyperion may break this due to it's ident format: [ni]=identhere, like this n=northman
+ HOSTLEN => 63, # I think I've seen 64 here before.
+ MASKLEN => 30 + 10 + 63 + 2, # 105, or maybe 106. the 2 constant is for !@
+
+ CHANNELLEN => 32, # From 005 reply. hyperion is 30.
+
+ SJ3 => 1,
+ NOQUIT => 1,
+ NICKIP => 1,
+ SJB64 => 1,
+ CLK => 1,
+
+ PREFIXAQ_DISABLE => 0,
+};
+die "NICKIP must be enabled if CLK is\n" if CLK && !NICKIP;
+
+use SrSv::IRCd::IO qw(ircd_connect ircsend ircsendimm ircd_flush_queue);
+use SrSv::IRCd::Event qw(addhandler callfuncs);
+use SrSv::IRCd::State qw($ircline $remoteserv $ircd_ready synced initial_synced set_server_state set_server_juped get_server_state get_online_servers);
+
+use SrSv::Unreal::Modes qw(@opmodes %opmodes $scm $ocm $acm);
+use SrSv::Unreal::Tokens;
+use SrSv::IRCd::Parse qw(parse_tkl parse_addline);
+use SrSv::Unreal::Base64 qw(itob64 b64toi);
+
+use SrSv::Text::Format qw( wordwrap );
+
+use SrSv::Agent;
+
+use SrSv::Process::InParent qw(update_userkill getRevUuid getUuid setRevUuid SetUUid);
+
+our %defer_mode;
+our %preconnect_defer_mode;
+our @userkill;
+our $unreal_protocol_version;
+our $count = 65;
+our %uuids; #NickServ -> AAAAAA
+our %reverse_uuids; #AAAAA -> NickServ
+addhandler('SEOS', undef(), undef(), 'ircd::eos', 1);
+addhandler('NETINFO', undef(), undef(), 'ircd::netinfo', 1);
+addhandler('VERSION', undef(), undef(), 'ircd::version', 1);
+addhandler('SERVER', undef(), undef(), 'ircd::handle_server', 1);
+addhandler('ENDBURST',undef(),undef(),'ircd::endburst',1);
+sub getRevUuid($) {
+ my $id = $_[0];
+ my $nick = $reverse_uuids{$id};
+ $uuids{lc $nick} = $id;
+ return $nick;
+}
+sub getUuid($) {
+ my $nick = lc $_[0];
+ my $id = $uuids{$nick};
+ print "getUuid $nick $id\n";
+ return $id;
+}
+sub setRevUuid ($$) {
+ my ($id, $nick) = @_;
+ $reverse_uuids{$id} = lc $nick;
+}
+sub setUuid ($$) {
+ my ($nick, $id) = @_;
+ $uuids{lc $nick} = $id;
+}
+sub serv_connect() {
+ my $remote = $main_conf{remote};
+ my $port = $main_conf{port};
+ ircd_connect($remote, $port);
+ #ircsendimm('PROTOCTL '.($tkn ? 'TOKEN ' : '').'NICKv2 UMODE2 TKLEXT'.
+ #(CLK ? ' CLK' : ' VHP'). # CLK obsoletes VHP. Plus if you leave VHP on, CLK doesn't work.
+ # (NOQUIT ? ' NOQUIT' : '').(SJ3 ? ' SJOIN SJOIN2 SJ3' : '').
+ # (NICKIP ? ' NICKIP' : '').
+ # (SJB64 ? ' SJB64 NS VL' : ''),
+ #CONNECTCRAP
+ ircsendimm( 'PASS :'.$main_conf{pass},
+ 'SERVER '.$main_conf{local}.' ' . $main_conf{pass} . ' 0 ' .$main_conf{numeric} . ' ' .$main_conf{info} );
+ ircsendimm ('BURST ' .time);
+ %preconnect_defer_mode = %defer_mode;
+ %defer_mode = ();
+}
+
+# Helper Functions
+
+sub handle_server($$$$;$$$) {
+# This is mostly a stub function, but we may need the $unreal_protocol_version
+# at a later date. Plus we may want to maintain a server tree in another module.
+ my ($src_server, $server_name, $num_hops, $info_line, $server_numeric, $protocol_version, $build_flags) = @_;
+ $unreal_protocol_version = $protocol_version if defined $protocol_version;
+}
+
+
+
+# Handler functions
+sub pong($$$) {
+ my ($src, $cookie, $dst) = @_;
+ # This will only make sense if you remember that
+ # $src is where it came from, $dst is where it went (us)
+ # we're basically bouncing it back, but changing from PING to PONG.
+ if (defined($dst) and defined($cookie)) {
+ # $dst is always $main_conf{local} anyway...
+ # this is only valid b/c we never have messages routed THROUGH us
+ # we are always an end point.
+ ircsendimm(":$dst $tkn{PONG}[$tkn] $src :$cookie");
+ }
+ else {
+ ircsendimm("$tkn{PONG}[$tkn] :$src");
+ }
+}
+sub endburst {
+ print "GOT ENDBURST\n\n";
+ ircd_flush_queue();
+ ircsendimm ("ENDBURST");
+ $ircd_ready = 1; #!
+}
+sub eos {
+ print "GOT EOS\n\n";
+
+ #foreach my $k (keys %servers) {
+ # print "Server: $k ircline: ",$servers{$k}[0], " state: ", $servers{$k}[1], "\n";
+ #}
+ #print "Synced: ", synced(), "\n\n";
+ #exit;
+
+ ircsendimm(':'.$main_conf{local}.' '.$tkn{EOS}[$tkn], 'VERSION');
+
+ agent_sync();
+ flushmodes(\%preconnect_defer_mode);
+ ircd_flush_queue();
+
+ $ircd_ready = 1;
+}
+
+sub netinfo($$$$$$$$) {
+ ircsendimm($tkn{NETINFO}[$tkn].' 0 '.time." $_[2] $_[3] 0 0 0 :$_[7]");
+ $main_conf{network} = $_[7];
+}
+
+sub tssync {
+ ircsendimm((SJB64 ? '@'.itob64($main_conf{numeric}) : ':'.$main_conf{local})." $tkn{TSCTL}[$tkn] SVSTIME ".time);
+}
+
+sub parse_sjoin($$$$) {
+ my ($server, $ts, $cn, $parms) = @_;
+ my (@users, @bans, @excepts, @invex, @blobs, $blobs, $chmodes, $chmodeparms);
+
+ $server = '' unless $server;
+
+ if($parms =~ /^:(.*)/) {
+ $blobs = $1;
+ } else {
+ ($chmodes, $blobs) = split(/ :/, $parms, 2);
+ ($chmodes, $chmodeparms) = split(/ /, $chmodes, 2);
+ }
+ @blobs = split(/ /, $blobs);
+
+ foreach my $x (@blobs) {
+ if($x =~ /^(\&|\"|\')(.*)$/) {
+ my $type;
+ push @bans, $2 if $1 eq '&';
+ push @excepts, $2 if $1 eq '"';
+ push @invex, $2 if $1 eq "\'";
+ } else {
+ $x =~ /^([*~@%+]*)(.*)$/;
+ my ($prefixes, $nick) = ($1, $2);
+ my @prefixes = split(//, $prefixes);
+ my $op;
+ foreach my $prefix (@prefixes) {
+ $op |= $opmodes{q} if ($prefix eq '*');
+ $op |= $opmodes{a} if ($prefix eq '~');
+ $op |= $opmodes{o} if ($prefix eq '@');
+ $op |= $opmodes{h} if ($prefix eq '%');
+ $op |= $opmodes{v} if ($prefix eq '+');
+ }
+
+ push @users, { NICK => $nick, __OP => $op };
+ }
+ }
+
+ return ($server, $cn, $ts, $chmodes, $chmodeparms, \@users, \@bans, \@excepts, \@invex);
+}
+
+# Send Functions
+
+sub kick($$$$) {
+ my ($src, $chan, $target, $reason) = @_;
+ $src = $main_conf{local} unless initial_synced();
+ my $srcId = ($src->{ID}?$src->{ID}:$src->{NICK});
+ my $targetId = ($target->{ID}?encodeUUID($target->{ID}):$target->{NICK});
+ ircsend(":$srcId $tkn{KICK}[$tkn] $chan $targetId :$reason");
+ callfuncs('KICK', 0, 2, [$srcId, $chan, $targetId, $reason]);
+}
+
+sub invite($$$) {
+ my ($src, $chan, $target) = @_;
+ my $srcId = ($src->{ID}?$src->{ID}:$src->{NICK});
+ my $targetId = ($target->{ID}?encodeUUID($target->{ID}):$target->{NICK});
+ ircsend(":$srcId $tkn{INVITE}[$tkn] $targetId $chan 0");
+}
+
+sub ping {
+# if(@_ == 1) {
+ ircsend(':'.$main_conf{local}.' '.$tkn{PING}[$tkn].' :'.$main_conf{local});
+# } else {
+# ircsend(':'.$_[2].' '.$tkn{PONG}[$tkn].' '.$_[0].' :'.$_[1]);
+# }
+}
+
+sub privmsg($$@) {
+ my ($src, $dst, @msgs) = @_;
+ my @bufs;
+ foreach my $buf (@msgs) {
+ # 3 spaces, two colons, PRIVMSG=7
+ # Length restrictions are for CLIENT Protocol
+ # hence the (MASKLEN - (NICKLEN + 1))
+ # Technically optimizable if we use $agent{lc $src}'s ident and host
+ my $buflen = length($src) + length($dst) + 12 + (MASKLEN - (NICKLEN + 1));
+ push @bufs, wordwrap($buf, (MAXBUFLEN - $buflen));
+ }
+ my $srcId = ($src->{ID}?$src->{ID}:$src->{NICK});
+
+ # submit a list of messages as a single packet to the server
+ ircsend(":$srcId $tkn{PRIVMSG}[$tkn] $dst :".join("\r\n".":$src $tkn{PRIVMSG}[$tkn] $dst :", @bufs));
+ callfuncs('LOOP_PRIVMSG', 0, 1, [$src, $dst, \@bufs]);
+}
+
+sub debug(@) {
+ my (@msgs) = @_;
+ debug_privmsg($main_conf{local}, $main_conf{diag}, @msgs);
+ write_log('diag', '<'.$main_conf{local}.'>', @msgs);
+}
+sub write_log () { }
+sub debug_nolog(@) {
+ my (@msgs) = @_;
+ debug_privmsg($main_conf{local}, $main_conf{diag}, @msgs);
+}
+
+sub debug_privmsg($$@) {
+ my ($src, $dst, @msgs) = @_;
+
+ my @bufs;
+ foreach my $buf (@msgs) {
+ # 3 spaces, two colons, PRIVMSG=7
+ # Length restrictions are for CLIENT Protocol
+ # hence the (MASKLEN - (NICKLEN + 1))
+ my $buflen = length($src) + length($dst) + 12 + (MASKLEN - (NICKLEN + 1));
+ push @bufs, wordwrap($buf, (MAXBUFLEN - $buflen));
+ }
+
+ # submit a list of messages as a single packet to the server
+ ircsendimm(":$src $tkn{PRIVMSG}[$tkn] $dst :".join("\r\n".":$src $tkn{PRIVMSG}[$tkn] $dst :", @bufs));
+ callfuncs('LOOP_PRIVMSG', 0, 1, [$src, $dst, \@bufs]);
+}
+
+sub notice($$@) {
+ my ($src, $dst, @msgs) = @_;
+ my $target = $dst; #lazy erry
+ my @bufs;
+ foreach my $buf (@msgs) {
+ # 3 spaces, two colons, NOTICE=6
+ # Length restrictions are for CLIENT Protocol
+ # hence the (MASKLEN - (NICKLEN + 1))
+ my $buflen = length($src) + length($dst) + 12 + (MASKLEN - (NICKLEN + 1));
+ push @bufs, wordwrap($buf, (MAXBUFLEN - $buflen));
+ }
+ my $srcId = ($src->{ID}?$src->{ID}:$src->{NICK});
+ my $targetId;
+ if (ref ($dst) eq "HASH") { #User Object
+ $targetId = ($target->{ID}?encodeUUID($target->{ID}):$target->{NICK});
+ }
+ else { # /notice #channel This probably sucks. Blame erry :(
+ $targetId = $dst;
+ }
+ print "targid $targetId\n";
+ ircsend(":$srcId $tkn{NOTICE}[$tkn] $targetId :".join("\r\n".":$srcId $tkn{NOTICE}[$tkn] $targetId :", @bufs));
+ callfuncs('LOOP_NOTICE', 0, 1, [$srcId, $targetId, \@bufs]);
+}
+
+sub ctcp($$@) {
+ my ($src, $dst, $cmd, @toks) = @_;
+ my $target = $dst; #lazy erry
+ my $srcId = ($src->{ID}?$src->{ID}:$src->{NICK});
+ my $targetId = ($target->{ID}?encodeUUID($target->{ID}):$target->{NICK});
+ privmsg($srcId, $targetId, "\x01".join(' ', ($cmd, @toks))."\x01");
+}
+
+sub ctcp_reply($$@) {
+ my ($src, $dst, $cmd, @toks) = @_;
+ my $target = $dst; #lazy erry
+ my $srcId = ($src->{ID}?$src->{ID}:$src->{NICK});
+ my $targetId = ($target->{ID}?encodeUUID($target->{ID}):$target->{NICK});
+ notice($srcId, $targetId, "\x01".join(' ', ($cmd, @toks))."\x01");
+}
+
+sub setumode($$$) {
+ my ($src, $dst, $modes) = @_;
+ my $target = $dst; #lazy erry
+ my $srcId = ($src->{ID}?$src->{ID}:$src->{NICK});
+ my $targetId = ($target->{ID}?encodeUUID($target->{ID}):$target->{NICK});
+ ircsend(":$srcId $tkn{SVSMODE}[$tkn] $targetId $modes");
+ callfuncs('UMODE', 0, undef, [$dst, $modes]);
+}
+
+sub setsvsstamp($$$) {
+ my ($src, $dst, $stamp) = @_;
+
+ ircsend(":$src $tkn{SVS2MODE}[$tkn] $dst +d $stamp");
+ # This function basically set the svsstamp to
+ # be the same as the userid. Not all ircd will
+ # support this function.
+ # We obviously already know the userid, so don't
+ # use a callback here.
+ #callfuncs('UMODE', 0, undef, [$dst, $modes]);
+}
+
+sub setagent_umode($$) {
+ my ($src, $modes) = @_;
+ ircsend(":$src $tkn{UMODE2}[$tkn] $modes");
+}
+
+sub setmode2($$@) {
+ my ($src, $dst, @modelist) = @_;
+ #debug(" --", "-- ircd::setmode2: ".$_[0], split(/\n/, Carp::longmess($@)), " --");
+ foreach my $modetuple (@modelist) {
+ my $target = $modetuple->[1];
+ setmode($src, $dst, $modetuple->[0], $modetuple->[1]);
+ }
+}
+sub ban_list($$$$@) {
+# Convenience function for lots of bans or excepts.
+ my ($src, $cn, $sign, $mode, @parms) = @_;
+ my $srcId = ($src->{ID}?$src->{ID}:$src->{NICK});
+ my @masklist;
+ foreach my $mask (@parms) {
+ push @masklist, [( ($sign >= 1) ? '+' : '-').$mode, $mask];
+ }
+ ircd::setmode2($srcId, $cn, @masklist);
+}
+
+sub setmode($$$;$) {
+ my ($src, $dst, $modes, $target) = @_;
+ my $srcId;
+ if (initial_synced()) {
+ $srcId = ($src->{ID}?$src->{ID}:($src->{UUID}?$src->{UUID}:$src->{NICK}));
+ }
+ else {
+ $src = $main_conf{numeric};
+ $srcId = $src;
+ }
+ my $targetId = ($target->{ID}?encodeUUID($target->{ID}):$target->{NICK});
+ callfuncs('MODE', undef, 1, [$srcId, $dst, $modes, $targetId]);
+ #print "$ircline -- setmode($srcId, $dst, $modes, $targetId)\n" ;
+ ircsend(":$srcId MODE $dst $modes $targetId");
+}
+
+sub setmode_many($$$;@) {
+ my ($src, $dst, $modes, @targets) = @_;
+ my $srcId;
+ if (initial_synced()) {
+ $srcId = ($src->{ID}?$src->{ID}:($src->{UUID}?$src->{UUID}:$src->{NICK}));
+ }
+ else {
+ $src = $main_conf{local};
+ $srcId = $src;
+ }
+ my $parms = "";
+ foreach my $target (@targets) {
+ my $targetId = ($target->{ID}?encodeUUID($target->{ID}):$target->{NICK});
+ $parms .= ($parms == ""?"":" ") . $targetId;
+ }
+ callfuncs('MODE', undef, 1, [$srcId, $dst, $modes, $parms]);
+ print "$ircline -- setmode($srcId, $dst, $modes, $parms)\n" ;
+ ircsend(":$srcId MODE $dst $modes $parms");
+}
+
+
+sub flushmodes(;$) {
+ my $dm = (shift or \%defer_mode);
+ my @k = keys(%$dm); my @v = values(%$dm);
+ for(my $i; $i<@k; $i++) {
+ my ($src, $dst) = split(/ /, $k[$i]);
+ my @m = @{$v[$i]};
+ foreach my $m (@m) {
+ my ($modes, $parms) = split(/ /, $m, 2);
+ setmode_real($src, $dst, $modes, $parms);
+ }
+ }
+ %$dm = ();
+}
+
+sub setmode_real($$$;$) {
+ my ($src, $dst, $modes, $parms) = @_;
+ print "$ircline -- setmode_real($src, $dst, $modes, $parms)\n";
+ # for server sources, there must be a timestamp. but you can put 0 for unspecified.
+ $parms =~ s/\s+$//; #trim any trailing whitespace, as it might break the simple parser in the ircd.
+
+ ircsend(":$src ".$tkn{MODE}[$tkn]." $dst $modes".($parms?" $parms":'').($src =~ /\./ ? ' 0' : ''));
+}
+
+sub settopic($$$$$) {
+ my ($src, $chan, $setter, $time, $topic) = @_;
+ $src = $main_conf{numeric} unless initial_synced();
+ #>> 38 :583AAAAAF TOPIC #erry :Welcome to erry(world|net). Have a cookie.
+ my $srcId = ($src->{ID}?$src->{ID}:$src->{NICK});
+ ircsend(":$srcId ".$tkn{TOPIC}[$tkn]." $chan :$topic");
+ callfuncs('TOPIC', undef, undef, [$srcId, $chan, $setter, $time, $topic]);
+}
+
+sub wallops ($$) {
+ my ($src, $message) = @_;
+ ircsend(":$src $tkn{WALLOPS}[$tkn] :$message");
+}
+
+sub globops ($$) {
+ my ($src, $message) = @_;
+ my $srcId = ($src->{ID}?$src->{ID}:$src->{NICK});
+ ircsend(":$srcId $tkn{GLOBOPS}[$tkn] :$message");
+}
+
+sub kline ($$$$$) {
+ my ($setter, $ident, $host, $expiry, $reason) = @_;
+ $setter = $main_conf{local} unless defined($setter);
+ $ident = '*' unless defined($ident);
+ # you need to use ADDLINE for this. GLINE is a user command
+ # format is
+ #>> 47 :583AAAAAA ADDLINE G test@testie inspircd.erry.omg 1308118489 0 :hi
+ #NOTE FOR ALL ADDLINES:
+ #note that you need to provide expiry alone, not expiry +time
+ #otherwise you will end up with insanely long bans
+ my $setId = getUuid($setter);
+ if ($setId) { $setter = $setId; }
+ my $line = ":$setter ADDLINE G $ident\@$host " . $main_conf{local} . " ". time() . " " . ($expiry)." :$reason";
+ ircsend($line);
+ #return ($type, +1, $ident, $host, $setter, $expire, $time, $reason);
+ callfuncs('TKL', undef, undef, [parse_addline($line)]);
+}
+
+sub unkline ($$$) {
+ my ($setter, $ident, $host) = @_;
+ my $line = "TKL - G $ident $host $setter";
+ my $setId = getUuid($setter);
+ if ($setId) { $setter = $setId; }
+ #:583AAAAAE DELLINE G test@test.com
+ my $line = ":$setter DELLINE G $ident\@$host";
+ ircsend($line);
+ callfuncs('TKL', undef, undef, [parse_delline($line)]);
+}
+
+sub zline ($$$$) {
+ my ($setter, $host, $expiry, $reason) = @_;
+ $setter=$main_conf{local} unless defined($setter);
+ my $setId = getUuid($setter);
+ if ($setId) { $setter = $setId; }
+ #:583AAAAAE ADDLINE Z test.com inspircd.erry.omg 1308216407 0 :go away
+ my $line = ":$setter ADDLINE Z $host " . $main_conf{local} . " ". time() . " " . ($expiry)." :$reason";
+ ircsend($line);
+ callfuncs('TKL', undef, undef, [parse_addline($line)]);
+}
+
+sub unzline ($$) {
+ my ($setter, $host) = @_;
+ my $setId = getUuid($setter);
+ if ($setId) { $setter = $setId; }
+ my $line = ":$setter DELLINE Z $host";
+ ircsend($line);
+ callfuncs('TKL', undef, undef, [parse_delline($line)]);
+}
+
+sub spamfilter($$$$$$$) {
+# Note the hardcoded zero (0).
+# Looks like theoretically one can have expirable spamfilters.
+# This is untested however.
+ my ($sign, $tkl_target, $tkl_action, $setter, $bantime, $reason, $regex) = @_;
+ my $tkl = "TKL ".($sign ? '+' : '-' )." F $tkl_target $tkl_action $setter 0 ".time()." $bantime $reason :$regex";
+ ircsend($tkl);
+ callfuncs('TKL', undef, undef, [parse_tkl($tkl)]);
+}
+
+sub update_userkill($) {
+ my ($target) = @_;
+
+ # This is a simple way to do it, that _could_ be defeated
+ # with enough users getting killed at once.
+ # The alternative would require a timer to expire the old entries.
+ return undef if (time() == $userkill[1] and $target eq $userkill[0]);
+ @userkill = ($target, time());
+
+ return 1;
+}
+
+sub irckill($$$) {
+ my ($src, $target, $reason) = @_;
+ $src = $main_conf{local} unless initial_synced();
+ my $srcId = ($src->{ID}?$src->{ID}:$src->{NICK});
+ my $targetId = ($target->{ID}?encodeUUID($target->{ID}):$target->{NICK});
+ my $srcNick = $target->{NICK};
+ return 0 unless update_userkill($targetId);
+ ircsendimm(":$srcId ".$tkn{KILL}[$tkn]." $targetId :$srcNick ($reason)");
+ callfuncs('KILL', 0, 1, [$srcId, $targetId, $srcNick, $reason]);
+}
+
+sub svssno($$$) {
+ my ($src, $target, $snomasks) = @_;
+ $src=$main_conf{local} unless defined($src);
+ # TODO:
+ # None, this doesn't affect us.
+
+ # SVSSNO is not in tokens.txt nor msg.h
+ ircsend(":$src ".'SVS2SNO'." $target $snomasks ".time);
+}
+
+sub svsnick($$$) {
+ my ($src, $target, $newnick) = @_;
+ $src=$main_conf{local} unless defined($src);
+ # note: we will get a NICK cmd back after a
+ # successful nick change.
+ # warning, if misused, this can KILL the user
+ # with a collision
+ my $srcId = ($src->{ID}?$src->{ID}:$src->{NICK});
+ my $targetId = ($target->{ID}?encodeUUID($target->{ID}):$target->{NICK});
+ ircsend(":$srcId ".$tkn{SVSNICK}[$tkn]." $targetId $newnick ".time);
+}
+
+sub svsnoop($$$) {
+ my ($targetserver, $bool, $src) = @_;
+ $src = $main_conf{local} unless defined($src);
+ if ($bool > 0) { $bool = '+'; } else { $bool = '-'; }
+#this is SVS NO-OP not SVS SNOOP
+ ircsend(":$main_conf{local} $tkn{SVSNOOP}[$tkn] $targetserver $bool");
+}
+
+#START TODO - erry
+
+sub svswatch ($$@) {
+# Changes the WATCH list of a user.
+# Syntax: SVSWATCH <nick> :<watch parameters>
+# Example: SVSWATCH Blah :+Blih!*@* -Bluh!*@* +Bleh!*@*.com
+# *** We do not track this info nor care.
+ my ($src, $target, @watchlist) = @_;
+ my $base_str = ":$src ".$tkn{SVSWATCH}[$tkn]." $target :";
+ my $send_str = $base_str;
+ while (@watchlist) {
+ my $watch = shift @watchlist;
+ if (length("$send_str $watch") > MAXBUFLEN) {
+ ircsend($send_str);
+ $send_str = $base_str;
+ }
+ $send_str = "$send_str $watch";
+ }
+ ircsend($send_str);
+}
+
+sub svssilence ($$@) {
+# Changes the SILENCE list of a user.
+# Syntax: SVSSILENCE <nick> :<silence parameters>
+# Example: SVSSILENCE Blah :+Blih!*@* -Bluh!*@* +Bleh!*@*.com
+# *** We do not track this info nor care.
+ my ($src, $target, @silencelist) = @_;
+ my $base_str = ":$src ".$tkn{SVSSILENCE}[$tkn]." $target :";
+ my $send_str = $base_str;
+ while (@silencelist) {
+ my $silence = shift @silencelist;
+ if (length("$send_str $silence") > MAXBUFLEN) {
+ ircsend($send_str);
+ $send_str = $base_str;
+ }
+ $send_str = "$send_str $silence";
+ }
+ ircsend($send_str);
+}
+
+sub svso($$$) {
+# Gives nick Operflags like the ones in O:lines.
+# SVSO <nick> <+operflags> (Adds the Operflags)
+# SVSO <nick> - (Removes all O:Line flags)
+# Example: SVSO SomeNick +bBkK
+# *** We do not track this info nor care.
+# *** We will see any umode changes later.
+# *** this cmd does not change any umodes!
+
+ my ($src, $target, $oflags) = @_;
+ $src = $main_conf{local} unless defined($src);
+ ircsend(":$src $tkn{SVSO}[$tkn] $target $oflags");
+
+}
+
+sub swhois($$$) {
+# *** We do not track this info nor care.
+ my ($src, $target, $swhois) = @_;
+ $src = $main_conf{local} unless defined($src);
+ ircsend(":$src $tkn{SWHOIS}[$tkn] $target :$swhois");
+}
+#END TODO - erry
+
+sub svsjoin($$@) {
+ my ($src, $target, @chans) = @_;
+ while(my @chanList = splice(@chans, 0, 10)) {
+ # split into no more than 10 at a time.
+ __svsjoin($src, $target, @chanList);
+ }
+}
+
+sub __svsjoin($$@) {
+ my ($src, $target, @chans) = @_;
+ # a note. a JOIN is returned back to us on success
+ # so no need to process this command.
+ # similar for svspart.
+ my $srcId = ($src->{ID}?$src->{ID}:$src->{NICK});
+ my $targetId = ($target->{ID}?encodeUUID($target->{ID}):$target->{NICK});
+ ircsend(($srcId?":$srcId":'')." $tkn{SVSJOIN}[$tkn] $targetId ".join(',', @chans));
+}
+
+sub svspart($$$@) {
+ my ($src, $target, $reason, @chans) = @_;
+ my $srcId = ($src->{ID}?$src->{ID}:$src->{NICK});
+ my $targetId = ($target->{ID}?encodeUUID($target->{ID}):$target->{NICK});
+ ircsend(($srcId ? ":$srcId" : '')." $tkn{SVSPART}[$tkn] $targetId ".join(',', @chans).
+ ($reason ? " :$reason" : ''));
+}
+
+sub sqline ($;$) {
+# we need to sqline most/all of our agents.
+# tho whether we want to put it in agent_connect
+# or leave it to the module to call it...
+ my ($nickmask, $reason) = @_;
+ #ircsend("$tkn{S1QLINE}[$tkn] $nickmask".($reason?" :$reason":''));
+ qline($nickmask, 0, $reason);
+}
+
+sub svshold($$$) {
+ my ($nickmask, $expiry, $reason) = @_;
+ #:583AAAAAA ADDLINE Q hell3o inspircd.erry.omg 1308295479 600 :Bye Bye
+ my $line = ':' . $main_conf{numeric} . ' ADDLINE Q '.$nickmask.' '.$main_conf{local}.' '. time() . ' ' . ($expiry ? $expiry : 0 ) . ' :'.$reason;
+ ircsend($line);
+ callfuncs('TKL', undef, undef, [parse_addline($line)]);
+}
+
+sub svsunhold($) {
+ my ($nickmask) = @_;
+ #>> 37 :583AAAAAA DELLINE Q errietta3
+ my $line = ":" . $main_conf{numeric} . ' DELLINE Q ' . $nickmask . "\n";
+ ircsend($line);
+ callfuncs('TKL', undef, undef, [parse_tkl($line)]);
+}
+
+sub qline($$$) {
+ my ($nickmask, $expiry, $reason) = @_;
+ #:583AAAAAA ADDLINE Q hell3o inspircd.erry.omg 1308295479 600 :Bye Bye
+
+ my $line = ':' . $main_conf{numeric} . ' ADDLINE Q '.$nickmask . ' ' . $main_conf{local} . ' '. time() . ' ' . ($expiry ? $expiry : 0).' :'.$reason;
+ ircsend($line);
+
+ # at startup we send these too early,
+ # before the handlers are initialized
+ # so they may be lost.
+ callfuncs('TKL', undef, undef, [parse_tkl($line)]);
+}
+
+sub unsqline ($) {
+# we need to sqline most/all of our agents.
+# tho whether we want to put it in agent_connect
+# or leave it to the module to call it...
+ my ($nickmask) = @_;
+ unqline($nickmask);
+}
+
+sub unqline($) {
+ my ($nickmask) = @_;
+# TKL version
+# TKL - Q * test services.SC.net
+ my $line = 'TKL - Q * '.$nickmask.' '.$main_conf{local};
+ ircsend($line);
+ callfuncs('TKL', undef, undef, [parse_tkl($line)]);
+}
+
+sub svskill($$$) {
+ my ($src, $target, $reason) = @_;
+ # SVSKILL requires a src, it will NOT work w/o one.
+ # not sure if it'll accept a servername or not.
+ # consider defaulting to ServServ
+ die('svskill called w/o $src') unless $src;
+ ircsend(':'.$src.' '.$tkn{SVSKILL}[$tkn].' '.$target.' :'.$reason);
+ callfuncs('QUIT', 0, undef, [$target, $reason]);
+}
+
+sub version($) {
+ my ($src) = @_;
+ #ircsend(":$main_conf{local} 351 $src $main::progname ver $main::version $main_conf{local} ".
+ # $main::extraversion);
+}
+
+sub userhost($) {
+ my ($target) = @_;
+ ircsend($tkn{USERHOST}[$tkn]." $target");
+}
+
+sub userip($) {
+ my ($target) = @_;
+ die "We're not supposed to use USERIP anymore!" if DEBUG and NICKIP;
+ ircsend(":$main::rsnick USERIP $target");
+}
+
+sub chghost($$$) {
+ my ($src, $target, $vhost) = @_;
+ my $srcId = ($src->{ID}?$src->{ID}:$src->{NICK});
+ my $targetId = ($target->{ID}?encodeUUID($target->{ID}):$target->{NICK});
+ ircsend(($srcId?":$srcId ":'').$tkn{CHGHOST}[$tkn]." $targetId $vhost");
+ callfuncs('CHGHOST', 0, 1, [$srcId, $targetId, $vhost]);
+}
+
+sub chgident($$$) {
+ my ($src, $target, $ident) = @_;
+ my $srcId = ($src->{ID}?$src->{ID}:$src->{NICK});
+ my $targetId = ($target->{ID}?encodeUUID($target->{ID}):$target->{NICK});
+ ircsend(($src?":$srcId ":'').$tkn{CHGIDENT}[$tkn]." $targetId $ident");
+ callfuncs('CHGIDENT', 0, 1, [$srcId, $targetId, $ident]);
+}
+
+sub jupe_server($$) {
+ my ($server, $reason) = @_;
+
+ # :nascent.surrealchat.net SERVER wyvern.surrealchat.net 2 :SurrealChat
+ die "You can't jupe $server"
+ if ((lc($server) eq lc($remoteserv)) or (lc($server) eq lc($main_conf{local})));
+ ircsend(':'.$main_conf{local}.' '.$tkn{SQUIT}[$tkn]." $server :");
+ ircsend(':'.$main_conf{local}.' '.$tkn{SERVER}[$tkn]." $server 2 :$reason");
+
+ set_server_juped($server);
+}
+sub agent_dojoin($$) {
+ my ($agent, $chan) = @_;
+ print "DOJOIN " . Dumper ($agent);
+ my $srcId;
+ if (ref($agent) ne "HASH") {
+ $srcId = getUuid($agent);
+ if (!$srcId) {
+ $srcId = $agent;
+ }
+ print "SRCID " . Dumper($srcId);
+ }
+ else {
+ my $src = $agent;
+ $srcId = ($src->{ID}?$src->{ID}:($src->{UUID}?$src->{UUID}:$src->{NICK}));
+ }
+ ircsend(":" . $srcId . " JOIN " . $chan);
+}
+
+sub agent_dopart ($$$) {
+ my ($agent, $chan, $reason) = @_;
+ my $srcId;
+ if (ref($agent) ne "HASH") {
+ $srcId = getUuid($agent);
+ if (!$srcId) {
+ $srcId = $agent;
+ }
+ }
+ else {
+ my $src = $agent;
+ $srcId = ($src->{ID}?$src->{ID}:($src->{UUID}?$src->{UUID}:$src->{NICK}));
+ }
+ ircsend(":$srcId $tkn{PART}[$tkn] $chan :$reason");
+}
+sub rehash_all_servers(;$) {
+ my ($type) = @_;
+
+ # Validate the type before passing it along.
+ # Very IRCd specific! May be version specific.
+ $type = undef() if(defined($type) && !($type =~ /^\-(motd|botmotd|opermotd|garbage)$/i));
+
+ foreach my $server (get_online_servers()) {
+ ircsend(':'.$main::rsnick.' '.$tkn{REHASH}[$tkn].' '.$server.(defined($type) ? ' '.$type : '') );
+ }
+}
+
+sub unban_nick($$@) {
+# This is an Unreal-specific server-protocol HACK.
+# It is not expected to be portable to other ircds.
+# Similar concepts may exist in other ircd implementations
+ my ($src, $cn, @nicks) = @_;
+ my $srcId = ($src->{ID}?$src->{ID}:$src->{NICK});
+ my $i = 0; my @nicklist = ();
+ while(my $nick = shift @nicks) {
+ push @nicklist, $nick;
+ if(++$i >= 10) {
+ ircsend(($src ? ":$src " : '' ).$tkn{SVSMODE}[$tkn]." $cn -".'b'x($i).' '.join(' ', @nicklist));
+ $i = 0; @nicklist = ();
+ }
+ }
+
+ ircsend(($srcId ? ":$srcId " : '' ).$tkn{SVSMODE}[$tkn]." $cn -".'b'x($i).' '.join(' ', @nicklist));
+ # We don't loopback this, as we'll receive back the list
+ # of removed bans.
+}
+
+sub clear_bans($$) {
+# This is an Unreal-specific server-protocol HACK.
+# It is not expected to be portable to other ircds.
+# Similar concepts may exist in other ircd implementations
+ my ($src, $cn) = @_;
+
+ ircsend(($src ? ":$src " : '' ).$tkn{SVSMODE}[$tkn]." $cn -b");
+ # We don't loopback this, as we'll receive back the list
+ # of removed bans.
+}
+
+# HostServ OFF would want this.
+# resets the vhost to be the cloakhost.
+sub reset_cloakhost($$) {
+ my ($src, $target) = @_;
+ setumode($src, $target, '-x+x'); # only works in 3.2.6.
+}
+
+# removes the cloakhost, so that vhost matches realhost
+sub disable_cloakhost($$) {
+ my ($src, $target) = @_;
+ setumode($src, $target, '-x'); # only works in 3.2.6.
+}
+
+# enables the cloakhost, so that vhost becomes the cloakhost
+sub enable_cloakhost($$) {
+ my ($src, $target) = @_;
+ setumode($src, $target, '+x'); # only works in 3.2.6.
+}
+
+sub agent_doconn ($$$$$) {
+ my ($nick, $ident, $host, $modes, $gecos) = @_;
+ my $char = chr($count);
+ my $uuid = $main_conf{numeric} . "AAAAA" . $char; #FIXME - erry
+ ircsend(":" . $main_conf{numeric} . " UID" . " $uuid " . time . " $nick $host $host $ident 127.0.0.1 ". (time+5) . " $modes " . ":$gecos" );
+ setUuid($nick,$uuid);
+ setRevUuid($uuid, $nick);
+ $count++;
+}
+
+sub nolag($$@) {
+ my ($src, $sign, @targets) = @_;
+ $src = $main_conf{local} unless $src;
+ foreach my $target (@targets) {
+ ircsend(':'.$src .' '.$tkn{SVS2NOLAG}[$tkn].' '.$sign.' '.$target);
+ }
+}
+
+1;
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-=cut
+#=cut
-THIS CODE IS alpha only, and untested. Don't just trust it blindly.
+#THIS CODE IS alpha only, and untested. Don't just trust it blindly.
-=cut
+#=cut
package SrSv::Insp::UUID;
int2chars($SID_int, \@SID);
my @UID = (0,0,0,0,0,0);
int2chars($UID_int, \@UID);
- print join('', @SID,@UID),"\n";
+ return join('', @SID,@UID);
}
1;
-=cut
-my $int = decodeUUID('751AAAAAA');
-print "$int\n";
-print log($int)/log(2), "\n";
-encodeUUID($int);
-=cut
+##=cut
+#my $int = decodeUUID('583AAAAAE');
+#print "$int\n";
+#print log($int)/log(2), "\n";
+print encodeUUID(142036011587731460);
+#print decodeUUID('583AAAAAK');
+#print encodeUUID (1);
+#=cut
+++ /dev/null
-#!/usr/bin/perl
-
-
-# This file is part of SurrealServices.
-#
-# SurrealServices is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 2,
-# as published by the Free Software Foundation.
-#
-# SurrealServices is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with SurrealServices; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-=cut
-
-THIS CODE IS alpha only, and untested. Don't just trust it blindly.
-
-=cut
-
-use strict;
-use warnings;
-
-sub isAlpha($) {
- my ($char) = @_;
- return ($char =~ /[A-Z]/);
-}
-
-sub getBase36($) {
- my ($char) = @_;
- if(isAlpha($char)) {
- my $val = (ord($char) - ord('A')) + 10;
- #print "$val\n";
- return $val;
- } else {
- return int($char);
- }
-}
-
-sub decodeUUID($) {
- my ($UUID) = @_;
- my @chars = split(//, $UUID);
- my @sidC = @chars[0..2];
- my @uidC = @chars[3..8];
- my $sidN = int($sidC[0]) << (4 + (6 * 2));
- $sidN |= getBase36($sidC[1]) << (4 + (6 * 1));
- $sidN |= getBase36($sidC[2]) << (4 + (6 * 0));
- my $uidN = 0;
- foreach my $char (@uidC) {
- #print "$char\n";
- $uidN <<= 6;
- $uidN |= getBase36($char);
- }
- return (($sidN << 48) | $uidN);
-}
-
-my $int = decodeUUID('751AAAAAA');
-print "$int\n";
-print log($int)/log(2), "\n";
use Exporter 'import';
# parse_sjoin shouldn't get used anywhere else, as we never produce SJOINs
# parse_tkl however is used for loopbacks.
-BEGIN { our @EXPORT_OK = qw(parse_line parse_tkl) }
+BEGIN { our @EXPORT_OK = qw(parse_line parse_tkl parse_addline) }
# FIXME
BEGIN { *SJB64 = \&ircd::SJB64; *CLK = \&ircd::CLK; *NICKIP = \&ircd::NICKIP; }
use SrSv::Debug;
use SrSv::IRCd::State qw($ircline $remoteserv create_server get_server_children set_server_state get_server_state %IRCd_capabilities);
use SrSv::IRCd::Queue qw(queue_size);
-use SrSv::IRCd::IO qw( ircsend );
+use SrSv::IRCd::IO qw( ircsend ircsendimm);
+use SrSv::IRCd::Send qw (getRevUuid getUuid setRevUuid setUuid);
use SrSv::Unreal::Modes qw(%opmodes);
# Unreal uses its own modified base64 for everything except NICKIP
sub parse_line($) {
my ($in) = @_;
- return unless $in;
+ if (!$in) {
+ return;
+ }
my $cmd;
if($in =~ /^(?:@|:)(\S+) (\S+)/) {
elsif ($in =~ /^(\S+)/) {
$cmd = $1;
}
-
my $sub = $cmdhash{$cmd};
unless (defined($sub)) {
print "Bailing out from $ircline:$cmd for lack of cmdhash\n" if DEBUG();
return @out;
}
-
+#parse_fjoin($server, $channel, $ts, $modes, @nicks, @status)
+sub parse_fjoin ($$$$$$) {
+ my ($server, $channel, $ts, $modes, $nicksref, $statusref) = @_;
+ my @status = @$statusref;
+ my @nicks = @$nicksref;
+ my $i = 0;
+ my @users;
+ foreach my $nick (@nicks) {
+ my $op = 0;
+ my @ops = split ("",$status[$i]);
+ foreach my $prefix (@ops) {
+ $op |= $opmodes{$prefix};
+ }
+ push @users, { NICK => ircd::getRevUuid($nick), __OP => $op};
+ $i++;
+ }
+ return ($server, $channel, $ts, $modes, undef, \@users, undef, undef, undef); #those are got from FMODE...
+}
sub parse_sjoin($$$$) {
my ($server, $ts, $cn, $parms) = @_;
my (@users, @bans, @excepts, @invex, @blobs, $blobs, $chmodes, $chmodeparms);
return ($server, $cn, $ts, $chmodes, $chmodeparms, \@users, \@bans, \@excepts, \@invex);
}
-
+sub parse_addline ($) {
+ my ($line) = @_;
+ #return ($type, +1, $ident, $host, $setter, $expire, $time, $reason);
+ #>> 47 :583AAAAAA ADDLINE G test@testie inspircd.erry.omg 1308118489 0 :hi
+ my ($setter, undef, $type, $mask, $server, $time, $expiry, $reason) = split (/ /, $line, 7);
+ $reason =~ /:(.*)/;
+ $reason = $1;
+ $setter =~ /:(.*)/;
+ $setter = $1;
+ my @masks = split (/@/,$mask, 1);
+ my $ident = $masks[0];
+ my $host = $masks[1];
+ #return ($type, +1, $ident, $host, $setter, $expire, $time, $reason);
+ return ($type, +1, $ident, $host, $setter, $expiry, $time, $reason);
+}
sub parse_tkl ($) {
my ($in) = @_;
# This function is intended to accept ALL tkl types,
# ($event, $src, $dst, $args)
return ('PING', undef, undef, WF_NONE, $1);
}
-
+sub UID ($) {
+ #:583 UID 583AAAAAJ 1307703236 erry__ localhost localhost errietta 127.0.0.1 1307703241 + :errietta
+ $_[0] =~ /^(:\S+) UID (\S+) (\d+) (\S+) (\S+) (\S+) (\S+) (\S+) (\d+) (\S+) :(.*)$/;
+ my ($server, $uid, $ts, $nick, $host, $vhost, $ident, $IP, $stamp, $modes, $gecos) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);
+ ircd::setRevUuid ($uid, $nick);
+ ircd::setUuid ($nick, $uid);
+ return ('NICKCONN', undef, undef, WF_NICK, $nick, 0, $ts, $ident, $host, $server, $stamp, $modes, $vhost, $gecos,
+ join('.', unpack('C4', MIME::Base64::decode($IP))));
+}
sub EOS($) {
my $event;
- $_[0] =~ /^(@|:)(\S+) (?:EOS|ES)/; # Sometimes there's extra crap on the end?
- my $server;
- if ($1 eq '@') {
- $server = $servernum[b64toi($2)];
+ print "EOS\n";
+ if ($_[1] != "ENDBURST") {
+ $_[0] =~ /^(@|:)(\S+) (?:EOS|ES)/; # Sometimes there's extra crap on the end?
+ my $server;
+ if ($1 eq '@') {
+ $server = $servernum[b64toi($2)];
+ }
+ else {
+ $server = $2;
+ }
+ set_server_state($server, 1);
+ return undef() unless get_server_state($remoteserv);
+ if($server eq $remoteserv) { $event = 'SEOS' } else { $event = 'EOS' }
+ print "Ok. we had EOS\n";
+ return ($event, undef, undef, WF_ALL, $server);
}
else {
- $server = $2;
+ print "This be it! Got endbrust!\n";
+ return ("ENDBURST", undef, undef, WF_ALL, $1);
}
- set_server_state($server, 1);
- return undef() unless get_server_state($remoteserv);
- if($server eq $remoteserv) { $event = 'SEOS' } else { $event = 'EOS' }
- print "Ok. we had EOS\n";
- return ($event, undef, undef, WF_ALL, $server);
}
sub SERVER($) {
$_[0] =~ /^:(\S+) (?:C|JOIN) (\S+)$/;
return ('JOIN', undef, 1, WF_CHAN, $1, $2);
}
-
+#>> 13 :97K FJOIN #erry 1307879417 +nt :o,97KAAAAAA ,97KAAAAAB
+sub FJOIN ($) {
+ $_[0] =~ m"^(:\S+) FJOIN (\S+) (\d+) (\S+) (.*)$";
+ my ($server, $channel, $ts, $modes, $userstring) = ($1, $2, $3, $4, $5);
+ my @users = split (" ", $userstring);
+ my (@nicks, @status);
+ foreach my $user (@users) {
+ my @params = split (",",$user);
+ push (@status, $params[0]);
+ push (@nicks, $params[1]);
+ }
+ return ('SJOIN', undef, undef, WF_CHAN, parse_fjoin($server, $channel, $ts, $modes, \@nicks, \@status));
+}
sub SJOIN($) {
if ($_[0] =~ /^(?:\~|SJOIN) (\S+) (\S+) (.*)$/) {
my ($ts, $cn, $payload) = ($1, $2, $3);
else {
$name = $2;
}
+ my $properName = getRevUuid ($name);
+ if ($properName) { $name = $properName; }
return ('MODE', undef, 1, WF_ALL, $name, $3, $4, $5);
}
elsif($_[0] =~ /^:(\S+) (?:G|MODE) (\S+) :(\S+)$/) {
else {
$name = $2;
}
- $event = 'PRIVMSG'; @args = ($name, $3, $4);
+ my $dest = $3;
+ my $reverse_uuid = ircd::getRevUuid($dest);
+ my $user_revuuid = ircd::getRevUuid($name);
+ unless ($reverse_uuid eq "") {
+ $dest = $reverse_uuid;
+ }
+ unless ($user_revuuid eq "") {
+ $name = $user_revuuid;
+ }
+ $event = 'PRIVMSG'; @args = ($name, $dest, $4);
}
elsif($_[0] =~ /^(@|:)(\S+) (?:B|NOTICE) (\S+) :(.*)$/) {
my $name;
sub NICK($) {
my ($event, @args);
+ #:97KAAAAAA NICK erry_ 1307878528
if($_[0] =~ /^:(\S+) (?:NICK|\&) (\S+) :?(\S+)$/) {
- return ('NICKCHANGE', undef, undef, WF_NICK, $1, $2, $3);
+ my $oldnick = ircd::getRevUuid ($1);
+ ircd::setRevUuid ($1, $2);
+ ircd::setUuid ($2, $1);
+ return ('NICKCHANGE', undef, undef, WF_NICK, $oldnick, $2, $3);
}
elsif(CLK && NICKIP && $_[0] =~ /^(?:NICK|\&) (\S+) (\d+) (\S+) (\S+) (\S+) (\S+) (\d+) (\S+) (\S+) (\S+) (\S+) :(.*)$/) {
#NICK Guest57385 1 !14b7t0 northman tabriel.tabris.net 38 0 +iowghaAxNWzt netadmin.SCnet.ops SCnet-3B0714C4.tabris.net CgECgw== :Sponsored By Skuld
sub QUIT($) {
$_[0] =~ /^:(\S+) (?:QUIT|\,) :(.*)$/;
- return ('QUIT', 0, undef, WF_NICK, $1, $2);
+ my $id = $1;
+ my $nick = ircd::getRevUuid($id);
+ if (!$nick) { $nick = $id; }
+ return ('QUIT', 0, undef, WF_NICK, $nick, $2);
}
sub KILL($) {
EOS => \&EOS,
ES => \&EOS,
-
+ ENDBURST => \&EOS,
SERVER => \&SERVER,
"\'" => \&SERVER,
SJOIN => \&SJOIN,
'~' => \&SJOIN,
-
+ FJOIN => \&FJOIN,
MODE => \&MODE,
G => \&MODE,
STATS => \&STATS,
'2' => \&STATS,
+ UID => \&UID,
);
}
package ircd;
use strict;
-
use IO::Socket::INET;
use Event;
use Carp;
use SrSv::Debug;
use SrSv::Log;
-
+use Exporter 'import';
+our @EXPORT = qw (agent_doconn getRevUuid getUuid setRevUuid setUuid);
# FIXME
use constant {
MAXBUFLEN => 510,
use SrSv::Unreal::Modes qw(@opmodes %opmodes $scm $ocm $acm);
use SrSv::Unreal::Tokens qw( :tokens );
-use SrSv::IRCd::Parse qw(parse_tkl);
+use SrSv::IRCd::Parse qw(parse_tkl parse_addline);
use SrSv::Unreal::Base64 qw(itob64 b64toi);
use SrSv::Text::Format qw( wordwrap );
use SrSv::Agent;
-use SrSv::Process::InParent qw(update_userkill);
+use SrSv::Process::InParent qw(update_userkill getRevUuid getUuid setRevUuid SetUUid);
our %defer_mode;
our %preconnect_defer_mode;
our @userkill;
our $unreal_protocol_version;
-
+our $count = 65;
+our %uuids; #NickServ -> AAAAAA
+our %reverse_uuids; #AAAAA -> NickServ
addhandler('SEOS', undef(), undef(), 'ircd::eos', 1);
addhandler('NETINFO', undef(), undef(), 'ircd::netinfo', 1);
addhandler('VERSION', undef(), undef(), 'ircd::version', 1);
addhandler('SERVER', undef(), undef(), 'ircd::handle_server', 1);
-
+addhandler('ENDBURST',undef(),undef(),'ircd::endburst',1);
+sub getRevUuid($) {
+ my $id = $_[0];
+ my $nick = $reverse_uuids{$id};
+ $uuids{lc $nick} = $id;
+ return $nick;
+}
+sub getUuid($) {
+ my $nick = lc $_[0];
+ print "Get uuid $nick " . $uuids{$nick} . "\n";
+ return $uuids{$nick};
+}
+sub setRevUuid ($$) {
+ my ($id, $nick) = @_;
+ $reverse_uuids{$id} = lc $nick;
+}
+sub setUuid ($$) {
+ my ($nick, $id) = @_;
+ $uuids{lc $nick} = $id;
+ print "Set uuid $nick $id\n";
+}
sub serv_connect() {
my $remote = main_conf_remote;
my $port = main_conf_port;
$unreal_protocol_version = $protocol_version if defined $protocol_version;
}
-# Handler functions
+
+# Handler functions
sub pong($$$) {
my ($src, $cookie, $dst) = @_;
# This will only make sense if you remember that
ircsendimm("@{[TOK_PONG]} :$src");
}
}
-
+sub endburst {
+ print "GOT ENDBURST\n\n";
+ ircd_flush_queue();
+ ircsendimm ("ENDBURST");
+ $ircd_ready = 1; #!
+}
sub eos {
- print "GOT EOS\n\n" if DEBUG;
+ print "GOT EOS\n\n";
#foreach my $k (keys %servers) {
# print "Server: $k ircline: ",$servers{$k}[0], " state: ", $servers{$k}[1], "\n";
my $buflen = length($src) + length($dst) + 5 + length(TOK_PRIVMSG) + (MASKLEN - (NICKLEN + 1));
push @bufs, wordwrap($buf, (MAXBUFLEN - $buflen));
}
-
+ my $properSrc = getUuid($src);
+ if ($properSrc) { $src = $properSrc; }
# submit a list of messages as a single packet to the server
ircsend(":$src @{[TOK_PRIVMSG]} $dst :".join("\r\n".":$src @{[TOK_PRIVMSG]} $dst :", @bufs));
return \@bufs;
my $buflen = length($src) + length($dst) + 5 + length(TOK_NOTICE) + (MASKLEN - (NICKLEN + 1));
push @bufs, wordwrap($buf, (MAXBUFLEN - $buflen));
}
-
+ my $propersrc = getUuid($src);
+ if ($propersrc) { $src = $propersrc; }
+ my $properdest = getUuid($dst);
+ if ($properdest) { $dst = $properdest; }
# submit a list of notices as a single packet to the server
ircsend(":$src @{[TOK_NOTICE]} $dst :".join("\r\n".":$src @{[TOK_NOTICE]} $dst :", @bufs));
callfuncs('LOOP_NOTICE', 0, 1, [$src, $dst, \@bufs]);
sub setmode($$$;$) {
my ($src, $dst, $modes, $parms) = @_;
$src = main_conf_local unless initial_synced();
-
+ my $properSrc = getUuid ($src);
+ if ($properSrc) { $src = $properSrc; }
callfuncs('MODE', undef, 1, [$src, $dst, $modes, $parms]);
print "$ircline -- setmode($src, $dst, $modes, $parms)\n" if DEBUG;
my ($setter, $ident, $host, $expiry, $reason) = @_;
$setter=main_conf_local unless defined($setter);
$ident = '*' unless defined($ident);
-
-
- #foreach my $ex (@except) { return 1 if $mask =~ /\Q$ex\E/i; }
-
- #my $line = "GLINE $mask $time :$reason";
- # you need to use TKL for this. GLINE is a user command
- # TKL is a server command.
- # format is
- # TKL +/- type ident host setter expiretime settime :reason
-#:nascent.surrealchat.net TKL + G * *.testing.only tabris!northman@netadmin.SCnet.ops 1089168439 1089168434 :This is just a test.
- my $line = "TKL + G $ident $host $setter ".($expiry + time()).' '.time()." :$reason";
-
+ # you need to use ADDLINE for this. GLINE is a user command
+ # format is
+ #>> 47 :583AAAAAA ADDLINE G test@testie inspircd.erry.omg 1308118489 0 :hi
+ my $line = ":$setter ADDLINE G $ident\@$host " . $main_conf{local} . " ". time() . " " . ($expiry + time())." :$reason";
ircsend($line);
- callfuncs('TKL', undef, undef, [parse_tkl($line)]);
+ #return ($type, +1, $ident, $host, $setter, $expire, $time, $reason);
+ callfuncs('TKL', undef, undef, [parse_addline($line)]);
}
sub unkline ($$$) {
# successful nick change.
# warning, if misused, this can KILL the user
# with a collision
-
-# ircsend(":$src @{[TOK_SVSNICK]} $oldnick $newnick ".time);
- ircsend("@{[TOK_SVSNICK]} $oldnick $newnick :".time);
+ ircsend(":$src @{[TOK_SVSNICK]} $oldnick $newnick ".time);
+# ircsend("@{[TOK_SVSNICK]} $oldnick $newnick :".time);
}
sub svsnoop($$$) {
}
sub svshold($$$) {
-# Not all IRCd will support this command, as such the calling module must check the IRCd capabilities first.
my ($nickmask, $expiry, $reason) = @_;
# TKL version - Allows timed qlines.
# TKL + Q * test services.SC.net 0 1092179497 :test
my $line = 'TKL + Q H '.$nickmask.' '.main_conf_local.' '.($expiry ? $expiry+time() : 0).' '.time().' :'.$reason;
ircsend($line);
-
- # at startup we send these too early,
- # before the handlers are initialized
- # so they may be lost.
- callfuncs('TKL', undef, undef, [parse_tkl($line)]);
+ callfuncs('TKL', undef, undef, [parse_addline($line)]);
}
sub svsunhold($) {
set_server_juped($server);
}
+sub agent_dojoin($$) {
+ my ($agent, $chan) = @_;
+ my $uuid = getUuid($agent);
+ if ($uuid) { $agent = $uuid; }
+ ircsend(":" . $agent . " JOIN " . $chan);
+}
+sub agent_dopart ($$$) {
+ my ($agent, $chan, $reason) = @_;
+ my $uuid = getUuid($agent);
+ if ($uuid) { $agent = $uuid; }
+ ircsend(":$agent $tkn{PART}[$tkn] $chan :$reason");
+}
sub rehash_all_servers(;$) {
my ($type) = @_;
setumode($src, $target, '+x'); # only works in 3.2.6.
}
+sub agent_doconn ($$$$$) {
+ my ($nick, $ident, $host, $modes, $gecos) = @_;
+ my $char = chr($count);
+ my $uuid = $main_conf{numeric} . "AAAAA" . $char; #FIXME - erry
+ ircsend(":" . $main_conf{numeric} . " UID" . " $uuid " . time . " $nick $host $host $ident 127.0.0.1 ". (time+5) . " $modes " . ":$gecos" );
+ setUuid($nick,$uuid);
+ setRevUuid($uuid, $nick);
+ $count++;
+}
+
sub nolag($$@) {
my ($src, $sign, @targets) = @_;
$src = main_conf_local unless $src;
SENDSNO => ['SENDSNO', 'Ss'],
EOS => ['EOS', 'ES'],
+ ENDBURST => ['ENDBURST'],
UMODE2 => ['UMODE2', "\|"],
REHASH => ['REHASH', 'O'],
use SrSv::Agent;
my $csnick = 'ConnectServ';
-
agent_connect($csnick, 'services', undef, '+pqzBHS', 'Connection Monitor');
+my $csUser = { NICK => $csnick, ID => ircd::getUuid($csnick); }
agent_join($csnick, main_conf_diag);
-ircd::setmode($csnick, main_conf_diag, '+o', $csnick);
+ircd::setmode($csUser, main_conf_diag, '+o', $csUser);
addhandler('NICKCONN', undef, undef, 'connectserv::ev_nickconn', 1);
sub ev_nickconn {
};
our $rsnick = 'ServServ';
-
+our $rsUser = { NICK => $rsnick, ID => ircd::getUuid($rsnick) };
addhandler('STATS', undef, undef, 'core::stats');
sub stats($$) {
my ($src, $token) = @_;
agent_connect($rsnick, 'service', undef, '+ABHSNaopqz', 'Services Control Agent');
agent_join($rsnick, main_conf_diag);
-ircd::setmode($rsnick, main_conf_diag, '+o', $rsnick);
+ircd::setmode($rsUser, main_conf_diag, '+o', $rsUser );
addhandler('SEOS', undef, undef, 'core::ev_connect', 1);
-
+addhandler('ENDBURST', undef, undef, 'core::ev_connect', 1);
sub ev_connect {
add_timer('perlserv__pingtimer', 60, __PACKAGE__,
"core::pingtimer");
addhandler('PRIVMSG', undef, 'servserv', 'core::dispatch', 1);
sub dispatch {
+ print "DISPATCH CALLED\n";
my ($src, $dst, $msg) = @_;
- my $user = { NICK => $src, AGENT => $rsnick };
+ my $user = { NICK => $src, AGENT => $rsnick, ID => getUuid($src) };
if(!adminserv::is_ircop($user)) {
notice($user, 'Access Denied');
ircd::globops($rsnick, "\002$src\002 failed access to $rsnick $msg");
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package services;
use strict;
-
+use Data::Dumper;
use SrSv::Conf::services;
use SrSv::MySQL qw($dbh);
our $qlreason = 'Reserved for Services';
foreach my $a (@agents) {
+ print "AGENT " . Dumper($a);
agent_connect($a->[0], 'services', undef, $a->[1], $a->[2]);
ircd::sqline($a->[0], $qlreason);
agent_join($a->[0], main_conf_diag);
- ircd::setmode($main::rsnick, main_conf_diag, '+o', $a->[0]);
+ my $rsUser = { NICK => $main::rsnick, ID => ircd::getUuid($main::rsnick) };
+ my $agent = { NICK => $a->[0], ID => ircd::getUuid ($a->[0]) };
+ ircd::setmode($agent, main_conf_diag, '+o', $agent);
}
-addhandler('SEOS', undef, undef, 'services::ev_connect');
+addhandler('ENDBURST', undef, undef, 'services::ev_connect');
sub ev_connect {
botserv::eos();
nickserv::cleanup_users();
operserv::expire();
}
-addhandler('EOS', undef, undef, 'services::eos');
+addhandler('ENDBURST', undef, undef, 'services::eos');
sub eos {
chanserv::eos($_[0]);
}
addhandler('CHGIDENT', undef, undef, 'nickserv::chgident');
addhandler('USERIP', undef, undef, 'nickserv::userip');
addhandler('SQUIT', undef, undef, 'nickserv::squit') if ircd::NOQUIT();
-
-addhandler('PRIVMSG', undef, 'nickserv', 'nickserv::dispatch');
+addhandler("OPERUP", undef, undef, 'nickserv::handle_oper');
+addhandler('PRIVMSG', undef, undef, 'nickserv::dispatch');
addhandler('PRIVMSG', undef, lc services_conf_nickserv, 'nickserv::dispatch') if services_conf_nickserv;
addhandler('BACK', undef, undef, 'nickserv::notify_auths');
addhandler('MODE', undef, qr/^#/, 'chanserv::chan_mode');
addhandler('TOPIC', undef, undef, 'chanserv::chan_topic');
-addhandler('PRIVMSG', undef, 'chanserv', 'chanserv::dispatch');
+addhandler('PRIVMSG', undef, undef, 'chanserv::dispatch');
addhandler('PRIVMSG', undef, lc services_conf_chanserv, 'chanserv::dispatch') if services_conf_chanserv;
# OperServ
-addhandler('PRIVMSG', undef, 'operserv', 'operserv::dispatch');
+addhandler('PRIVMSG', undef, undef, 'operserv::dispatch');
addhandler('PRIVMSG', undef, lc services_conf_operserv, 'operserv::dispatch') if services_conf_operserv;
add_timer('flood_expire', 10, __PACKAGE__, 'services::flood_expire');
}
# MemoServ
-addhandler('PRIVMSG', undef, 'memoserv', 'memoserv::dispatch');
+addhandler('PRIVMSG', undef, undef, 'memoserv::dispatch');
addhandler('PRIVMSG', undef, lc services_conf_memoserv, 'memoserv::dispatch') if services_conf_memoserv;
addhandler('BACK', undef, undef, 'memoserv::notify');
addhandler('NOTICE', undef, qr/^#/, 'botserv::chan_msg');
# AdminServ
-addhandler('PRIVMSG', undef, 'adminserv', 'adminserv::dispatch');
+addhandler('PRIVMSG', undef, undef, 'adminserv::dispatch');
addhandler('PRIVMSG', undef, lc services_conf_adminserv, 'adminserv::dispatch') if services_conf_adminserv;
add_timer('', 30, __PACKAGE__, 'services::maint');
add_timer('', 60, __PACKAGE__, 'nickserv::expire_silence_timed');
# HostServ
-addhandler('PRIVMSG', undef, 'hostserv', 'hostserv::dispatch');
+addhandler('PRIVMSG', undef, undef, 'hostserv::dispatch');
addhandler('PRIVMSG', undef, lc services_conf_hostserv, 'hostserv::dispatch') if services_conf_hostserv;
# $nick should be a registered root nick, if applicable
$flags{$flags[$i]} = 1 << $i;
}
$allflags = (1 << scalar(@flags)) - 1;
+
+our $asnick_default = 'AdminServ';
+our $asnick = $asnick_default;
+our $asuser = { NICK => $asnick, ID => "123AAAAAG" };
+
our @levels = ('Normal User', 'HelpOp', 'Operator', 'Administrator', 'Root');
# BE CAREFUL CHANGING THESE
our @defflags = (
);
}
-our $asnick_default = 'AdminServ';
-our $asnick = $asnick_default;
our (
### ADMINSERV COMMANDS ###
sub dispatch($$$) {
- my ($src, $dst, $msg) = @_;
+ my ($user, $dstUser, $msg) = @_;
$msg =~ s/^\s+//;
my @args = split(/\s+/, $msg);
my $cmd = shift @args;
-
- my $user = { NICK => $src, AGENT => $dst };
-
- services::ulog($asnick, LOG_INFO(), "cmd: [$msg]", $user);
+ $user -> {AGENT} = $dstUser;
+ my $src = $user->{NICK};
+ return unless (lc $dstUser->{NICK} eq lc $asnick);
+ services::ulog($asuser, LOG_INFO(), "cmd: [$msg]", $user);
unless(is_svsop($user) or is_ircop($user)) {
notice($user, $err_deny);
- ircd::globops($asnick, "\002$src\002 failed access to $asnick $msg");
+ ircd::globops($asuser, "\002$src\002 failed access to $asnick $msg");
return;
}
$set_svs_level->execute($level, $oper, $root);
notice($user, "\002$nick\002 is now a \002Services $levels[$level]\002.");
- wlog($asnick, LOG_INFO(), "$src added $root as a Services $levels[$level].");
+ wlog($asuser, LOG_INFO(), "$src added $root as a Services $levels[$level].");
}
sub as_svs_del($$) {
$delete_svsop->execute($root);
notice($user, "\002$nick\002 has been stripped of services rank.");
- wlog($asnick, LOG_INFO(), "$src stripped $root of services rank.")
+ wlog($asuser, LOG_INFO(), "$src stripped $root of services rank.")
}
sub as_svs_list($$) {
my $nflag = $flags{$flag};
my ($level, $nick) = get_best_svs_level($user);
-
+ print ("LEVELS $defflags[$level] $nflag" . "\n");
if($defflags[$level] & $nflag) {
- return $nick if (($nflag == $flags{'HELP'}) or is_ircop($user));
+ return $nick if (($nflag == $flags{'HELP'}) or is_ircop($user));
}
return undef;
return $nick if(defined($level) and !defined($rlev));
if($level >= $rlev) {
- return $nick if (($rlev == S_HELP) or is_ircop($user));
+ return $nick ; #if (($rlev == S_HELP) or is_ircop($user)) FIXME - erry
+ #Problem is inspircd has a gay way of identifying opers, instead of umode +o it sends OPERTYPE crap.
}
return undef;
$user->{SVSOP_LEVEL} = $level; $user->{SVSOP_NICK} = $nick;
if(wantarray) {
+ print "LEVEL $level\n";
return ($level, $nick);
} else {
return $level;
use SrSv::Agent;
use SrSv::Process::Worker 'ima_worker'; #FIXME
-
+use SrSv::Insp::UUID;
use SrSv::Text::Format qw(columnar);
use SrSv::Errors;
+use Data::Dumper;
use SrSv::Conf2Consts qw( main services );
our $bsnick_default = 'BotServ';
our $bsnick = $bsnick_default;
our $botchmode;
+our $bsuser = { NICK => $bsnick, ID => "123AAAAAF" };
if(!ircd::PREFIXAQ_DISABLE()) {
$botchmode = '+q';
} else {
};
sub dispatch($$$) {
- my ($src, $dst, $msg) = @_;
-
- if(lc $dst eq lc $bsnick or lc $dst eq lc $bsnick_default ) {
- bs_dispatch($src, $dst, $msg);
+ my ($user, $dstUser, $msg) = @_;
+ $user -> {AGENT} = $dstUser;
+ my $src = $user->{NICK};
+ my $dst = $dstUser->{NICK};
+ if(lc $dstUser->{NICK} eq lc $bsnick or lc $dstUser->{NICK} eq lc $bsnick_default ) {
+ bs_dispatch($user, $dstUser, $msg);
}
elsif($dst =~ /^#/) {
if($msg =~ /^\!/) {
### BOTSERV COMMANDS ###
sub bs_dispatch($$$) {
- my ($src, $dst, $msg) = @_;
+ my ($user, $dst, $msg) = @_;
$msg =~ s/^\s+//;
my @args = split(/\s+/, $msg);
my $cmd = shift @args;
- my $user = { NICK => $src, AGENT => $dst };
+ $user->{AGENT} = $dst;
+ my $src = $user->{NICK};
return if flood_check($user);
agent_part($oldbot, $cn, "Unassigned by \002$src\002.");
}
-
-
if($bot) {
$assign_bot->execute($bot, $cn);
- bot_join($chan, $bot);
+ my $botUser = { NICK=>$bot, ID=>ircd::getUuid($bot) };
+ bot_join($chan, $botUser);
notice($user, "\002$bot\002 now assigned to \002$cn\002.");
} else {
$unassign_bot->execute($cn);
ircd::sqline($botnick, $services::qlreason);
agent_connect($botnick, $botident, $bothost, '+pqBSrz', $botgecos);
agent_join($botnick, main_conf_diag);
- ircd::setmode($main::rsnick, main_conf_diag, '+h', $botnick);
-
+ my $bot = { NICK => $botnick};
+ get_user_id ($bot);
+ my $rsuser = { NICK => $main::rsnick };
+ get_user_id ($rsuser);
+ $rsuser->{ID} = encodeUUID($rsuser->{ID});
+ ircd::setmode($rsuser, main_conf_diag, '+h', $bot);
notice($user, "Bot $botnick connected.");
}
ircd::sqline($botnick, $services::qlreason);
agent_connect($botnick, $botident, $bothost, '+pqBSrz', $botgecos);
agent_join($botnick, main_conf_diag);
- ircd::setmode($main::rsnick, main_conf_diag, '+h', $botnick);
+ my $rsnick = $main::rsnick;
+ my $rsuser = { NICK => $main::rsnick };
+ get_user_id ($rsuser);
+ $rsuser->{ID} = encodeUUID($rsuser->{ID});
+ my $bot = { NICK => $botnick };
+ get_user_id ($bot);
+ ircd::setmode($rsuser, main_conf_diag, '+h', $bot);
notice($user, "Bot $botnick connected.");
$get_bots_chans->execute($oldnick);
while(my ($cn) = $get_bots_chans->fetchrow_array()) {
my $chan = { CHAN => $cn };
- bot_join($chan, $botnick)
+ my $botUser = { NICK=>$botnick, ID=>ircd::getUuid($botnick) };
+ bot_join($chan, $botUser)
if chanserv::get_user_count($chan) or cr_chk_flag($chan, CRF_BOTSTAY(), 1);
}
$get_bots_chans->finish();
### CHANNEL COMMANDS ###
sub chan_dispatch($$$) {
- my ($src, $cn, $msg) = @_;
-
+ my ($user, $cn, $msg) = @_;
+ my $src = $user->{NICK};
my @args = split(/\s+/, $msg);
my $cmd = lc(shift @args);
$cmd =~ s/^\!//;
my $chan = { CHAN => $cn };
- my $user = { NICK => $src, AGENT => agent($chan) };
my %cmdhash = (
'voice' => \&give_ops,
sub give_ops {
my ($user, $chan, $cmd, undef, @args) = @_;
+
chanserv::cs_setmodes($user, $cmd, $chan, @args);
}
sub up {
### BOT COMMANDS ###
sub bot_dispatch($$$) {
- my ($src, $bot, $msg) = @_;
-
+ my ($user, $bot, $msg) = @_;
my ($cmd, $cn, $botmsg) = split(/ /, $msg, 3);
-
- my $user = { NICK => $src, AGENT => $bot };
+ my $src = $user->{NICK};
my $chan = { CHAN => $cn };
-
return if flood_check($user);
-
if ($cmd =~ /^join$/i) {
- if (adminserv::can_do($user, 'BOT')) {
- agent_join($bot, $cn);
- } else {
- notice($user, $err_deny);
- }
+ if (adminserv::can_do($user, 'BOT')) {
+ agent_join($bot, $cn);
+ } else {
+ notice($user, $err_deny);
+ }
}
elsif ($cmd =~ /^part$/i) {
- if (adminserv::can_do($user, 'BOT')) {
- agent_part($bot, $cn, "$src requested part");
- } else {
- notice($user, $err_deny);
- }
+ if (adminserv::can_do($user, 'BOT')) {
+ agent_part($bot, $cn, "$src requested part");
+ } else {
+ notice($user, $err_deny);
+ }
}
elsif ($cmd =~ /^say$/i) {
bot_say($user, $chan, $botmsg);
while(my ($nick, $ident, $vhost, $gecos, $flags) = $get_all_bots->fetchrow_array) {
agent_connect($nick, $ident, $vhost, '+pqBSrz'.(($flags & F_DEAF())?'d':''), $gecos);
ircd::sqline($nick, $services::qlreason);
+ my $bot = { NICK => $nick };
+ get_user_id ($bot);
agent_join($nick, main_conf_diag);
- ircd::setmode($main::rsnick, main_conf_diag, '+h', $nick);
+ my $rsuser = { NICK => $main::rsnick };
+ get_user_id ($rsuser);
+ $rsuser->{ID} = encodeUUID($rsuser->{ID});
+ ircd::setmode($rsuser, main_conf_diag, '+h', $bot);
}
}
while(my ($cn, $nick) = $get_botchans->fetchrow_array) {
my $chan = { CHAN => $cn };
if(chanserv::get_user_count($chan)) {
- bot_join($chan, $nick);
+ my $botUser = { NICK=>$nick, ID=>ircd::getUuid($nick) };
+ bot_join($chan, $botUser);
}
elsif(cr_chk_flag($chan, CRF_BOTSTAY(), 1)) {
+ my $botUser = { NICK=>$nick, ID=>ircd::getUuid($nick) };
bot_join($chan, $nick);
my $modelock = chanserv::get_modelock($chan);
ircd::setmode(main_conf_local, $cn, $modelock) if $modelock;
}
sub bot_join($;$) {
- my ($chan, $nick) = @_;
-
+ my ($chan, $bot) = @_;
my $cn = $chan->{CHAN};
-
- $nick = agent($chan) unless $nick;
-
+ $bot = agent($chan) unless $bot;
+ my $nick = $bot->{NICK};
unless(is_agent_in_chan($nick, $cn)) {
- agent_join($nick, $cn);
- ircd::setmode($nick, $cn, $botchmode, $nick.(ircd::PREFIXAQ_DISABLE() ? ' '.$nick : '') );
+ agent_join($bot, $cn);
+ get_user_id ($bot);
+ my $bot2 = { NICK => $nick, ID => encodeUUID($bot->{ID}) };
+ print "!!!!!!!! BOT $nick " . $bot->{ID} . "\n";
+ ircd::setmode($bot2, $cn, $botchmode, $bot );
}
}
my $cn = $chan->{CHAN};
my $bot = get_chan_bot($chan);
$nick = agent($chan) unless $nick;
-
return if (lc $chanserv::enforcers{lc $cn} eq lc $nick);
if(is_agent_in_chan($nick, $cn)) {
use SrSv::MySQL::Glob;
use SrSv::Util qw( makeSeqList );
-
+use Data::Dumper;
use constant {
UOP => 1,
VOP => 2,
our $csnick_default = 'ChanServ';
our $csnick = $csnick_default;
+our $csUser = { NICK => $csnick, ID => "123AAAAAC" };
our ($cur_lock, $cnt_lock);
$find_bans, $list_bans, $wipe_bans,
$find_bans_chan_user, $delete_bans_chan_user,
- $add_auth, $list_auth_chan, $get_auth_nick, $get_auth_num, $find_auth,
+ $add_auth, $list_auth_chan, $check_auth_chan, $get_auth_nick, $get_auth_num, $find_auth,
$set_bantype, $get_bantype,
SELECT nickalias.nrid, (".NTF_AUTH()."), 1, ?, ? FROM nickalias WHERE nickalias.alias=?");
$list_auth_chan = $dbh->prepare("SELECT nickreg.nick, nicktext.data FROM nickreg, nicktext
WHERE nickreg.id=nicktext.nrid AND nicktext.type=(".NTF_AUTH().") AND nicktext.chan=?");
+ $check_auth_chan = $dbh->prepare("SELECT nickreg.nick, nicktext.data FROM nickreg, nicktext
+ WHERE nickreg.id=nicktext.nrid AND nicktext.type=(".nickserv::NTF_AUTH().") AND nicktext.chan=? AND nickreg.nick=?");
$get_auth_nick = $dbh->prepare("SELECT nicktext.data FROM nickreg, nickalias, nicktext
WHERE nickreg.id=nicktext.nrid AND nickreg.id=nickalias.nrid AND nicktext.type=(".NTF_AUTH().")
AND nicktext.chan=? AND nickalias.alias=?");
);
sub dispatch($$$) {
- my ($src, $dst, $msg) = @_;
-
+ my ($user, $dstUser, $msg) = @_;
+ my $src = $user->{NICK};
$msg =~ s/^\s+//;
my @args = split(/\s+/, $msg);
my $cmd = shift @args;
-
- my $user = { NICK => $src, AGENT => $dst };
-
+ $user->{AGENT} = $dstUser;
+ get_user_id ($user);
return if flood_check($user);
-
+ return unless (lc $dstUser->{NICK} eq lc $csnick);
if(!defined($high_priority_cmds{lc $cmd}) &&
!adminserv::is_svsop($user) &&
$SrSv::IRCd::State::queue_depth > main_conf_highqueue)
$get_all_acc->finish();
unless($n) {
- push @reply, "\002$tnick\002 has no access to \002$cn\002.";
+ $check_auth_chan -> execute ($cn, $tnick);
+ if (my ($nick, $data) = $check_auth_chan->fetchrow_array()) {
+ my ($adder, $old, $level, $time) = split(/:/, $data);
+ push @reply, "\002$tnick\002 is awaiting authorization to be added to the $cn \002$levels[$level]\002 list.\n";
+ }
+ else {
+ push @reply, "\002$tnick\002 has no access to \002$cn\002.";
+ }
}
}
notice($user, @reply);
sub cs_setmodes($$$@) {
my ($user, $cmd, $chan, @args) = @_;
no warnings 'void';
- my $agent = $user->{AGENT} or $csnick;
+ my $agent = $user->{AGENT} or $csUser;
my $src = get_user_nick($user);
my $cn = $chan->{CHAN};
my $self;
my @targets = split(/\,/, $target);
foreach $target (@targets) {
- my $tuser = { NICK => $target };
+ my $tuser = { NICK => $target, UID => ircd::getUuid ($target) };
my $targetlevel = get_best_acc($tuser, $chan);
if(lc $target eq lc agent($chan) or adminserv::is_service($tuser)) {
if($ban) {
kickban($chan, $tuser, undef, $reason, 1);
} else {
- ircd::kick(agent($chan), $cn, $target, $reason) unless adminserv::is_service($user);
+ ircd::kick(agent($chan), $cn, $tuser, $reason) unless adminserv::is_service($user);
}
}
ircd::flushmodes() if($ban);
$set_close->execute($cn, $reason, $oper, $type);
cr_set_flag($chan, (CRF_FREEZE | CRF_CLOSE | CRF_DRONE), 0); #unset flags
cr_set_flag($chan, CRF_HOLD, 1); #set flags
-
+ cr_set_flag($chan, $type, 1); #set flags
my $src = get_user_nick($user);
my $time = gmtime2(time);
my $cmsg = "is closed [$src $time]: $reason";
enforcer_join($chan) if (get_user_count($chan) <= 1);
ircd::setmode($agent, $cn, '+b', $mask);
ircd::flushmodes() unless $noflush;
- ircd::kick($agent, $cn, $nick, $reason);
+ ircd::kick($agent, $cn, $user, $reason);
return 1;
}
foreach my $user (@$users) {
next if adminserv::is_ircop($user) or adminserv::is_svsop($user, adminserv::S_HELP());
- ircd::kick($agent, $cn, get_user_nick($user), $reason);
+ ircd::kick($agent, $cn, $user, $reason);
}
}
$get_chan_users->execute($cn);
while(my ($nick, $uid) = $get_chan_users->fetchrow_array) {
my $user = { NICK => $nick, ID => $uid };
- ircd::kick($agent, $cn, $nick, $reason)
+ ircd::kick($agent, $cn, $user, $reason)
unless adminserv::is_ircop($user) or adminserv::is_svsop($user, adminserv::S_HELP());
$i++;
}
$get_chan_users_mask->execute($cn, $nick, $ident, $host, $host, $host);
while(my ($nick, $uid) = $get_chan_users_mask->fetchrow_array) {
my $user = { NICK => $nick, ID => $uid };
- ircd::kick($agent, $cn, $nick, $reason)
+ ircd::kick($agent, $cn, $user, $reason)
unless adminserv::is_service($user);
$i++;
}
$get_chan_users_mask_noacc->execute($cn, $nick, $ident, $host, $host, $host);
while(my ($nick, $uid) = $get_chan_users_mask_noacc->fetchrow_array) {
my $user = { NICK => $nick, ID => $uid };
- ircd::kick($agent, $cn, $nick, $reason)
+ ircd::kick($agent, $cn, $user, $reason)
unless adminserv::is_service($user);
$i++;
}
$get_chan_users->execute($cn);
while(my ($nick, $uid) = $get_chan_users->fetchrow_array) {
- my $user = { NICK => $nick, ID => $uid };
+ my $user = { NICK => $nick };
+ get_user_id ($user);
my $opmodes = get_op($user, $chan);
for(my $i; $i < 5; $i++) {
if($opmodes & 2**$i) {
- push @modelist, ['-'.$opmodes[$i], $nick];
+ push @modelist, ['-'.$opmodes[$i], $user];
}
}
}
my ($chan, @userlist) = @_;
my $cn = $chan->{CHAN};
my $count;
- if (defined(&ircd::unban_nick)) {
- my @nicklist;
- foreach my $tuser (@userlist) {
- push @nicklist, get_user_nick($tuser);
- }
- ircd::unban_nick(agent($chan), $cn, @nicklist);
- return scalar(@nicklist);
+ if (defined(&ircd::unban_users)) {
+ ircd::unban_users(@userlist);
}
foreach my $tuser (@userlist) {
unless($tuid = get_user_id($tuser)) {
next;
}
-
my (@bans);
# We don't handle extended bans. Yet.
$find_bans_chan_user->execute($cn, $tuid, 0);
unless(defined($root)) {
(undef, $root) = get_best_acc($tuser, $chan, 2);
}
-
$get_nick_akick->execute($cn, $root);
my ($reason) = $get_nick_akick->fetchrow_array(); $get_nick_akick->finish();
-
return 0 if adminserv::is_svsop($tuser, adminserv::S_HELP());
if(defined($reason) && $reason =~ /\|/) {
($reason, undef) = split(/ ?\| ?/, $reason, 2);
sub check_akick($$;$) {
my ($user, $chan, $check_only) = @_;
-
+ print "Do status!\n";
if(adminserv::is_svsop($user, adminserv::S_HELP())) {
return 0;
}
sub akickban(@) {
my ($cn, $knick, $bnick, $ident, $host, $reason, $bident) = @_;
-
my $target = { NICK => $knick };
my $chan = { CHAN => $cn };
return 0 if adminserv::is_svsop($target, adminserv::S_HELP());
$ident =~ tr/\%\_/\*\?/;
$host =~ tr/\%\_/\*\?/;
}
+ if(defined($reason) && $reason =~ /\|/) {
+ ($reason, undef) = split(/ ?\| ?/, $reason, 2);
+ }
if(defined($reason) && $reason =~ /\|/) {
($reason, undef) = split(/ ?\| ?/, $reason, 2);
unban_user($chan, $user);
}
- ircd::svsjoin($csnick, get_user_nick($user), @cns) if @cns;
+ ircd::svsjoin($csUser, $user, @cns) if @cns;
}
### DATABASE UTILITY FUNCTIONS ###
$doneg = 0 unless defined($doneg);
my $cn = $chan->{CHAN};
-
if ($acc < 0) {
# Do akick stuff here.
}
if($masks[$sign] & 2**$i) {
$out .= $l[$i];
- push @args, $nick;
+ my $user_ = { NICK => $nick, AGENT => $csnick};
+ get_user_id ($user_);
+ push @args, $user_;
}
}
}
if(@args) {
- ircd::setmode(agent($chan), $cn, $out, join(' ', @args));
+ ircd::setmode_many(agent($chan), $cn, $out, @args);
}
}
my $noreply = $data->{NOREPLY};
my $acc = $data->{ACC};
my $overrideMsg = $data->{OVERRIDE_MSG};
-
if(my $nick = __can_do($chan, $perm, $user, $acc)) {
# This is becoming increasingly complicated
# and checking if an override was used is becoming tricky.
sub __can_do($$$;$) {
my ($chan, $perm, $user, $acc) = @_;
+ if(my ($nick, undef) = __can_do($chan, $perm, $acc, $user, $noreply)) {
+ return (wantarray ? ($nick, 0) : $nick);
+ } elsif ( $user and adminserv::is_svsop($user, adminserv::S_HELP()) ) {
+ #$set_lastused->execute($cn, get_user_id($user));
+ my ($nick, $override) = check_override($user, $perm);
+ if(services_conf_log_overrides && $override) {
+ # FIXME: This doesn't log enough information, and likely needs to be pushed up in the call-chain
+ my $src = get_user_nick($user);
+ my $cn = $chan->{CHAN};
+ wlog($csnick, LOG_INFO(), "\002$src\002 used override \002$perm\002 on \002$cn\002");
+ }
+ return (wantarray ? ($nick, $override) : $nick) if $override;
+ }
+ return 0;
+}
+
+sub __can_do($$$;$$) {
+ my ($chan, $perm, $acc, $user, $noreply) = @_;
my $nick;
my $cn = $chan->{CHAN};
$perm = uc $perm;
-
my $level;
unless(exists($chan->{"PERM::$perm"})) {
$level = $chan->{"PERM::$perm"} = get_level($chan, $perm);
}
}
$nick = 1 unless $nick;
-
+ print "ACcc $acc $level\n";
if($acc >= $level and !cr_chk_flag($chan, (CRF_CLOSE | CRF_FREEZE | CRF_DRONE))) {
set_lastused($cn, get_user_id($user)) if $user;
return (wantarray ? ($nick, 0) : $nick);
sub agent($) {
my ($chan) = @_;
- return $chan->{AGENT} if($chan->{AGENT});
+ if($chan->{AGENT}) {
+ my $a = $chan->{AGENT};
+ $a->{ID} = ircd::getUuid($a->{NICK});
+ return $a;
+ }
unless(initial_synced()) {
- return $csnick;
+ return $csUser;
}
-
$botserv::get_chan_bot->execute($chan->{CHAN});
- my ($agent) = $botserv::get_chan_bot->fetchrow_array;
-
- $agent = $csnick unless $agent;
-
+ my $agentnick = $botserv::get_chan_bot->fetchrow_array;
+ my ($agent) = { NICK => $agentnick, ID => ircd::getUuid($agentnick)};
+ $agent = $csUser unless $agentnick;
return $chan->{AGENT} = $agent;
}
$drop_chantext->execute($cn);
$drop_nicktext->execute($cn); # Leftover channel auths
$drop->execute($cn);
- ircd::setmode($csnick, $cn, '-r');
+ ircd::setmode($csUser, $cn, '-r');
}
sub drop_nick_chans($) {
# Due to special casing of '0' this wrapper should be used
# by anyone handling a JOIN (not SJOIN, it's a JOIN) event.
# This is an RFC1459 requirement.
- my ($nick, $cn) = @_;
- my $user = { NICK => $nick };
+ my ($user, $cn) = @_;
my $chan = { CHAN => $cn };
if ($cn == 0) {
}
sub handle_sjoin($$$$$$$) {
+ print "wheeeeeeeeee\n";
my ($server, $cn, $ts, $chmodes, $chmodeparms, $userarray, $banarray, $exceptarray) = @_;
my $chan = { CHAN => $cn };
} else {
update_modes($cn, "$chmodes $chmodeparms") if $chmodes;
}
+ print "HANDLE SJOIN $cn\n";
+ print Dumper (@$userarray);
user_join_multi($chan, $userarray) if scalar @$userarray;
foreach my $ban (@$banarray) {
my $cn = $chan->{CHAN};
my $seq = $ircline;
my $multi_tradeoff = 2; # could use some synthetic-benchmark tuning
-
foreach my $user (@$users) {
$user->{__ID} = get_user_id($user);
unless (defined($user->{__ID})) {
my ($reason, $opnick, $time) = get_close($chan);
my $cmsg = "$cn is closed: $reason";
my $preenforce = $enforcers{lc $chan};
-
if (cr_chk_flag($chan, CRF_CLOSE)) {
kickban_multi($chan, $users, $cmsg);
}
}
if(($count == 0 or !is_agent_in_chan($bot, $cn)) and initial_synced()) {
- unless (lc($bot) eq lc($csnick)) {
+ unless ($bot eq $csUser) {
unless(is_agent_in_chan($bot, $cn)) {
botserv::bot_join($chan);
}
}
}
- return unless synced() and not cr_chk_flag($chan, (CRF_CLOSE | CRF_DRONE));
-
+ #return unless synced() and not cr_chk_flag($chan, (CRF_CLOSE | CRF_DRONE));
+ return unless not cr_chk_flag($chan, (CRF_CLOSE | CRF_DRONE));
+ #commands aren't sent before synced() anyway
my $n;
foreach my $user (@$users) {
if(do_status($user, $chan)) {
sub user_part($$$) {
my ($nick, $cn, $reason) = @_;
-
my $user = ( ref $nick eq 'HASH' ? $nick : { NICK => $nick });
-
user_part_multi($user, [ $cn ], $reason);
}
# Other ircds may not do so.
# There is also KICK. some IRCds allow KICK #chan user1,user2,...
# Unreal it's _supposed_ to work, but it does not.
-
my ($user, $chanlist, $reason) = @_;
my @chans;
foreach my $cn (@$chanlist) {
push @chans, { CHAN => $cn };
-
}
my $uid = get_user_id($user);
sub process_kick($$$$) {
my ($src, $cn, $target, $reason) = @_;
- my $tuser = { NICK => $target };
+ my $tuser = { NICK => $target, ID => ircd::getUuid($target)};
user_part($tuser, $cn, 'Kicked by '.$src.' ('.$reason.')');
my $chan = { CHAN => $cn };
if ( !(is_agent($src) or $src =~ /\./ or adminserv::is_ircop({ NICK => $src })) and
({modes::splitmodes(get_modelock($chan))}->{Q}->[0] eq '+') )
{
- my $srcUser = { NICK => $src };
+ my $srcUser = { NICK => $src, ID => ircd::getUuid($src) };
#ircd::irckill(agent($chan), $src, "War script detected (kicked $target past +Q in $cn)");
nickserv::kline_user($srcUser, 300, "War script detected (kicked $target past +Q in $cn)");
# SVSJOIN won't work while they're banned, unless you invite.
- ircd::invite(agent($chan), $cn, $target);
- ircd::svsjoin(undef, $target, $cn);
+ ircd::invite(agent($chan), $cn, $tuser);
+ ircd::svsjoin(undef, $tuser, $cn);
unban_user($chan, $tuser);
}
}
sub chan_mode($$$$) {
- my ($src, $cn, $modes, $args) = @_;
- my $user = { NICK => $src };
+ my ($user, $cn, $modes, $args) = @_;
+ my $src;
+ if (ref($user) eq "HASH") {
+ $src = $user->{NICK};
+ }
+ else {
+ $src = $user;
+ }
my $chan = { CHAN => $cn };
my ($sign, $num);
if($mode eq '-') { $sign = 0; next; }
my $arg = shift(@args) if($mode =~ $scm or $mode =~ $ocm);
- my $auser = { NICK => $arg };
-
+ my $auser = { ID => $arg };
+ get_user_nick ($auser);
if($mode =~ /^[vhoaq]$/) {
next if $arg eq '';
next if is_agent($arg);
if($opguard and $sign == 1 and
!can_keep_op($user, $chan, $auser, $mode)
) {
- $unmodes .= $mode;
- push @unargs, $arg;
+ push @unargs, ["-" . $mode, $auser];
} else {
my $nid = get_user_id($auser) or next;
my ($r, $i);
#process_ban($cn, $arg, $src, 128, $sign);
}
}
- ircd::setmode(agent($chan), $cn, $unmodes, join(' ', @unargs)) if($opguard and @unargs);
+ ircd::setmode2(agent($chan), $cn, @unargs) if($opguard and @unargs);
}
sub process_ban($$$$) {
}
sub chan_topic {
- my ($src, $cn, $setter, $time, $topic) = @_;
+ my ($src, $cn, $suser, $time, $topic) = @_;
my $chan = { CHAN => $cn };
- my $suser = { NICK => $setter, AGENT => agent($chan) };
-
+ $suser -> {AGENT} = agent($chan);
+ my $setter = $suser -> {NICK};
return if cr_chk_flag($chan, CRF_CLOSE, 1);
if(current_message->{SYNC}) { # We don't need to undo our own topic changes.
+ print "Line @{[__LINE__]}\n";
$set_topic1->execute($setter, $time, $cn);
$set_topic2->execute($cn, $topic);
return;
}
-
if(!synced()) {
+ print "Line @{[__LINE__]}\n";
$get_topic->execute($cn);
my ($ntopic, $nsetter, $ntime) = $get_topic->fetchrow_array;
if($topic ne '' and $time == $ntime or can_do($chan, 'SETTOPIC', undef, { ACC => 0 })) {
+ print "Line @{[__LINE__]}\n";
$set_topic1->execute($setter, $time, $cn);
$set_topic2->execute($cn, $topic);
} else {
+ print "Line @{[__LINE__]}\n";
ircd::settopic(agent($chan), $cn, $nsetter, $ntime, $ntopic);
}
}
+ #lc($src) ne lc($setter) or - removed from previous line because
+ #i think it was breaking it for insp & idk what it did
+ #erry
- elsif(lc($src) ne lc($setter) or can_do($chan, 'SETTOPIC', $suser)) {
+ # as explained on IRC, the intent is to determine whether it's being set due to a
+ # net.unsplit, or b/c a user is doing it. You can probably do something more useful
+ # by paying attn to timestamp
+ # - tabris
+ elsif(can_do($chan, 'SETTOPIC', $suser)) {
+ print "Line @{[__LINE__]}\n",
+ "condition : ", can_do($chan, 'SETTOPIC', $suser),$/;
$set_topic1->execute($setter, $time, $cn);
$set_topic2->execute($cn, $topic);
} else {
+ print "Line @{[__LINE__]}\n";
$get_topic->execute($cn);
my ($ntopic, $nsetter, $ntime) = $get_topic->fetchrow_array;
ircd::settopic(agent($chan), $cn, $nsetter, $ntime, $ntopic);
if($type == CRF_DRONE) {
chan_kill($chan, $cn.$cmsg);
} else {
+ my $user = { NICK => $opnick};
+ get_user_id ($user);
ircd::settopic(agent($chan), $cn, $opnick, $time, "Channel".$cmsg);
clear_users($chan, "Channel".$cmsg);
}
our $hsnick_default = 'HostServ';
our $hsnick = $hsnick_default;
-
+our $hsuser = { NICK => $hsnick, ID => "123AAAAAH" };
sub init() {
import SrSv::DB::StubGen (
dbh => $dbh,
}
sub dispatch($$$) {
- my ($src, $dst, $msg) = @_;
+ my ($user, $dstUser, $msg) = @_;
+ my $src = $user->{NICK};
$msg =~ s/^\s+//;
my @args = split(/\s+/, $msg);
my $cmd = shift @args;
-
- my $user = { NICK => $src, AGENT => $dst };
-
+ $user->{AGENT} = $dstUser;
+ get_user_id ($user);
return if flood_check($user);
-
+ return unless (lc $dstUser->{NICK} eq lc $hsnick);
if(lc $cmd eq 'on') {
hs_on($user, $src, 0);
}
notice($user, "You don't have a vHost.") unless $identify;
return;
}
+
if ($vident) {
- ircd::chgident($hsnick, $src, $vident);
+ ircd::chgident($hsuser, $src, $vident);
}
- ircd::chghost($hsnick, $src, $vhost);
+ ircd::chghost($hsuser, $src, $vhost);
notice($user, "Your vHost has been changed to \002".($vident?"$vident\@":'')."$vhost\002");
}
my $src = get_user_nick($user);
# This requires a hack that is only known to work in UnrealIRCd 3.2.6 and later.
- ircd::reset_cloakhost($hsnick, $src);
+ ircd::reset_cloakhost($hsuser, $src);
notice($user, "vHost reset to cloakhost.");
}
our $msnick_default = 'MemoServ';
our $msnick = $msnick_default;
-
+our $msuser = { NICK => $msnick, ID => "123AAAAAE" };
our (
$send_memo, $send_chan_memo, $get_chan_recipients,
$add_ignore, $get_ignore_num, $del_ignore_nick, $list_ignore, $chk_ignore,
$wipe_ignore, $purge_ignore,
+ $get_first_unread
);
sub init() {
+ $get_first_unread = $dbh->prepare("SELECT memo.src, memo.chan, memo.time, memo.flag, memo.msg FROM memo, nickreg WHERE nickreg.nick=? AND memo.dstid=nickreg.id AND memo.flag=0 LIMIT 1");
$send_memo = $dbh->prepare("INSERT INTO memo SELECT ?, id, NULL, UNIX_TIMESTAMP(), NULL, ? FROM nickreg WHERE nick=?");
$send_chan_memo = $dbh->prepare("INSERT INTO memo SELECT ?, nickreg.id, ?, ?, NULL, ? FROM chanacc, nickreg
WHERE chanacc.chan=? AND chanacc.level >= ? AND chanacc.nrid=nickreg.id
### MEMOSERV COMMANDS ###
sub dispatch($$$) {
- my ($src, $dst, $msg) = @_;
+ my ($user, $dstUser, $msg) = @_;
$msg =~ s/^\s+//;
my @args = split(/\s+/, $msg);
my $cmd = shift @args;
-
- my $user = { NICK => $src, AGENT => $dst };
-
+ $user -> {AGENT} = $dstUser;
+ return unless (lc $dstUser->{NICK} eq lc $msnick);
+ get_user_id ($user);
return if flood_check($user);
if($SrSv::IRCd::State::queue_depth > main_conf_highqueue && !adminserv::is_svsop($user)) {
notice($user, get_user_agent($user)." is too busy right now. Please try your command again later.");
}
}
elsif($cmd =~ /^read$/i) {
- if(@args == 1 and (lc($args[0]) eq 'last' or $args[0] > 0)) {
+ if(@args == 1 and (lc($args[0]) eq 'last' or $args[0] > 0 or (lc($args[0]) eq 'unread'))) {
ms_read($user, $args[0]);
} else {
- notice($user, 'Syntax: READ <num|LAST>');
+ notice($user, 'Syntax: READ <num|LAST|UNREAD>');
}
}
elsif($cmd =~ /^list$/i) {
return;
}
@nums = ($num);
- } else {
+ }
+ elsif (lc($num) eq 'unread') {
+ $get_first_unread->execute($root);
+ $get_memo_full->execute($root, $num-1);
+ unless(($from, $chan, $time, $flag, $msg) = $get_first_unread->fetchrow_array) {
+ notice($user, "You have no unread memos.");
+ return;
+ }
+ $set_flag->execute(1, $from, $root, $chan, $time);
+ my @reply;
+ push @reply, "Memo \002$num\002 from \002$from\002 ".
+ ($chan ? "to \002$chan\002 " : "to \002$root\002 ").
+ "at ".gmtime2($time), $msg, ' --';
+ notice ($user, @reply);
+ return;
+ }
+ else {
@nums = makeSeqList($num);
}
my ($user, $root) = @_;
my (@nicks);
- unless(ref($user)) {
+ unless(ref($user) eq "HASH") {
$user = { NICK => $user };
}
$get_chan_recipients->execute($cn, $level);
while(my ($u) = $get_chan_recipients->fetchrow_array) {
- notice({ NICK => $u, AGENT => $msnick },
+ notice({ NICK => $u, AGENT => $msuser },
"You have a new memo from \002$src\002 to \002$cn\002. To read it, type: \002/ms read last\002");
}
}
my ($nick, $msg) = @_;
foreach my $u (get_nick_user_nicks $nick) {
- notice({ NICK => $u, AGENT => $msnick }, $msg);
+ notice({ NICK => $u, AGENT => $msuser }, $msg);
}
}
use SrSv::NickControl::Enforcer qw(%enforcers);
use SrSv::Email;
-
+use SrSv::Insp::UUID;
use SrSv::Util qw( makeSeqList );
-
+use SrSv::IRCd::Send qw (getRevUuid ircd::getUuid setRevUuid setUuid);
use SrSv::Debug;
use SrSv::NickReg::NickText;
use SrSv::IPv6;
require SrSv::MySQL::Stub;
-
+use Data::Dumper;
use constant {
# Clone exception max limit.
# This number typically means infinite/no-limit.
our $nsnick_default = 'NickServ';
our $nsnick = $nsnick_default;
-
+our $nsuser = { NICK => $nsnick, ID => "123AAAAAB" }; #FIXME - erry
our $cur_lock;
our $cnt_lock = 0;
);
our (
- $nick_check,
- $nick_create, $nick_create_old, $nick_change, $nick_quit, $nick_delete, $nick_id_delete,
+ $nick_check, $nick_checkExists,
+ $nick_create, $nick_create2, $nick_create_old, $nick_change, $nick_quit, $nick_delete, $nick_id_delete,
$get_quit_empty_chans, $nick_chan_delete, $chan_user_partall,
$get_hostless_nicks,
-
+ $id_change,
$get_squit_lock, $squit_users, $squit_nickreg, $get_squit_empty_chans, $squit_lastquit,
$del_nickchg_id, $add_nickchg, $reap_nickchg,
$set_authcode_ntf, $get_authcode_ntf,
$get_nicks_by_email,
+
+ $nick_deleteChanUser, $nick_deleteNickCh, $nick_deleteNickId,
+ $id_delUser
);
sub init() {
$nick_check = $dbh->prepare("SELECT id FROM user WHERE nick=? AND online=0 AND time=?");
+ $nick_checkExists = $dbh -> prepare ("SELECT nick FROM user WHERE id=? AND time=?");
+ $nick_deleteChanUser = $dbh -> prepare ("DELETE FROM chanuser WHERE nickid=?");
+ $nick_deleteNickCh = $dbh -> prepare ("DELETE FROM nickchg WHERE nickid=?");
+ $nick_deleteNickId = $dbh -> prepare ("DELETE FROM nickid WHERE id=?");
+ $id_delUser = $dbh->prepare ("DELETE FROM user WHERE id=?");
$nick_create = $dbh->prepare("INSERT INTO user SET nick=?, time=?, inval=0, ident=?, host=?, vhost=?, server=?, modes=?,
gecos=?, flags=?, cloakhost=?, online=1");
+ $nick_create2 = $dbh->prepare("INSERT INTO user SET id=?, nick=?, time=?, inval=0, ident=?, host=?, vhost=?, server=?, modes=?,
+ gecos=?, flags=?, cloakhost=?, online=1");
# $nick_create = $dbh->prepare("INSERT INTO user SET id=(RAND()*294967293)+1, nick=?, time=?, inval=0, ident=?, host=?, vhost=?, server=?, modes=?, gecos=?, flags=?, cloakhost=?, online=1");
$nick_create_old = $dbh->prepare("UPDATE user SET nick=?, ident=?, host=?, vhost=?, server=?, modes=?, gecos=?,
flags=?, cloakhost=?, online=1 WHERE id=?");
- $nick_change = $dbh->prepare("UPDATE user SET nick=?, time=? WHERE nick=?");
+ $nick_change = $dbh->prepare("UPDATE user SET nick=? WHERE nick=?");
$nick_quit = $dbh->prepare("UPDATE user SET online=0, quittime=UNIX_TIMESTAMP() WHERE nick=?");
$nick_delete = $dbh->prepare("DELETE FROM user WHERE nick=?");
$nick_id_delete = $dbh->prepare("DELETE FROM nickid WHERE id=?");
);
sub dispatch($$$) {
- my ($src, $dst, $msg) = @_;
+ $nsuser = { NICK => $nsnick, ID => "123AAAAAB" }; #FIXME = erry
+ my ($user, $dstUser, $msg) = @_;
+ return unless (lc $dstUser->{NICK} eq lc $nsnick);
$msg =~ s/^\s+//;
my @args = split(/\s+/, $msg);
my $cmd = shift @args;
-
- my $user = { NICK => $src, AGENT => $dst };
-
+ get_user_id ($user);
+ my $src = $user->{NICK};
+ $user->{AGENT} = $dstUser;
return if flood_check($user);
-
if(!defined($high_priority_cmds{lc $cmd}) &&
!adminserv::is_svsop($user) &&
$SrSv::IRCd::State::queue_depth > main_conf_highqueue)
notice($user, "Cannot only change case of nick");
return;
}
- ircd::svsnick($nsnick, $src, $nick);
- ircd::setumode($nsnick, $nick, '+r');
+ ircd::svsnick($nsuser, $user, $nick);
+ ircd::setumode($nsuser, $user, '+r');
return 1;
}
}
$update_lastseen->execute($uid);
$logout->execute($uid);
delete($user->{NICKFLAGS});
- ircd::nolag($nsnick, '-', get_user_nick($user));
+ ircd::nolag($nsnick, '-', $user);
notice($user, 'You are now logged out');
services::ulog($nsnick, LOG_INFO(), "used NickServ LOGOUT", $user);
}
} else {
my $ghostbusters = @ghostbusters_quotes[int rand(scalar(@ghostbusters_quotes))];
- ircd::irckill($nsnick, $nick, "GHOST command used by $src ($ghostbusters)");
+ ircd::irckill($nsuser, $user, "GHOST command used by $src ($ghostbusters)");
notice($user, "Your ghost has been disconnected");
services::ulog($nsnick, LOG_INFO(), "used NickServ GHOST on $nick", $user);
#nick_delete($nick);
else {
$identify->execute($uid, $src); $identify->finish();
notice($user, 'You are now registered and identified.');
- ircd::setumode($nsnick, $src, '+r');
+ ircd::setumode($nsuser, $user, '+r');
}
$id_update->execute($src, $uid); $id_update->finish();
- services::ulog($nsnick, LOG_INFO(), "registered $src (email: $email)".
+ services::ulog($nsuser, LOG_INFO(), "registered $src (email: $email)".
(services_conf_validate_email ? ' requires email validation code' : ''),
$user);
} else {
$del_nicktext->execute(NTF_UMODE, $target); $del_nicktext->finish(); # don't allow dups
$set_umode_ntf->execute($modes, $target); $set_umode_ntf->finish();
foreach my $usernick (get_nick_user_nicks $target) {
- ircd::setumode($nsnick, $usernick, $modes)
+ ircd::setumode($nsuser, $user, $modes)
}
my @out;
}
$set_watch->execute($mask, time(), $root);
- ircd::svswatch($nsnick, $src, "+$mask");
+ ircd::svswatch($nsuser, $user, "+$mask");
notice($user, "\002$mask\002 added to \002$target\002's watch list.");
return;
}
return;
}
$del_watch->execute($root, $mask);
- ircd::svswatch($nsnick, $src, "-$mask");
+ ircd::svswatch($nsuser, $user, "-$mask");
notice($user, "\002$mask\002 removed from \002$target\002's watch list.");
}
elsif ($cmd =~ /^list$/i) {
$set_silence->execute($mask, time(), $expiry, $comment, $root);
}
- ircd::svssilence($nsnick, $src, "+$mask");
+ ircd::svssilence($nsuser, $user, "+$mask");
notice($user, "\002$mask\002 added to $subj SILENCE list.");
}
elsif ($cmd =~ /^del(ete)?$/i) {
push @out_masks, "-$mask";
push @reply, "\002$mask\002 removed from $subj SILENCE list.";
}
- ircd::svssilence($nsnick, $src, @out_masks);
+ ircd::svssilence($nsuser, $user, @out_masks);
notice($user, @reply);
}
elsif ($cmd =~ /^list$/i) {
$nick = get_root_nick($nick);
foreach my $t (get_nick_user_nicks $nick) {
- ircd::notice($nsnick, $t, (ref $msg ? @$msg : $msg)) unless(lc $t eq lc $src);
+ my $user = { NICK => $nick, AGENT => $nsuser };
+ get_user_id ($user);
+ ircd::notice($nsuser, $user, (ref $msg ? @$msg : $msg)) unless(lc $t eq lc $src);
if(is_alias_of($nick, $t)) {
- ircd::setumode($nsnick, $t, '-r');
+ ircd::setumode($nsuser, $user, '-r');
}
}
# For a single alias:
sub unidentify_single($$) {
my ($nick, $msg) = @_;
-
+ my $user = { NICK => $nick, AGENT => $nsuser };
+ get_user_id ($user);
if(is_online($nick)) {
- ircd::setumode($nsnick, $nick, '-r');
+ ircd::setumode($nsuser, $user, '-r');
}
}
my ($c) = $count_clones->fetchrow_array;
if($c > $lim) {
- ircd::irckill($nsnick, $src, "Session Limit Exceeded");
+ ircd::irckill($nsuser, $user, "Session Limit Exceeded");
return 1;
}
}
my ($user, $nick, $root, $flags, $svsnick) = @_;
my $uid = get_user_id($user);
my $src = get_user_nick($user);
-
$identify_ign->execute($uid, $root);
$id_update->execute($root, $uid);
$get_umode_ntf->finish();
if(adminserv::get_svs_level($root)) {
$umodes = modes::merge_umodes('+h', $umodes);
- ircd::nolag($nsnick, '+', $src);
+ ircd::nolag($nsuser, '+', $user);
}
$umodes = modes::merge_umodes('+r', $umodes) if(is_identified($user, $src));
hostserv::hs_on($user, $root, 1);
- nickserv::do_svssilence($user, $root);
- nickserv::do_svswatch($user, $root);
-
- chanserv::akick_alluser($user);
- chanserv::set_modes_allchan($user, $flags & NRF_NEVEROP);
- chanserv::fix_private_join_before_id($user);
-
- services::ulog($nsnick, LOG_INFO(), "identified to nick $nick (root: $root)", $user);
-
- memoserv::notify($user, $root);
- notify_auths($user, $root) if $flags & NRF_AUTH;
+ if(my @chans = get_autojoin_ntf($nick)) {
+ ircd::svsjoin($nsuser, $user, @chans);
+ }
my $enforced;
if(enforcer_quit($nick)) {
}
if (lc($src) eq lc($nick)) {
- ircd::setumode($nsnick, $src, $umodes);
+ ircd::setumode($nsuser, $user, $umodes);
$update_nickalias_last->execute($nick); $update_nickalias_last->finish();
}
elsif($svsnick) {
- ircd::svsnick($nsnick, $src, $nick);
- ircd::setumode($nsnick, $nick, modes::merge_umodes('+r', $umodes) );
+ ircd::svsnick($nsuser, $user, $nick);
+ ircd::setumode($nsuser, $user, modes::merge_umodes('+r', $umodes) );
# the update _should_ be taken care of in nick_change()
#$update_nickalias_last->execute($nick); $update_nickalias_last->finish();
}
elsif(defined $umodes) {
- ircd::setumode($nsnick, $src, $umodes);
+ ircd::setumode($nsuser, $user, $umodes);
}
+
do_ajoin($user, $nick);
+
+ nickserv::do_svssilence($user, $root);
+ nickserv::do_svswatch($user, $root);
+
+ chanserv::akick_alluser($user);
+ chanserv::set_modes_allchan($user, $flags & NRF_NEVEROP);
+ chanserv::fix_private_join_before_id($user);
+
+ services::ulog($nsnick, LOG_INFO(), "identified to nick $nick (root: $root)", $user);
+
+ memoserv::notify($user, $root);
+ notify_auths($user, $root) if $flags & NRF_AUTH;
+>>>>>>> .merge-right.r3531
return ($enforced ? 2 : 1);
}
sub guestnick($) {
my ($nick) = @_;
-
$set_guest->execute(1, $nick);
my $randnick = 'Guest'.int(rand(10)).int(rand(10)).int(rand(10)).int(rand(10)).int(rand(10));
#Prevent collisions.
while (is_online($randnick)) {
$randnick = 'Guest'.int(rand(10)).int(rand(10)).int(rand(10)).int(rand(10)).int(rand(10));
}
- ircd::svsnick($nsnick, $nick, $randnick);
+ my $user = { NICK => $nick, AGENT => $nsuser };
+ get_user_id ($user);
+ ircd::svsnick($nsuser, $user, $randnick);
return $randnick;
}
foreach my $user (get_nick_users $nick) {
$user->{AGENT} = $nsnick;
- ircd::svssilence($nsnick, get_user_nick($user), map ( { '-'.$_->[0] } @entries) );
+ $user->{ID} = ircd::getUuid($nick);
+ ircd::svssilence($nsuser, $user, map ( { '-'.$_->[0] } @entries) );
#notice($user, "The following SILENCE entries have expired: ".
# join(', ', map ( { $_->[0] } @entries) ));
notice($user, map( { "The following SILENCE entry has expired: \002".$_->[0]."\002 ".$_->[1] } @entries ) );
push @silences, "+$mask";
}
$get_silences->finish;
- ircd::svssilence($nsnick, $target, @silences);
+ ircd::svssilence($nsuser, $user, @silences);
return;
}
push @watches, "+$mask";
}
$get_watches->finish;
- ircd::svswatch($nsnick, $target, @watches);
+ ircd::svswatch($nsuser, $user, @watches);
return;
}
$get_umode_ntf->execute($rootnick);
my ($umodes) = $get_umode_ntf->fetchrow_array; $get_umode_ntf->finish();
- ircd::setumode($nsnick, $target, $umodes) if $umodes;
+ ircd::setumode($nsuser, $user, $umodes) if $umodes;
return
}
sub notify_auths($$) {
- my ($user, $nick) = @_;
-
+ my $user = @_;
+ my $nick = get_user_nick ($user);
$get_num_nicktext_type->execute($nick, NTF_AUTH);
my ($count) = $get_num_nicktext_type->fetchrow_array(); $get_num_nicktext_type->finish();
notice($user, "$nick has $count channel authorizations awaiting action.",
return if nr_chk_flag($nick, NRF_EMAILREG());
my $lev = protect_level($nick);
- my $user = { NICK => $nick, AGENT => $nsnick };
-
+ my $user = { NICK => $nick, AGENT => $nsuser };
+ get_user_id ($user);
notice($user,
"This nickname is registered and protected. If it is your",
"nick, type \002/msg NickServ IDENTIFY <password>\002. Otherwise,",
sub warn_countdown($) {
my ($cookie) = @_;
my ($nick, $rem) = split(/ /, $cookie);
- my $user = { NICK => $nick, AGENT => $nsnick };
-
+ my $user = { NICK => $nick, AGENT => $nsuser };
+ get_user_id($user);
if (is_identified($user, $nick)) {
+ print "Line 2778\n";
$update_nickalias_last->execute($nick); $update_nickalias_last->finish();
return;
}
- elsif(!(is_online($nick)) or !(is_registered($nick))) { return; }
+ elsif(!(is_online($nick)) or !(is_registered($nick))) { print "Line 2782\n"; return; }
if($rem == 0) {
notice($user, 'Your nick is now being changed.');
sub collide($) {
my ($nick) = @_;
-
+ my $newnick = guestnick($nick);
ircd::svshold($nick, 60, "If this is your nick, type /NS SIDENTIFY $nick \002password\002");
$enforcers{lc $nick} = 1;
add_timer($nick, 60, __PACKAGE__, "nickserv::enforcer_delete");
-
- return guestnick($nick);
+ return $newnick;
}
sub enforcer_delete($) {
$get_umodes->execute($uid);
my ($umodes) = $get_umodes->fetchrow_array;
$get_umodes->finish();
+ print "UMODES $umodes\n";
return $umodes;
};
$get_nick_inval->execute($id);
my ($nick, $inval) = $get_nick_inval->fetchrow_array;
if($inval > 3) {
- ircd::irckill($nsnick, $nick, 'Too many invalid passwords.');
+ ircd::irckill($nsuser, $user, 'Too many invalid passwords.');
# unnecessary as irckill calls the quit handler.
#nick_delete($nick);
return 0;
my $nick = get_user_nick($user);
if(is_registered($nick)) {
if(is_identified($user, $nick)) {
- ircd::setumode($nsnick, $nick, '+r');
+ ircd::setumode($nsuser, $user, '+r');
$update_nickalias_last->execute($nick); $update_nickalias_last->finish();
return 1;
} else {
add_timer('fix_vhosts', 5, __PACKAGE__, 'nickserv::fix_vhosts');
$get_hostless_nicks->execute();
while (my ($nick) = $get_hostless_nicks->fetchrow_array) {
- ircd::notice($nsnick, main_conf_diag, "HOSTLESS NICK $nick");
+ ircd::notice($nsuser, main_conf_diag, "HOSTLESS NICK $nick");
ircd::userhost($nick);
ircd::userip($nick);
}
### IRC EVENTS ###
sub nick_create {
- my ($nick, $time, $ident, $host, $vhost, $server, $svsstamp, $modes, $gecos, $ip, $cloakhost) = @_;
- my $user = { NICK => $nick };
+ my ($user, $time, $ident, $host, $vhost, $server, $svsstamp, $modes, $gecos, $ip, $cloakhost) = @_;
+ my $nick = get_user_nick ($user);
get_lock($nick);
if ($vhost eq '*') {
if ({modes::splitumodes($modes)}->{x} eq '+') {
}
my $id;
+ if ($id = get_user_id( $user )) {
+ #$id = decodeUUID ($id);
+ $nick_checkExists->execute ($id, $time);
+ my $exists = $nick_checkExists -> fetchrow_array();
+ my $flags = (synced() ? UF_FINISHED() : 0);
+ unless (defined($exists)) {
+ $nick_deleteChanUser -> execute ($id);
+ $nick_deleteNickCh -> execute ($id);
+ $nick_deleteNickId -> execute ($id);
+ $id_delUser -> execute ($id);
+ $nick_create2 -> execute ($id, $nick, $time, $ident, $host, $vhost, $server, $modes, $gecos, $flags, $cloakhost);
+ }
+ else {
+ $nick_create_old->execute ($nick, $ident, $host, $vhost, $server, $modes, $gecos, $flags, $cloakhost, $id);
+ }
+ $add_nickchg->execute($ircline, $nick, $nick);
+ release_lock($nick);
+ check_identify($user);
+ return $id;
+ }
if($svsstamp) {
$get_user_nick->execute($svsstamp);
my ($oldnick) = $get_user_nick->fetchrow_array();
while($i < 10 and !$nick_create->execute($nick, $time, $ident, $host, $vhost, $server, $modes, $gecos, $flags, $cloakhost)) { $i++ }
$id = get_user_id( { NICK => $nick } ); # There needs to be a better way to do this
}
- ircd::setsvsstamp($nsnick, $nick, $id) unless $svsstamp == $id;
+ ircd::setsvsstamp($nsuser, $user, $id) unless $svsstamp == $id;
$add_nickchg->execute($ircline, $nick, $nick);
}
sub nick_delete($$) {
- my ($nick, $quit) = @_;
- my $user = { NICK => $nick };
-
+ my ($user, $quit) = @_;
+ my $nick = $user->{NICK};
get_lock($nick);
-
my $id = get_user_id($user);
-
$del_nickchg_id->execute($id); $del_nickchg_id->finish();
-
$quit_update->execute($quit, $id); $quit_update->finish();
$update_lastseen->execute($id); $update_lastseen->finish();
-
$get_quit_empty_chans->execute($id);
-
$chan_user_partall->execute($id); $chan_user_partall->finish();
#$nick_chan_delete->execute($id); $nick_chan_delete->finish();
$nick_quit->execute($nick); $nick_quit->finish();
-
release_lock($nick);
-
while(my ($cn) = $get_quit_empty_chans->fetchrow_array) {
chanserv::channel_emptied({CHAN => $cn});
}
$get_quit_empty_chans->finish();
+ ns_logout ($user);
}
sub squit($$$) {
}
sub nick_change($$$) {
- my ($old, $new, $time) = @_;
-
+ my ($user, $new, $time) = @_;
+ my $old = $user->{NICK};
return if(lc $old eq lc $new);
-
+ print "NICK CHANGE: $old -> $new ($time)\n";
get_lock($old);
nick_cede($new);
- $nick_change->execute($new, $time, $old);
+ $nick_change->execute($new, $old);
$add_nickchg->execute($ircline, $new, $new);
release_lock($old);
-
if($new =~ /^guest/i) {
$get_guest->execute($new);
my ($guest) = $get_guest->fetchrow_array();
}
return;
}
-
- ircd::setumode($nsnick, $new, '-r')
- unless check_identify({ NICK => $new });
+ my $user = { NICK => $new, AGENT => $nsuser };
+ get_user_id($user);
+ ircd::setumode($nsuser, $user, '-r')
+ unless check_identify({ NICK => $new });
+}
+sub handle_oper($) {
+ my ($user) = @_;
+ my $nick = $user->{NICK};
+ get_lock($nick);
+ my $id = get_user_id($user);
+ $get_umodes->execute($id);
+ my ($omodes) = $get_umodes->fetchrow_array;
+ $set_umodes->execute(modes::add($omodes, "o", 0), $id);
+ #this is _safe_. even an oper block with no privs gets +o
+ #it's just not passed to srsv for some reason, all we get is :UID opertype X
}
-
sub umode($$) {
- my ($nick, $modes) = @_;
- my $user = { NICK => $nick };
-
+ my ($user, $modes) = @_;
+ my $nick = $user->{NICK};
get_lock($nick);
my $id = get_user_id($user);
our $osnick_default = 'OperServ';
our $osnick = $osnick_default;
-
+our $osuser = { NICK => $osnick, ID => "123AAAAAD" };
my %newstypes = (
u => 'User',
o => 'Oper'
}
sub dispatch($$$) {
- my ($src, $dst, $msg) = @_;
+ my ($user, $dstUser, $msg) = @_;
$msg =~ s/^\s+//;
my @args = split(/\s+/, $msg);
my $cmd = shift @args;
-
- my $user = { NICK => $src, AGENT=> $dst };
-
+ $user -> {AGENT} = $dstUser;
+ my $src = $user -> {NICK};
+ return unless (lc $dstUser->{NICK} eq lc $osnick);
+ get_user_id ($user);
services::ulog($osnick, LOG_INFO(), "cmd: [$msg]", $user);
return if flood_check($user);
- unless(adminserv::is_svsop($user) or adminserv::is_ircop($user)) {
+ unless(defined(adminserv::is_svsop($user)) or adminserv::is_ircop($user)) {
notice($user, $err_deny);
if($cmd =~ /^set/i) {
nickserv::kill_user($user, "OS SET doesn't exist here");
notice($user, "You don't have the right access");
return $event::SUCCESS;
}
- ircd::svsjoin($osnick, $target, @chans);
+ ircd::svsjoin($osuser, $target, @chans);
}
sub os_fpart($$@) {
}
$reason = join(' ', @params) if @params;
- ircd::svspart($osnick, $target, $reason, @chans);
+ ircd::svspart($osuser, $target, $reason, @chans);
}
sub os_qline_add($$$$) {
return $event::SUCCESS;
}
nickserv::enforcer_quit($newnick);
- ircd::svsnick($osnick, $curnick, $newnick);
+ ircd::svsnick($osuser, $curnick, $newnick);
notice($user, $curnick.' changed to '.$newnick);
return $event::SUCCESS;
}
my $hostmask = $hostname;
$hostmask =~ s/\*/\%/g;
my $ret = $del_clone_exceptname->execute($hostmask);
- ircd::notice($osnick, main_conf_diag, "hostname: $hostname; hostmask: $hostmask");
+ ircd::notice($osuser, main_conf_diag, "hostname: $hostname; hostmask: $hostmask");
if($ret == 1) {
notice($user, "\002$hostname\002 successfully deleted from the hostname exception list");
return $event::SUCCESS;
}
-
sub os_svskill($$$) {
my ($user, $targets, $reason) = @_;
return $event::SUCCESS;
}
- ircd::svskill($osnick, $target, $reason);
+ ircd::svskill($osuser, $target, $reason);
}
return $event::SUCCESS;
}
foreach my $target (split(',', $targets)) {
- my $tuser = { NICK => $target, AGENT => $osnick };
+ my $tuser = { NICK => $target, AGENT => $osuser };
if (!get_user_id($tuser)) {
notice($user, $target.' is not online.');
return $event::SUCCESS;
}
unless($zline) {
if(!$remove) {
- ircd::kline($opernick, $ident, $host, $expiry, $reason);
+ ircd::kline(ircd::getUuid($osnick), $ident, $host, $expiry, $reason);
} else {
ircd::unkline($opernick, $ident, $host);
}
return;
}
if(!$remove) {
- ircd::zline($opernick, $host, $expiry, $reason);
+ ircd::zline($osnick, $host, $expiry, $reason);
} else {
ircd::unzline($opernick, $host);
}
}
foreach my $tuser (&$func($arg)) {
next unless is_online($tuser);
- $tuser->{AGENT} = $osnick;
+ $tuser->{AGENT} = $osuser;
nickserv::kill_user($tuser,
"Killed by \002".get_user_nick($user)."\002".
($msg ? ": $msg" : '')
}
foreach my $tuser (&$func($arg)) {
next unless is_online($tuser);
- $tuser->{AGENT} = $osnick;
+ $tuser->{AGENT} = $osuser;
nickserv::kline_user($tuser, services_conf_chankilltime,
"K:Lined by \002".get_user_nick($user)."\002".
($msg ? ": $msg" : '')
notice($user, "Must have message to send") unless(@args);
foreach my $tuser (&$func($arg)) {
next unless is_online($tuser);
- $tuser->{AGENT} = $osnick;
+ $tuser->{AGENT} = $osuser;
notice($tuser,
"Automated message from \002".get_user_nick($user),
$msg
foreach my $tuser (&$func($arg)) {
next unless is_online($tuser);
my $cn = $msg; # not a message, most cases it is
- $tuser->{AGENT} = $osnick;
- ircd::svsjoin($osnick, get_user_nick($tuser), $cn);
+ $tuser->{AGENT} = $osuser;
+ ircd::svsjoin($osuser, get_user_nick($tuser), $args[0]);
}
}
else {