====== PunBB or FluxBB Authentication backend ====== This backend provides authentication against a [[http://www.punbb.org|PunBB]] 1.2.x forum installed on the same server. It provides Single-Sign-On for (SSO) the forum and the wiki by reusing PunBB's cookies. ===== Requirements ===== * A recent PunBB 1.2.x forum installation (1.3.x support is in beta) / Works also with PunBB's fork: FluxBB 1.2.x and 1.4.rc1 * The forum needs to be on the same domain as the wiki * magic_quotes_gpc needs to be **off** ((Either disable in your ''php.ini'' or use ''php_value magic_quotes_gpc off'' in ''.htaccess'')) ===== Configuration ===== The backend reuses your PunBB configuration. You just need to enable it and set is the ''PUN_ROOT'' define pointing to the installation dir of your PunBB forum. Just add it to your ''conf/local.protected.php'': $conf['useacl'] =1; $conf['authtype']='punbb'; define('PUN_ROOT','/path/to/punbb/'); This path must be an absolute path, like ''/var/www/free.fr/2/8/mysite/punbb/'' for example and must end with a slash **/**. To have your admin users recognized you need to set your [[config:superuser]] option to the name of the PunBB administrator group. How this group is named, varies with the used language of your forum. In a English setup it is usually ''@Administrators'', while French users might need to use ''@Administrateurs''. ===== Source and Installation with PunBB 1.2.x or FluxBB 1.2.x ===== Up to DokuWiki 2008-05-05 this backend was included in the DokuWiki install. Newer versions no longer come with this backend. To install the backend, create a ''inc/auth/punbb.class.php'' file and copy and paste the following code: */ if(!defined('PUN_ROOT')) define('PUN_ROOT', DOKU_INC.'../forum/'); if(get_magic_quotes_gpc()){ nice_die('Sorry the punbb auth backend requires the PHP option magic_quotes_gpc to be disabled for proper operation. Either setup your PHP install accordingly or choose a different auth backend.'); } require_once PUN_ROOT.'include/common.php'; require_once DOKU_INC.'inc/auth/mysql.class.php'; #dbg($GLOBALS); #dbg($pun_user); class auth_punbb extends auth_mysql { /** * Constructor. * * Sets additional capabilities and config strings */ function auth_punbb(){ global $conf; $this->cando['external'] = true; $this->cando['logoff'] = true; // make sure we use a crypt understood by punbb if(function_exists('sha1')){ $conf['passcrypt'] = 'sha1'; }else{ $conf['passcrypt'] = 'md5'; } // get global vars from PunBB config global $db_host; global $db_name; global $db_username; global $db_password; global $db_prefix; // now set up the mysql config strings $conf['auth']['mysql']['server'] = $db_host; $conf['auth']['mysql']['user'] = $db_username; $conf['auth']['mysql']['password'] = $db_password; $conf['auth']['mysql']['database'] = $db_name; $conf['auth']['mysql']['checkPass'] = "SELECT u.password AS pass FROM ${db_prefix}users AS u, ${db_prefix}groups AS g WHERE u.group_id = g.g_id AND u.username = '%{user}' AND g.g_title != 'Guest'"; $conf['auth']['mysql']['getUserInfo'] = "SELECT password AS pass, realname AS name, email AS mail, id, g_title as `group` FROM ${db_prefix}users AS u, ${db_prefix}groups AS g WHERE u.group_id = g.g_id AND u.username = '%{user}'"; $conf['auth']['mysql']['getGroups'] = "SELECT g.g_title as `group` FROM ${db_prefix}users AS u, ${db_prefix}groups AS g WHERE u.group_id = g.g_id AND u.username = '%{user}'"; $conf['auth']['mysql']['getUsers'] = "SELECT DISTINCT u.username AS user FROM ${db_prefix}users AS u, ${db_prefix}groups AS g WHERE u.group_id = g.g_id"; $conf['auth']['mysql']['FilterLogin'] = "u.username LIKE '%{user}'"; $conf['auth']['mysql']['FilterName'] = "u.realname LIKE '%{name}'"; $conf['auth']['mysql']['FilterEmail'] = "u.email LIKE '%{email}'"; $conf['auth']['mysql']['FilterGroup'] = "g.g_title LIKE '%{group}'"; $conf['auth']['mysql']['SortOrder'] = "ORDER BY u.username"; $conf['auth']['mysql']['addUser'] = "INSERT INTO ${db_prefix}users (username, password, email, realname) VALUES ('%{user}', '%{pass}', '%{email}', '%{name}')"; $conf['auth']['mysql']['addGroup'] = "INSERT INTO ${db_prefix}groups (g_title) VALUES ('%{group}')"; $conf['auth']['mysql']['addUserGroup']= "UPDATE ${db_prefix}users SET group_id=%{gid} WHERE id='%{uid}'"; $conf['auth']['mysql']['delGroup'] = "DELETE FROM ${db_prefix}groups WHERE g_id='%{gid}'"; $conf['auth']['mysql']['getUserID'] = "SELECT id FROM ${db_prefix}users WHERE username='%{user}'"; $conf['auth']['mysql']['updateUser'] = "UPDATE ${db_prefix}users SET"; $conf['auth']['mysql']['UpdateLogin'] = "username='%{user}'"; $conf['auth']['mysql']['UpdatePass'] = "password='%{pass}'"; $conf['auth']['mysql']['UpdateEmail'] = "email='%{email}'"; $conf['auth']['mysql']['UpdateName'] = "realname='%{name}'"; $conf['auth']['mysql']['UpdateTarget']= "WHERE id=%{uid}"; $conf['auth']['mysql']['delUserGroup']= "UPDATE ${db_prefix}users SET g_id=4 WHERE id=%{uid}"; $conf['auth']['mysql']['getGroupID'] = "SELECT g_id AS id FROM ${db_prefix}groups WHERE g_title='%{group}'"; $conf['auth']['mysql']['TablesToLock']= array("${db_prefix}users", "${db_prefix}users AS u", "${db_prefix}groups", "${db_prefix}groups AS g"); $conf['auth']['mysql']['debug'] = 1; // call mysql constructor $this->auth_mysql(); } /** * Just checks against the $pun_user variable */ function trustExternal($user,$pass,$sticky=false){ global $USERINFO; global $conf; global $lang; global $pun_user; global $pun_config; $sticky ? $sticky = true : $sticky = false; //sanity check // someone used the login form if(!empty($user)){ if($this->checkPass($user,$pass)){ $expire = ($sticky) ? time() + 31536000 : 0; $uinfo = $this->getUserData($user); pun_setcookie($uinfo['id'], auth_cryptPassword($pass), $expire); $pun_user = array(); $pun_user['password'] = auth_cryptPassword($pass); $pun_user['username'] = $user; $pun_user['realname'] = $uinfo['name']; $pun_user['email'] = $uinfo['mail']; $pun_user['g_title'] = $uinfo['group']; }else{ //invalid credentials - log off msg($lang['badlogin'],-1); auth_logoff(); return false; } } if(isset($pun_user) && !$pun_user['is_guest']){ // okay we're logged in - set the globals $USERINFO['pass'] = $pun_user['password']; $USERINFO['name'] = $pun_user['realname']; $USERINFO['mail'] = $pun_user['email']; $USERINFO['grps'] = array($pun_user['g_title']); $_SERVER['REMOTE_USER'] = $pun_user['username']; $_SESSION[DOKU_COOKIE]['auth']['user'] = $pun_user['username']; $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO; return true; } // to be sure auth_logoff(); return false; } /** * remove punbb cookie on logout */ function logOff(){ global $pun_user; $pun_user = array(); $pun_user['is_guest'] = 1; pun_setcookie(1, random_pass(8), time() + 31536000); } } //Setup VIM: ex: et ts=2 enc=utf-8 : ===== Source and Installation - punbb 1.3.x ===== Up to DokuWiki 2008-05-05 this backend was included in the DokuWiki install. Newer versions no longer come with this backend. To install the backend, create a ''inc/auth/punbb.class.php'' file and copy and paste the following code: */ // needed if you use URL rewrite in you Wiki and Punbb // i.e.: example.com/wiki/article and example.com/punbb/topic/1515/subject/ define('FORUM_IGNORE_REQUEST_URI', 1); // do not confirm the action in punbb, usefull for ajax in dokuwiki define('FORUM_SKIP_CSRF_CONFIRM', 1); if(!defined('FORUM_ROOT')) define('FORUM_ROOT', DOKU_INC.'../forum/'); if(get_magic_quotes_gpc()){ nice_die('Sorry the punbb auth backend requires the PHP option magic_quotes_gpc to be disabled for proper operation. Either setup your PHP install accordingly or choose a different auth backend.'); } require_once FORUM_ROOT.'include/common.php'; require_once DOKU_INC.'inc/auth/mysql.class.php'; #dbg($GLOBALS); #dbg($forum_user); class auth_punbb extends auth_mysql { /** * Constructor. * * Sets additional capabilities and config strings */ function auth_punbb(){ global $conf; $this->cando['external'] = true; $this->cando['logoff'] = true; // make sure we use a crypt understood by punbb if(function_exists('sha1')){ $conf['passcrypt'] = 'sha1'; }else{ $conf['passcrypt'] = 'md5'; } // get global vars from PunBB config global $db_host; global $db_name; global $db_username; global $db_password; global $db_prefix; // now set up the mysql config strings $conf['auth']['mysql']['server'] = $db_host; $conf['auth']['mysql']['user'] = $db_username; $conf['auth']['mysql']['password'] = $db_password; $conf['auth']['mysql']['database'] = $db_name; $conf['auth']['mysql']['checkPass'] = "SELECT u.password AS pass FROM ${db_prefix}users AS u, ${db_prefix}groups AS g WHERE u.group_id = g.g_id AND u.username = '%{user}' AND g.g_title != 'Guest'"; $conf['auth']['mysql']['getUserInfo'] = "SELECT password AS pass, realname AS name, email AS mail, id, g_title as `group` FROM ${db_prefix}users AS u, ${db_prefix}groups AS g WHERE u.group_id = g.g_id AND u.username = '%{user}'"; $conf['auth']['mysql']['getGroups'] = "SELECT g.g_title as `group` FROM ${db_prefix}users AS u, ${db_prefix}groups AS g WHERE u.group_id = g.g_id AND u.username = '%{user}'"; $conf['auth']['mysql']['getUsers'] = "SELECT DISTINCT u.username AS user FROM ${db_prefix}users AS u, ${db_prefix}groups AS g WHERE u.group_id = g.g_id"; $conf['auth']['mysql']['FilterLogin'] = "u.username LIKE '%{user}'"; $conf['auth']['mysql']['FilterName'] = "u.realname LIKE '%{name}'"; $conf['auth']['mysql']['FilterEmail'] = "u.email LIKE '%{email}'"; $conf['auth']['mysql']['FilterGroup'] = "g.g_title LIKE '%{group}'"; $conf['auth']['mysql']['SortOrder'] = "ORDER BY u.username"; $conf['auth']['mysql']['addUser'] = "INSERT INTO ${db_prefix}users (username, password, email, realname) VALUES ('%{user}', '%{pass}', '%{email}', '%{name}')"; $conf['auth']['mysql']['addGroup'] = "INSERT INTO ${db_prefix}groups (g_title) VALUES ('%{group}')"; $conf['auth']['mysql']['addUserGroup']= "UPDATE ${db_prefix}users SET group_id=%{gid} WHERE id='%{uid}'"; $conf['auth']['mysql']['delGroup'] = "DELETE FROM ${db_prefix}groups WHERE g_id='%{gid}'"; $conf['auth']['mysql']['getUserID'] = "SELECT id FROM ${db_prefix}users WHERE username='%{user}'"; $conf['auth']['mysql']['updateUser'] = "UPDATE ${db_prefix}users SET"; $conf['auth']['mysql']['UpdateLogin'] = "username='%{user}'"; $conf['auth']['mysql']['UpdatePass'] = "password='%{pass}'"; $conf['auth']['mysql']['UpdateEmail'] = "email='%{email}'"; $conf['auth']['mysql']['UpdateName'] = "realname='%{name}'"; $conf['auth']['mysql']['UpdateTarget']= "WHERE id=%{uid}"; $conf['auth']['mysql']['delUserGroup']= "UPDATE ${db_prefix}users SET g_id=4 WHERE id=%{uid}"; $conf['auth']['mysql']['getGroupID'] = "SELECT g_id AS id FROM ${db_prefix}groups WHERE g_title='%{group}'"; $conf['auth']['mysql']['TablesToLock']= array("${db_prefix}users", "${db_prefix}users AS u", "${db_prefix}groups", "${db_prefix}groups AS g"); $conf['auth']['mysql']['debug'] = 1; // call mysql constructor $this->auth_mysql(); } /** * Just checks against the $forum_user variable */ function trustExternal($user,$pass,$sticky=false){ global $USERINFO; global $conf; global $lang; global $forum_user; global $pun_config; $sticky ? $sticky = true : $sticky = false; //sanity check // someone used the login form if(!empty($user)){ if($this->checkPass($user,$pass)){ $expire = ($sticky) ? time() + 31536000 : 0; $uinfo = $this->getUserData($user); forum_setcookie($uinfo['id'], auth_cryptPassword($pass), $expire); $forum_user = array(); $forum_user['password'] = auth_cryptPassword($pass); $forum_user['username'] = $user; $forum_user['realname'] = $uinfo['name']; $forum_user['email'] = $uinfo['mail']; $forum_user['g_title'] = $uinfo['group']; }else{ //invalid credentials - log off msg($lang['badlogin'],-1); auth_logoff(); return false; } } if(isset($forum_user) && !$forum_user['is_guest']){ // okay we're logged in - set the globals $USERINFO['pass'] = $pun_user['password']; $USERINFO['name'] = utf8_encode($forum_user['realname']); $USERINFO['mail'] = $forum_user['email']; $USERINFO['grps'] = array($forum_user['g_title']); $_SERVER['REMOTE_USER'] = utf8_encode($forum_user['username']); $_SESSION[DOKU_COOKIE]['auth']['user'] = utf8_encode($forum_user['username']); $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO; return true; } // to be sure auth_logoff(); return false; } /** * remove punbb cookie on logout */ function logOff(){ global $forum_user; $forum_user = array(); $forum_user['is_guest'] = 1; forum_setcookie(1, random_key(8), time() + 31536000); } } //Setup VIM: ex: et ts=2 enc=utf-8 : ===== Source and Installation - FluxBB 1.4 ===== Same instructions as with FluxBB 1.2.x, but there are some functions in the file **inc/utf8.php** already defined by FluxBB 1.4 (version 1.4.2), these are: * utf8_strlen * utf8_substr * utf8_ltrim * utf8_rtrim * utf8_trim * utf8_strtolower * utf8_strtoupper * utf8_ucfirst * utf8_strpos * utf8_bad_replace Error message: **Fatal error: Cannot redeclare utf8_strlen() (previously declared in ......./inc/utf8.php:132) in ......./include/utf8/mbstring/core.php on line 28** So we need to edit inc/utf8.php in order to only let DokuWiki define these functions if we're not using FluxBB, by adding an check around these function: if(!defined('PUN_ROOT')) { ... } === Example: utf8_strlen === replace: function utf8_strlen($string){ return strlen(utf8_decode($string)); } with: if(!defined('PUN_ROOT')){ function utf8_strlen($string){ return strlen(utf8_decode($string)); } } You'll have to apply these modifications 10 times in inc/utf8.php . [[oli_v_ier@yahoo.fr|olivier]] [[id.2ndr@laposte.net|id2ndr]] ==== dokuwiki 2010-11-07 "Anteater" ==== With these version a small modification should be done to avoid the error bellow : Fatal error: Call to a member function query() on a non-object in /var/www/forum/include/functions.php on line 185 * Add the line bellow in ''conf/local.protected.php'' (after the definition of PUN_ROOT variable) :include PUN_ROOT.'include/common.php'; * Remove the line in ''inc/auth/punbb.class.php'' :require_once PUN_ROOT.'include/common.php'; === PunBB CSRF & Ajax problem === If you want to make ajax-quicksearch work, You should define the constant FORUM_SKIP_CSRF_CONFIRM before including any PunBB code so, the code above should be like below : define("FORUM_SKIP_CSRF_CONFIRM", 1); include PUN_ROOT.'include/common.php'; ===== Discussion ===== * Some username are not understand by DokuWiki (Pérot became P�rot or Pérot) DokuWiki uses UTF-8 and PunBB ISO8859-1, so this is just a character encoding problem. In order to get the right usernames, open /dokuwiki/inc/auth/punbb.class.php, find (l136 on v. 2007-06-26b) : if(isset($pun_user) && !$pun_user['is_guest']){ // okay we're logged in - set the globals $USERINFO['pass'] = $pun_user['password']; $USERINFO['name'] = $pun_user['realname']; $USERINFO['mail'] = $pun_user['email']; $USERINFO['grps'] = array($pun_user['g_title']); $_SERVER['REMOTE_USER'] = $pun_user['username']; $_SESSION[DOKU_COOKIE]['auth']['user'] = $pun_user['username']; $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO; return true; } And replace by : if(isset($pun_user) && !$pun_user['is_guest']){ // okay we're logged in - set the globals $USERINFO['pass'] = $pun_user['password']; $USERINFO['name'] = utf8_encode($pun_user['realname']); $USERINFO['mail'] = $pun_user['email']; $USERINFO['grps'] = array($pun_user['g_title']); $_SERVER['REMOTE_USER'] = utf8_encode($pun_user['username']); $_SESSION[DOKU_COOKIE]['auth']['user'] = utf8_encode($pun_user['username']); $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO; return true; } //[[http://www.punbb.fr|Maximilien Thiel]] 2007-11-13 - 11:00 UTC +01:00// * As punbb 1.3 will support utf8, a better patch is : // okay we're logged in - set the globals $USERINFO['pass'] = $pun_user['password']; $USERINFO['name'] = preg_match('/^1\.2/',$pun_config['o_cur_version']) ? utf8_encode($pun_user['realname']) : $pun_user['realname']; $USERINFO['mail'] = $pun_user['email']; $USERINFO['grps'] = array($pun_user['g_title']); (only the $USERINFO['name'] line is changed)\\ [[http://www.zeitoun.net|Stéphane Gully]] * I think there is a problem when you use DokuWiki's ACL : a regular member with appropriate rights under PunBB can not edit a page though ACL seems properly configured (changes forbidden in : but allowed in :help: ). The problem may come from the fact DokuWiki has a "user" group while PunBB has a "members" and this is not *always* correctly seen. * yann: edit the file conf/acl.auth.php, add there the group members (duplicate the line with "user", and replace "user" by "members". * Better yet, use the group Members as is defined in the table groups in the PunBB MySQL database.