]> jfr.im git - irc/SurrealServices/srsv.git/commitdiff
first hack at merging erry's work + the current release 0.4.3,
authortabris <redacted>
Wed, 6 Jul 2011 04:21:49 +0000 (04:21 +0000)
committertabris <redacted>
Wed, 6 Jul 2011 04:21:49 +0000 (04:21 +0000)
making 0.5.0

it's probably VERY broken right now, for either insp or Unreal.

git-svn-id: http://svn.tabris.net/repos/srsv@3532 70d4eda1-72e9-0310-a436-91e5bd24443c

23 files changed:
branches/0.5.0/SrSv/Agent.pm
branches/0.5.0/SrSv/IRCd/Event.pm
branches/0.5.0/SrSv/IRCd/IO.pm
branches/0.5.0/SrSv/IRCd/Parse.pm
branches/0.5.0/SrSv/IRCd/Send.pm
branches/0.5.0/SrSv/IRCd/State.pm
branches/0.5.0/SrSv/Insp/Parse.pm [new file with mode: 0644]
branches/0.5.0/SrSv/Insp/Send.pm [new file with mode: 0644]
branches/0.5.0/SrSv/Insp/UUID.pm
branches/0.5.0/SrSv/Insp/decodeUUID.pl [deleted file]
branches/0.5.0/SrSv/Unreal/Parse.pm
branches/0.5.0/SrSv/Unreal/Send.pm
branches/0.5.0/SrSv/Unreal/Tokens.pm
branches/0.5.0/modules/connectserv.pm
branches/0.5.0/modules/core.pm
branches/0.5.0/modules/services.pm
branches/0.5.0/modules/serviceslibs/adminserv.pm
branches/0.5.0/modules/serviceslibs/botserv.pm
branches/0.5.0/modules/serviceslibs/chanserv.pm
branches/0.5.0/modules/serviceslibs/hostserv.pm
branches/0.5.0/modules/serviceslibs/memoserv.pm
branches/0.5.0/modules/serviceslibs/nickserv.pm
branches/0.5.0/modules/serviceslibs/operserv.pm

index 2856bdfcb1516e97dacc9276b347d223bc998e81..c548b9b2d85f459bb997b604a09058b1bd47a2a4 100644 (file)
@@ -39,11 +39,11 @@ use SrSv::Debug;
 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 }
 
@@ -63,6 +63,7 @@ sub is_agent_in_chan($$) {
        $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;
@@ -79,16 +80,26 @@ sub agent_connect($$$$$) {
        }
 
        $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($$) {
@@ -129,27 +140,11 @@ sub is_invalid_agentname($$$) {
        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($$) {
@@ -157,12 +152,25 @@ 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);
 }
index d5b1d87a661a87e492bee88f7a432231dfa9a883..e9d56fe6175f36826a19eb4bf80a8edc686fdaee 100644 (file)
@@ -74,7 +74,6 @@ sub callfuncs {
                $sync = 0;
                $wf = $_[3];
        }
-
        $message = {
                CLASS => 'IRCD',
                TYPE => $_[0],
index 0d7263ade4daf1172351446c9f3473752f58ac75..0aeb1035916e7395254c1edfc776e0080c3b8208 100644 (file)
@@ -19,7 +19,7 @@ package SrSv::IRCd::IO;
 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",
@@ -27,7 +27,7 @@ use constant {
 
 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;
index f24abe021db53aed7be6a98fda7d3f5a0bd5bbf4..aef043a0d85a7889df1526e99b857da52e96d44c 120000 (symlink)
@@ -1 +1 @@
-../Unreal/Parse.pm
\ No newline at end of file
+../Insp/Parse.pm
\ No newline at end of file
index 0ccfe74086d69f9ab86ab8fe7fd115df6d600e37..48afa4ff9cbeb8e09ff1a7e8ccf17ab5c462bb60 120000 (symlink)
@@ -1 +1 @@
-../Unreal/Send.pm
\ No newline at end of file
+../Insp/Send.pm
\ No newline at end of file
index 8e47ab34a7ed194f6c62817da3506347661941c8..44d923a523c089c8aa65af83a86b4e422645c999 100644 (file)
@@ -69,9 +69,7 @@ sub calc_synced {
        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;
diff --git a/branches/0.5.0/SrSv/Insp/Parse.pm b/branches/0.5.0/SrSv/Insp/Parse.pm
new file mode 100644 (file)
index 0000000..1d72162
--- /dev/null
@@ -0,0 +1,833 @@
+#      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;
diff --git a/branches/0.5.0/SrSv/Insp/Send.pm b/branches/0.5.0/SrSv/Insp/Send.pm
new file mode 100644 (file)
index 0000000..52e3ca3
--- /dev/null
@@ -0,0 +1,878 @@
+#      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;
index 7e71aedecd6360400efbfa28ae0ed1315fc880f6..f43585725cc90fe78c32e7be277cf2e9d4328dd9 100644 (file)
 #       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;
 
@@ -105,14 +105,16 @@ sub encodeUUID($) {
        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
diff --git a/branches/0.5.0/SrSv/Insp/decodeUUID.pl b/branches/0.5.0/SrSv/Insp/decodeUUID.pl
deleted file mode 100755 (executable)
index c74bba1..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/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";
index fea1497db4a93f56768d3c40ee5f192fc24eb2c2..abcbc5db085f0e1137a0e26f53cae958e5e4902e 100644 (file)
@@ -21,7 +21,7 @@ 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) }
+BEGIN { our @EXPORT_OK = qw(parse_line parse_tkl parse_addline) }
 
 # FIXME
 BEGIN { *SJB64 = \&ircd::SJB64; *CLK = \&ircd::CLK; *NICKIP = \&ircd::NICKIP; }
@@ -39,7 +39,8 @@ BEGIN {
 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
@@ -65,7 +66,9 @@ our %cmdhash;
 
 sub parse_line($) {
        my ($in) = @_;
-       return unless $in;
+       if (!$in) {
+               return;
+       }
        my $cmd;
 
        if($in =~ /^(?:@|:)(\S+) (\S+)/) {
@@ -74,7 +77,6 @@ sub parse_line($) {
        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();
@@ -105,7 +107,24 @@ sub parse_line($) {
 
        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);
@@ -145,7 +164,21 @@ sub parse_sjoin($$$$) {
 
        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,
@@ -199,22 +232,37 @@ sub PING($) {
        # ($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($) {
@@ -293,7 +341,19 @@ sub JOIN($) {
        $_[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);
@@ -335,6 +395,8 @@ sub MODE($) {
                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+)$/) {
@@ -354,7 +416,16 @@ sub MESSAGE($) {
                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;
@@ -386,8 +457,12 @@ sub AWAY($) {
 
 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
@@ -448,7 +523,10 @@ sub NICK($) {
 
 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($) {
@@ -663,7 +741,7 @@ BEGIN {
 
                EOS             =>      \&EOS,
                ES              =>      \&EOS,
-
+               ENDBURST => \&EOS,
                SERVER          =>      \&SERVER,
                "\'"            =>      \&SERVER,
 
@@ -683,7 +761,7 @@ BEGIN {
 
                SJOIN           =>      \&SJOIN,
                '~'             =>      \&SJOIN,
-
+               FJOIN   =>   \&FJOIN,
                MODE            =>      \&MODE,
                G               =>      \&MODE,
 
@@ -757,6 +835,7 @@ BEGIN {
 
                STATS           =>      \&STATS,
                '2'             =>      \&STATS,
+               UID => \&UID,
        );
 }
 
index 4102cea259beae528a55646284d8ca7a8c370345..d0acf5fa67197faab22028ad668599ffd87dc237 100644 (file)
@@ -16,7 +16,6 @@
 package ircd;
 
 use strict;
-
 use IO::Socket::INET;
 use Event;
 use Carp;
@@ -28,7 +27,8 @@ use SrSv::Conf2Consts qw( main );
 
 use SrSv::Debug;
 use SrSv::Log;
-
+use Exporter 'import';
+our @EXPORT = qw (agent_doconn getRevUuid getUuid setRevUuid setUuid);
 # FIXME
 use constant {
        MAXBUFLEN => 510,
@@ -59,25 +59,47 @@ use SrSv::IRCd::State qw($ircline $remoteserv $ircd_ready synced initial_synced
 
 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;
@@ -105,8 +127,9 @@ sub handle_server($$$$;$$$) {
        $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
@@ -122,9 +145,14 @@ sub pong($$$) {
                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";
@@ -226,7 +254,8 @@ sub __privmsg($$@) {
                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;
@@ -265,7 +294,10 @@ sub notice($$@) {
                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]);
@@ -328,7 +360,8 @@ sub ban_list($$$$@) {
 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;
@@ -398,20 +431,13 @@ sub kline ($$$$$) {
         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 ($$$) {
@@ -497,9 +523,8 @@ sub svsnick($$$) {
     # 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($$$) {
@@ -602,17 +627,12 @@ sub sqline ($;$) {
 }
 
 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($) {
@@ -704,7 +724,19 @@ sub jupe_server($$) {
 
        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) = @_;
 
@@ -767,6 +799,16 @@ sub enable_cloakhost($$) {
        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;
index ed81216b7fa7119e3b4f4e05e87089bd1f0d88bd..84e8713b7c2c9f2b784637ed6020238c59da5b8b 100644 (file)
@@ -92,6 +92,7 @@ my %unrealTokens = (
        SENDSNO         => ['SENDSNO',  'Ss'],
 
        EOS             => ['EOS',      'ES'],
+       ENDBURST => ['ENDBURST'],
        UMODE2          => ['UMODE2',   "\|"],
 
        REHASH          => ['REHASH',   'O'],
index 9381a77ec41aba34675c07d30cf1b0bf73a90a4a..fb5fdf0898a60b792e3dee27f4591d890a6d5c4f 100644 (file)
@@ -39,10 +39,10 @@ my %userlist;
 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 {
index 5fcde609e6132fee78842f170b8fe2ef89c31c23..52049abe73591188184142320d5e119827aa680f 100644 (file)
@@ -42,7 +42,7 @@ proc_init {
 };
 
 our $rsnick = 'ServServ';
-
+our $rsUser = { NICK => $rsnick, ID => ircd::getUuid($rsnick) };
 addhandler('STATS', undef, undef, 'core::stats');
 sub stats($$) {
        my ($src, $token) = @_;
@@ -62,10 +62,10 @@ sub pingtimer($) {
 
 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");
@@ -74,8 +74,9 @@ sub ev_connect {
 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");
index c7102fd7da92aca76ecf957e80dac45ffd47057b..d399daacde992b224bbee18f9c694155424adc35 100644 (file)
@@ -15,7 +15,7 @@
 #      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);
@@ -78,13 +78,16 @@ if(services_conf_hostserv) {
 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();
@@ -93,7 +96,7 @@ sub ev_connect {
        operserv::expire();
 }
 
-addhandler('EOS', undef, undef, 'services::eos');
+addhandler('ENDBURST', undef, undef, 'services::eos');
 sub eos {
        chanserv::eos($_[0]);
 }
@@ -113,8 +116,8 @@ addhandler('CHGHOST', undef, undef, 'nickserv::chghost');
 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');
@@ -127,11 +130,11 @@ addhandler('KICK', undef, undef, 'chanserv::process_kick');
 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');
@@ -142,7 +145,7 @@ sub 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');
 
@@ -152,7 +155,7 @@ addhandler('PRIVMSG', undef, undef, 'botserv::dispatch');
 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');
@@ -160,7 +163,7 @@ 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
index 9d8a0516f8bfecb54911e1f7ca1346be19f004dc..8b7a95d4557a617cf218914b2dd876ed318b5849 100644 (file)
@@ -59,6 +59,11 @@ for(my $i = scalar(@flags) - 1; $i >= 0; $i--) {
        $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 = (
@@ -71,8 +76,6 @@ our @defflags = (
 );
 
 }
-our $asnick_default = 'AdminServ';
-our $asnick = $asnick_default;
 
 
 our (
@@ -104,18 +107,18 @@ sub init() {
 ### 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;
        }
 
@@ -186,7 +189,7 @@ sub as_svs_add($$$) {
        $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($$) {
@@ -203,7 +206,7 @@ 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($$) {
@@ -267,9 +270,9 @@ sub can_do($$) {
        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;
@@ -282,7 +285,8 @@ sub is_svsop($;$) {
        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;
@@ -361,6 +365,7 @@ sub get_best_svs_level($) {
        $user->{SVSOP_LEVEL} = $level; $user->{SVSOP_NICK} = $nick;
        
        if(wantarray) {
+               print "LEVEL $level\n";
                return ($level, $nick);
        } else {
                return $level;
index b64c85d13708befb0e8778ca120aec4208f4c9dd..b27b7c2e4e6662d6f07575ce2d498a44a676cede 100644 (file)
@@ -22,9 +22,10 @@ use Safe;
 
 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 );
 
@@ -45,6 +46,7 @@ use constant {
 our $bsnick_default = 'BotServ';
 our $bsnick = $bsnick_default;
 our $botchmode;
+our $bsuser = { NICK => $bsnick, ID => "123AAAAAF" };
 if(!ircd::PREFIXAQ_DISABLE()) {
        $botchmode = '+q';
 } else {
@@ -95,10 +97,12 @@ sub init() {
 };
 
 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 =~ /^\!/) {
@@ -120,12 +124,13 @@ sub dispatch($$$) {
 ### 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);
 
@@ -251,11 +256,10 @@ sub bs_assign($$$) {
                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);
@@ -316,8 +320,12 @@ sub bs_add($$$$$) {
        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.");
 }
 
@@ -456,14 +464,21 @@ sub bs_change($$$$$$) {
        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();
@@ -480,14 +495,13 @@ sub bs_change($$$$$$) {
 ### 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,
@@ -579,6 +593,7 @@ sub chan_dispatch($$$) {
 
        sub give_ops {
                my ($user, $chan, $cmd, undef, @args) = @_;
+               
                chanserv::cs_setmodes($user, $cmd, $chan, @args);
        }
        sub up {
@@ -748,28 +763,24 @@ sub bot_say($$$) {
 ### 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);
@@ -824,8 +835,13 @@ sub register() {
        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);
        }
 }
 
@@ -834,9 +850,11 @@ sub eos() {
        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;
@@ -859,15 +877,16 @@ sub unset_flag($$) {
 }
 
 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 );
        }
 }
 
@@ -876,7 +895,6 @@ sub bot_part_if_needed($$$;$) {
        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)) {
index 8fed714cd076f5f31fcf52376da064e33c166811..0103253574f6556d62cb802b04fd4639f5f8b226 100644 (file)
@@ -58,7 +58,7 @@ use SrSv::MySQL qw( $dbh :sql_types );
 use SrSv::MySQL::Glob;
 
 use SrSv::Util qw( makeSeqList );
-
+use Data::Dumper;
 use constant {
        UOP => 1,
        VOP => 2,
@@ -142,6 +142,7 @@ $chanuser_table = 0;
 
 our $csnick_default = 'ChanServ';
 our $csnick = $csnick_default;
+our $csUser = { NICK => $csnick, ID => "123AAAAAC" };
 
 our ($cur_lock, $cnt_lock);
 
@@ -207,7 +208,7 @@ our (
        $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,
 
@@ -494,6 +495,8 @@ sub init() {
                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=?");
@@ -538,16 +541,15 @@ our %high_priority_cmds = (
 );
 
 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) 
@@ -2100,7 +2102,14 @@ sub cs_why($$@) {
                $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);
@@ -2109,7 +2118,7 @@ sub cs_why($$@) {
 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;
@@ -2266,7 +2275,7 @@ sub cs_kick($$$;$$) {
 
        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)) {
@@ -2298,7 +2307,7 @@ sub cs_kick($$$;$$) {
                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);
@@ -2561,7 +2570,7 @@ sub cs_close($$$) {
        $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";
@@ -3429,7 +3438,7 @@ sub kickban($$$$;$) {
        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;
 }
 
@@ -3444,7 +3453,7 @@ sub kickban_multi($$$) {
 
        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);
        }
 }
 
@@ -3460,7 +3469,7 @@ sub clear_users($$)  {
        $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++;
        }
@@ -3489,7 +3498,7 @@ sub kickmask($$$$)  {
        $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++;
        }
@@ -3519,7 +3528,7 @@ sub kickmask_noacc($$$$)  {
        $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++;
        }
@@ -3536,11 +3545,12 @@ sub clear_ops($) {
 
        $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];
                        }
                }
        }
@@ -3571,13 +3581,8 @@ sub unban_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) {
@@ -3585,7 +3590,6 @@ sub unban_user($@) {
                unless($tuid = get_user_id($tuser)) {
                        next;
                }
-
                my (@bans);
                # We don't handle extended bans. Yet.
                $find_bans_chan_user->execute($cn, $tuid, 0);
@@ -3636,10 +3640,8 @@ sub do_nick_akick($$;$) {
        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);
@@ -3649,7 +3651,7 @@ sub do_nick_akick($$;$) {
 
 sub check_akick($$;$) {
        my ($user, $chan, $check_only) = @_;
-
+       print "Do status!\n";
        if(adminserv::is_svsop($user, adminserv::S_HELP())) {
                return 0;
        }
@@ -3732,7 +3734,6 @@ sub akick_allchan($) {
 
 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());
@@ -3746,6 +3747,9 @@ sub akickban(@) {
                $ident =~ tr/\%\_/\*\?/;
                $host =~ tr/\%\_/\*\?/;
        }
+       if(defined($reason) && $reason =~ /\|/) {
+               ($reason, undef) = split(/ ?\| ?/, $reason, 2);
+       }
 
        if(defined($reason) && $reason =~ /\|/) {
                ($reason, undef) = split(/ ?\| ?/, $reason, 2);
@@ -3824,7 +3828,7 @@ sub fix_private_join_before_id($) {
                unban_user($chan, $user);
        }
 
-       ircd::svsjoin($csnick, get_user_nick($user), @cns) if @cns;
+       ircd::svsjoin($csUser, $user, @cns) if @cns;
 }
 
 ### DATABASE UTILITY FUNCTIONS ###
@@ -4177,7 +4181,6 @@ sub set_modes($$$;$$) {
        $doneg = 0 unless defined($doneg);
        my $cn = $chan->{CHAN};
 
-
        if ($acc < 0) {
        # Do akick stuff here.
        }
@@ -4233,13 +4236,15 @@ sub set_mode_mask($$$$) {
 
                        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);
        }
 }
 
@@ -4296,7 +4301,6 @@ sub can_do($$$;$) {
        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.
@@ -4330,10 +4334,27 @@ sub can_do($$$;$) {
 
 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);
@@ -4354,7 +4375,7 @@ sub __can_do($$$;$) {
                }
        }
        $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);
@@ -4412,17 +4433,19 @@ sub can_keep_op($$$$) {
 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;
 }
 
@@ -4445,7 +4468,7 @@ sub drop($) {
        $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($) {
@@ -4547,8 +4570,7 @@ sub user_join($$) {
 # 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) {
@@ -4563,6 +4585,7 @@ sub user_join($$) {
 }
 
 sub handle_sjoin($$$$$$$) {
+       print "wheeeeeeeeee\n";
        my ($server, $cn, $ts, $chmodes, $chmodeparms, $userarray, $banarray, $exceptarray) = @_;
        my $chan = { CHAN => $cn };
 
@@ -4571,6 +4594,8 @@ sub handle_sjoin($$$$$$$) {
        } 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) {
@@ -4586,7 +4611,6 @@ sub user_join_multi($$) {
        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})) {
@@ -4640,7 +4664,6 @@ sub user_join_multi($$) {
                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);
                }
@@ -4657,15 +4680,16 @@ sub user_join_multi($$) {
        }
 
        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)) {
@@ -4698,9 +4722,7 @@ sub user_join_multi($$) {
 
 sub user_part($$$) {
        my ($nick, $cn, $reason) = @_;
-
        my $user = ( ref $nick eq 'HASH' ? $nick : { NICK => $nick });
-
        user_part_multi($user, [ $cn ], $reason);
 }
 
@@ -4713,12 +4735,10 @@ sub user_part_multi($$$) {
 # 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);
@@ -4750,26 +4770,32 @@ sub channel_emptied($) {
 
 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);
 
@@ -4794,8 +4820,8 @@ sub chan_mode($$$$) {
                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);
@@ -4808,8 +4834,7 @@ sub chan_mode($$$$) {
                        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);
@@ -4836,7 +4861,7 @@ sub chan_mode($$$$) {
                        #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($$$$) {
@@ -4852,33 +4877,46 @@ 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);
@@ -4897,6 +4935,8 @@ sub eos(;$) {
                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);
                }
index 6649ee03d8a7578b3d955eef2b570576a1019335..f8e7c96c09217bbce02ee41cacee30d0b5a75f68 100644 (file)
@@ -36,7 +36,7 @@ require SrSv::DB::StubGen;
 
 our $hsnick_default = 'HostServ';
 our $hsnick = $hsnick_default;
-
+our $hsuser = { NICK => $hsnick, ID => "123AAAAAH" };
 sub init() {
 import SrSv::DB::StubGen (
        dbh => $dbh,
@@ -57,15 +57,15 @@ services_mysql_stubgen(
 }
 
 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);
        }
@@ -121,10 +121,11 @@ sub hs_on($$;$) {
                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");
 }
@@ -134,7 +135,7 @@ sub hs_off($) {
        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.");
 }
index 5f28602bf7e0b9899185a1074739d5b21cab3dfd..d58d1b4379adbec1d5f0c32d51c0347b5980b4a7 100644 (file)
@@ -48,7 +48,7 @@ use constant (
 
 our $msnick_default = 'MemoServ';
 our $msnick = $msnick_default;
-
+our $msuser = { NICK => $msnick, ID => "123AAAAAE" };
 our (
        $send_memo, $send_chan_memo, $get_chan_recipients,
 
@@ -63,9 +63,11 @@ our (
 
        $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
@@ -120,13 +122,13 @@ sub init() {
 ### 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.");
@@ -150,10 +152,10 @@ sub dispatch($$$) {
                }
        }
        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) {
@@ -255,7 +257,23 @@ sub ms_read($$) {
                        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);
        }
 
@@ -414,7 +432,7 @@ sub notify($;$) {
        my ($user, $root) = @_;
        my (@nicks);
 
-       unless(ref($user)) {
+       unless(ref($user) eq "HASH") {
                $user = { NICK => $user };
        }
 
@@ -458,7 +476,7 @@ sub send_chan_memo($$$$) {
        
        $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");
        }
 }
@@ -467,7 +485,7 @@ sub notice_all_nicks($$) {
        my ($nick, $msg) = @_;
 
        foreach my $u (get_nick_user_nicks $nick) {
-               notice({ NICK => $u, AGENT => $msnick }, $msg);
+               notice({ NICK => $u, AGENT => $msuser }, $msg);
        }
 }
 
index af0fe8c197f7026bb7a13a1633ad4c0b83853dc2..3b8e0a932b78a4d8ba160af681716d02ebd52eec 100644 (file)
@@ -46,9 +46,9 @@ use SrSv::Hash::Passwords;
 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;
@@ -56,7 +56,7 @@ 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.
@@ -78,7 +78,7 @@ use constant {
 
 our $nsnick_default = 'NickServ';
 our $nsnick = $nsnick_default;
-
+our $nsuser = { NICK => $nsnick, ID => "123AAAAAB" }; #FIXME - erry
 our $cur_lock;
 our $cnt_lock = 0;
 
@@ -110,11 +110,11 @@ our %protect_level = (
 );
        
 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,
@@ -178,16 +178,26 @@ our (
        $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=?");
@@ -646,15 +656,16 @@ our %high_priority_cmds = (
 );
 
 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)
@@ -908,8 +919,8 @@ sub ns_identify($$$;$) {
                                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;
                }
        }
@@ -956,7 +967,7 @@ sub ns_logout($) {
        $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);
 }
@@ -1038,7 +1049,7 @@ my @ghostbusters_quotes = (
 
        } 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);
@@ -1091,11 +1102,11 @@ sub ns_register($$$) {
                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 {
@@ -1516,7 +1527,7 @@ sub ns_set($$$$) {
                        $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;
@@ -1867,7 +1878,7 @@ sub ns_watch($$$;$) {
                }
 
                $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;
        }
@@ -1878,7 +1889,7 @@ sub ns_watch($$$;$) {
                        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) {
@@ -1987,7 +1998,7 @@ sub get_silence_by_num($$) {
 
                        $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) {
@@ -2019,7 +2030,7 @@ sub get_silence_by_num($$) {
                        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) {
@@ -2476,9 +2487,11 @@ sub unidentify($$;$) {
        $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');
                }
        }
 
@@ -2488,9 +2501,10 @@ sub unidentify($$;$) {
 # 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');
        }
 }
 
@@ -2510,7 +2524,7 @@ sub kill_clones($$) {
        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;
        }
 }
@@ -2527,7 +2541,6 @@ sub do_identify ($$$;$$) {
        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);
 
@@ -2548,23 +2561,15 @@ sub do_identify ($$$;$$) {
        $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)) {
@@ -2573,19 +2578,33 @@ sub do_identify ($$$;$$) {
        }
 
        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);
 }
 
@@ -2680,14 +2699,15 @@ sub get_hostmask($) {
 
 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;
 }
@@ -2788,7 +2808,8 @@ sub do_expired_silences($$) {
 
        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 ) );
@@ -2810,7 +2831,7 @@ sub do_svssilence($$) {
                push @silences, "+$mask";
        }
        $get_silences->finish;
-       ircd::svssilence($nsnick, $target, @silences);
+       ircd::svssilence($nsuser, $user, @silences);
        return;
 }
 
@@ -2830,7 +2851,7 @@ sub do_svswatch($$) {
                push @watches, "+$mask";
        }
        $get_watches->finish;
-       ircd::svswatch($nsnick, $target, @watches);
+       ircd::svswatch($nsuser, $user, @watches);
        return;
 }
 
@@ -2841,13 +2862,13 @@ sub do_umode($$) {
        $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.", 
@@ -2861,8 +2882,8 @@ sub protect($) {
 
        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,",
@@ -2888,13 +2909,14 @@ sub protect($) {
 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.');
@@ -2909,12 +2931,11 @@ sub warn_countdown($) {
 
 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($) {
@@ -2986,6 +3007,7 @@ sub get_user_modes($) {
        $get_umodes->execute($uid);
        my ($umodes) = $get_umodes->fetchrow_array;
        $get_umodes->finish();
+       print "UMODES $umodes\n";
        return $umodes;
 };
 
@@ -3116,7 +3138,7 @@ sub inc_nick_inval($) {
        $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;
@@ -3170,7 +3192,7 @@ sub check_identify($) {
        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 {
@@ -3209,7 +3231,7 @@ sub fix_vhosts() {
        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);
        }
@@ -3230,8 +3252,8 @@ sub nick_cede($) {
 ### 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 '+') {
@@ -3247,6 +3269,26 @@ sub nick_create {
        }
 
        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();
@@ -3268,7 +3310,7 @@ sub nick_create {
                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);
 
@@ -3302,30 +3344,23 @@ sub nick_create_post($) {
 }
 
 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($$$) {
@@ -3355,16 +3390,15 @@ 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();
@@ -3375,15 +3409,25 @@ sub nick_change($$$) {
                }
                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);
index bee506a726a8430b4996f23245b507df6f54577f..eac60918fa12b57439fc98c0602afd5bd4122d41 100644 (file)
@@ -47,7 +47,7 @@ use constant {
 
 our $osnick_default = 'OperServ';
 our $osnick = $osnick_default;
-
+our $osuser = { NICK => $osnick, ID => "123AAAAAD" };
 my %newstypes = (
        u => 'User',
        o => 'Oper'
@@ -138,17 +138,18 @@ sub init() {
 }
 
 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");
@@ -412,7 +413,7 @@ sub os_fjoin($$@) {
                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($$@) {
@@ -436,7 +437,7 @@ sub os_fpart($$@) {
        }
        $reason = join(' ', @params) if @params;
        
-       ircd::svspart($osnick, $target, $reason, @chans);
+       ircd::svspart($osuser, $target, $reason, @chans);
 }
 
 sub os_qline_add($$$$) {
@@ -618,7 +619,7 @@ sub os_svsnick($$$) {
                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;
 }
@@ -809,7 +810,7 @@ sub os_except_hostname_del($$) {
        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");
@@ -918,7 +919,6 @@ sub os_rehash($;$) {
        return $event::SUCCESS;
 }
 
-
 sub os_svskill($$$) {
        my ($user, $targets, $reason) = @_;
        
@@ -935,7 +935,7 @@ sub os_svskill($$$) {
                        return $event::SUCCESS;
                }
 
-               ircd::svskill($osnick, $target, $reason);
+               ircd::svskill($osuser, $target, $reason);
        }
 
        return $event::SUCCESS;
@@ -951,7 +951,7 @@ sub os_kill($$$) {
        }
 
        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;
@@ -1008,7 +1008,7 @@ sub os_gline($$$@) {
        }
        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);
                }
@@ -1034,7 +1034,7 @@ sub os_gline($$$@) {
                        return;
                }
                if(!$remove) {
-                       ircd::zline($opernick, $host, $expiry, $reason);
+                       ircd::zline($osnick, $host, $expiry, $reason);
                } else {
                        ircd::unzline($opernick, $host);
                }
@@ -1117,7 +1117,7 @@ sub __os_massmod($$$$@) {
                }
                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" : '')
@@ -1131,7 +1131,7 @@ sub __os_massmod($$$$@) {
                }
                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" : '')
@@ -1142,7 +1142,7 @@ sub __os_massmod($$$$@) {
                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
@@ -1163,8 +1163,8 @@ sub __os_massmod($$$$@) {
                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 {