# ================================================================== # Plugins::GMail::Auth_UBB - Auto Generated Install Module # # Plugins::GMail::Auth_VBulletin # Author : Scott Beck # Version : 1.0 # Updated : Tue Apr 24 21:37:44 2001 # # ================================================================== # package Plugins::GMail::Auth_VBulletin; # ================================================================== use strict; use vars qw/$AUTH_DBH $AUTH_CFG $VB_CFG/; use DBI; use GT::Base qw/:all/; use GT::Plugins qw/STOP CONTINUE/; use GMail::Auth; use GMail::Plugins; use GMail qw/:all/; @Plugins::GMail::Auth_VBulletin::ISA = qw/GT::Base/; sub authenticate { # ------------------------------------------------------------------- # This is the main function, and is called once every request. # my $status = shift; if ($status and $IN->param('username')) { remote_init(); remote_check_relation() or return EXIT; } return $status if ($status); # User authenticated already in GMail. # Don't override the login form. my $url = $IN->url; if ($url =~ /login\.cgi/) { return $status; } # Otherwise, the user didn't authenticate, so let's load the config information. remote_init(); # Now we check to see if it's a valid user. my $remote_user = remote_username() or return remote_error("Invalid VBulletin Session"); # Check to see if the user already has an entry in Gossamer Mail. my $sth = $DB->table('auth_vb')->select('gmail_user', { vb_user => $remote_user }); my ($username) = $sth->fetchrow; # Check to see if we are filtering based on user group. if ($AUTH_CFG->{vbulletin_groups}) { remote_groups($remote_user) or return EXIT; } # Already in Gossamer Mail if ($username) { $PLG->dispatch('GMail::Auth::get_user', sub { GMail::Auth->get_user(@_) }, $username) or return remote_error("Unable to fetch user: $GMail::Auth::error"); $PLG->dispatch('GMail::Auth::create_session', sub { GMail::Auth->create_session(@_) }, $USER->{email}) or return remote_error("Unable to create session: $GMail::Auth::error"); require GMail::Folders; GMail::Folders->update(); } # Not in Gossamer Mail but signing up. elsif ($IN->param('username')) { my $id; require GMail::NoAuth::Join; unless ($id = GMail::NoAuth::Join->add_user) { $GMail::NoAuth::Join::error ||= ''; # Silence -w my $t = GMail->template_set; $IN->param(t => [$t]); $CFG->load_template_set($t); GMail->print_page('vb_sign_in.htm', { error => \$GMail::NoAuth::Join::error }); return EXIT; } my $username = $IN->param('username') . '@' . $IN->param('domain'); my $uid = $id->{userid}; if (! $uid) { my $p = GT::SQL->prefix; $uid = $id->{$p . 'users.userid'}; } $DB->table('auth_vb')->insert({ gmail_userid => $uid, gmail_user => $username, vb_user => $remote_user, }); $PLG->dispatch('GMail::Auth::get_user', sub { GMail::Auth->get_user(@_) }, $username) or return remote_error("Unable to fetch user: $GMail::Auth::error"); $PLG->dispatch('GMail::Auth::create_session', sub { GMail::Auth->create_session(@_) }, $USER->{email}) or return remote_error("Unable to create session: $GMail::Auth::error"); require GMail::Folders; GMail::Folders->update(); } # Not in Gossamer Mail, so print signup form. else { my $t = GMail->template_set; $CFG->load_template_set($t); GMail->print_page('vb_sign_in.htm'); return EXIT; } return 1; } sub add_user { # ------------------------------------------------------------------- # Can't add a user from Gossamer Mail. # return 1 if (caller(2) eq 'GMail::NoAuth::Join' or caller(3) eq 'GMail::NoAuth::Join'); my $opt = shift; if ($opt->{email} eq ADMIN) { return 1; } GT::Plugins->action(STOP); # Make sure we don't run the main code. $GMail::Auth::error ||= ''; # Silence -w $GMail::Auth::error = "You can only create users from the VBulletin admin panel."; return; } sub insert_dgraph { # ------------------------------------------------------------------- # This handles inserting a user demographics information. # my $uid = shift; my ($remote_user) = $DB->table('auth_vb')->select('vb_user', { gmail_userid => $uid })->fetchrow; my $record = get_rec($remote_user) or return; $record = Plugins::GMail::Auth_VBulletin->map($record); $DB->table('dgraph')->add($record); } sub valid_user { # ------------------------------------------------------------------- # Takes a user name, pass and this plugins config hash. Returns # true if this user is in the vb auth system. # my ($user, $pass) = @_; my $rec = get_rec($user) or return; my $valid = 0; if ($pass eq $rec->{password}) { $valid = 1; } else { require GT::MD5; import GT::MD5 'md5_hex'; $valid = $pass eq md5_hex($rec->{password}); } $valid ? return Plugins::GMail::Auth_VBulletin->map($rec) : return; } sub map { # ------------------------------------------------------------------- # Map what we can from VB # my ($self, $rec) = @_; my $ret = {}; @{$ret}{qw/ email password dgraph_email /} = delete(@{$rec}{qw/ username password email /}); if (index($rec->{email}, ',') != -1) { ($ret->{dgraph_last_name}, $ret->{dgraph_first_name}) = split /\s*,\s*/ => delete $rec->{email}; } elsif (index($rec->{email}, ' ') != -1) { ($ret->{dgraph_first_name}, $ret->{dgraph_last_name}) = split /\s+/ => delete $rec->{email}; } else { $ret->{dgraph_first_name} = delete $rec->{email}; } @{$ret}{keys %$rec} = (values %$rec); return $ret; } sub get_rec { # ------------------------------------------------------------------- # Given a VB username returns the VB record # remote_init(); my ($username) = @_; my $sth = $AUTH_DBH->prepare("SELECT * FROM user WHERE username = ?"); $sth->execute($username); return $sth->fetchrow_hashref; } sub info { # ------------------------------------------------------------------- # Called from the sign in template, and returns a list of dgraph tags. # my $ret = { map { $_ => $IN->param($_) || $GMail::Template::TAGS{$_} || '' } keys %{$DB->table('dgraph')->cols}, keys %{$DB->table('users')->cols} }; # Now we check to see if it's a valid user. my $remote_user = remote_username() or return remote_error("Invalid VBulletin session"); # Look up the user information in the user table my $record = get_rec($remote_user) or return remote_error("VBulletin session does not have matching user?"); $record = Plugins::GMail::Auth_VBulletin->map($record); # Try to fill out as much form info as we can for (keys %{$record}) { $ret->{$_} ||= $record->{$_}; } $ret->{confirm} = $ret->{password}; $ret->{email} =~ s/[\@ "';\$!*]/_/g; # Try to suggest a nice name for the user. my $i = ''; until (!$DB->table('users')->count(GT::SQL::Condition->new([email => LIKE => $ret->{email}.$i.'@%']))) { $i ||= 0; $i++; } $ret->{username} = $ret->{email} . $i; return $ret; } sub join { # ------------------------------------------------------------------- # This hook just redirects you to an error page. # GT::Plugins->action(STOP); # Make sure we don't run the main code. remote_init(); return remote_error("Can't call join with this plugin."); } sub help { # ------------------------------------------------------------------- # Simple help message. # print $IN->header; my $message = qq~ Plugins::GMail::Auth_VBulletin
Plugin: Auth_VBulletin

Auth_VBulletin

This plugin integrates your user database into VBulletin, a popular forum package available at:

http://www.vbulletin.com

From the options page, you can set specific user groups to have access to the email (perfect for making the email system a paid option), and you can set what URL's the plugin should redirect to if the plugin can't validate the user.

For more information on this plugin, please visit the support forum.

~; print $message; } sub remote_init { # ------------------------------------------------------------------- # Load the config file and connect to the database. # return 1 if ($AUTH_DBH); $AUTH_CFG = GMail::Plugins->get_plugin_user_cfg('Auth_VBulletin'); $VB_CFG = {}; my $path; my $vb2_path = "$AUTH_CFG->{vbulletin_dir}/admin/config.php"; my $vb3_path = "$AUTH_CFG->{vbulletin_dir}/includes/config.php"; if (-e $vb3_path) { $path = $vb3_path; } elsif (-e $vb2_path) { $path = $vb2_path; } else { die "Unable to locate VBulletin installation path."; } open F, $path or die "Could not open $path; Reason: $!"; while () { next if m[^//] || /^\s*$/; if (/\$(\w+)\s*=\s*['"]([^'"]+)['"]/) { $VB_CFG->{$1} = $2; } } close F; $AUTH_DBH = DBI->connect("DBI:mysql:$VB_CFG->{dbname}:$VB_CFG->{servername}", $VB_CFG->{dbusername}, $VB_CFG->{dbpassword}) or die "Can't connect to sql server. Reason: $DBI::errstr"; return 1; } sub remote_username { # ------------------------------------------------------------------- # Looks up the forum user based on input. # my $userid = $IN->cookie('bbuserid'); my $pass = $IN->cookie('bbpassword'); my ($user, $db_userid, $db_pass); # Lookup the user based on userid/password if ($userid and $pass) { my $sth = $AUTH_DBH->prepare('SELECT username, password, userid FROM user WHERE userid = ?') or die "Error: $DBI::errstr"; $sth->execute($userid) or die "Error: $DBI::errstr"; ($user, $db_pass, $db_userid) = $sth->fetchrow or return; if ($db_pass ne $pass) { require GT::MD5; import GT::MD5 'md5_hex'; if ($pass ne md5_hex($db_pass)) { return; } } } # Lookup the user based on session key. else { my $session_id = $IN->cookie('sessionhash') || $IN->param('sessionhash') || $IN->param('s') || return; # First get the userid. my $sth = $AUTH_DBH->prepare('SELECT userid FROM session WHERE sessionhash = ?') or die "Error: $DBI::errstr"; $sth->execute($session_id) or die "Error: $DBI::errstr"; ($sth->rows > 0) or return; ($db_userid) = $sth->fetchrow; # Now load the username. $sth = $AUTH_DBH->prepare('SELECT username, userid FROM user WHERE userid = ?') or die "Error: $DBI::errstr"; $sth->execute($db_userid) or die "Error: $DBI::errstr"; ($sth->rows > 0) or return; ($user) = $sth->fetchrow; } return $user; } sub remote_groups { # ------------------------------------------------------------------- # Makes sure a user is in only a particular vbulletin user group. # my $username = shift; my $groups = $AUTH_CFG->{vbulletin_groups}; $groups =~ /^[\s,\d]+$/ or die "Invalid setting in groups: $groups"; my $sth = $AUTH_DBH->prepare("SELECT username FROM user WHERE username = ? AND usergroupid IN ($groups)") or die "Error: $DBI::errstr"; $sth->execute($username) or die "Error: $DBI::errstr"; my ($new_user) = $sth->fetchrow; if (! $new_user) { warn "VBulletin Plugin: User $username is not in groups: $groups\n" if ($CFG->{debug}); print $IN->redirect($AUTH_CFG->{redirect_groups}); return; } return 1; } sub remote_info { # ------------------------------------------------------------------- # Prints a diagnositc of cookie information for debugging. # my $userid = $IN->cookie('bbuserid'); my $pass = $IN->cookie('bbpassword'); my $session_id = $IN->cookie('sessionhash') || $IN->param('sessionhash') || $IN->param('s'); return "user: '$userid' pass: '$pass' session: '$session_id'"; } sub remote_error { # ------------------------------------------------------------------- # Redirects a user to an error page. # my $msg = shift || ''; $msg .= "\nUnable to validate user: " . remote_info() . "\n"; warn "VBulletin Plugin: $msg\nRedirecting to: $AUTH_CFG->{redirect_error}\n" if ($CFG->{debug}); print $IN->redirect($AUTH_CFG->{redirect_error}); return EXIT; } sub remote_check_relation { # ------------------------------------------------------------------- # Check to see if the user is in the auth table. # my $sth = $DB->table('auth_vb')->select('vb_user', { gmail_userid => $USER->{userid} }); $sth->rows and return 1; # Oops, in GMail, but not the auth table. Let's try and add them in. my $remote_username = remote_username() or return remote_error("User is in GMail, but not logged into Remote Auth!"); # Check to see if we are filtering based on user group. if ($AUTH_CFG->{vbulletin_groups}) { remote_groups($remote_username) or return; } # Add them in. $DB->table('auth_vb')->insert({ gmail_userid => $USER->{userid}, gmail_user => $USER->{email}, vb_user => $remote_username }); return 1; } END { # Disconnect from the database. $AUTH_DBH and $AUTH_DBH->disconnect; } 1;