Updating session handle to remove explicit phpBB3 dependancy.
This commit is contained in:
parent
901f879bba
commit
a79795d96b
@ -20,12 +20,12 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
## @class
|
||||
# The SessionHandler class provides cookie-based session facilities for
|
||||
# maintaining user state over http transactions. This code depends on
|
||||
# The SessionHandler class provides cookie-based session facilities for
|
||||
# maintaining user state over http transactions. This code depends on
|
||||
# integration with a phpBB3 database: a number of custom tables are needed
|
||||
# (see config docs), but user handling is tied to phpBB3 user tables, and
|
||||
# a number of joins between custom tables and phpBB3 ones require the two
|
||||
# to share database space. This code provides session verification, and
|
||||
# a number of joins between custom tables and phpBB3 ones require the two
|
||||
# to share database space. This code provides session verification, and
|
||||
# takes some steps towards ensuring security against cookie hijacking, but
|
||||
# as with any cookie based auth system there is the potential for security
|
||||
# issues.
|
||||
@ -47,7 +47,6 @@ use MIME::Base64;
|
||||
use Data::Dumper;
|
||||
|
||||
# Custom module imports
|
||||
use phpBB3;
|
||||
use Logging qw(die_log);
|
||||
|
||||
# Globals...
|
||||
@ -72,7 +71,7 @@ sub new {
|
||||
my $self = {
|
||||
cgi => undef,
|
||||
dbh => undef,
|
||||
phpbb => undef,
|
||||
auth => undef,
|
||||
template => undef,
|
||||
settings => undef,
|
||||
@_,
|
||||
@ -81,7 +80,7 @@ sub new {
|
||||
# Ensure that we have objects that we need
|
||||
return set_error("cgi object not set") unless($self -> {"cgi"});
|
||||
return set_error("dbh object not set") unless($self -> {"dbh"});
|
||||
return set_error("phpbb object not set") unless($self -> {"phpbb"});
|
||||
return set_error("auth object not set") unless($self -> {"auth"});
|
||||
return set_error("template object not set") unless($self -> {"template"});
|
||||
return set_error("settings object not set") unless($self -> {"settings"});
|
||||
|
||||
@ -98,12 +97,12 @@ sub new {
|
||||
|
||||
# Now try to obtain a session id - start by looking at the cookies
|
||||
$self -> {"sessid"} = $self -> {"cgi"} -> cookie($cookiebase."_sid"); # The session id cookie itself
|
||||
$self -> {"sessuser"} = $self -> {"cgi"} -> cookie($cookiebase."_u"); # Which user does this session claim to be for?
|
||||
$self -> {"sessuser"} = $self -> {"cgi"} -> cookie($cookiebase."_u"); # Which user does this session claim to be for?
|
||||
$self -> {"autokey"} = $self -> {"cgi"} -> cookie($cookiebase."_k"); # Do we have an autologin key for the user?
|
||||
|
||||
# If we don't have a session id now, try to pull it from the query string
|
||||
$self -> {"sessid"} = $self -> {"cgi"} -> param("sid") if(!$self -> {"sessid"});
|
||||
|
||||
|
||||
# If we have a session id, we need to check it
|
||||
if($self -> {"sessid"}) {
|
||||
# Try to get the session...
|
||||
@ -119,9 +118,9 @@ sub new {
|
||||
if(!$self -> session_expired($session)) {
|
||||
# The session is valid, and can be touched.
|
||||
$self -> touch_session($session);
|
||||
|
||||
|
||||
return $self;
|
||||
} # if(!$self -> session_expired($session)) {
|
||||
} # if(!$self -> session_expired($session)) {
|
||||
} # if($self -> ip_check($ENV{"REMOTE_ADDR"}, $session -> {"session_ip"})) {
|
||||
} # if($session) {
|
||||
} # if($sessid) {
|
||||
@ -133,7 +132,7 @@ sub new {
|
||||
|
||||
## @method $ create_session($user, $persist)
|
||||
# Create a new session. If the user is not specified, this creates an anonymous session,
|
||||
# otherwise the session is attached to the user.
|
||||
# otherwise the session is attached to the user.
|
||||
#
|
||||
# @param user Optional user ID to associate with the session.
|
||||
# @param persist If true, and autologins are permitted, an autologin key is generated for
|
||||
@ -147,27 +146,27 @@ sub create_session {
|
||||
|
||||
# nuke the cookies, it's the only way to be sure
|
||||
delete($self -> {"cookies"}) if($self -> {"cookies"});
|
||||
|
||||
|
||||
# get the current time...
|
||||
my $now = time();
|
||||
|
||||
# If persistent logins are not permitted, disable them
|
||||
$self -> {"autokey"} = $persist = '' if(!$self -> {"phpbb"} -> get_config("allow_autologin"));
|
||||
$self -> {"autokey"} = $persist = '' if(!$self -> {"auth"} -> get_config("allow_autologin"));
|
||||
|
||||
# Set a default last visit, might be updated later
|
||||
$self -> {"last_visit"} = $now;
|
||||
|
||||
# If we have a key, and a user in the cookies, try to get it
|
||||
if($self -> {"autokey"} && $self -> {"sessuser"} && $self -> {"sessuser"} != $phpBB3::ANONYMOUS) {
|
||||
if($self -> {"autokey"} && $self -> {"sessuser"} && $self -> {"sessuser"} != $self -> {"auth"} -> {"ANONYMOUS"}) {
|
||||
my $autocheck = $self -> {"dbh"} -> prepare("SELECT u.* FROM ".
|
||||
$self -> {"phpbb"} -> {"prefix"}."users AS u, ".
|
||||
$self -> {"auth"} -> {"prefix"}."users AS u, ".
|
||||
$self -> {"settings"} -> {"database"} -> {"keys"}." AS k
|
||||
WHERE u.user_id = ?
|
||||
WHERE u.user_id = ?
|
||||
AND u.user_type IN (0, 3)
|
||||
AND k.user_id = u.user_id
|
||||
AND k.key_id = ?");
|
||||
$autocheck -> execute($self -> {"sessuser"}, md5_hex($self -> {"autokey"}))
|
||||
or return set_error("Unable to peform user lookup query\nError was: ".$self -> {"dbh"} -> errstr);
|
||||
or return set_error("Unable to peform user lookup query\nError was: ".$self -> {"dbh"} -> errstr);
|
||||
|
||||
$userdata = $autocheck -> fetchrow_hashref;
|
||||
|
||||
@ -176,11 +175,11 @@ sub create_session {
|
||||
$self -> {"autokey"} = '';
|
||||
$self -> {"sessuser"} = $user;
|
||||
|
||||
my $userh = $self -> {"dbh"} -> prepare("SELECT * FROM ".$self -> {"phpbb"} -> {"prefix"}."users
|
||||
my $userh = $self -> {"dbh"} -> prepare("SELECT * FROM ".$self -> {"auth"} -> {"prefix"}."users
|
||||
WHERE user_id = ?
|
||||
AND user_type IN (0, 3)");
|
||||
$userh -> execute($self -> {"sessuser"})
|
||||
or return set_error("Unable to peform user lookup query\nError was: ".$self -> {"dbh"} -> errstr);
|
||||
or return set_error("Unable to peform user lookup query\nError was: ".$self -> {"dbh"} -> errstr);
|
||||
|
||||
$userdata = $userh -> fetchrow_hashref;
|
||||
}
|
||||
@ -189,12 +188,12 @@ sub create_session {
|
||||
# the user doesn't exist, is inactive, or is a bot. Just get the anonymous user
|
||||
if(!$userdata) {
|
||||
$self -> {"autokey"} = '';
|
||||
$self -> {"sessuser"} = $phpBB3::ANONYMOUS;
|
||||
$self -> {"sessuser"} = $self -> {"auth"} -> {"ANONYMOUS"};
|
||||
|
||||
my $userh = $self -> {"dbh"} -> prepare("SELECT * FROM ".$self -> {"phpbb"} -> {"prefix"}."users
|
||||
my $userh = $self -> {"dbh"} -> prepare("SELECT * FROM ".$self -> {"auth"} -> {"prefix"}."users
|
||||
WHERE user_id = ?");
|
||||
$userh -> execute($self -> {"sessuser"})
|
||||
or return set_error("Unable to peform user lookup query\nError was: ".$self -> {"dbh"} -> errstr);
|
||||
or return set_error("Unable to peform user lookup query\nError was: ".$self -> {"dbh"} -> errstr);
|
||||
|
||||
$userdata = $userh -> fetchrow_hashref;
|
||||
|
||||
@ -209,22 +208,22 @@ sub create_session {
|
||||
|
||||
# Fall back on now if we have no last visit time
|
||||
$self -> {"last_visit"} = $visitr -> [0] if($visitr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Determine whether the session can be made persistent (requires the user to be registered, and normal)
|
||||
my $is_registered = ($userdata -> {"user_id"} && $userdata -> {"user_id"} != $phpBB3::ANONYMOUS && ($userdata -> {"user_type"} == 0 || $userdata -> {"user_type"} == 3));
|
||||
my $is_registered = ($userdata -> {"user_id"} && $userdata -> {"user_id"} != $self -> {"auth"} -> {"ANONYMOUS"} && ($userdata -> {"user_type"} == 0 || $userdata -> {"user_type"} == 3));
|
||||
$persist = (($self -> {"autokey"} || $persist) && $is_registered) ? 1 : 0;
|
||||
|
||||
# Do we already have a session id? If we do, and it's an anonymous session, we want to nuke it
|
||||
if($self -> {"sessid"}) {
|
||||
my $killsess = $self -> {"dbh"} -> prepare("DELETE FROM ".$self -> {"settings"} -> {"database"} -> {"sessions"}.
|
||||
" WHERE session_id = ? AND session_user_id = ?");
|
||||
$killsess -> execute($self -> {"sessid"}, $phpBB3::ANONYMOUS)
|
||||
$killsess -> execute($self -> {"sessid"}, $self -> {"auth"} -> {"ANONYMOUS"})
|
||||
or return set_error("Unable to remove anonymous session\nError was: ".$self -> {"dbh"} -> errstr);
|
||||
}
|
||||
|
||||
|
||||
# generate a new session id. The md5 of a unique ID should be unique enough...
|
||||
$self -> {"sessid"} = md5_hex($self -> {"phpbb"} -> unique_id());
|
||||
$self -> {"sessid"} = md5_hex($self -> {"auth"} -> unique_id());
|
||||
|
||||
# store the time
|
||||
$self -> {"session_time"} = $now;
|
||||
@ -239,7 +238,7 @@ sub create_session {
|
||||
$ENV{"REMOTE_ADDR"},
|
||||
$persist)
|
||||
or return set_error("Unable to peform session creation\nError was: ".$self -> {"dbh"} -> errstr);
|
||||
|
||||
|
||||
$self -> set_login_key($self -> {"sessuser"}, $ENV{"REMOTE_ADDR"}) if($persist);
|
||||
|
||||
return $self;
|
||||
@ -261,8 +260,8 @@ sub delete_session {
|
||||
|
||||
# If we're not dealing with anonymous, we need to store the visit time,
|
||||
# and nuke any autologin key for the now defunct session
|
||||
if($self -> {"sessuser"} != $phpBB3::ANONYMOUS) {
|
||||
|
||||
if($self -> {"sessuser"} != $self -> {"auth"} -> {"ANONYMOUS"}) {
|
||||
|
||||
# If we don't have a session time for some reason, make it now
|
||||
$self -> {"session_time"} = time() if(!$self -> {"session_time"});
|
||||
|
||||
@ -281,7 +280,7 @@ sub delete_session {
|
||||
" WHERE key_id = ? AND user_id = ?");
|
||||
$nukekeys -> execute(md5_hex($self -> {"autokey"}), $self -> {"sessuser"})
|
||||
or return set_error("Unable to remove session key\nError was: ".$self -> {"dbh"} -> errstr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# clear all the session settings internally for safety
|
||||
@ -318,7 +317,7 @@ sub encode_querystring {
|
||||
sub decode_querystring {
|
||||
my $self = shift;
|
||||
my $query = shift;
|
||||
|
||||
|
||||
# Bomb if we don't have a query, or it is not valid base64
|
||||
return "" if(!$query || $query =~ m{[^A-Za-z0-9+/=]});
|
||||
|
||||
@ -337,11 +336,11 @@ sub session_cookies {
|
||||
# removed before any changes are made... but this shouldn't really be called before
|
||||
# create_session in reality anyway.
|
||||
if(!$self -> {"cookies"}) {
|
||||
my $expires = "+".($self -> {"phpbb"} -> get_config("max_autologin_time") || 365)."d";
|
||||
my $expires = "+".($self -> {"auth"} -> get_config("max_autologin_time") || 365)."d";
|
||||
my $sesscookie = $self -> create_cookie($self -> {"settings"} -> {"config"} -> {"cookie_name"}.'_sid', $self -> {"sessid"}, $expires);
|
||||
my $sessuser = $self -> create_cookie($self -> {"settings"} -> {"config"} -> {"cookie_name"}.'_u', $self -> {"sessuser"}, $expires);
|
||||
my $sesskey;
|
||||
if($self -> {"sessuser"} != $phpBB3::ANONYMOUS) {
|
||||
if($self -> {"sessuser"} != $self -> {"auth"} -> {"ANONYMOUS"}) {
|
||||
if($self -> {"autokey"}) {
|
||||
$sesskey = $self -> create_cookie($self -> {"settings"} -> {"config"} -> {"cookie_name"}.'_k', $self -> {"autokey"}, $expires);
|
||||
}
|
||||
@ -363,7 +362,7 @@ sub session_cookies {
|
||||
## @method ip_check($userip, $sessip)
|
||||
# Checks whether the specified IPs match. The degree of match required depends
|
||||
# on the ip_check setting in the SessionHandler object this is called on: 0 means
|
||||
# that no checking is done, number between 1 and 4 indicate sections of the
|
||||
# that no checking is done, number between 1 and 4 indicate sections of the
|
||||
# dotted decimal IPs are checked (1 = 127., 2 = 127.0, 3 = 127.0.0., etc)
|
||||
#
|
||||
# @param userip The IP the user is connecting from.
|
||||
@ -375,7 +374,7 @@ sub ip_check {
|
||||
my $sessip = shift;
|
||||
|
||||
# How may IP address segments should be compared?
|
||||
my $iplen = $self -> {"phpbb"} -> get_config('ip_check');
|
||||
my $iplen = $self -> {"auth"} -> get_config('ip_check');
|
||||
|
||||
# bomb immediately if we aren't checking IPs
|
||||
return 1 if($iplen == 0);
|
||||
@ -399,10 +398,10 @@ sub session_cleanup {
|
||||
my $self = shift;
|
||||
|
||||
my $now = time();
|
||||
my $timelimit = $now - $self -> {"phpbb"} -> get_config("session_length");
|
||||
my $timelimit = $now - $self -> {"auth"} -> get_config("session_length");
|
||||
|
||||
# We only want to run the garbage collect occasionally
|
||||
if($self -> {"settings"} -> {"config"} -> {"lastgc"} < $now - $self -> {"phpbb"} -> get_config("session_gc")) {
|
||||
if($self -> {"settings"} -> {"config"} -> {"lastgc"} < $now - $self -> {"auth"} -> get_config("session_gc")) {
|
||||
# Okay, we're due a garbage collect, update the config to reflect that we're doing it
|
||||
$self -> {"settings"} -> set_db_config($self -> {"dbh"}, $self -> {"settings"} -> {"database"} -> {"settings"}, "lastgc", $now);
|
||||
|
||||
@ -410,9 +409,9 @@ sub session_cleanup {
|
||||
my $nukesess = $self -> {"dbh"} -> prepare("DELETE FROM ".$self -> {"settings"} -> {"database"} -> {"sessions"}.
|
||||
" WHERE session_user_id = ?
|
||||
AND session_time < ?");
|
||||
$nukesess -> execute($phpBB3::ANONYMOUS, $timelimit)
|
||||
$nukesess -> execute($self -> {"auth"} -> {"ANONYMOUS"}, $timelimit)
|
||||
or return set_error("Unable to remove expired guest sessions\nError was: ".$self -> {"dbh"} -> errstr);
|
||||
|
||||
|
||||
# now get the most recent expired sessions for each user
|
||||
my $lastsess = $self -> {"dbh"} -> prepare("SELECT session_user_id,MAX(session_time) FROM ".$self -> {"settings"} -> {"database"} -> {"sessions"}.
|
||||
" WHERE session_time < ?
|
||||
@ -424,7 +423,7 @@ sub session_cleanup {
|
||||
my $updatelast;
|
||||
if($self -> {"settings"} -> {"database"} -> {"lastvisit"}) {
|
||||
$updatelast = $self -> {"dbh"} -> prepare("UPDATE ".$self -> {"settings"} -> {"database"} -> {"lastvisit"}.
|
||||
" SET last_visit = ?
|
||||
" SET last_visit = ?
|
||||
WHERE user_id = ?");
|
||||
}
|
||||
|
||||
@ -458,13 +457,13 @@ sub session_expired {
|
||||
|
||||
# If the session is not an autologin session, and the last update was before the session length, it is expired
|
||||
if(!$sessdata -> {"session_autologin"}) {
|
||||
return 1 if($sessdata -> {"session_time"} < time() - ($self -> {"phpbb"} -> get_config("session_length") + 60));
|
||||
return 1 if($sessdata -> {"session_time"} < time() - ($self -> {"auth"} -> get_config("session_length") + 60));
|
||||
|
||||
} else {
|
||||
my $max_autologin = $self -> {"phpbb"} -> get_config("max_autologin_time");
|
||||
my $max_autologin = $self -> {"auth"} -> get_config("max_autologin_time");
|
||||
|
||||
# If the session is autologin, and it is older than the max autologin time, or autologin is not enabled, it's expired
|
||||
return 1 if(!$self -> {"phpbb"} -> get_config("allow_autologin") ||
|
||||
return 1 if(!$self -> {"auth"} -> get_config("allow_autologin") ||
|
||||
($max_autologin && $sessdata -> {"session_time"} < time() - ((86400 * $max_autologin) + 60)));
|
||||
}
|
||||
|
||||
@ -474,7 +473,7 @@ sub session_expired {
|
||||
|
||||
|
||||
## @method $ get_session($sessid)
|
||||
# Obtain the data for the session with the specified session ID. If there is no
|
||||
# Obtain the data for the session with the specified session ID. If there is no
|
||||
# session with the specified id in the database, this returns undef, otherwise it
|
||||
# returns a reference to a hash containing the session data.
|
||||
#
|
||||
@ -522,7 +521,7 @@ sub set_login_key {
|
||||
my $self = shift;
|
||||
|
||||
my $key = $self -> {"autokey"};
|
||||
my $key_id = $self -> {"phpbb"} -> unique_id(substr($self -> {"sessid"}, 0, 8));
|
||||
my $key_id = $self -> {"auth"} -> unique_id(substr($self -> {"sessid"}, 0, 8));
|
||||
|
||||
# If we don't have a key, we want to create a new key in the table
|
||||
if(!$key) {
|
||||
|
121
phpBB3.pm
121
phpBB3.pm
@ -25,12 +25,12 @@
|
||||
# a perl script low-level access to the data stored in a phpBB3 database,
|
||||
# and they should be used with caution. Unlike phpBB3, no security checks
|
||||
# are done on, for example, whether the user is supposed to be able to see
|
||||
# a topic in a forum: while it would be technically possible to achieve
|
||||
# a topic in a forum: while it would be technically possible to achieve
|
||||
# this, it would add a dramatic overhead to the listing and fetching of
|
||||
# posts and would involve session shenanigans to ensure users are logged
|
||||
# into a phpBB3 account.
|
||||
#
|
||||
#
|
||||
#
|
||||
package phpBB3;
|
||||
|
||||
use strict;
|
||||
@ -84,7 +84,7 @@ BEGIN {
|
||||
"e" => "%Z",
|
||||
"I" => "", # UNSUPPORTED: (capital i) Whether or not the date is in daylight saving time 1 if Daylight Saving Time, 0 otherwise.
|
||||
"O" => "%z",
|
||||
"P" => "", # UNSUPPORTED: Difference to Greenwich time (GMT) with colon between hours and minutes (added in PHP 5.1.3)
|
||||
"P" => "", # UNSUPPORTED: Difference to Greenwich time (GMT) with colon between hours and minutes (added in PHP 5.1.3)
|
||||
"T" => "%Z",
|
||||
"Z" => "", # UNSUPPORTED: Timezone offset in seconds. The offset for timezones west of UTC is always negative, and for those east of UTC is always positive.
|
||||
"c" => "%FT%T%z",
|
||||
@ -114,7 +114,7 @@ BEGIN {
|
||||
# you do not need to provide the username, password, or data_src.
|
||||
#
|
||||
# @param args A hash of key, value pairs to initialise the object with.
|
||||
# @return A new phpBB3 object, or undef if no database connection has been provided or
|
||||
# @return A new phpBB3 object, or undef if no database connection has been provided or
|
||||
# established.
|
||||
sub new {
|
||||
my $invocant = shift;
|
||||
@ -130,6 +130,7 @@ sub new {
|
||||
allowanon => 0,
|
||||
dbopts => { RaiseError => 0, AutoCommit => 1 },
|
||||
url => "/",
|
||||
ANONYMOUS => $ANONYMOUS,
|
||||
@_,
|
||||
};
|
||||
|
||||
@ -139,7 +140,7 @@ sub new {
|
||||
# try to open the database connection with those credentials.
|
||||
if(!$obj -> {"dbh"} && $self -> {"username"} & $obj -> {"password"} && $obj -> {"data_src"}) {
|
||||
$obj -> {"dbh"} = DBI -> connect($obj -> {"data_src"},
|
||||
$obj -> {"username"},
|
||||
$obj -> {"username"},
|
||||
$obj -> {"password"},
|
||||
$obj -> {"dbopts"})
|
||||
or return set_error("Unable to open database connection - ".$DBI::errstr);
|
||||
@ -221,10 +222,10 @@ sub register_user {
|
||||
my $content = $www -> content();
|
||||
return "Unexpected content in response to registration first step accept."
|
||||
unless($content =~ /PLEASE DO NOT ATTEMPT TO REGISTER USING THIS FORM/);
|
||||
|
||||
|
||||
$www -> form_id('register')
|
||||
or return "Unable to locate the second step registration form.";
|
||||
|
||||
|
||||
# Now we can fill in fields to submit
|
||||
$www -> field ('username' , $args -> {"username"});
|
||||
$www -> field ('email' , $args -> {"email"});
|
||||
@ -235,7 +236,7 @@ sub register_user {
|
||||
$www -> field ('question2' , 'chris page');
|
||||
$www -> select('lang' , 'en');
|
||||
$www -> select('tz' , '0');
|
||||
|
||||
|
||||
# And submit that
|
||||
$www -> click('submit');
|
||||
return "Failed when posting registration second step. Response was: ".$www -> res -> message if(!$www -> success());
|
||||
@ -334,7 +335,7 @@ sub get_group {
|
||||
# group_id - the id of the group to check in.
|
||||
# If user_id is specified, username is ignored if it is also provided. If user_id
|
||||
# is not provided, username must be (ie: you must specify at least one of username
|
||||
# or user_id, and user_id takes precedence) Similarly, you must specify at least
|
||||
# or user_id, and user_id takes precedence) Similarly, you must specify at least
|
||||
# one of group or group_id, and group_id takes precedence over group.
|
||||
#
|
||||
# @param args A hash of arguments.
|
||||
@ -356,38 +357,38 @@ sub user_in_group {
|
||||
|
||||
# If we don't have a user_id, we need to look it up
|
||||
if(!$args{"user_id"}) {
|
||||
my $user = $self -> get_user($args{'username'})
|
||||
my $user = $self -> get_user($args{'username'})
|
||||
or return set_error("Unable to find user $args{'username'}");
|
||||
$args{"user_id"} = $user -> {"user_id"};
|
||||
}
|
||||
|
||||
# If we don't have a group_id, we need to look it up
|
||||
if(!$args{"group_id"}) {
|
||||
my $group = $self -> get_group($args{'group'})
|
||||
my $group = $self -> get_group($args{'group'})
|
||||
or return set_error("Unable to find user $args{'group'}");
|
||||
$args{"group_id"} = $group -> {"group_id"};
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Now we should have a user id and group id, so we can go look in the user_group table
|
||||
my $ugh = $self -> {"dbh"} -> prepare("SELECT * FROM ".$self -> {"prefix"}."user_group
|
||||
WHERE group_id = ? AND user_id = ?");
|
||||
$ugh -> execute($args{"group_id"}, $args{"user_id"})
|
||||
or die "phpBB3::user_in_group(): Unable to execute user_group lookup query.\nError was: ".$self -> {"dbh"} -> errstr."\n";
|
||||
|
||||
|
||||
# Do we have one or more rows?
|
||||
my $ugr = $ugh -> fetchrow_arrayref();
|
||||
|
||||
|
||||
return defined($ugr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
## @method $ valid_user($username, $password)
|
||||
# Attempt to confirm whether the provided user credentials are valid. This will check
|
||||
# whether the specified username corresponds to a valid user, and if it does it will
|
||||
# check that the hash of the provided password matches. If the password matches, this
|
||||
# returns a reference to a hash containing the user's entry in the users table.
|
||||
#
|
||||
#
|
||||
# @param username The username of the user to check.
|
||||
# @param password The password to check against this user.
|
||||
# @return A reference to a hash containing the user's data, or undef if an error
|
||||
@ -422,8 +423,8 @@ sub get_profile_url {
|
||||
|
||||
|
||||
## @method $ email_in_use($email)
|
||||
# Determine whether the specified email address is already in use within the
|
||||
# system.
|
||||
# Determine whether the specified email address is already in use within the
|
||||
# system.
|
||||
#
|
||||
# @param email The email address to check.
|
||||
# @return true if the email address already exists within the database, false
|
||||
@ -432,7 +433,7 @@ sub email_in_use {
|
||||
my $self = shift;
|
||||
my $email = shift;
|
||||
|
||||
my $emailh = $self -> {'dbh'} -> prepare("SELECT user_id FROM ".$self -> {"prefix"}."users
|
||||
my $emailh = $self -> {'dbh'} -> prepare("SELECT user_id FROM ".$self -> {"prefix"}."users
|
||||
WHERE user_email LIKE ?");
|
||||
$emailh -> execute($email)
|
||||
or die "phpBB3::email_in_use(): Unable to execute email lookup query.\nError was: ".$self -> {"dbh"} -> errstr."\n";
|
||||
@ -485,16 +486,16 @@ sub is_valid_password {
|
||||
# Session handling
|
||||
|
||||
## @method @ get_session(void)
|
||||
# Attempt to obtain the userid and username of the current session user. This
|
||||
# attempts to determine whether the session in the user's cookies is a valid
|
||||
# phpBB3 session, and if it is it returns a reference to a hash containing user
|
||||
# Attempt to obtain the userid and username of the current session user. This
|
||||
# attempts to determine whether the session in the user's cookies is a valid
|
||||
# phpBB3 session, and if it is it returns a reference to a hash containing user
|
||||
# and session data. This will update the timestamp on the session, if needed.
|
||||
#
|
||||
# @return A reference to a hash containing user and session data if the session
|
||||
# is valid, undef otherwise.
|
||||
#
|
||||
# @todo This does not currently support forwarded_for checks, referer checks,
|
||||
# or load limiting. It also does not support 'alternative' auth methods:
|
||||
# @todo This does not currently support forwarded_for checks, referer checks,
|
||||
# or load limiting. It also does not support 'alternative' auth methods:
|
||||
# only database auth is supported.
|
||||
sub get_session {
|
||||
my $self = shift;
|
||||
@ -505,7 +506,7 @@ sub get_session {
|
||||
|
||||
# First, try to obtain a session id - start by looking at the cookies
|
||||
my $sessid = $self -> {"cgi"} -> cookie($cookiebase."_sid");
|
||||
my $sessuser = $self -> {"cgi"} -> cookie($cookiebase."_u"); # Which users does this session claim to be?
|
||||
my $sessuser = $self -> {"cgi"} -> cookie($cookiebase."_u"); # Which users does this session claim to be?
|
||||
my $autokey = $self -> {"cgi"} -> cookie($cookiebase."_k"); # Do we have an autologin key for the user?
|
||||
|
||||
# If we don't have a session id now, try to pull it from the query string
|
||||
@ -515,13 +516,13 @@ sub get_session {
|
||||
return set_error("Unable to obtain a session id for user.") if(!$sessid);
|
||||
|
||||
# Obtain the session and user record from the database
|
||||
my $sessh = $self -> {"dbh"} -> prepare("SELECT u.*,s.*
|
||||
my $sessh = $self -> {"dbh"} -> prepare("SELECT u.*,s.*
|
||||
FROM ".$self -> {"prefix"}."users AS u, ".$self -> {"prefix"}."sessions AS s
|
||||
WHERE s.session_id = ? AND u.user_id = s.session_user_id");
|
||||
$sessh -> execute($sessid)
|
||||
or die "phpBB3::get_session(): Unable to obtain session and user data from database.\nError was: ".$self -> {"dbh"} -> errstr."\n";
|
||||
my $sessdata = $sessh -> fetchrow_hashref();
|
||||
|
||||
|
||||
# if we have a session, we need to validate it
|
||||
if($sessdata) {
|
||||
# If we have anonymous disabled, at this is the anon user, exit immediately
|
||||
@ -546,7 +547,7 @@ sub get_session {
|
||||
if($self -> get_config("browser_check")) {
|
||||
$valid_ua = substr(lc($sessdata -> {"session_browser"}), 0, 150) eq
|
||||
substr(lc($self -> {"cgi"} -> user_agent()), 0, 150);
|
||||
}
|
||||
}
|
||||
|
||||
# If the ip and browser checks are okay, continue with the validation
|
||||
# TODO: add referer and forwarded_for checks here?
|
||||
@ -560,17 +561,17 @@ sub get_session {
|
||||
# If the session claims to be autologin, but the server doesn't support it, expire the session
|
||||
} elsif(!$self -> get_config("allow_autologin")) {
|
||||
$expired = 1;
|
||||
|
||||
|
||||
# Otherwise, if check whether a maximum autologin time limit has been set, and that the session is within it
|
||||
} else {
|
||||
my $max_autologin = $self -> get_config("max_autologin_time");
|
||||
$expired = ($max_autologin && $sessdata -> {"session_time"} < (time() - ($max_autologin + 60)));
|
||||
}
|
||||
|
||||
|
||||
# If the session has not expired, we want to touch it
|
||||
if(!$expired) {
|
||||
if(time() - $sessdata -> {"session_time"} > 60) {
|
||||
my $touch = $self -> {"dbh"} -> prepare("UPDATE ".$self -> {"prefix"}."sessions
|
||||
my $touch = $self -> {"dbh"} -> prepare("UPDATE ".$self -> {"prefix"}."sessions
|
||||
SET session_time = ?
|
||||
WHERE session_id = ?");
|
||||
$touch -> execute(time(), $sessdata -> {"session_id"})
|
||||
@ -602,9 +603,9 @@ sub get_session {
|
||||
#
|
||||
# @note <b>This function does no permissions checking whatsoever.</b> It is up
|
||||
# to the caller to determine whether or not the forum should be visible.
|
||||
# If you expose private forums with this function, you have nobody to
|
||||
# If you expose private forums with this function, you have nobody to
|
||||
# blame but yourself. You have been warned.
|
||||
#
|
||||
#
|
||||
# @param forumid The id of the forum to obtain data on.
|
||||
# @return A reference to a hash containing the forum data, or undef if the
|
||||
# forum does not exist in the database.
|
||||
@ -629,21 +630,21 @@ sub get_forum {
|
||||
# Given a forum id, a topic count, and an offset, obtain a list of topic IDs
|
||||
# for topics in the forum. This follows the same treatement of posts as the forum
|
||||
# view in phpBB3: announcements always appear at the start of the list, regardles
|
||||
# of the offset. The remaining posts are sorted so that sticky topics will
|
||||
# of the offset. The remaining posts are sorted so that sticky topics will
|
||||
# appear before normal topics, but are otherwise treated normally.
|
||||
#
|
||||
# @note <b>This function does no permissions checking whatsoever.</b> It is up
|
||||
# to the caller to determine whether or not the forum should be visible.
|
||||
# If you expose private forums with this function, you have nobody to
|
||||
# If you expose private forums with this function, you have nobody to
|
||||
# blame but yourself. You have been warned.
|
||||
#
|
||||
# @param forum The ID of the forum to obtain a topic list for.
|
||||
# @param count The number of topics ids to return, if not specified defaults to 10.
|
||||
# @param count The number of topics ids to return, if not specified defaults to 10.
|
||||
# if set to 0, all post ids are returned.
|
||||
# @param offset The number of posts to skip, if not specified defaults to 0. This is
|
||||
# ignored if count is set to 0.
|
||||
# @param sort_by_last If true, posts are sorted by the last reply time rather
|
||||
# than the default creation time order (note that this must
|
||||
# than the default creation time order (note that this must
|
||||
# be true to generate the same listing phpBB3 shows)
|
||||
# @return A reference to an array of topic ids, or undef if no topics are available
|
||||
# or an error ocurred.
|
||||
@ -677,7 +678,7 @@ sub get_topic_ids {
|
||||
# always having announcements at the front.
|
||||
my $announceh = $self -> {"dbh"} -> prepare("SELECT topic_id FROM ".$self -> {"prefix"}."topics
|
||||
WHERE forum_id = ? AND topic_type = 2
|
||||
$order
|
||||
$order
|
||||
".($fetchall ? "" : "LIMIT $count"));
|
||||
$announceh -> execute($forum)
|
||||
or die "phpBB3::get_topic_ids(): Unable to obtain announcement topic list.\nError was: ".$self -> {"dbh"} -> errstr."\n";
|
||||
@ -707,7 +708,7 @@ sub get_topic_ids {
|
||||
}
|
||||
|
||||
} # if($count) {
|
||||
|
||||
|
||||
# And we're done. Return a reference to the topics array if it has any contents,
|
||||
# undef if it does not.
|
||||
return scalar(@topics) ? \@topics : set_error("");
|
||||
@ -717,7 +718,7 @@ sub get_topic_ids {
|
||||
## @method $ get_topic($topicid)
|
||||
# Obtain the data for the topic identified by the specified topicid. This will attempt
|
||||
# to locate a topic entry with the specified topicid and return a reference to a hash
|
||||
# containing the topic information.
|
||||
# containing the topic information.
|
||||
#
|
||||
# @param topicid The id of the topic to look up.
|
||||
# @return A reference to a hash containing the topic data, undef if the topic could
|
||||
@ -754,7 +755,7 @@ sub get_topic_firstpost {
|
||||
or return set_error("Unable to locate topic $topicid in the database");
|
||||
|
||||
# Now we can obtain the first post and user details
|
||||
my $posth = $self -> {"dbh"} -> prepare("SELECT p.*, u.*
|
||||
my $posth = $self -> {"dbh"} -> prepare("SELECT p.*, u.*
|
||||
FROM ".$self -> {"prefix"}."posts AS p, ".$self -> {"prefix"}."users AS u
|
||||
WHERE p.post_id = ? AND u.user_id = p.poster_id");
|
||||
$posth -> execute($topic -> {"topic_first_post_id"})
|
||||
@ -774,15 +775,15 @@ sub get_topic_firstpost {
|
||||
"post_uid" => $post -> {"bbcode_uid"},
|
||||
"poster_username" => $post -> {"username"},
|
||||
"poster_userid" => $post -> {"user_id"}};
|
||||
|
||||
# If the user has an avatar, we want to record it. Note that this expects phpBB3
|
||||
|
||||
# If the user has an avatar, we want to record it. Note that this expects phpBB3
|
||||
# to have enforced any restrictions on avatar types.
|
||||
if($post -> {"user_avatar_type"}) {
|
||||
# width and height should be there regardless of type
|
||||
$pdata -> {"avatar_width"} = $post -> {"user_avatar_width"};
|
||||
$pdata -> {"avatar_height"} = $post -> {"user_avatar_height"};
|
||||
|
||||
# type 1 is uploaded
|
||||
# type 1 is uploaded
|
||||
if($post -> {"user_avatar_type"} == 1) {
|
||||
$pdata -> {"avatar_url"} = $self -> get_config("server_protocol").
|
||||
$self -> get_config("server_name").
|
||||
@ -792,7 +793,7 @@ sub get_topic_firstpost {
|
||||
# type 2 avatars are remote linked, so the url should be usable as-is
|
||||
} elsif($post -> {"user_avatar_type"} == 2) {
|
||||
$pdata -> {"avatar_url"} = $post -> {"user_avatar"};
|
||||
|
||||
|
||||
# type 3 avatars are gallery avatars
|
||||
} elsif($post -> {"user_avatar_type"} == 3) {
|
||||
$pdata -> {"avatar_url"} = $self -> get_config("server_protocol").
|
||||
@ -863,14 +864,14 @@ sub get_smilie_url {
|
||||
|
||||
|
||||
## @method $ get_config($name, $default)
|
||||
# Obtain the value for the specified phpBB3 configuration variable. This will
|
||||
# return the value for the specified configuration variable if it is found. If
|
||||
# it is not found, but default is specified, the default is returned, otherwise
|
||||
# Obtain the value for the specified phpBB3 configuration variable. This will
|
||||
# return the value for the specified configuration variable if it is found. If
|
||||
# it is not found, but default is specified, the default is returned, otherwise
|
||||
# this returns undef.
|
||||
#
|
||||
# @param name The name of the variable to obtain the value for
|
||||
# @param default An optional default value to return if the named variable can not be found
|
||||
# @return The value for the named variable, or the default or undef if the
|
||||
# @return The value for the named variable, or the default or undef if the
|
||||
# variable is not present.
|
||||
sub get_config {
|
||||
my $self = shift;
|
||||
@ -890,7 +891,7 @@ sub get_config {
|
||||
# Otherwise, return the default or undef
|
||||
return $default;
|
||||
}
|
||||
|
||||
|
||||
|
||||
## @method $ unique_id($extra)
|
||||
# Generate a unique ID that can be used with phpBB3 tables.
|
||||
@ -915,8 +916,8 @@ sub unique_id {
|
||||
# by the php date() function into something that can be passed to strftime to get the same
|
||||
# result. Note that the following php date() format options are not supported and will be
|
||||
# replaced with the empty string: S, t, L, B, u, I, O, and T. The following options are
|
||||
# partially supported but the resulting strings are not identical: n (will generate the
|
||||
# same output as m), g (hour has a leading space instead of zero), and G (hour has a
|
||||
# partially supported but the resulting strings are not identical: n (will generate the
|
||||
# same output as m), g (hour has a leading space instead of zero), and G (hour has a
|
||||
# leading space instead of zero)
|
||||
#
|
||||
# @param format The php date() format string to convert.
|
||||
@ -960,13 +961,13 @@ sub set_error {
|
||||
# Seriously internal stuff
|
||||
|
||||
# The following functions have been ported wholesale from the phpBB3 'includes/functions.php'
|
||||
# The port has been done with minimal regard for perlification, and it almost certainly
|
||||
# The port has been done with minimal regard for perlification, and it almost certainly
|
||||
# could be implemented in a far more efficient and perl-friendly fashion.
|
||||
#
|
||||
# Beware, voodoo programming follows.
|
||||
|
||||
## @fn $ _hash_encode64($input, $count, $itoa64)
|
||||
# Convert a number into an encoded string form.
|
||||
# Convert a number into an encoded string form.
|
||||
#
|
||||
# @param input The number to encode.
|
||||
# @param count The number of characters in the number to convert.
|
||||
@ -977,13 +978,13 @@ sub _hash_encode64 {
|
||||
|
||||
my $output = '';
|
||||
my $i = 0;
|
||||
|
||||
|
||||
while($i < $count) {
|
||||
my $value = ord(substr($input, $i++, 1));
|
||||
$output .= substr($itoa64, $value & 0x3F, 1);
|
||||
|
||||
$value |= ord(substr($input, $i, 1)) << 8 if($i < $count);
|
||||
|
||||
|
||||
$output .= substr($itoa64, ($value >> 6) & 0x3F, 1);
|
||||
last if($i++ >= $count);
|
||||
|
||||
@ -991,7 +992,7 @@ sub _hash_encode64 {
|
||||
|
||||
$output .= substr($itoa64, ($value >> 12) & 0x3F, 1);
|
||||
last if($i++ >= $count);
|
||||
|
||||
|
||||
$output .= substr($itoa64, ($value >> 18) & 0x3F, 1);
|
||||
}
|
||||
|
||||
@ -1011,7 +1012,7 @@ sub _hash_crypt_private {
|
||||
my ($password, $setting, $itoa64) = @_;
|
||||
|
||||
my $output = '*';
|
||||
|
||||
|
||||
return $output if(substr($setting, 0, 3) ne '$H$');
|
||||
|
||||
my $count_log2 = index($itoa64, substr($setting, 3, 1));
|
||||
@ -1036,9 +1037,9 @@ sub _hash_crypt_private {
|
||||
|
||||
## @fn $ _check_hash($password, $hash)
|
||||
# Determine whether the specified password hashes to the same string as the provided hash.
|
||||
# This checks whether the plain-text password, and the previously generated hash, are
|
||||
# This checks whether the plain-text password, and the previously generated hash, are
|
||||
# actually representing the same string by hashing the plain-text password and comparing
|
||||
# it to the specified hash. This function can handle phpBB3 (salted md5 hash) and phpBB2
|
||||
# it to the specified hash. This function can handle phpBB3 (salted md5 hash) and phpBB2
|
||||
# (straight md5 hash) hashes and chooses the appropriate algorithm based on the length of
|
||||
# the hash string: if it is 34 characters, it is assumed to be a phpBB3 hash, otherwise it
|
||||
# is assumed to be a hex encoded 32 character string.
|
||||
|
Loading…
x
Reference in New Issue
Block a user