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.
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:
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | <? /* 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: <blockquote data-secret="3xwDhGgX6q" class="wp-embedded-content"><a href="http://www.barattalo.it/php/phpbb-login-integration/" class="blpwp" target="_blank">How to integrate phpbb forum login</a></blockquote><iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted" style="position: absolute; clip: rect(1px, 1px, 1px, 1px); width: 1264px; height: 712.053px;" src="http://www.barattalo.it/php/phpbb-login-integration/embed/#?secret=3xwDhGgX6q" data-secret="3xwDhGgX6q" title="“How to integrate phpbb forum login” — Appunti" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe> * 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:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 | // 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
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 | // 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:
1 2 3 | // 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.
i’ve found a problem .. Fatal error: Call to undefined function execute_row() when i’m trying to login.
what is execute_row() ??
Thx.
Ramdhan
Nevermind … I’ve found the problem
This looks like it’s pretty happening.
http://svmods.com/facebook-connect-for-phpbb.html
Haven’t tried it yet, but it looks like it works on the guy’s demo site.
Does this handle checking for an existing user by username/email address?
I had a quick look through it but couldn’t see any reference to it.
Cheers,
Dave
Produse Albire Dinti
Albiti-va dintii rapid si eficient cu gama Crest Whitestrips. Veti obtine un zambet alb si stralucitor in numai 3 zile.
i love your tutorial but im having big time problem
Is any1 know how to solve that error:
Fatal error: Call to a member function sql_query() on a non-object in \forum\includes\cache.php on line 51
??
It is always showing when im trying to login thx for any help in advance
General Error
SQL ERROR [ mysqli ]
Can’t connect to MySQL server.
An sql error occurred while fetching this page. Please contact an administrator if this problem persists.
Why spend money when you could learn for free ? That is the idea on the internet. Regardless of what you are searching for, the Internet always has an answer for you.
Buongiorno Giulio.
Mi permetto di disturbarti, riguardo al tuo post
– How to integrate phpbb forum login
siamo un gruppetto di programmatori dilettanti che hanno un proprio sito
con un proprio sistema di registrazione ed autenticazione.
scritto da noi e quindi facilmente modificabile e configurabile basato su un db mysql.
vorremmo appunto integrarlo con un forum
la mia domanda base era (prima di perdere decine di ore in un lavoro al limite delle nostre capacità)
– è, secondo te, possibile accedere a phpbb tramite il nostro sistema di login
utilizzando il tuo sistema, ma PASSANDO i dati dei sottogruppi/forum a cui l’utente può accedere
ovvero che l’utente A possa partecipare ai sottoforum Sezione1, sezione2
mentre l’utente B possa accedere ai sottoforum Sezione1 e Sezione3 ecc ecc
basandoci sui dati del nostro db opportunamente adattati?
Se sì, partirebbe la seconda domanda: come? :-)
ma sarebbe già sufficiente sapere di lavorare su un obiettivo possibile!
Grazie per l’attenzione
Hello.
Thank you for this tutorial. It is exactly what I need.
But I have one question.
I have my index.php with the form to login.
When I log in, the form calls login_member.php in which I have my authentication process with the phpBB3Integration.class included.
At the end of the authentication, I redirect the user to the index.php page. But if I try to use the variable $user, I have this error “Notice: Undefined variable: user”.
Do I have to insert another code in index.php ?
Thank you.
Possibile lo è, di sicuro. E forse visto quanto tempo è passato dal vostro commento, l’avete già fatto!
Thanks for the tutorial, very helpful.
Btw, i found a bug:
When you insert a new user into phpbb_users table, you must insert the original username in “username” column, but in “username_clean” you must insert the username with all lowercase character. In your script, this doesn’t happen, being the username_clean not converted to lowercase. So, for example, if i create in my register.php script a user with uppercase letters (for example Alberto), the username_clean column will contain “Alberto” insted of “alberto”.
why is this important? Because if i create a user in my register.php script with username containing some uppercase letter, i will never be able to login into the forum. Don’t ask me why, but it happens.
How to fix this bug?
Easy:
change into phpbbintegration.class.php the following line
$sql .= “NULL, ‘0’, ‘2’, ‘00000000006xv1ssxs\ni1cjyo000000\nqlc4pi000000\nzik0zi000000’, ‘0’, ‘” . $ip . “‘, ‘” . time () . “‘, ‘$username’, ‘$username’,”;
with the following two lines
$username_lower = strtolower($username);
$sql .= “NULL, ‘0’, ‘2’, ‘00000000006xv1ssxs\ni1cjyo000000\nqlc4pi000000\nzik0zi000000’, ‘0’, ‘” . $ip . “‘, ‘” . time () . “‘, ‘$username’, ‘$username_lower’,”;
Hope it helped
The createSqlToAddUserRow needs to escape the fields it’s adding.
At present, this code is vulnerable to SQL injection.
Thanks, but it lacks of these functions:
-changeUsername() // to change forum’s username
-deleteUser() // to delete a user upon website user deletion
i am pretty sure there is bug in filling username_clean in phpBB_users when using capital letters.
as soon phpBB_users.usernameclean contains capital letters, the user is not recognized (not by phpBB admin, which is really strange), as soon as I manually changed phpBB_users.cleanname (its only the cleanname) to small letters only, everything works.
you can see it at the bots, the username clean is always small letters.
Not sure if this is still reviewed, but I have a problem with the login portion. The addition of the user to phpbb works fine, but it will not log them in. I am using version 3. Any thoughts on where the issue might be? I have essentially the exact same code for the login as you mention above. Thanks.
Hi,
I integrated phpbb w/ my php site as you instructed. It’s working great but new users who register thru my script are not showing as newest member. That is why I always click Resynchronise statistics in admin panel to show new members. Please advise for my issue.
I really appreciate for your Integration class.
Thank you,
Naung