Jayd Saucedo

Blog

Utilizing the vBulletin Database in Your Main Site
You have a forum, you have a main site, but you don’t want to have users register twice and login twice. So what we need to do is use the vBulletin database to extract user information. Vbulletin, of course, has its own developer tools that allow people to do just this, but if you’ve ever tried using them you’d quickly come to realize that they are incredibly bloated and difficult to implement. This is why, whenever I am faced with the task of implementing vBulletin with a main site, I choose to create my own system and the method for doing that is exactly what I intend to share in this post.

Recognizing that a user is logged in:

There are two ways to recognize that a user is logged in. One is through cookies, the other is through sessions. We need to create a system that recognizes both. Obviously, whenever a user is logged in they will have established some sort of session, but if a user chooses to use cookies so that the browser remembers their information then we need a system that can handle that as well.

Sessions:

First let’s cover sessions. Vbulletin doesn’t use PHP sessions, they use cookies. It might seem silly that both the vbulletin sessions and cookies both use the cookie system, but the sessions expire when you close the browser, and are thus just as good as PHP sessions. The way vBulletin handles sessions is through the database, it sets up a cookie with an identification hash and then stores that hash within the database. It then checks the database against your cookie every time you view a page. The way it generates your id hash is by taking your IP and user agent and MD5 encrypting them together. This information should never change as you are viewing the website, so it will remain consistent.

	$ip = implode('.', array_slice(explode('.', $_SERVER['REMOTE_ADDR']), 0, 4 - 1));
	$newidhash = md5($_SERVER['HTTP_USER_AGENT'] . $ip);

So what we do to figure out if a user has an established session is to check for the “bb_sessionhash” cookie, which contains the session hash. The session hash is an encryption of your username and password, but we don’t have to worry about that. All we need to do is use the session hash stored in the user’s cookie to search the database for their id hash. If we find the user then we must check the stored ID hash, set when they logged in, with their current ID hash, which we just generated and stored in “$newidhash” and then check that against a timeout time.

return ($idhash == $newidhash && (time() - $lastactive) < 900) ? $userid : false;

The timeout time serves to establish that the user will no longer be logged in if they do not visit a page on your website for more than 900 seconds. This is the default time in vBulletin. If their stored ID hash matches their current ID hash then that means their session is valid, and if they have visited a page within the last 900 seconds then their session is still valid.

All in all the function for checking a user session looks like this:

function get_session($hash){
	
	dbconnect();
	
	$hash = mysql_real_escape_string($hash);
	

	$ip = implode('.', array_slice(explode('.', $_SERVER['REMOTE_ADDR']), 0, 4 - 1));
	$newidhash = md5($_SERVER['HTTP_USER_AGENT'] . $ip);
		
	$query = "SELECT * FROM session WHERE sessionhash = '".$hash."' LIMIT 1";
	$result = mysql_query($query);	 
	
	if(mysql_num_rows($result) > 0){
		$row = mysql_fetch_array($result);
		
		$sessionhash = $row['sessionhash'];
		$idhash = $row['idhash'];
		$userid = $row['userid'];
		$lastactive = $row['lastactivity'];
				
		return ($idhash == $newidhash && (time() - $lastactive) < 900) ? $userid : false;
	}
	return false;	
}

where “dbconnect()” is a connection to your vbulletin database. This function will return a userid, which we will use later with another function to fetch all of the users data.

Cookies:

Next, if the user doesn’t have an established session, we need to see if the user has any cookies. There are two cookies that are set by vBulletin. The first one contains the user id, and is appropriately named “bb_userid” and the second one contains an encrypted password, and is appropriately named “bb_password”. So the first thing we do is fetch the user information with the id stored in the “bb_userid” cookie.

$id = mysql_real_escape_string($id);
$query = "SELECT * FROM user WHERE userid = ".$id." LIMIT 1";
$result = mysql_query($query);	

if a result is returned with that userid then you must fetch the encrypted password that is stored in the database and check that against the encrypted password that is stored in the user’s cookie. vBulletin has a rather odd way of creating cookie password hashes. They include a salt in the MD5, which is encrypted in MD5 with the plaintext password that was MD5’d and then MD5’d together with a salt that was MD5’d. So many levels on encryption! The salt that the cookie hash uses can be found in your “/includes/functions.php “ file under “define('COOKIE_SALT’, ‘a1083425cdcadc90cdab016422f8b6e5’)”. You might be curious as to where they got this obscure salt from, it’s unique to every user’s vBulletin, and I’m pretty sure it’s just an MD5 of your customer ID number. Anyway, once you wrap your head around that you should have something like this.

if(md5($dbpass . '0d582e0835ec6697262764ae6cb467fb') == $pass){
	return $username;
}
return false;

All in all my “get_cookie” function looks like this:

function get_cookie($id, $pass){

	dbconnect();
	
	$id = mysql_real_escape_string($id);
	
	$query = "SELECT * FROM user WHERE userid = ".$id." LIMIT 1";
	$result = mysql_query($query);	

	if(mysql_num_rows($result) > 0){
		$row = mysql_fetch_array($result);
		$dbpass = $row['password'];
		
		// vb might change the salt from time to time. can be found in the /includes/functions.php file
		if(md5($dbpass . '0d582e0835ec6697262764ae6cb467fb') == $pass){
			return $id;
		}
	}
	return false;	
}

There shouldn’t be any surprises here. But we need a function that uses these functions to check both these values, and determine if a user is logged in. That is as simple as this:

function check_login(){
	if(isset($_COOKIE['bb_userid']) && isset($_COOKIE['bb_password'])){
		if(get_cookie($_COOKIE['bb_userid'], $_COOKIE['bb_password'])){
			return $_COOKIE['bb_userid'];
		}
	}
	if(isset($_COOKIE['bb_sessionhash'])){
		if(get_session($_COOKIE['bb_sessionhash'])){
			return get_session($_COOKIE['bb_sessionhash']);
		}
	}
	return false;
}

There shouldn't be any surprises here either. First I check for any cookies, then I check for a session, if neither exist or both return invalid then the user isn't logged in. We also need a function that fetches all the user information from the database so we can display it on the page. That function is as simple as this:

function user_info($id){
	dbconnect();
	$result = mysql_query("SELECT * FROM user WHERE userid = ".mysql_real_escape_string($id)." LIMIT 1";);
	return mysql_fetch_array($result);
}

Finally we need a something that pulls all the functions together. That will look like this:

if($li = check_login()){
	dbconnect();
	$uinfo = user_info($li);
	
	$q_lastactivity = "UPDATE user SET lastactivity = '".time()."' WHERE userid = ".$li." LIMIT 1";
	mysql_query($q_lastactivity);
	
	if((time() - $uinfo['lastactivity']) > 900){
		$q_lastvisit = "UPDATE user SET lastvisit = '".$uinfo['lastactivity']."' WHERE userid = ".$li." LIMIT 1";
		mysql_query($q_lastvisit);	}
}

As you can see it uses the check_login function, stores the value returned in the “$li” variable, and then uses that variable to fetch user information. It then updates the last activity information for use by the session function. Finally, if a cookie is being used and the user has been away for more than 900 seconds it will update the “lastvisit” value in the database.

Creating a login form, a logout link, and displaying user data:

We sound done, right? WRONG. We need to create a login box that will display user information when a user has logged in, as well as provide a logout link.

Check if a user is logged in and display their information.

if($li){
	echo "Welcome, ".$uinfo["username"]."!";
	echo "
You last visited: ".timeBetween($uinfo["lastvisit"], time()) ." at ". date("h:i A", $uinfo["lastvisit"]); //echo "
Private Messages: Unread: ".$uinfo['pmunread'].", Total: ".$uinfo['pmtotal']."."; echo "
Click Here to logout!"; }

You see that we are using the “$li” and “$uinfo” variables from the other part of our script. The timeBetween function figures out how much time has passed between the last visit and the current time and displays it in a friendly way (e.g 30 seconds ago, 4 days ago, etc). If a user isn’t logged in then we must display a login form. I literally just copied and pasted my login form from my vBulletin page.

			
Remember Me? Not registered? | Forgot Password

This will automatically redirect to the previous page upon successful login as well. So no need to worry about that. Finally, we need to provide a way to logout. The simplest way to do this is just to destroy all the cookies. Which is exactly what this does:

if(isset($_GET['logout']) && $_GET['logout'] == 1){
	setcookie("bb_userid", "1", time() - 3600, "/", ".your website.com");
	setcookie("bb_password", "1", time() - 3600, "/", ".your website.com");
	setcookie("bb_sessionhash", "1", time() - 3600, "/", ".your website.com");
	header("LOCATION: ".$_SERVER['HTTP_REFERER']);
}

You’ll notice that I use a URL variable. That means I can simply link people to “script.php?logout=1” and they will then be logged out. This is exactly what I did in the code I posted previously.

This is it. This is all the information you need to create a website that implements your vBulletin database. If you have any questions, comments, or concerns please feel free to send me an e-mail.