]>
Commit | Line | Data |
---|---|---|
5e682044 | 1 | # This file is part of SurrealServices. |
2 | # | |
3 | # SurrealServices is free software; you can redistribute it and/or modify | |
4 | # it under the terms of the GNU General Public License as published by | |
5 | # the Free Software Foundation; either version 2 of the License, or | |
6 | # (at your option) any later version. | |
7 | # | |
8 | # SurrealServices is distributed in the hope that it will be useful, | |
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | # GNU General Public License for more details. | |
12 | # | |
13 | # You should have received a copy of the GNU General Public License | |
14 | # along with SurrealServices; if not, write to the Free Software | |
15 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
16 | ||
17 | package SrSv::IRCd::Parse; | |
18 | ||
19 | use strict; | |
20 | ||
21 | use Exporter 'import'; | |
22 | # parse_sjoin shouldn't get used anywhere else, as we never produce SJOINs | |
23 | # parse_tkl however is used for loopbacks. | |
24 | BEGIN { our @EXPORT_OK = qw(parse_line parse_tkl parse_addline) } | |
25 | ||
26 | # FIXME | |
27 | BEGIN { *SJB64 = \&ircd::SJB64; *CLK = \&ircd::CLK; *NICKIP = \&ircd::NICKIP; } | |
28 | ||
29 | use SrSv::Conf 'main'; | |
30 | ||
31 | use SrSv::Debug; | |
32 | use SrSv::IRCd::State qw($ircline $remoteserv create_server get_server_children set_server_state get_server_state %IRCd_capabilities); | |
33 | use SrSv::IRCd::Queue qw(queue_size); | |
34 | use SrSv::IRCd::IO qw( ircsend ircsendimm); | |
35 | use SrSv::IRCd::Send qw (getRevUuid getUuid setRevUuid setUuid); | |
36 | use SrSv::Unreal::Modes qw(%opmodes); | |
026939ee | 37 | use SrSv::RunLevel 'main_shutdown'; |
5e682044 | 38 | # Unreal uses its own modified base64 for everything except NICKIP |
39 | use SrSv::Unreal::Base64 qw(b64toi itob64); | |
40 | use SrSv::User '/./'; | |
41 | # Unreal uses unmodified base64 for NICKIP. | |
42 | # Consider private implementation, | |
43 | # tho MIME's is probably faster | |
44 | use MIME::Base64; | |
45 | use Data::Dumper; | |
7b3a5814 | 46 | use SrSv::Insp::UUID; |
5e682044 | 47 | # FIXME |
48 | use constant { | |
49 | # Wait For | |
50 | WF_NONE => 0, | |
51 | WF_NICK => 1, | |
52 | WF_CHAN => 2, | |
53 | WF_ALL => 3, | |
54 | }; | |
55 | ||
56 | use SrSv::Shared qw(@servernum); | |
57 | ||
58 | our %cmdhash; | |
59 | ||
60 | sub parse_line($) { | |
61 | my ($in) = @_; | |
62 | if (!$in) { | |
63 | return; | |
64 | } | |
65 | my $cmd; | |
66 | ||
67 | if($in =~ /^(?:@|:)(\S+) (\S+)/) { | |
68 | $cmd = $2; | |
69 | } | |
70 | elsif ($in =~ /^(\S+)/) { | |
71 | $cmd = $1; | |
72 | } | |
73 | my $sub = $cmdhash{$cmd}; | |
74 | unless (defined($sub)) { | |
75 | print "Bailing out from $ircline:$cmd for lack of cmdhash\n" if DEBUG(); | |
76 | return undef(); | |
77 | } | |
78 | my ($event, $src, $dst, $wf, @args) = &$sub($in); | |
79 | unless (defined($event)) { | |
80 | print "Bailing out from $ircline:$cmd for lack of event\n" if DEBUG; | |
81 | return undef(); | |
82 | } | |
83 | #return unless defined $event; | |
84 | ||
85 | my (@recipients, @out); | |
86 | if(defined($dst)) { | |
87 | #$args[$dst] = lc $args[$dst]; | |
88 | @recipients = split(/\,/, $args[$dst]); | |
89 | } | |
90 | #if(defined($src)) { $args[$src] = lc $args[$src]; } | |
91 | ||
92 | if(@recipients > 1) { | |
93 | foreach my $rcpt (@recipients) { | |
94 | $args[$dst] = $rcpt; | |
95 | push @out, [$event, $src, $dst, $wf, [@args]]; | |
96 | } | |
97 | } else { | |
98 | @out = [$event, $src, $dst, $wf, [@args]]; | |
99 | } | |
100 | ||
101 | return @out; | |
102 | } | |
103 | #parse_fjoin($server, $channel, $ts, $modes, @nicks, @status) | |
104 | sub parse_fjoin ($$$$$$) { | |
105 | my ($server, $channel, $ts, $modes, $idsr, $statusref) = @_; | |
106 | my @status = @$statusref; | |
107 | my @ids = @$idsr; | |
108 | my $i = 0; | |
109 | my @users; | |
110 | foreach my $id (@ids) { | |
111 | my $op = 0; | |
112 | my @ops = split ("",$status[$i]); | |
113 | foreach my $prefix (@ops) { | |
114 | $op |= $opmodes{$prefix}; | |
115 | } | |
7b3a5814 | 116 | my $user = {ID => $id, __OP=>$op}; #ID'S are _already_ decoded in FJOIN! |
5e682044 | 117 | get_user_nick ($user); |
118 | push @users, $user; | |
119 | $i++; | |
120 | } | |
121 | return ($server, $channel, $ts, $modes, undef, \@users, undef, undef, undef); #bans etc are got from FMODE.. | |
122 | } | |
123 | sub parse_sjoin($$$$) { | |
124 | my ($server, $ts, $cn, $parms) = @_; | |
125 | my (@users, @bans, @excepts, @invex, @blobs, $blobs, $chmodes, $chmodeparms); | |
126 | ||
127 | $server = '' unless $server; | |
128 | ||
129 | if($parms =~ /^:(.*)/) { | |
130 | $blobs = $1; | |
131 | } else { | |
132 | ($chmodes, $blobs) = split(/ :/, $parms, 2); | |
133 | ($chmodes, $chmodeparms) = split(/ /, $chmodes, 2); | |
134 | } | |
135 | @blobs = split(/ /, $blobs); | |
136 | ||
137 | foreach my $x (@blobs) { | |
138 | if($x =~ /^(\&|\"|\')(.*)$/) { | |
139 | my $type; | |
140 | push @bans, $2 if $1 eq '&'; | |
141 | push @excepts, $2 if $1 eq '"'; | |
142 | push @invex, $2 if $1 eq "\'"; | |
143 | } else { | |
144 | $x =~ /^([*~@%+]*)(.*)$/; | |
145 | my ($prefixes, $nick) = ($1, $2); | |
146 | my @prefixes = split(//, $prefixes); | |
147 | my $op = 0; | |
148 | foreach my $prefix (@prefixes) { | |
149 | $op |= $opmodes{q} if ($prefix eq '*'); | |
150 | $op |= $opmodes{a} if ($prefix eq '~'); | |
151 | $op |= $opmodes{o} if ($prefix eq '@'); | |
152 | $op |= $opmodes{h} if ($prefix eq '%'); | |
153 | $op |= $opmodes{v} if ($prefix eq '+'); | |
154 | } | |
155 | ||
156 | push @users, { NICK => $nick, __OP => $op }; | |
157 | } | |
158 | } | |
159 | ||
160 | return ($server, $cn, $ts, $chmodes, $chmodeparms, \@users, \@bans, \@excepts, \@invex); | |
161 | } | |
162 | sub parse_addline ($) { | |
163 | my ($line) = @_; | |
164 | #return ($type, +1, $ident, $host, $setter, $expire, $time, $reason); | |
165 | #>> 47 :583AAAAAA ADDLINE G test@testie inspircd.erry.omg 1308118489 0 :hi | |
166 | my ($setter, undef, $type, $mask, $server, $time, $expiry, $reason) = split (/ /, $line, 7); | |
167 | $reason =~ /:(.*)/; | |
168 | $reason = $1; | |
169 | $setter =~ /:(.*)/; | |
170 | $setter = $1; | |
171 | my @masks = split (/@/,$mask, 1); | |
172 | my $ident = $masks[0]; | |
173 | my $host = $masks[1]; | |
174 | #return ($type, +1, $ident, $host, $setter, $expire, $time, $reason); | |
175 | return ($type, +1, $ident, $host, $setter, $expiry, $time, $reason); | |
176 | } | |
177 | sub parse_tkl ($) { | |
178 | my ($in) = @_; | |
179 | # This function is intended to accept ALL tkl types, | |
180 | # tho maybe not parse all of them in the first version. | |
181 | ||
182 | # Discard first token, 'TKL' | |
183 | my (undef, $sign, $type, $params) = split(/ /, $in, 4); | |
184 | ||
185 | # Yes, TKL types are case sensitive! | |
186 | # also be aware (and this applies to the net.pm generator functions too) | |
187 | # This implementation may appear naiive, but Unreal assumes that, for a given | |
188 | # TKL type, that all parameters are non-null. | |
189 | # Thus, if any parameters ARE null, Unreal WILL segfault. | |
190 | ## Update: this problem may have been fixed since Unreal 3.2.2 or so. | |
191 | if ($type eq 'G' or $type eq 'Z' or $type eq 's' or $type eq 'Q') { | |
192 | # format is | |
193 | # TKL + type ident host setter expiretime settime :reason | |
194 | # TKL - type ident host setter | |
195 | # for Q, ident is always '*' or 'h' (Services HOLDs) | |
196 | if ($sign eq '+') { | |
197 | my ($ident, $host, $setter, $expire, $time, $reason) = split(/ /, $params, 6); | |
198 | ||
199 | $reason =~ s/^\://; | |
200 | return ($type, +1, $ident, $host, $setter, $expire, $time, $reason); | |
201 | } | |
202 | elsif($sign eq '-') { | |
203 | my ($ident, $host, $setter) = split(/ /, $params, 3); | |
204 | return ($type, -1, $ident, $host, $setter); | |
205 | } | |
206 | } | |
207 | elsif($type eq 'F') { | |
208 | # TKL + F cpnNPq b saturn!attitude@netadmin.SCnet.ops 0 1099959668 86400 Possible_mIRC_DNS_exploit :\/dns (\d+\.){3}\d | |
209 | # TKL + F u g saturn!attitude@saturn.netadmin.SCnet.ops 0 1102273855 604800 sploogatheunbreakable:_Excessively_offensive_behavior,_ban_evasion. :.*!imleetnig@.*\.dsl\.mindspring\.com | |
210 | # TKL - F u Z tabris!northman@tabris.netadmin.SCnet.ops 0 0 :do_not!use@mask | |
211 | if ($sign eq '+') { | |
212 | my ($target, $action, $setter, $expire, $time, $bantime, $reason, $mask) = split(/ /, $params, 8); | |
213 | $mask =~ s/^\://; | |
214 | return ($type, +1, $target, $action, $setter, $expire, $time, $bantime, $reason, $mask); | |
215 | } | |
216 | elsif($sign eq '-') { | |
217 | my ($target, $action, $setter, $expire, $time, $mask) = split(/ /, $params, 6); | |
218 | $mask =~ s/^\://; | |
219 | return ($type, -1, $target, $action, $setter, $mask); | |
220 | } | |
221 | } | |
222 | } | |
223 | ||
224 | sub PING($) { | |
225 | my ($event, $src, $dst, @args); | |
226 | $_[0] =~ /^(?:8|PING) :(\S+)$/; | |
227 | # ($event, $src, $dst, $args) | |
228 | return ('PING', undef, undef, WF_NONE, $1); | |
229 | } | |
230 | sub UID ($) { | |
231 | #:583 UID 583AAAAAJ 1307703236 erry__ localhost localhost errietta 127.0.0.1 1307703241 + :errietta | |
7b3a5814 | 232 | $_[0] =~ /^(:\S+) UID (\S+) (\d+) (\S+) (\S+) (\S+) (\S+) (\S+) (\d+) (\S+) :(.*)$/; |
233 | my ($server, $uid, $stamp, $nick, $host, $vhost, $ident, $IP, $ts, $modes, $gecos) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12); | |
234 | print "UID $uid " . decodeUUID($uid) . "\n"; | |
235 | my $user = { NICK => $nick, ID => decodeUUID($uid) }; | |
236 | return ('NICKCONN', undef, undef, WF_NICK, $user, 0, $ts, $ident, $host, $server, $stamp, $modes, $vhost, $gecos, | |
237 | join('.', unpack('C4', MIME::Base64::decode($IP)))); | |
5e682044 | 238 | } |
239 | sub EOS($) { | |
240 | my $event; | |
241 | print "EOS\n"; | |
242 | if ($_[1] != "ENDBURST") { | |
243 | $_[0] =~ /^(@|:)(\S+) (?:EOS|ES)/; # Sometimes there's extra crap on the end? | |
244 | my $server; | |
245 | if ($1 eq '@') { | |
246 | $server = $servernum[b64toi($2)]; | |
247 | } | |
248 | else { | |
249 | $server = $2; | |
250 | } | |
251 | print "SERVER $server\n"; | |
252 | set_server_state($server, 1); | |
253 | return undef() unless get_server_state($remoteserv); | |
254 | if($server eq $remoteserv) { $event = 'SEOS' } else { $event = 'EOS' } | |
255 | print "Ok. we had EOS\n"; | |
256 | return ($event, undef, undef, WF_ALL, $server); | |
257 | } | |
258 | else { | |
259 | print "wot\n"; | |
260 | $_[0] =~ /^:(\S+) ENDBURST/; | |
261 | my $server = $1; | |
262 | set_server_state($server, 1); | |
263 | print "server $server remote $remoteserv\n"; | |
264 | return undef() unless get_server_state($remoteserv); | |
265 | print "This be it! Got endbrust!\n"; | |
266 | return ("ENDBURST", undef, undef, WF_ALL, $1); | |
267 | } | |
268 | } | |
269 | ||
270 | sub SERVER($) { | |
271 | #ircd::debug($_[0]) if $debug; | |
272 | ||
273 | if($_[0] =~ /^(?:SERVER|\') (\S+) (\S+) :(U[0-9]+)-([A-Za-z0-9]+)-([0-9]+) (.*)$/) { | |
92c29160 | 274 | # SERVER test-tab.surrealchat.net 1 :U2307-FhinXeOoZEmM-200 SurrealChat |
275 | # cmd, servername, hopCount, U<protocol>-<buildflags>-<numeric> infoLine | |
5e682044 | 276 | $remoteserv = $1; |
277 | create_server($1); | |
278 | $servernum[$5] = $1; | |
279 | ||
280 | return ('SERVER', undef, undef, WF_ALL, undef, $1, $2, $6, $5, $3, $4); | |
281 | # src, serverName, numHops, infoLine, serverNumeric, protocolVersion, buildFlags | |
282 | } | |
283 | elsif($_[0] =~ /^(:|@)(\S+) (?:SERVER|\') (\S+) (\d+) (\d+) :(.*)$/) { | |
284 | # @38 SERVER test-hermes.surrealchat.net 2 100 :SurrealChat | |
285 | # source, cmd, new server, hopCount, serverNumeric, infoLine | |
286 | my ($numeric, $name); | |
287 | if ($1 eq '@') { | |
288 | $name = $servernum[b64toi($2)]; | |
289 | } | |
290 | else { | |
291 | $name = $2; | |
292 | } | |
293 | create_server($3, $name); | |
294 | $servernum[$5] = $3; | |
295 | ||
296 | return ('SERVER', undef, undef, WF_ALL, $name, $3, $4, $6, $5); | |
297 | # src, serverName, numHops, infoLine, serverNumeric | |
298 | } | |
299 | if($_[0] =~ /^(?:SERVER|\') (\S+) (\S+) :(.*)$/) { | |
300 | $remoteserv = $1; | |
301 | create_server($1); | |
302 | return ('SERVER', undef, undef, WF_ALL, undef, $1, $2, $3); | |
303 | # src, serverName, numHops, infoLine | |
304 | } | |
305 | elsif($_[0] =~ /^:(\S+) (?:SERVER|\') (\S+) (\d+) :(.*)$/) { | |
306 | # source, new server, hop count, description | |
307 | create_server($2, $1); | |
308 | return ('SERVER', undef, undef, WF_ALL, $1, $2, $3, $4); | |
309 | # src, serverName, numHops, infoLine | |
310 | } | |
311 | elsif ($_[0] =~ /SERVER (\S+) (\S+) (\d+) (\S+) :(.*)$/) { | |
312 | #SERVER inspircd.erry.omg mypass 0 583 :erry World | |
313 | #SERVER servername password hopcount SID :Server Desc | |
314 | $remoteserv = $4; | |
315 | create_server ($4); | |
316 | #since from now on we'll be getting commands as sent from the SID it's much wiser to keep that than the name. | |
317 | return ("SERVER", undef, undef, WF_ALL, undef, $1, $3, $5, $4); | |
318 | } | |
319 | } | |
320 | ||
321 | sub SQUIT($) { | |
322 | if($_[0] =~ /^(?:SQUIT|-) (\S+) :(.*)$/) { | |
323 | my $list = [get_server_children($1)]; | |
324 | set_server_state($1, undef()); | |
325 | return ('SQUIT', undef, undef, WF_ALL, undef, $list, $2); | |
326 | } | |
327 | elsif($_[0] =~ /^(:|@)(\S+) (?:SQUIT|-) (\S+) :(.*)$/) { | |
328 | my $name; | |
329 | if ($1 eq '@') { | |
330 | $name = $servernum[b64toi($2)]; | |
331 | } | |
332 | else { | |
333 | $name = $2; | |
334 | } | |
335 | my $list = [get_server_children($3)]; | |
336 | set_server_state($3, undef()); | |
337 | return ('SQUIT', undef, undef, WF_ALL, $name, $list, $4); | |
338 | } | |
339 | } | |
340 | ||
341 | sub NETINFO($) { | |
342 | $_[0] =~ /^(?:NETINFO|AO) (\S+) (\S+) (\S+) (\S+) (\S+) (\S+) (\S+) :(.*)$/; | |
343 | return ('NETINFO', undef, undef, WF_NONE, $1, $2, $3, $4, $5, $6, $7, $8); | |
344 | } | |
345 | ||
346 | sub PROTOCTL($) { | |
347 | $_[0] =~ /^PROTOCTL (.*)$/; | |
348 | return ('PROTOCTL', undef, undef, WF_NONE, $1); | |
349 | } | |
350 | ||
351 | sub JOIN($) { | |
352 | $_[0] =~ /^:(\S+) (?:C|JOIN) (\S+)$/; | |
7b3a5814 | 353 | my $user = { ID => decodeUUID($1) }; |
5e682044 | 354 | get_user_nick ($user); |
355 | return ('JOIN', undef, 1, WF_CHAN, $user, $2); | |
356 | } | |
357 | ||
358 | sub FJOIN ($) { | |
359 | #>> 13 :97K FJOIN #erry 1307879417 +nt :o,97KAAAAAA ,97KAAAAAB | |
92c29160 | 360 | if ($_[0] =~ m"^(:\S+) FJOIN (\S+) (\d+) (\S+) (:?)(.*)$") { |
361 | my ($server, $channel, $ts, $modes, $userstring) = ($1, $2, $3, $4, $6); | |
362 | my @users = split (" ", $userstring); | |
363 | my (@ids, @status); | |
364 | foreach my $user (@users) { | |
365 | my @params = split (",",$user); | |
366 | push (@status, $params[0]); | |
7b3a5814 | 367 | push (@ids, decodeUUID($params[1])); |
92c29160 | 368 | } |
369 | return ('SJOIN', undef, undef, WF_CHAN, parse_fjoin($server, $channel, $ts, $modes, \@ids, \@status)); | |
370 | } | |
371 | #>> 15 :583 FJOIN #opers 1310128904 +Pis : | |
372 | #CHANNELS CONFIGURED TO STAY OPEN WITH CHMODE +P (INSP) | |
373 | elsif ($_[0] =~ m"^(:\S+) FJOIN (\S+) (\d+) (\S+) :$") { | |
374 | print "WHOOOOOOF"; | |
375 | #FIXME - Update channel modes. | |
5e682044 | 376 | } |
5e682044 | 377 | } |
378 | sub SJOIN($) { | |
379 | if ($_[0] =~ /^(?:\~|SJOIN) (\S+) (\S+) (.*)$/) { | |
380 | my ($ts, $cn, $payload) = ($1, $2, $3); | |
381 | if ($ts =~ s/^!//) { | |
382 | $ts = b64toi($ts); | |
383 | } | |
384 | return ('SJOIN', undef, undef, WF_CHAN, parse_sjoin($remoteserv, $ts, $cn, $payload)); | |
385 | } | |
386 | elsif($_[0] =~ /^(@|:)(\S+) (?:\~|SJOIN) (\S+) (\S+) (.*)$/) { | |
387 | my ($server, $ts, $cn, $payload) = ($2, $3, $4, $5); | |
388 | if ($1 eq '@') { | |
389 | $server = $servernum[b64toi($2)]; | |
390 | } | |
391 | else { | |
392 | $server = $2; | |
393 | } | |
394 | if ($ts =~ s/^!//) { | |
395 | $ts = b64toi($ts); | |
396 | } | |
397 | return ('SJOIN', undef, undef, WF_CHAN, parse_sjoin($server, $ts, $cn, $payload)); | |
398 | } | |
399 | } | |
400 | ||
401 | sub PART($) { | |
402 | my $user; | |
403 | ||
404 | if($_[0] =~ /^:(\S+) (?:D|PART) (\S+) :(.*)$/) { | |
7b3a5814 | 405 | $user = {ID => decodeUUID($1)}; |
5e682044 | 406 | get_user_nick ($user); |
407 | return ('PART', undef, 0, WF_CHAN, $user, $2, $3); | |
408 | } | |
409 | elsif($_[0] =~ /^:(\S+) (?:D|PART) (\S+)$/) { | |
7b3a5814 | 410 | $user = {ID => decodeUUID($1)}; |
92c29160 | 411 | get_user_nick ($user); |
5e682044 | 412 | return ('PART', undef, 0, WF_CHAN, $user, $2, undef); |
413 | } | |
414 | } | |
415 | sub FMODE($) { | |
416 | #:583AAAAAR FMODE #erry 1308214721 +ib test!*@* When any mode in the channel is set. | |
417 | #: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. | |
418 | if($_[0] =~ /^:(\S+) FMODE (#\S+) (\d+) (\S+) ?(.*)$/) { | |
419 | my $id = $1; | |
7b3a5814 | 420 | my $user; |
421 | print "FMODE ID $id " . length($id); | |
422 | if (length($id) > 3) { #UID | |
423 | print "FFFFFFFFFFF\n"; | |
424 | $user = {ID => decodeUUID($id)}; | |
425 | get_user_nick ($user); | |
426 | } | |
427 | else { #SID | |
428 | $user = $id; | |
429 | } | |
430 | my $name; | |
431 | my $argz = $5; | |
432 | my @args = split(/ /, $argz); | |
433 | my $modes = $4; | |
434 | print "============MODES $modes=================\n"; | |
435 | print "5: $4\n"; | |
436 | print "6: $5\n"; | |
437 | my @modes = split(//, $modes); | |
438 | my @userargs; | |
439 | foreach my $mode (@modes) { | |
440 | if($mode eq '+' or $mode eq '-') { next; } | |
441 | if ($mode !~ /^[vhoaq]$/) { next; } | |
442 | my $arg = shift (@args); | |
443 | next if $arg eq ''; | |
444 | my $id = decodeUUID($arg); | |
445 | my $tuser = {ID=>$id}; | |
446 | get_user_nick ($tuser); | |
447 | push @userargs, $tuser; | |
448 | } | |
449 | return ('MODE', undef, 1, WF_ALL, $user, $2, $4, $5, @userargs); | |
5e682044 | 450 | } |
451 | } | |
452 | sub MODE($) { | |
453 | my $user; | |
7b3a5814 | 454 | if($_[0] =~ /^(@|:)(\S+) (?:G|MODE) (#\S+) (.*)(?: \d+)?$/) { |
5e682044 | 455 | my $name; |
456 | if ($1 eq '@') { | |
457 | $name = $servernum[b64toi($2)]; | |
458 | $user = {NICK => $name}; | |
459 | } | |
460 | else { | |
461 | $name = $2; | |
7b3a5814 | 462 | $user = { ID=>decodeUUID($name)}; |
5e682044 | 463 | get_user_nick ($user); |
464 | } | |
7b3a5814 | 465 | my $argz = $6; |
466 | my @args = split(/ /, $argz); | |
467 | my $modes = $5; | |
468 | print "============MODES $modes=================\n"; | |
469 | print "5: $5\n"; | |
470 | print "6: $6\n"; | |
471 | my @modes = split(//, $modes); | |
472 | my $newargs = ""; | |
473 | foreach my $mode (@modes) { | |
474 | if($mode eq '+' or $mode eq '-') { next; } | |
475 | my $arg = shift (@args); | |
476 | next if $arg eq ''; | |
477 | my $id = encodeUUID($arg); | |
478 | my $tuser = {ID=>$id}; | |
479 | my $nick = get_user_nick ($tuser); | |
480 | print "!!!!!!!!!!!1!!!!!$nick\n"; | |
481 | $newargs .= ($newargs eq ""?$nick:" $nick"); # what an awful way to do it. | |
482 | } | |
483 | my $arguements; | |
484 | if ($newargs eq "") { | |
485 | $arguements = $argz; | |
486 | } | |
487 | else { | |
488 | $arguements = $newargs; | |
489 | } | |
490 | return ('MODE', undef, 1, WF_ALL, $user, $3, $4, $arguements); | |
5e682044 | 491 | } |
492 | elsif($_[0] =~ /^:(\S+) (?:G|MODE) (\S+) :(\S+)$/) { | |
493 | # We shouldn't ever get this, as UMODE2 is preferred | |
7b3a5814 | 494 | $user = { ID => decodeUUID($1) }; |
5e682044 | 495 | get_user_nick ($user); |
496 | return ('UMODE', 0, 0, WF_ALL, $user, $3); | |
497 | } | |
498 | ||
499 | } | |
500 | ||
7b3a5814 | 501 | |
5e682044 | 502 | sub MESSAGE($) { |
503 | my ($event, @args); | |
504 | if($_[0] =~ /^(@|:)(\S+) (?:\!|PRIVMSG) (\S+) :(.*)$/) { | |
505 | ||
506 | my ($name, $srcUser, $dstUser) ; | |
507 | if ($1 eq '@') { | |
508 | $name = $servernum[b64toi($2)]; | |
509 | $srcUser = {NICK=>$name}; | |
510 | } | |
511 | else { | |
512 | $name = $2; | |
7b3a5814 | 513 | $srcUser = {ID=>decodeUUID($name)}; |
5e682044 | 514 | unless (get_user_nick ($srcUser)) { |
515 | $srcUser = {NICK=>$name}; | |
516 | get_user_id ($name); | |
517 | } | |
518 | } | |
519 | my $dest = $3; | |
7b3a5814 | 520 | $dstUser = {ID=>($dest)}; |
5e682044 | 521 | unless (get_user_nick ($dstUser)) { |
522 | $dstUser = {NICK=>$dest}; | |
523 | } | |
5e682044 | 524 | $event = 'PRIVMSG'; @args = ($srcUser, $dstUser, $4); |
525 | } | |
526 | elsif($_[0] =~ /^(@|:)(\S+) (?:B|NOTICE) (\S+) :(.*)$/) { | |
527 | my $name; | |
528 | if ($1 eq '@') { | |
529 | $name = $servernum[b64toi($2)]; | |
530 | } | |
531 | else { | |
532 | $name = $2; | |
533 | } | |
534 | $event = 'NOTICE'; @args = ($name, $3, $4); | |
535 | } | |
536 | $args[1] =~ s/\@${main_conf{local}}.*//io; | |
537 | ||
538 | if(queue_size > 50 and $event eq 'PRIVMSG' and $args[1] !~ /^#/ and $args[2] =~ /^\w/) { | |
539 | 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..."); | |
540 | } | |
541 | ||
542 | return ($event, 0, 1, WF_ALL, @args); | |
543 | } | |
544 | ||
545 | sub AWAY($) { | |
546 | if($_[0] =~ /^:(\S+) (?:6|AWAY) :(.*)$/) { | |
7b3a5814 | 547 | my $user = {ID=>decodeUUID($1)}; |
5e682044 | 548 | get_user_nick($user); |
549 | return ('AWAY', undef, undef, WF_ALL, $user, $2); | |
550 | } | |
551 | elsif($_[0] =~ /^:(\S+) (?:6|AWAY)$/) { | |
7b3a5814 | 552 | my $user = {ID => decodeUUID($1)}; |
5e682044 | 553 | get_user_nick ($user); |
554 | return ('BACK', undef, undef, WF_ALL, $user); | |
555 | } | |
556 | } | |
557 | ||
558 | sub NICK($) { | |
559 | my ($event, @args); | |
560 | #:97KAAAAAA NICK erry_ 1307878528 | |
561 | if($_[0] =~ /^:(\S+) (?:NICK|\&) (\S+) :?(\S+)$/) { | |
7b3a5814 | 562 | my $user = {ID => decodeUUID($1)}; |
5e682044 | 563 | get_user_nick ($user); |
7b3a5814 | 564 | set_user_nick (decodeUUID($1), $2); |
565 | set_user_id ($2, decodeUUID($1)); | |
5e682044 | 566 | return ('NICKCHANGE', undef, undef, WF_NICK, $user, $2, $3); |
567 | } | |
568 | } | |
569 | ||
570 | sub QUIT($) { | |
92c29160 | 571 | if ($_[0] =~ /^:(\S+) QUIT :Killed \((\S+) \((.*)\)\)$/) { |
572 | #:583AAAAAH QUIT :Killed (erry (die)) | |
7b3a5814 | 573 | my $victim = {ID=>decodeUUID($1)}; |
92c29160 | 574 | get_user_nick ($victim); |
575 | my $murderer = {NICK=>$2}; | |
576 | get_user_id ($murderer); | |
577 | my $reason = $3; | |
578 | return ('KILL', 0, 1, WF_NICK, $murderer, $victim, $reason, undef); | |
579 | } | |
580 | elsif ($_[0] =~ /^:(\S+) QUIT :(.*)$/) { | |
7b3a5814 | 581 | my $user = {ID=>decodeUUID($1)}; |
92c29160 | 582 | get_user_nick ($user); |
583 | return ('QUIT', 0, undef, WF_NICK, $user, $2); | |
5e682044 | 584 | } |
92c29160 | 585 | } |
586 | sub OPERQUIT ($) { | |
587 | if ($_[0] =~ /^:(\S+) QUIT :(.*)$/) { | |
7b3a5814 | 588 | my $user = {ID=>decodeUUID($1)}; |
92c29160 | 589 | get_user_nick ($user); |
590 | return ('QUIT', 0, undef, WF_NICK, $user, $2); | |
5e682044 | 591 | } |
5e682044 | 592 | } |
593 | ||
92c29160 | 594 | sub KILL($) { |
595 | #All insp sends is :583AAAAAH QUIT :Killed (erry (die)) | |
596 | #_VERY_ helpful. | |
597 | #UNLESS you kill someone who's in the services server: | |
598 | #:583AAAAAA KILL 123AAAAAA :Killed (erry (die)) | |
599 | #:123AAAAAA OPERQUIT :Killed (erry (die)) | |
600 | #And yes, for (some?) opers it's OPERQUIT not QUIT | |
601 | #Joy, JOY, JOY! | |
602 | $_[0] =~ /^:(\S+) KILL (\S+) :(.*)$/; | |
7b3a5814 | 603 | my $murderer = {ID=>decodeUUID($1)}; |
92c29160 | 604 | get_user_nick ($murderer); |
7b3a5814 | 605 | my $victim = {ID=>decodeUUID($2)}; |
92c29160 | 606 | get_user_nick ($victim); |
607 | return ("KILL", 0, 1, WF_NICK, $murderer, $victim, $3, undef); | |
608 | } | |
5e682044 | 609 | sub KICK($) { |
610 | #:tabris KICK #diagnostics SurrealBot :i know you don't like this. but it's for science! | |
611 | $_[0] =~ /^(@|:)(\S+) (?:KICK|H) (\S+) (\S+) :(.*)$/; | |
612 | # source, chan, target, reason | |
613 | #$src = 0; #$dst = 2; | |
614 | my $name; | |
615 | if ($1 eq '@') { | |
616 | $name = $servernum[b64toi($2)]; | |
617 | } | |
618 | else { | |
619 | $name = $2; | |
620 | } | |
7b3a5814 | 621 | my $user = {ID => decodeUUID($name)}; |
5e682044 | 622 | unless (get_user_nick ($user)) { |
623 | $user = {NICK => $name}; | |
624 | get_user_id ($user); | |
625 | } | |
626 | return ('KICK', 0, undef, WF_CHAN, $user, $3, $4, $5); | |
627 | } | |
628 | ||
629 | sub HOST($) { | |
630 | if($_[0] =~ /^:(\S+) (?:CHGHOST|AL) (\S+) (\S+)$/) { | |
631 | #:Agent CHGHOST tabris tabris.netadmin.SCnet.ops | |
632 | return ('CHGHOST', 0, 1, WF_CHAN, $1, $2, $3); | |
633 | #setter, target, vhost | |
634 | } | |
635 | elsif($_[0] =~ /^:(\S+) (?:SETHOST|AA) (\S+)$/) { | |
636 | #:tabris SETHOST tabris.netadmin.SCnet.ops | |
637 | return ('CHGHOST', 0, 1, WF_CHAN, $1, $1, $2); | |
638 | } | |
639 | ||
640 | elsif ($_[0] =~ /^:(?:\S* )?302 (\S+) :(\S+?)\*?=[+-].*?\@(.*)/) { | |
641 | #:serebii.razorville.co.uk 302 leif :Jesture=+~Jesture00@buzz-3F604D09.sympatico.ca | |
642 | return ('CHGHOST', 0, 1, WF_CHAN, $1, $2, $3); | |
643 | } | |
644 | } | |
645 | ||
646 | ||
647 | sub USERIP($) { | |
648 | $_[0] =~ /^:(?:\S* )?340 (\S+) :(\S+?)\*?=[+-].*?\@((?:\.|\d)*)/; | |
649 | return ('USERIP', 0, 1, WF_CHAN, $1, $2, $3); | |
650 | } | |
651 | ||
652 | sub IDENT($) { | |
653 | if($_[0] =~ /^:(\S+) (?:CHGIDENT|AL) (\S+) (\S+)$/) { | |
654 | return ('CHGIDENT', 0, 1, WF_ALL, $1, $2, $3); | |
655 | #setter, target, IDENT | |
656 | } | |
657 | elsif($_[0] =~ /^:(\S+) (?:SETIDENT|AD) (\S+)$/) { | |
658 | return ('CHGIDENT', 0, 1, WF_ALL, $1, $1, $2); | |
659 | #setter, target, ident | |
660 | } | |
661 | } | |
662 | ||
663 | ||
664 | sub TOPIC($) { | |
665 | if ($_[0] =~ /^:(\S+) TOPIC (\S+) :(.*)$/) { | |
666 | #:583AAAAAF TOPIC #erry :Welcome to erry(world|net). Have a cookie. | |
7b3a5814 | 667 | my $setter = { ID => decodeUUID($1) }; |
5e682044 | 668 | get_user_nick ($setter); |
669 | return ('TOPIC', 0, 1, WF_ALL, $setter, $2, $setter, 0, $3); | |
670 | } | |
671 | } | |
672 | ||
673 | sub UMODE($) { | |
674 | #:tabris | +oghaANWt | |
675 | $_[0] =~ /^:(\S+) (?:UMODE2|\|) (\S+)$/; | |
676 | # src, umodes | |
677 | # a note, not all umodes are passed | |
678 | # +s, +O, and +t are not passed. possibly others | |
679 | # also not all umodes do we care about. | |
680 | # umodes we need care about: | |
681 | # oper modes: hoaACN,O oper-only modes: HSq | |
682 | # regular modes: rxB,izV (V is only somewhat, as the ircd | |
683 | # does the conversions from NOTICE to PRIVSMG for us). | |
684 | ||
685 | # Yes, I'm changing the event type on this | |
686 | # It's better called UMODE, and easily emulated | |
687 | # on IRCds with only MODE. | |
688 | return ('UMODE', 0, 0, WF_ALL, $1, $2); | |
689 | } | |
690 | sub OPERTYPE ($) { | |
691 | #:583AAAAAB OPERTYPE SuperNetAdmin | |
692 | #Every OPERTYPE will get +o, so it's safe to assume they're opers, | |
693 | #even if we don't give them privs (either in inspircd or srsv) | |
694 | $_[0] =~ /^:(\S+) OPERTYPE (\S+)$/; | |
7b3a5814 | 695 | my $user = { ID => decodeUUID($1) }; |
5e682044 | 696 | get_user_nick ($user); |
697 | return ("OPERUP", 0, 0, WF_ALL, $user); | |
698 | } | |
699 | sub SVSMODE($) { | |
700 | #:tabris | +oghaANWt | |
701 | $_[0] =~ /^:(\S+) (?:SVS2?MODE|n|v) (\S+) (\S+)$/; | |
702 | # src, umodes | |
703 | # a note, not all umodes are passed | |
704 | # +s, +O, and +t are not passed. possibly others | |
705 | # also not all umodes do we care about. | |
706 | # umodes we need care about: | |
707 | # oper modes: hoaACN,O oper-only modes: HSq | |
708 | # regular modes: rxB,izV (V is only somewhat, as the ircd | |
709 | # does the conversions from NOTICE to PRIVSMG for us). | |
710 | ||
711 | return ('UMODE', 0, 0, WF_ALL, $2, $3); | |
712 | } | |
713 | ||
714 | sub WHOIS($) { | |
715 | # :tab WHOIS ConnectServ :ConnectServ | |
716 | if($_[0] =~ /^:(\S+) (?:WHOIS|\#) (\S+)$/) { | |
717 | return ('WHOIS', 0, undef, WF_NONE, $1, $2); | |
718 | } | |
719 | elsif($_[0] =~ /^:(\S+) (?:WHOIS|\#) (\S+) :(\S+)$/) { | |
720 | return ('WHOIS', 0, undef, WF_NONE, $1, $3); | |
721 | } | |
722 | } | |
723 | ||
724 | sub TSCTL($) { | |
725 | $_[0] =~ /^:(\S+) (?:TSCTL|AW) alltime$/; | |
726 | ircsend(":$main_conf{local} NOTICE $1 *** Server=$main_conf{local} TSTime=". | |
727 | time." time()=".time." TSOffset=0"); | |
728 | return; | |
729 | } | |
730 | ||
731 | sub VERSION($) { | |
732 | $_[0] =~ /^:(\S+) (?:VERSION|\+).*$/; | |
733 | return ('VERSION', 0, undef, WF_NONE, $1); | |
734 | } | |
735 | ||
736 | sub TKL($) { | |
737 | if ($_[0] =~ /^(@|:)(\S+) (?:TKL|BD) (.*)$/) { | |
738 | # We discard the source anyway. | |
739 | #my $server; | |
740 | #if ($1 eq '@') { | |
741 | # $server = $servernum[b64toi($2)]; | |
742 | #} | |
743 | #else { | |
744 | # $server = $2; | |
745 | #} | |
746 | return ('TKL', undef, undef, WF_NONE, parse_tkl("TKL $3")); | |
747 | } | |
748 | elsif ($_[0] =~ /^(?:TKL|BD) (.*)$/) { | |
749 | return ('TKL', undef, undef, WF_NONE, parse_tkl("TKL $1")); | |
750 | } | |
751 | } | |
752 | ||
753 | sub SNOTICE($) { | |
754 | $_[0] =~ /^(@|:)(\S+) (SENDSNO|Ss|SMO|AU) ([A-Za-z]) :(.*)$/; | |
755 | #@servernumeric Ss snomask :message | |
756 | my $name; | |
757 | if ($1 eq '@') { | |
758 | $name = $servernum[b64toi($2)]; | |
759 | } | |
760 | else { | |
761 | $name = $2; | |
762 | } | |
763 | my $event; | |
764 | $event = 'SENDSNO' if(($3 eq 'SENDSNO' or $3 eq 'Ss')); | |
765 | $event = 'SMO' if(($3 eq 'SMO' or $3 eq 'AU')); | |
766 | return ($event, 0, undef, WF_NONE, $name, $4, $5); | |
767 | } | |
768 | ||
769 | sub GLOBOPS($) { | |
770 | $_[0] =~ /^(@|:)(\S+) (?:GLOBOPS|\]) :(.*)$/; | |
771 | #@servernumeric [ :message | |
772 | my $name; | |
773 | if ($1 eq '@') { | |
774 | $name = $servernum[b64toi($2)]; | |
775 | } | |
776 | else { | |
777 | $name = $2; | |
778 | } | |
779 | return ('GLOBOPS', 0, undef, WF_NONE, $name, $3); | |
780 | } | |
781 | ||
782 | sub ISUPPORT($) { | |
783 | $_[0] =~ /^:(\S+) (?:105|005) (\S+) (.+) :are supported by this server$/; | |
784 | # :test-tab.surrealchat.net 105 services.SC.net CMDS=KNOCK,MAP,DCCALLOW,USERIP :are supported by this server | |
785 | foreach my $token (split(/\s+/, $3)) { | |
786 | my ($key, $value) = split('=', $token); | |
787 | $IRCd_capabilities{$key} = ($value ? $value : 1); | |
788 | } | |
789 | } | |
790 | ||
026939ee | 791 | sub CAPAB { |
792 | #CAPAB MODULES :m_botmode.so,m_chanprotect.so,m_chghost.so,m_chgident.so,m_cloaking.so,m_deaf.so,m_delayjoin.so,m_delaymsg.so,m_gecosban.so,m_globops.so,m_helpop.so,m_messageflood.so,m_muteban.so,m_nokicks.so,m_nonicks.so,m_nonotice.so,m_nopartmsg.so,m_ojoin.so,m_operchans.so,m_operinvex.so,m_permchannels.so,m_redirect.so,m_regex_glob.so,m_remove.so,m_sajoin.so,m_sakick.so,m_sanick.so,m_sapart.so,m_saquit.so,m_serverban.so,m_services_account.so,m_servprotect.so,m_setident.so,m_showwhois.so,m_shun.so | |
793 | #CAPAB MODULES :m_silence.so,m_watch.so | |
794 | #CAPAB MODSUPPORT :m_chghost.so,m_chgident.so,m_gecosban.so,m_muteban.so,m_nopartmsg.so,m_remove.so,m_sajoin.so,m_sakick.so,m_sanick.so,m_sapart.so,m_saquit.so,m_serverban.so,m_services_account.so,m_showwhois.so,m_silence.so,m_watch.so | |
795 | #CAPAB CHANMODES :admin=&a ban=b c_registered=r delayjoin=D delaymsg=d flood=f founder=~q halfop=%h inviteonly=i key=k limit=l moderated=m noextmsg=n nokick=Q nonick=N nonotice=T official-join=!Y op=@o operonly=O permanent=P private=p redirect=L reginvite=R regmoderated=M secret=s topiclock=t voice=+v | |
796 | #6 CAPAB USERMODES :bot=B cloak=x deaf=d helpop=h invisible=i oper=o regdeaf=R servprotect=k showwhois=W snomask=s u_registered=r wallops=w | |
797 | #CAPAB CAPABILITIES :NICKMAX=32 CHANMAX=65 MAXMODES=20 IDENTMAX=12 MAXQUIT=256 MAXTOPIC=308 MAXKICK=256 MAXGECOS=129 MAXAWAY=201 IP6SUPPORT=1 PROTOCOL=1202 HALFOP=1 PREFIX=(Yqaohv)!~&@%+ CHANMODES=b,k,Ldfl,DMNOPQRTimnprst USERMODES=,,s,BRWdhikorwx SVSPART=1 | |
798 | #--- | |
799 | #What we care about: CHANMODES :admin=&a founder=~q Determines if we can set +a and +q on people, halfop %h: likewise... cloak=x determines if we can have cloaks or vhosts. in the modules we care about chghost, chgident, cloaking for vhosts, m_silence and m_watch for silence and watch respectively. Also c_registered, we can _NOT_ continue w/o it. | |
800 | #I HAVE NO IDEA where to get the watch/silence list limit!!! | |
801 | #let's do this the lame way! | |
a1a0e944 | 802 | #FIXME this is so ugly |
026939ee | 803 | my $capab = $_[0]; |
804 | print "CAPAB $_[0]\n"; | |
805 | $capab =~ /CAPAB (\S+)/; | |
806 | my $type = $1; | |
807 | if ($type eq "END" && $IRCd_capabilities {"REG"} eq "") { | |
808 | ircd::debug ("WARNING: SurrealServices requires m_services_account.so to be loaded in Inspircd."); | |
809 | ircd::debug ("m_services_account.so not loaded! Shutting down NOW!"); | |
810 | print "m_services_account.so not loaded! Shutting down NOW!\n"; | |
811 | main_shutdown; | |
812 | } | |
813 | if ($capab =~ /m_chghost/ && $type eq "MODSUPPORT") { | |
814 | $IRCd_capabilities{"CHGHOST"} = 1; | |
815 | } | |
816 | if ($capab =~ /m_chgident/ && $type eq "MODSUPPORT") { | |
817 | $IRCd_capabilities{"CHGIDENT"} = 1; | |
818 | } | |
819 | if ($capab =~ /m_cloaking/ ) { | |
820 | $IRCd_capabilities{"CLOAKHOST"} = 1; | |
821 | } | |
822 | if ($capab =~ /cloak=(\S)/ ) { | |
823 | $IRCd_capabilities{"CLOAK"} = $1; | |
824 | } | |
825 | if ($capab =~ /admin=(\S)(\S)/) { | |
826 | $IRCd_capabilities{"ADMIN"} = $2; | |
827 | } | |
828 | if ($capab =~ /founder=(\S)(\S)/) { | |
829 | $IRCd_capabilities{"FOUNDER"} = $2; | |
830 | } | |
1eb006d9 | 831 | if ($capab =~ /halfop=(\S)(\S)/) { |
832 | $IRCd_capabilities{"HALFOP"} = $2; | |
833 | } | |
026939ee | 834 | if ($capab =~ /silence/) { |
835 | $IRCd_capabilities{"SILENCE"} = 32; #unless we can make it TELL US | |
836 | } | |
837 | if ($capab =~ /watch/) { | |
838 | $IRCd_capabilities{"WATCH"} = 32; #unless we can make it TELL US | |
839 | } | |
840 | if ($capab =~ /registered/) { | |
841 | $IRCd_capabilities{"REG"} = 1; | |
842 | } | |
a1a0e944 | 843 | $IRCd_capabilities {"INSP"} = 1; #this is _horrible_ |
026939ee | 844 | |
845 | } | |
5e682044 | 846 | sub STATS($) { |
847 | $_[0] =~ /^:(\S+) (?:STATS|2) (\S) :(.+)$/; | |
848 | return ('STATS', undef, undef, WF_NONE, $1, $2, $3) | |
849 | } | |
850 | ||
851 | BEGIN { | |
852 | %cmdhash = ( | |
853 | PING => \&PING, | |
854 | '8' => \&PING, | |
855 | ||
856 | EOS => \&EOS, | |
857 | ES => \&EOS, | |
858 | ENDBURST => \&EOS, | |
859 | SERVER => \&SERVER, | |
860 | "\'" => \&SERVER, | |
861 | ||
862 | SQUIT => \&SQUIT, | |
863 | '-' => \&SQUIT, | |
864 | ||
865 | NETINFO => \&NETINFO, | |
866 | AO => \&NETINFO, | |
867 | ||
868 | PROTOCTL => \&PROTOCTL, | |
869 | ||
870 | JOIN => \&JOIN, | |
871 | C => \&JOIN, | |
872 | ||
873 | PART => \&PART, | |
874 | D => \&PART, | |
875 | ||
876 | SJOIN => \&SJOIN, | |
877 | '~' => \&SJOIN, | |
878 | FJOIN => \&FJOIN, | |
879 | FMODE => \&FMODE, | |
880 | MODE => \&MODE, | |
881 | G => \&MODE, | |
882 | ||
883 | PRIVMSG => \&MESSAGE, | |
884 | '!' => \&MESSAGE, | |
885 | NOTICE => \&MESSAGE, | |
886 | B => \&MESSAGE, | |
887 | ||
888 | AWAY => \&AWAY, | |
889 | '6' => \&AWAY, | |
890 | ||
891 | NICK => \&NICK, | |
892 | '&' => \&NICK, | |
893 | ||
894 | QUIT => \&QUIT, | |
895 | ',' => \&QUIT, | |
896 | ||
897 | KILL => \&KILL, | |
898 | '.' => \&KILL, | |
899 | ||
900 | KICK => \&KICK, | |
901 | H => \&KICK, | |
902 | ||
903 | CHGHOST => \&HOST, | |
904 | AL => \&HOST, | |
905 | SETHOST => \&HOST, | |
906 | AA => \&HOST, | |
907 | '302' => \&HOST, | |
908 | ||
909 | '340' => \&USERIP, | |
910 | ||
911 | CHGIDENT => \&IDENT, | |
912 | AZ => \&IDENT, | |
913 | SETIDENT => \&IDENT, | |
914 | AD => \&IDENT, | |
915 | ||
916 | TOPIC => \&TOPIC, | |
917 | ')' => \&TOPIC, | |
918 | ||
919 | UMODE2 => \&UMODE, | |
920 | '|' => \&UMODE, | |
921 | ||
922 | TSCTL => \&TSCTL, | |
923 | AW => \&TSCTL, | |
924 | ||
925 | VERSION => \&VERSION, | |
926 | '+' => \&VERSION, | |
927 | ||
928 | TKL => \&TKL, | |
929 | BD => \&TKL, | |
930 | ||
931 | WHOIS => \&WHOIS, | |
932 | '#' => \&WHOIS, | |
933 | ||
934 | SENDSNO => \&SNOTICE, | |
935 | Ss => \&SNOTICE, | |
936 | ||
937 | SMO => \&SNOTICE, | |
938 | AU => \&SNOTICE, | |
939 | ||
940 | GLOBOPS => \&GLOBOPS, | |
941 | ']' => \&GLOBOPS, | |
942 | ||
943 | '105' => \&ISUPPORT, | |
944 | '005' => \&ISUPPORT, | |
945 | ||
946 | SVSMODE => \&SVSMODE, | |
947 | 'n' => \&SVSMODE, | |
948 | SVS2MODE => \&SVSMODE, | |
949 | 'v' => \&SVSMODE, | |
950 | ||
951 | STATS => \&STATS, | |
952 | '2' => \&STATS, | |
953 | UID => \&UID, | |
954 | OPERTYPE => \&OPERTYPE, | |
026939ee | 955 | OPERQUIT => \&OPERQUIT, #Opers are so special, they get their own QUIT. SOme of the time. |
956 | CAPAB => \&CAPAB, | |
7b3a5814 | 957 | FMODE => \&FMODE |
5e682044 | 958 | ); |
959 | } | |
960 | ||
961 | 1; |