]>
jfr.im git - irc/SurrealServices/srsv.git/blob - branches/erry-devel/SrSv/User.pm
1 # This file is part of SurrealServices.
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.
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.
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
21 SrSv::User - Track users
25 use SrSv::User qw(get_user_id get_user_nick get_user_agent is_online chk_online get_user_flags set_user_flag chk_user_flag);
31 use Exporter
'import';
35 UF_ONLINE
=> 2, # not used yet
38 our @EXPORT_OK = (qw(get_user_id get_user_nick get_user_agent is_online chk_online
39 $get_user_id $get_user_nick
41 get_user_flags set_user_flag chk_user_flag set_user_flag_all
42 get_host get_vhost get_cloakhost get_user_info
43 flood_inc flood_check get_flood_level
47 my @flood = qw( flood_inc flood_check get_flood_level );
48 my @flags = qw( get_user_flags set_user_flag chk_user_flag set_user_flag_all );
50 flags
=> [keys(%constants)],
52 user_flags
=> [@flags],
55 require constant; import
constant (\
%constants);
58 use SrSv
::MySQL
::Stub
{
59 __getIPV4
=> ['SCALAR', "SELECT INET_NTOA(ip) FROM user WHERE id=?"],
64 use SrSv
::Process
::Init
;
65 use SrSv
::MySQL
'$dbh';
66 use SrSv
::NickControl
::Enforcer
qw(%enforcers);
67 use SrSv
::IRCd
::State
qw(synced);
68 use SrSv
::Agent
qw(is_agent);
69 use SrSv
::User
::Notice
;
70 use SrSv
::IRCd
::Send qw
(getUuid getRevUuid
);
74 $get_user_id, $get_user_nick, $get_nickchg, $is_online,
76 $get_user_flags, $set_user_flag, $unset_user_flag, $set_user_flag_all,
78 $get_host, $get_vhost, $get_cloakhost, $get_ip, $get_user_info,
82 $get_user_id = $dbh->prepare("SELECT id FROM user WHERE nick=?");
83 $get_user_nick = $dbh->prepare("SELECT nick FROM user WHERE id=?");
84 $get_nickchg = $dbh->prepare("SELECT nickchg.nickid, user.nick FROM nickchg, user WHERE user.id=nickchg.nickid AND nickchg.nick=?");
85 $is_online = $dbh->prepare("SELECT 1 FROM user WHERE nick=? AND online=1");
87 $get_user_flags = $dbh->prepare("SELECT flags FROM user WHERE id=?");
88 $set_user_flag = $dbh->prepare("UPDATE user SET flags=(flags | (?)) WHERE id=?");
89 $unset_user_flag = $dbh->prepare("UPDATE user SET flags=(flags & ~(?)) WHERE id=?");
90 $set_user_flag_all = $dbh->prepare("UPDATE user SET flags=flags | ?");
92 $get_host = $dbh->prepare("SELECT ident, host FROM user WHERE id=?");
93 $get_vhost = $dbh->prepare("SELECT ident, vhost FROM user WHERE id=?");
94 $get_cloakhost = $dbh->prepare("SELECT 1, cloakhost FROM user WHERE id=?");
95 $get_user_info = $dbh->prepare("SELECT ident, host, vhost, gecos, server FROM user WHERE id=?");
97 require SrSv
::MySQL
::Stub
;
98 import SrSv
::MySQL
::Stub
{
99 __flood_check
=> ['SCALAR', "SELECT flood FROM user WHERE id=?"],
100 __flood_inc
=> ['NULL', "UPDATE user SET flood = flood + ? WHERE id=?"],
101 __flood_expire
=> ['NULL', "UPDATE user SET flood = flood >> 1"], # shift is faster than mul
104 sub get_flood_level
($) {
107 if(defined($user->{FLOOD
})) {
108 return $user->{FLOOD
};
110 my $flev = __flood_check
(get_user_id
($user));
111 $user->{FLOOD
} = $flev;
116 my ($user, $amount) = @_;
117 $amount = 1 unless defined($amount);
119 get_flood_level
($user);
120 $user->{FLOOD
} += $amount;
121 __flood_inc
($amount, get_user_id
($user));
122 return $user->{FLOOD
};
125 sub flood_check
($;$) {
126 my ($user, $amount) = @_;
128 if(adminserv
::is_svsop
($user, adminserv
::S_HELP
()) or adminserv
::is_service
($user)) {
131 my $flev = flood_inc
($user, $amount);
134 kill_user
($user, "Flooding services.");
138 notice
($user, "You are flooding services.") if $amount == 1;
149 return undef if(is_agent
($user->{NICK
}) and not $enforcers{lc $user->{NICK
}});
151 unless(ref($user) eq 'HASH') {
152 die("invalid get_user_nick call");
154 my $nick = $user->{NICK
};
156 die("get_user_id called on empty string");
158 my $properId = ircd
::getUuid
($user->{NICK
});
159 if ($properId != "") {
160 print "Decoding $properId\n";
161 $properId = decodeUUID
($properId);
162 return $user->{ID
} = $properId;
164 else { print "Null properId. User->id" . $user->{ID
} . "\n"; }
165 if(exists($user->{ID
})) { print "Returning user_>id " . $user->{ID
} . "\n"; return $user->{ID
}; }
169 # a cheat for isServer()
170 if($user->{NICK
} =~ /\./) {
171 return $user->{ID
} = undef;
175 while($n < 10 and !defined($id)) {
177 $get_user_id->execute($nick);
178 ($id) = $get_user_id->fetchrow_array;
179 print "Finally got id from query: $id\n";
181 $get_nickchg->execute($nick);
182 ($id, $nick2) = $get_nickchg->fetchrow_array;
186 #unless($id) { log::wlog(__PACKAGE__, log::DEBUG(), "get_user_id($nick) failed."); }
188 if(defined($nick2) and lc $nick2 ne lc $user->{NICK
}) {
189 $user->{OLDNICK
} = $user->{NICK
};
190 $user->{NICK
} = $nick2;
193 return $user->{ID
} = $id;
196 sub get_user_nick
($) {
199 unless(ref($user) eq 'HASH') {
200 die("invalid get_user_nick call");
202 if(exists($user->{NICK
}) and is_online
($user->{NICK
})) {
203 my $realnick = ircd
::getRevUuid
($user->{NICK
});
205 $user->{ID
} = $user->{NICK
};
206 $user->{NICK
} = $realnick;
210 return $user->{NICK
};
214 # Possible bug? This next bit only works to chase the nick-change
215 # if the caller already did a get_user_id to find out
216 # if the user exists in the user table, and thus get $user->{ID}
217 # I don't know if calling get_user_id here is safe or not.
220 $get_user_nick->execute($user->{ID
});
221 ($nick) = $get_user_nick->fetchrow_array;
224 # avoid returning an undef/NULL here. That's only legal for get_user_id
225 # If the user does not exist, we must avoid modifying the input
226 # so that it may be used for the error paths.
227 return (defined $nick ? $user->{NICK
} = $nick : $user->{NICK
});
230 sub get_user_agent
($) {
234 eval { $user->{AGENT
} };
236 die("invalid get_user_agent call");
239 die "invalid get_user_agent call" unless ref($user) eq 'HASH';
241 if(exists($user->{AGENT
})) {
242 return $user->{AGENT
}
254 if(exists($user->{ONLINE
})) { return $user->{ONLINE
}; }
255 $nick = get_user_nick
($user);
260 $is_online->execute($nick);
261 my ($status) = $is_online->fetchrow_array;
262 $is_online->finish();
264 $user->{ONLINE
} = ($status ? 1 : 0);
271 my ($user, $target) = @_;
273 unless(is_online
($target)) {
275 $target = get_user_nick
($target);
278 notice
($user, "\002$target\002: No such user.");
285 sub set_user_flag
($$;$) {
286 my ($user, $flag, $sign) = @_;
287 my $uid = get_user_id
($user);
288 $sign = 1 unless defined($sign);
291 $user->{FLAGS
} = ( ( defined $user->{FLAGS
} ? $user->{FLAGS
} : 0 ) | $flag );
292 $set_user_flag->execute($flag, $uid);
294 $user->{FLAGS
} = ( ( defined $user->{FLAGS
} ? $user->{FLAGS
} : 0 ) & ~($flag) );
295 $unset_user_flag->execute($flag, $uid);
299 sub chk_user_flag
($$;$) {
300 my ($user, $flag, $sign) = @_;
301 my $flags = get_user_flags
($user);
302 $sign = 1 unless defined($sign);
304 return ($sign ? ($flags & $flag) : !($flags & $flag));
307 sub get_user_flags
($) {
309 my $uid = get_user_id
($user);
312 unless (exists($user->{FLAGS
})) {
313 $get_user_flags->execute($uid);
314 ($flags) = $get_user_flags->fetchrow_array;
315 $get_user_flags->finish();
317 $flags = $user->{FLAGS
};
320 return $user->{FLAGS
} = $flags;
323 sub set_user_flag_all
($) {
326 $set_user_flag_all->execute($flags);
327 $set_user_flag_all->finish();
335 $id = get_user_id
($user);
337 $id = get_user_id
({ NICK
=> $user });
339 return undef unless $id;
341 $get_host->execute($id);
342 my ($ident, $host) = $get_host->fetchrow_array;
344 return ($ident, $host);
347 sub get_cloakhost
($) {
352 $id = get_user_id
($user);
354 $id = get_user_id
({ NICK
=> $user });
356 return undef unless $id;
358 $get_cloakhost->execute($id);
359 my ($valid, $cloakhost) = $get_cloakhost->fetchrow_array;
360 $get_cloakhost->finish;
362 # Beware, $cloakhost may be NULL while the user entry exists
363 # if $cloakhost == undef, check $valid before assuming no such user.
364 return ($valid, $cloakhost);
372 $id = get_user_id
($user);
374 $id = get_user_id
({ NICK
=> $user });
376 return undef unless $id;
378 $get_vhost->execute($id);
379 my ($ident, $vhost) = $get_vhost->fetchrow_array;
381 return ($ident, $vhost);
384 sub get_user_info
($) {
387 my $uid = get_user_id
($user);
388 return undef() unless $uid;
390 $get_user_info->execute($uid);
391 my ($ident, $host, $vhost, $gecos, $server) = $get_user_info->fetchrow_array();
392 $get_user_info->finish;
394 return ($ident, $host, $vhost, $gecos, $server);
397 sub get_user_ipv4
($) {
402 if(exists $user->{IP
}) {
405 $id = get_user_id
($user);
407 $id = get_user_id
({ NICK
=> $user });
409 return undef unless $id;
411 my $ip = getIPV4
($id);
413 return $user->{IP
} = $ip;
420 return get_user_ipv4
(@_);