• Skip to content
  • Skip to menu

Barattalo

code snippets, classes and other stuff for developers 

Rss 2.0

  • Home
  • Me
  • Mini Bots PHP Class
  • Facebook Connect Tutorial
  • HTML fixer

Sep 17 2010

How to integrate phpbb forum login

Category: Php — Giulio Pons @ 5:34 pm

I have had to install phpbb forum on a website that already had a user table and I want to keep the users of my table as the only users of the web site. I want to give to my users the access to the phpbb functionalities.

I’ve searched for a ready-to-use component but it seems that it doesn’t exists. I’ve tried to watch the source of phpbb to understand if changing the whole code to match my table was a valid path to run, but it seems to be too complex, there are too many occurrence of the user table in the code. So I’ve tried to understand if mapping records could be a solution and I’ve found many people that walk this way. I’ve found a Php class that does some of the work mapping users but it wasn’t enough, so here is my 10 steps tutorial.

phpbb integration forum scheme

STEP 1: install phpbb forum (i’ve used version 3)
Read documentation of phpbb on how to install the forum, it’s quite easy, there is a good wizard. For the admin user choose a username that is an admin on your user table so the mapping will be correct.

STEP 2: download this phpbbintegration.class.php [download]
This class does a relevant job: it allows you to copy your users from your community into phpbb tables.
It also does the update password and something more:

<?
/*
	PHPBB3 Integration class
	=================================================================================
	this class is based on the work of Jonathan Gibb, http://www.polr.co.uk
	and modified by Giulio Pons http://www.barattalo.it to handle also
	the login process.
	A complete tutorial can be found here: 

http://www.barattalo.it/2010/09/17/phpbb-login-integration/

	* Functionality:
	* --------------
	* Add a user to PHPBB3
	* Change users password on PHPBB3
	* Disable/ban user on PHPBB3
	* Enable/un-ban user on PHPBB3
	=================================================================================
*/
									// CONFIG
									// ======
define('ROOT_PATH', "../forum/");	// map this dir to your own installation of phpbb
define('IN_PHPBB', true);
if (!defined('IN_PHPBB') || !defined('ROOT_PATH')) exit();
$phpEx = "php";
$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : ROOT_PATH . '/';
include($phpbb_root_path . 'common.' . $phpEx);
$user->session_begin();
$auth->acl($user->data);
$user->setup();

class Phpbb3Integration {
	var $table_prefix;
	var $connection;
	var $lang;
	var $default_timezone;
	var $user_dst;
	var $user_dateformat;
	var $user_colour;

	function Phpbb3Integration($table_prefix = 'phpbb_') {
														// CONFIG
														// ======
		$this->lang					= "it";				// language, I've tried "it" and "en"
		$this->default_timezone		= "1.00";			// +1 hour
		$this->user_dst				= 1;				// use legal time
		$this->user_dateformat		= "|d/m/Y|, G:i";	// date format
		$this->user_colour			= "9E8DA7";			// user colour
		$this->table_prefix			= $table_prefix;
	}

	function connect($server,$dbuser,$dbpass,$dbname) {
		$this->connection = mysql_connect ( $server, $dbuser, $dbpass );
		if (!$this->connection) return false;
		if (!mysql_select_db ( $dbname, $this->connection )) return false;
		return true;
	}

	function addNewUser($username,$password,$email,$ip) {
		$sql = $this->createSqlToAddUserRow ( $username, $password, $email, $ip );
		mysql_query ( $sql, $this->connection );
		$id = mysql_insert_id ( $this->connection );
		$sql = $this->createSqlToAddUserGroupRow ( $id );
		mysql_query ( $sql, $this->connection );
	}

	function changeUserPassword($username,$password) {
		$sql = $this->createSqlToUpdateUserPassword ( $username, $password );
		mysql_query ( $sql, $this->connection );
	}

	function disableUser($username) {
		// first get phpbb internal id for username
		$sql = "select user_id from " . $this->table_prefix . "users where username = '$username'";
		$query = mysql_query ( $sql, $this->connection );
		if (! $query) return false;
		$id = mysql_result ( $query, 0 );
		// create ban row
		$banSql = "insert into " . $this->table_prefix . 'banlist (ban_userid,  ban_start,  ban_reason, ban_give_reason)';
		$banSql .= "values ('$id','" . time () . "', 'External Integration','Banned by External Integration')";
		mysql_query ( $banSql, $this->connection );
	}

	function enableUser($username) {
		// first get phpbb internal id for username
		$sql = "select user_id from " . $this->table_prefix . "users where username = '$username'";
		$query = mysql_query ( $sql, $this->connection );
		if (! $query) return false;
		$id = mysql_result ( $query, 0 );
		// delete ban row
		$deleteSql = "DELETE FROM " . $this->table_prefix . 'banlist where ban_userid = ' . $id;
		$query = mysql_query ( $deleteSql, $this->connection );
		return ($query != false);
	}

	// Helper Methods
	// ==============
	/**
	 * Generate salt for hash generation
	 */
	function _hash_gensalt_private($input,&$itoa64,$iteration_count_log2 = 6) {
		if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) $iteration_count_log2 = 8;
		$output = '$H$';
		$output .= $itoa64 [min ( $iteration_count_log2 + ((PHP_VERSION >= 5) ? 5 : 3), 30 )];
		$output .= $this->_hash_encode64 ( $input, 6, $itoa64 );
		return $output;
	}

	/**
	 * Encode hash
	 */
	function _hash_encode64($input,$count,&$itoa64) {
		$output = '';
		$i = 0;
		do {
			$value = ord ( $input [$i ++] );
			$output .= $itoa64 [$value & 0x3f];
			if ($i < $count) $value |= ord ( $input [$i] ) << 8;
			$output .= $itoa64 [($value >> 6) & 0x3f];
			if ($i ++ >= $count) break;
			if ($i < $count) $value |= ord ( $input [$i] ) << 16;
			$output .= $itoa64 [($value >> 12) & 0x3f];
			if ($i ++ >= $count) break;
			$output .= $itoa64 [($value >> 18) & 0x3f];
		} while ( $i < $count );
		return $output;
	}

	/**
	 * The crypt function/replacement
	 */
	function _hash_crypt_private($password,$setting,&$itoa64) {
		$output = '*';
		// Check for correct hash
		if (substr ( $setting, 0, 3 ) != '$H$') return $output;
		$count_log2 = strpos ( $itoa64, $setting [3] );
		if ($count_log2 < 7 || $count_log2 > 30) return $output;
		$count = 1 << $count_log2;
		$salt = substr ( $setting, 4, 8 );
		if (strlen ( $salt ) != 8) return $output;

		/**
		 * We're kind of forced to use MD5 here since it's the only
		 * cryptographic primitive available in all versions of PHP
		 * currently in use.  To implement our own low-level crypto
		 * in PHP would result in much worse performance and
		 * consequently in lower iteration counts and hashes that are
		 * quicker to crack (by non-PHP code).
		 */
		if (PHP_VERSION >= 5) {
			$hash = md5 ( $salt . $password, true );
			do {
				$hash = md5 ( $hash . $password, true );
			} while ( -- $count );
		} else {
			$hash = pack ( 'H*', md5 ( $salt . $password ) );
			do {
				$hash = pack ( 'H*', md5 ( $hash . $password ) );
			} while ( -- $count );
		}
		$output = substr ( $setting, 0, 12 );
		$output .= $this->_hash_encode64 ( $hash, 16, $itoa64 );
		return $output;
	}

	function unique_id($extra = 'c') {
		static $dss_seeded = false;
		global $config;
		$val = $config ['rand_seed'] . microtime ();
		$val = md5 ( $val );
		$config ['rand_seed'] = md5 ( $config ['rand_seed'] . $val . $extra );
		$dss_seeded = true;
		return substr ( $val, 4, 16 );
	}

	function phpbb_hash($password) {
		$itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
		$random_state = $this->unique_id ();
		$random = '';
		$count = 6;
		if (($fh = @fopen ( '/dev/urandom', 'rb' ))) {
			$random = fread ( $fh, $count );
			fclose ( $fh );
		}
		if (strlen ( $random ) < $count) {
			$random = '';
			for($i = 0; $i < $count; $i += 16) {
				$random_state = md5 ( $this->unique_id () . $random_state );
				$random .= pack ( 'H*', md5 ( $random_state ) );
			}
			$random = substr ( $random, 0, $count );
		}
		$hash = $this->_hash_crypt_private ( $password, $this->_hash_gensalt_private ( $random, $itoa64 ), $itoa64 );
		if (strlen ( $hash ) == 34) return $hash;
		return md5 ( $password );
	}

	function createSqlToAddUserRow($username,$password,$email,$ip) {
		$sql = "INSERT INTO `" . $this->table_prefix . "users` (";
		$sql .= "`user_id`, `user_type`, `group_id`, `user_permissions`, `user_perm_from`, `user_ip`, `user_regdate`, `username`, `username_clean`, `user_password`, `user_passchg`, `user_pass_convert`, `user_email`, `user_email_hash`, `user_birthday`, `user_lastvisit`, `user_lastmark`, `user_lastpost_time`, `user_lastpage`, `user_last_confirm_key`, `user_last_search`, `user_warnings`, `user_last_warning`, `user_login_attempts`, `user_inactive_reason`, `user_inactive_time`, `user_posts`, `user_lang`, `user_timezone`, `user_dst`, `user_dateformat`, `user_style`, `user_rank`, `user_colour`, `user_new_privmsg`, `user_unread_privmsg`, `user_last_privmsg`, `user_message_rules`, `user_full_folder`, `user_emailtime`, `user_topic_show_days`, `user_topic_sortby_type`, `user_topic_sortby_dir`, `user_post_show_days`, `user_post_sortby_type`, `user_post_sortby_dir`, `user_notify`, `user_notify_pm`, `user_notify_type`, `user_allow_pm`, `user_allow_viewonline`, `user_allow_viewemail`, `user_allow_massemail`, `user_options`, `user_avatar`, `user_avatar_type`, `user_avatar_width`, `user_avatar_height`, `user_sig`, `user_sig_bbcode_uid`, `user_sig_bbcode_bitfield`, `user_from`, `user_icq`, `user_aim`, `user_yim`, `user_msnm`, `user_jabber`, `user_website`, `user_occ`, `user_interests`, `user_actkey`, `user_newpasswd`, `user_form_salt`";
		$sql .= ")";
		$sql .= "VALUES (";
		$sql .= "NULL, '0', '2', '00000000006xv1ssxs\ni1cjyo000000\nqlc4pi000000\nzik0zi000000', '0', '" . $ip . "', '" . time () . "', '$username', '$username',";
		$sql .= "'" . $this->phpbb_hash ( $password ) . "', '" . time () . "', '0', '$email',";
		$sql .= " '0', '', '" . time () . "', '" . time () . "', '" . time () . "', '', '',";
		$sql .= "'0', '0', '0', '0', '0', '0', '0',";
		$sql .= "'{$this->lang}', '{$this->default_timezone}', '{$this->user_dst}', '{$this->user_dateformat}', '1', '0',";
		$sql .= "'{$this->user_colour}', '0', '0', '0', '0', '-3', '0', '0', 't', 'd', '0', 't', 'a', '0', '1', '0', '1', '1', '1',";
		$sql .= "'1', '895', '', '0', '0', '0', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '1a99da7f3160cc5c'";
		$sql .= ")";
		return $sql;
	}

	function createSqlToAddUserGroupRow($phpbb_user_id) {
		$sql = "INSERT INTO `" . $this->table_prefix . "user_group` (`group_id`, `user_id`, `group_leader`, `user_pending`) VALUES ('2', '$phpbb_user_id', '0', '0')";
		return $sql;
	}

	function createSqlToUpdateUserPassword($username,$newPassword) {
		$sql = "update `" . $this->table_prefix . "users` set user_password = '" . $this->phpbb_hash ( $newPassword ) . "' where username = '" . $username . "'";
		return $sql;
	}

}
?>

Note: there is a line of code at the beginning that you have to config, and there are a few lines inside the constructor, change them to match your phpbb3 installation.

STEP 3: handle conflicts
Since I’m using original phpbb files there are some possible conflicts to handle when you include the phpbbintegration.class.php, so, follow these rules in the pages that use phpbbintegration class:
- don’t use a class called “Session” since this is the name of the class that handles sessions in phpbb code.
- don’t use global variables with those names: $db, $user, $auth. Those variables are the main objects of the phpbb user system, so rename your variables.

STEP 4: modify your registration process to handle the creation of the users also on the phpbb tables
In my community I use an opt-in process so I’ve added the copy of the user after the opt-in process is completed:

// my includes... add the new class:
include("res/inc/PHPBB3Integration.class.php");

// ...my php that make the registered user valid
// such as the update to flag the email as valid
// after the opt-in process.

// ...
$userobj = getUserData($id); // user obj contains the data of the user in my community
$_SESSION['logged']=$userobj['id']; // login my user
// ...

// ----------------------------------------
// the new code to add: copy the new user into forum
$forum = new Phpbb3Integration();
$forum->connect ( WEBDOMAIN, DEFUSERNAME, DEFDBPWD, DEFDBNAME );
$forum->addNewUser ( $userobj['username'], $userobj['password'], $userobj['email'], getIP() );
// ----------------------------------------
// log in the user using the the phpbb auth object
$auth->login( $userobj['username'], $userobj['password'], true, 1, 0);

STEP 5: modify your login to login also on the forum

// my includes... add the new class:
include("res/inc/PHPBB3Integration.class.php");

$username = $_POST['user'];
$password = $_POST['pass'];

$userobj= execute_row("select * from myusers where status=1 and username='".addslashes($username)."' and password='".addslashes($password)."'");

if(is_array($userobj) && $row['id']>0) {
	$_SESSION['logged']=$userobj['id']; // login my user
	// login on phpbb forum
	$auth->login( $userobj['username'], $userobj['password'], true, 1, 0);
} else {
	die("login failed");
}

STEP 6: modify your logout process to logout also on the forum
Add the include of the class and add those lines to you logout:

// logout from phpbb
$user->session_kill();
$user->session_begin();

STEP 7: disable native registration in phpbb
Login in with the admin in the phpbb forum and disable the registration of new users, there is specific option to set in the administration control panel.

STEP 8: modify templates to remove phpbb unwanted features
You have to remove the blocks that print the login form from login_body.html file placed in the forum/styles/[skinname]/templates directory (remove also the reset password) and remove the block for login in login_forum.html. If you don’t want to remove the login forms you can modify them to post to your system and go back to the forum.
Remember that you also have to remove the block that show the commands to change email and password in ucp_profile_reg_details.html.

STEP 9: modify your change password process
You have to change the password also in the phpbb forum using the integration class changeUserPassword method.

The whole integration process can be quite unobtrusive if you don’t have code conflicts (step 3) and it’s good since we didn’t touch the phpbb code, but only its config files and its templates, so it could happen that this tutorial will works also after the future upgrades.

STEP 10: first porting
It could be necessary, if you have an already existing community, that you first have to make a script the copy all your active user to your phpbb forum. Just make a script that has the connection to the db, include the integration class, and the cycle through your user and for each record call the addNewUser function.

Share

Tags: forum, integration, login, phpbb, phpbb3, tutorial, user table

Comments (9)


Feb 16 2010

How to capture enter key pressed in a form (JavaScript)

Category: Html,Javascript — Giulio Pons @ 12:08 pm

Suppose you have a login form and you want to send the form when user press enter on his keyboard and not only by clicking on the submit button.
This can be achieved capturing a specific event when the user is typing. We have to capture the keypress event and listen to trigger an action when the enter key is pressed.
In the html form we have to add the “onkeypress” attribute that will contain a call to a javascript fnction that to the job.
The javascript function receive also a string parameter, so you can customize and reuse this code (it’s the ‘formid’ parameter).
The “evt” and “thisObj” parameters return the event handler and the object (the input type) that made the call to the function. The event parameter is important, the object that calls the fnction is not important as parameter since it’s used only to blur the input field.

Here is the javascript function that handle the event:

<script type="text/javascript">
	function submitonenter(formid,evt,thisObj) {
		evt = (evt) ? evt : ((window.event) ? window.event : "")
		if (evt) {
			// process event here
			if ( evt.keyCode==13 || evt.which==13 ) {
				thisObj.blur();
				document.getElementById(formid).submit();
			}
		}
	}
</script>

This is the html form with the “onkeypress” listener:

<form id='formlogin' action='file.php' method='post'>
	<input type='text' name='username' />
	<input name='pass' type='password' onkeypress="submitonenter('formlogin',event,this)" />
	<input type='submit' value='login'/>
</form>
Share

Tags: event, events, events handller, keypress, login, login form

Comments (0)



  • Categories
    • Asp
    • Css
    • Facebook
    • Google Maps
    • Html
    • Javascript
    • MsSQL
    • MySql
    • Php
    • Spiders & web bots
    • Uncategorized
  • Blogroll
    • Date Concerti
    • Fabrizio La Scimmia
    • Il Bloggatore
    • Ku ku photos
    • Me on Rockit
    • Rockit.it
    • Twirl.it
  • Print and study
    • Building website for iphone
    • Seo staff in Italian
  • Things to test
    • Building website for iphone
    • Counter with Google Analytics
    • htaccess mp3
    • Open inviter
  • Tags
    • Php
    • Spiders & web bots
    • Javascript
    • Spider
    • curl
    • MySql
    • Regular expression
    • spiders
    • Php
    • bot
    • programming
    • Google Maps
    • webbot
    • Web bot
    • Google Maps

top

Powered by WordPress and Stardust

Created by Tommaso Baldovino