<?php
/**
PLEASE NOTE:
This code is broken in Drupal 5.3. The session ID being used is no
longer the default PHP session, but a custom-rolled one.
You can hard-code the session ID needed into your script. See the
code below for a description of how to do this. If someone wants to
write a more dynamic solution, I'd be greatly appreciative.
*/
/**
* Drupal authentication backend.
*
* Use Drupal's session and DB backend to authenticate a Dokuwiki user.
* All user-handling is delegated to Drupal, including login dialogs,
* adding and deleting users etc. All login, logout, register etc. links
* need to direct the user to the appropriate Drupal page.
*
* This only logs a user in if they are already logged into Drupal, i.e.
* if the Drupal session cookie is still present.
*
* Usage:
*
* 1) Copy this file into your Dokuwiki 'auth' directory--{dokuwiki-base}/inc/auth/.
* It must be called 'drupal_ext.class.php'.
* 2) In {dokuwiki-base}/conf/local.php, set the following variables:
*
* $conf['auth']['drupal']['file'] = '{drupal-base}/sites/{inst-dir}/settings.php';
* $conf['authtype'] = 'drupal_ext';
*
* where {drupal-base} is your Drupal installation's base directory, and {inst-dir}
* refers to the particular sub-directory for this Drupal instance. This might be
* 'all' if you only have one Drupal instance, or 'www.example.com' if you have more
* than one.
*
* Original concept inspired by Mohammed Sameer's <msameer@foolab.org> script
* for authenticating using Drupal. His script does not provide automatic logging, but
* requires the user to log in twice, once into Drupal and next into Dokuwiki.
*
* @author Walter Gildersleeve <walter@coalface.net>
* @todo This assumes that Drupal is using MySQL--any way to alter this?
*/
class auth_drupal_ext extends auth_basic {
var $url;
var $db_prefix = '';
var $session_id;
/**
c'tor
*/
function auth_drupal_ext() {
global $conf;
$this->cando['external'] = true;
// Drupal is using ini_set in the $drupal_file
$ini = ini_get("error_reporting");
ini_set("error_reporting", 0);
//now we can load the file without PHP complaining
$drupal_file = $conf['auth']['drupal']['file'];
include ($drupal_file);
ini_set("error_reporting", $ini);
//Following Drupal variables are interesting for us:
// $db_url, $db_prefix
$this->url = parse_url($db_url);
$this->url['path'] = substr($this->url['path'], 1);
$this->db_prefix = $db_prefix;
//Decode url-encoded information in the db connection string
$this->url['user'] = urldecode($this->url['user']);
// Test if database url has a password.
if(isset($this->url['pass'])) {
$this->url['pass'] = urldecode($this->url['pass']);
} else {
$this->url['pass'] = '';
}
$this->url['host'] = urldecode($this->url['host']);
$this->url['path'] = urldecode($this->url['path']);
$this->session_id = ini_get('session.cookie_domain');
}
/**
Strip the leading at-sign from role names.
@param $role The original role name.
@return string The role name without any preceding at-sign.
*/
function _tg($role) {
return preg_replace("/^@/", "", $role);
}
/**
* Authenticate the user using Drupal session information. User must login
* via the Drupal interface; no login work is done here.
*
* @param string $user Ignored.
* @param string $pass Ignored.
* @param bool $sticky Ignored.
* @return bool true on successful auth
* @todo Drupal roles aren't recognized. Only the super-user in Drupal has
* Dokuwiki admin rights.
*/
function trustExternal($user,$pass,$sticky=false) {
global $conf;
global $USERINFO;
$logged_in = false;
$link = mysql_connect($this->url['host'], $this->url['user'], $this->url['pass']);
if (!$link) {
msg('Could not connect: ' . mysql_error());
return;
}
if (!mysql_select_db($this->url['path'], $link)) {
msg('Can\'t select the database: ' . mysql_error());
mysql_close($link);
return;
}
$cookie = $_COOKIE['PHPSESSID'];
//for Drupal 5.3+, you need to find the session key generated for your site.
//it'll be in the form "SESS[md5], where [md5] is generated using your site's base URL.
//This remains constant between users and sessions, so once you find it you can simply
//cut-and-paste it into the script.
//EXAMPLE:
//$cookie = $_COOKIE['SESS5992b5d0b3fd1cf0b8b1e1518a578dad'];
$query = 'SELECT u.uid,u.name,u.mail,s.hostname,s.timestamp FROM '.$this->db_prefix.
'users u INNER JOIN '.$this->db_prefix.'sessions s ON u.uid=s.uid WHERE s.sid="'.
$cookie.'" && u.status=1';
/*
MySQL versions before 4 don't use explicit inner join syntax, so you'll have to use the
implicit syntax. It might look something like this:
$users_db = $this->db_prefix.'users';
$sessions_db = $this->db_prefix.'sessions';
'SELECT ' . $users_db . '.uid,' . $users_db . '.name,' . $users_db . 'mail,' . $sessions_db .
'.hostname,' . $sessions_db . '.timestamp FROM ' . $users_db . ',' . $sessions_db .
' WHERE ' . $users_db . '.uid=' . $sessions_id . '.uid AND ' . $sessions_db . '.sid="' .
$cookie . '" AND ' . $users_db . '.status=1';
*/
$result = mysql_query($query);
if ($result) {
$tmp = mysql_fetch_row($result);
if ($tmp) {
$uid = $tmp[0];
$USERINFO['name'] = $tmp[1];
$USERINFO['mail'] = $tmp[2];
$USERINFO['pass'] = '';
$_SERVER['REMOTE_USER'] = $tmp[1];
$_SESSION[DOKU_COOKIE]['auth']['user'] = $tmp[1];
$_SESSION[DOKU_COOKIE]['auth']['buid'] = auth_browseruid();
$_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO;
/* now for the roles */
if ($uid == 1) {/* super user, everything's allowed */
$USERINFO['grps'] = array($this->_tg($conf['superuser']), $this->_tg($conf['defaultgroup']));
} else {
$query = 'SELECT r.name FROM '.$this->db_prefix.'users_roles u INNER JOIN '.
$this->db_prefix.'role r WHERE u.uid='.$uid.' && u.rid=r.rid';
$result = mysql_query($query);
if ($result) {
$tmp = mysql_fetch_row($result);
if ($tmp) {
$USERINFO['grps'] = array($tmp[0], $this->_tg($conf['defaultgroup']));
}
} else {
msg('Error querying the database [' . mysql_error() . ']');
}
}
$logged_in = true;
}
} else {
msg('Error querying the database [' . mysql_error() . ']');
}
mysql_close($link);
return $logged_in;
}
}
?>
Comments
Post new comment