Revision [19907]
This is an old revision of WikkaWithphpBB made by WebHorn on 2008-05-12 18:22:39.
Using the phpBB users table for logging in
See also:
This is a very simple hack to get Wikka to read from the users table of a phpBB database rather than its own. It is assuming that you have installed your Wikka into the same database as phpBB and that your phpBB tables are prefixed with "phpbb_" ("phpbb3_" for the v3.0 examples) and that their names have not been edited.
This will allow users from your phpBB forum to login to your wiki with their existing username and password.
Please note that for suggested changes phpBB and wikka should use the same database - otherwise it is necessary to give rights to wikka's database to read phpBB's database - and to write name of phpBB's database before its tables.
Using PHPBB 3.x
Contributed by Paul Young, using the example code by JeremyCoates in Method 2 below.phpBB3 changed its user authentication mechanism. phpBB3 no longer stores MD5 hashes of passwords; instead it does a "true" one-way, one-time, non-recoverable hash of the password using [http://www.openwall.com/phpass/|phpass]. The output of the hash is different each time, so you can't just select the password in the phpBB database and do a compare against a MD5 of the submitted password anymore - you have to algorithmically compare them using phpass. They also changed how and where they indicate if a user is active or inactive.
It's not difficult, but you will need to bring in code from phpBB to your Wikka files.
One final note, this code works for me on my server, but could stand to be further tested. Feel free to correct if you find a bug.
/Wikka.php (in Wikka 1.1.6.2 its /libs/Wakka.class.php)
Find:
function LoadUser($name, $password = 0) { return $this->LoadSingle("select * from ".$this->config['table_prefix']."users where name = '".mysql_real_escape_string($name)."' ".($password === 0 ? "" : "and password = '".mysql_real_escape_string($password)."'")." limit 1"); }
Replace with:
/**
* PHPBB Integration
*
* function LoadUser($name, $password = 0) { return $this->LoadSingle("select * from ".$this->config['table_prefix']."users where name = '".mysql_real_escape_string($name)."' ".($password === 0 ? "" : "and password = '".mysql_real_escape_string($password)."'")." limit 1"); }
*/
function LoadUser($name, $password = 0) {
$user = $this->LoadSingle("select
p.username as name
,p.user_password as password
,p.user_email as email
,p.user_regdate as signuptime
,w.revisioncount
,w.changescount
,w.doubleclickedit
,w.show_comments
from ".phpbb3_."users p
left join " . $this->config['table_prefix'] . "users w ON p.username = w.name
where p.username = '".mysql_real_escape_string($name)."' and p.user_type != 1 limit 1");
if (isset($user['signuptime'])) {
$user['signuptime'] = date('Y-m-d H:i:s', $user['signuptime']);
}
return $user;
* PHPBB Integration
*
* function LoadUser($name, $password = 0) { return $this->LoadSingle("select * from ".$this->config['table_prefix']."users where name = '".mysql_real_escape_string($name)."' ".($password === 0 ? "" : "and password = '".mysql_real_escape_string($password)."'")." limit 1"); }
*/
function LoadUser($name, $password = 0) {
$user = $this->LoadSingle("select
p.username as name
,p.user_password as password
,p.user_email as email
,p.user_regdate as signuptime
,w.revisioncount
,w.changescount
,w.doubleclickedit
,w.show_comments
from ".phpbb3_."users p
left join " . $this->config['table_prefix'] . "users w ON p.username = w.name
where p.username = '".mysql_real_escape_string($name)."' and p.user_type != 1 limit 1");
if (isset($user['signuptime'])) {
$user['signuptime'] = date('Y-m-d H:i:s', $user['signuptime']);
}
return $user;
function LoadUsers() { return $this->LoadAll("select * from ".$this->config['table_prefix']."users order by name"); }
Replace With:
/**
* PHPBB Integration
*
* function LoadUsers() { return $this->LoadAll("select * from ".$this->config['table_prefix']."users order by name"); }
*/
function LoadUsers() { $users = $this->LoadAll("select
p.username as name
,p.user_password as password
,p.user_email as email
,p.user_regdate as signuptime
,w.revisioncount
,w.changescount
,w.doubleclickedit
,w.show_comments
from ".phpbb3_."users p
left join " . $this->config['table_prefix'] . "users w ON p.username = w.name
where p.user_type != 1
order by username");
foreach ($users as $key => $user) {
if (isset($user['signuptime'])) {
$user['signuptime'] = date('Y-m-d H:i:s', $user['signuptime']);
}
$users[$key] = $user;
}
return $users;
}
Finally, copy and paste these phpass functions from phpBB into the bottom of file, before the "?>"
(php)* PHPBB Integration
*
* function LoadUsers() { return $this->LoadAll("select * from ".$this->config['table_prefix']."users order by name"); }
*/
function LoadUsers() { $users = $this->LoadAll("select
p.username as name
,p.user_password as password
,p.user_email as email
,p.user_regdate as signuptime
,w.revisioncount
,w.changescount
,w.doubleclickedit
,w.show_comments
from ".phpbb3_."users p
left join " . $this->config['table_prefix'] . "users w ON p.username = w.name
where p.user_type != 1
order by username");
foreach ($users as $key => $user) {
if (isset($user['signuptime'])) {
$user['signuptime'] = date('Y-m-d H:i:s', $user['signuptime']);
}
$users[$key] = $user;
}
return $users;
}
Finally, copy and paste these phpass functions from phpBB into the bottom of file, before the "?>"
function phpbb_hash($password)
{
$itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$random_state = 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(unique_id() . $random_state);
$random .= pack('H*', md5($random_state));
}
$random = substr($random, 0, $count);
}
$hash = _hash_crypt_private($password, _hash_gensalt_private($random, $itoa64), $itoa64);
if (strlen($hash) 34)
34)
{
return $hash;
}
return md5($password);
}function phpbb_check_hash($password, $hash)
{
$itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
if (strlen($hash)
34)
{
return (_hash_crypt_private($password, $hash, $itoa64) $hash) ? true : false;
$hash) ? true : false;
}
return (md5($password)
$hash) ? true : false;
}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 .= _hash_encode64($input, 6, $itoa64);
return $output;
}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;
}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;
}
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 .= _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);
return substr($val, 4, 16);
}==/actions/usersettings.php== Find:
default: input is valid
$this->Query('UPDATE '.$this->config['table_prefix'].'users SET '.
"email = '".mysql_real_escape_string($email)."', ".
"doubleclickedit = '".mysql_real_escape_string($doubleclickedit)."', ".
"show_comments = '".mysql_real_escape_string($show_comments)."', ".
"revisioncount = '".mysql_real_escape_string($revisioncount)."', ".
"changescount = '".mysql_real_escape_string($changescount)."' ".
"WHERE name = '".$user['name']."' LIMIT 1");
Replace with:
$tmpUser = $this->LoadUser($user['name']);
if (is_null($tmpUser['show_comments'])) {
$this->Query("INSERT INTO ".$this->config['table_prefix']."users SET ".
"signuptime = '".mysql_real_escape_string($user['signuptime'])."',".
"name = '".mysql_real_escape_string($user['name'])."', ".
"email = '".mysql_real_escape_string($user['email'])."'");
}
Find:
case (md5($_POST['password']) != $existingUser['password']):
$error = ERROR_WRONG_PASSWORD; $password_highlight = INPUT_ERROR_STYLE; break; Replace With: case (!phpbb_check_hash($_POST['password'],$existingUser['password'])):
$error = ERROR_WRONG_PASSWORD; $password_highlight = INPUT_ERROR_STYLE; break; Using PHPBB 2.xMethod 1/Wikka.php (in Wikka 1.1.6.2 its /libs/Wakka.class.php)Find: function LoadUser($name, $password = 0) { return $this->LoadSingle("select * from ".$this->config['table_prefix']."users where name = '".mysql_real_escape_string($name)."' ".($password === 0 ? "" : "and password = '".mysql_real_escape_string($password)."'")." limit 1"); }
Replace with: function LoadUser($name, $password = 0) { return $this->LoadSingle("select * from ".phpbb_."users where username = '".mysql_real_escape_string($name)."' ".($password === 0 ? "" : "and user_password = '".mysql_real_escape_string($password)."'")." limit 1"); }
Find: function LoadUsers() { return $this->LoadAll("select * from ".$this->config['table_prefix']."users order by name"); }
Replace with: function LoadUsers() { return $this->LoadAll("select * from ".phpbb_."users order by username"); }
Find: function GetUserName() { if ($user = $this->GetUser()) $name = $user["name"]; else if (!$name = gethostbyaddr($_SERVER["REMOTE_ADDR"])) $name = $_SERVER["REMOTE_ADDR"]; return $name; }
Replace with: function GetUserName() { if ($user = $this->GetUser()) $name = $user["username"]; else if (!$name = gethostbyaddr($_SERVER["REMOTE_ADDR"])) $name = $_SERVER["REMOTE_ADDR"]; return $name; }
Find: function SetUser($user) { $_SESSION["user"] = $user; $this->SetPersistentCookie("user_name", $user["name"]); $this->SetPersistentCookie("pass", $user["password"]); }
Replace with: function SetUser($user) { $_SESSION["user"] = $user; $this->SetPersistentCookie("user_name", $user["username"]); $this->SetPersistentCookie("pass", $user["user_password"]); }
/handlers/page/acls.phpFind: echo "\t".'<option value="'.$this->htmlspecialchars_ent($user['name']).'">'.$user['name'].'</option>'."\n";
Replace with: echo "\t".'<option value="'.$this->htmlspecialchars_ent($user['username']).'">'.$user['username'].'</option>'."\n";
added by KiltanneN - feel free to remove or correct /actions/usersettings.phpFind:Replace with: added by EniBevoli - fix to show the name of the user again in the User Settings page Find: Replace with: added by KiltanneN - feel free to remove or correct I changed several things in the highscores.php code. Mostly they were changing the "name" to "username" but there was also the table prefix thing that had to be fixed up. Here's the full code: /actions/highscores.php<?php
# highscores.php {{HighScores}} # by Chris Tessmer # 19 Dec 2002 # license: GPL $str = 'SELECT Count(*) AS cnt, `username` FROM phpbb_users, ' ; $str .= $this->config["table_prefix"].'pages '; $str .= "WHERE `username` = `owner` AND `latest` = 'Y' GROUP BY username ORDER BY cnt DESC;"; $rankQuery = $this->Query( $str ); $str = 'SELECT COUNT(*) FROM '.$this->config["table_prefix"].'pages WHERE `latest` = \'Y\' '; $totalQuery = $this->Query( $str ); $total = mysql_result($totalQuery, 0); print( "<blockquote><table>" ); $i = 0; while( $row = mysql_fetch_array($rankQuery) ) { $i++; $str = '<tr>'; $str .= "<td>$i. </td>"; $str .= '<td>'. $this->Format( $row["username"] ) .'</td>'; $str .= '<td> </td>'; $str .= '<td> </td>'; $str .= '<td>'.$row["cnt"].'</td>'; $str .= '<td> </td>'; $str .= '<td>'. round( ($row["cnt"]/$total)*100, 2).'% </td>'; $str .= '</tr>'; print( $str ); } print( "</table></blockquote>" ); ?> Method 2Added by JeremyCoatesAdvantages over Method 1:
/Wikka.php (in Wikka 1.1.6.2 its /libs/Wakka.class.php)Find: function LoadUser($name, $password = 0) { return $this->LoadSingle("select * from ".$this->config['table_prefix']."users where name = '".mysql_real_escape_string($name)."' ".($password === 0 ? "" : "and password = '".mysql_real_escape_string($password)."'")." limit 1"); }
Replace with: /**
* PHPBB Integration * * function LoadUser($name, $password = 0) { return $this->LoadSingle("select * from ".$this->config['table_prefix']."users where name = '".mysql_real_escape_string($name)."' ".($password === 0 ? "" : "and password = '".mysql_real_escape_string($password)."'")." limit 1"); } */ function LoadUser($name, $password = 0) { $user = $this->LoadSingle("select p.username as name ,p.user_password as password ,p.user_email as email ,p.user_regdate as signuptime ,w.revisioncount ,w.changescount ,w.doubleclickedit ,w.show_comments from ".phpbb_."users p left join " . $this->config['table_prefix'] . "users w ON p.username = w.name where p.username = '".mysql_real_escape_string($name)."' ".($password === 0 ? "" : "and p.user_password = '".mysql_real_escape_string($password)."'")." and p.user_active = 1 limit 1"); if (isset($user['signuptime'])) { $user['signuptime'] = date('Y-m-d H:i:s', $user['signuptime']); } return $user; } Find: function LoadUsers() { return $this->LoadAll("select * from ".$this->config['table_prefix']."users order by name"); }
Replace with: /**
* PHPBB Integration * * function LoadUsers() { return $this->LoadAll("select * from ".$this->config['table_prefix']."users order by name"); } */ function LoadUsers() { $users = $this->LoadAll("select p.username as name ,p.user_password as password ,p.user_email as email ,p.user_regdate as signuptime ,w.revisioncount ,w.changescount ,w.doubleclickedit ,w.show_comments from ".phpbb_."users p left join " . $this->config['table_prefix'] . "users w ON p.username = w.name where p.user_active = 1 order by username"); foreach ($users as $key => $user) { if (isset($user['signuptime'])) { $user['signuptime'] = date('Y-m-d H:i:s', $user['signuptime']); } $users[$key] = $user; } return $users; } /actions/usersettings.phpFind: default: // input is valid
$this->Query('UPDATE '.$this->config['table_prefix'].'users SET '. "email = '".mysql_real_escape_string($email)."', ". "doubleclickedit = '".mysql_real_escape_string($doubleclickedit)."', ". "show_comments = '".mysql_real_escape_string($show_comments)."', ". "revisioncount = '".mysql_real_escape_string($revisioncount)."', ". "changescount = '".mysql_real_escape_string($changescount)."' ". "WHERE name = '".$user['name']."' LIMIT 1"); Replace with: default: // input is valid
/** * PHPBB Integration * * Insert the user into the Wakka users table */ $tmpUser = $this->LoadUser($user['name']); if (is_null($tmpUser['show_comments'])) { $this->Query("INSERT INTO ".$this->config['table_prefix']."users SET ". "signuptime = '".mysql_real_escape_string($user['signuptime'])."',". "name = '".mysql_real_escape_string($user['name'])."', ". "email = '".mysql_real_escape_string($user['email'])."'"); } /** * End PHPBB Integration */ $this->Query('UPDATE '.$this->config['table_prefix'].'users SET '. "email = '".mysql_real_escape_string($email)."', ". "doubleclickedit = '".mysql_real_escape_string($doubleclickedit)."', ". "show_comments = '".mysql_real_escape_string($show_comments)."', ". "revisioncount = '".mysql_real_escape_string($revisioncount)."', ". "changescount = '".mysql_real_escape_string($changescount)."' ". "WHERE name = '".$user['name']."' LIMIT 1"); /actions/highscores.phpFind: $str = 'SELECT Count(*) AS cnt, `name` FROM ';
$str .= $this->config["table_prefix"] . 'users, ' ; $str .= $this->config["table_prefix"].'pages '; $str .= "WHERE `name` = `owner` AND `latest` = 'Y' GROUP BY name ORDER BY cnt DESC;"; Replace with: $str = 'SELECT Count(*) AS cnt, `username` AS name FROM phpbb_users, ' ;
$str .= $this->config["table_prefix"].'pages '; $str .= "WHERE `username` = `owner` AND `latest` = 'Y' GROUP BY username ORDER BY cnt DESC;"; Configuration to disable UserRegistration is still required, either patch for 1.1.6.2 or update config setting in 1.1.6.3 (or later) see UserRegistration for more details. PHPBB 2.0.xIf you want to force Wiki names in PHPBB logins (it will save pain later!) /includes/functions_validate.phpFind (in function validate_username): // Don't allow " and ALT-255 in username.
if (strstr($username, '"') || strstr($username, '"') || strstr($username, chr(160))) { return array('error' => true, 'error_msg' => $lang['Username_invalid']); } return array('error' => false, 'error_msg' => ''); Replace with: // Don't allow " and ALT-255 in username.
if (strstr($username, '"') || strstr($username, '"') || strstr($username, chr(160))) { return array('error' => true, 'error_msg' => $lang['Username_invalid']); } /** * Wikka Integration * Wiki Username validation */ $include_path = get_include_path(); set_include_path(get_include_path() . PATH_SEPARATOR . realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..')); include_once('wikka.config.php'); include_once('libs/Wakka.class.php'); class WakkaPHPBBHack extends Wakka { function WakkaPHPBBHack($config) { parent::Wakka($config); ob_start(); include_once('actions/usersettings.php'); ob_end_clean(); } } $wakka = new WakkaPHPBBHack($wakkaConfig); set_include_path($include_path); // Check for wiki names if (!$wakka->IsWikiName($username)) { return array('error' => true, 'error_msg' => preg_replace('`[#"]`', '', ERROR_WIKINAME)); } // Check for reserved pages in wiki if ($wakka->ExistsPage($username)) { return array('error' => true, 'error_msg' => ERROR_RESERVED_PAGENAME); } /** * End Wikka integration */ return array('error' => false, 'error_msg' => ''); Wikka Wiki and phpBB: using phpBB user information and allow Wikka-specific user settingsAdded on July 29, 2005 by EniBevoliI still have to make a easily readable diff output (such as "Find" - "Replace with" above; I already translated some text strings to German, so diff'ing is currently a mess) so that other users can edit their own files, but since I have finally come to a solution outlined below, I thought it would be a beneficial for others to simply post my results right away. The existing work on the Wikka Wiki / phpBB integration was a big starting point; without this information, I wouldn't even had a clue what to do. :) Features / How it works:
Requirements: - After the integration of Wikka Wiki and phpBB is done, user registration via Wikka Wiki must be disabled, new accounts should only be added via phpBB; see UserRegistration for more information about how to disable user registration It took me quite some time to figure out why turning off "double click edit" didn't work - it is a bug with Wikka Wiki 1.1.6.0. :) I don't include the bug fix here, since it is already outlined in WikkaBugs. Changed files:
As I said, I'm still compiling the changes in an easily readable format and will update this page when I'm done. To Do / Questions / Open Issues:
CategoryUserContributions |