| Current File : /home/jvzmxxx/wiki/extensions/AuthJoomlaEasy/AuthJoomlaEasy.php |
<?php
/*
* Oorspronkelijk document: AuthDrupal.php
* Signin integration for MediaWiki as slave of Joomla user DB.
*
* Implemented/tested using Joomla 1.7.3 and MediaWiki 1.18;
*
* Original Drupal 2006/01/06 by Mitch Schwenk <tazzytazzy2 (at) yahoo (dot) com>
* Rewrite, Jan-March 2007 by Maarten van Dantzich (drupal.org user maartenvd)
* Rewrite Joomla, Mei 2009 - Jan 2012 by Harold Prins (haroldprins.nl)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
$wgExtensionCredits['parserhook'][] = array (
'name' => 'AuthJoomla2',
'author' => 'Mitch Schwenk, Maarten van Dantzich, Harold Prins',
'url' => 'http://www.haroldprins.nl',
);
require_once ( 'includes/AuthPlugin.php' );
/**
* Setup functie, starten vanaf LocalSettings.php
*
* Args:
* cookie set by user plugin mediawikilogin.php during Joomla login
*/
function SetupAuthJoomla() {
global $wgHooks; //Joomla event functie
global $wgAuth; //Joomla variabele
// If there is a Joomla cookie, install the user hook
if (! empty( $_COOKIE['MW'.md5('Joomla')] )) {
$wgHooks['UserLoadFromSession'][] = 'Auth_joomla_autologin_hook'; /* Hook for magical authN */
$wgHooks['PersonalUrls'][] = 'Auth_joomla_logoutlink_hook'; /* Disallow logout link */
$wgAuth = new AuthJoomla2();
} else {
// The cookie set by Joomla disappeared, so we should be logged out.
// if there are cookies from a previous session, try to get rid of em
authjoomla_StaticUserLogout();
$wgHooks['PersonalUrls'][] = 'Auth_joomla_loginlink_hook'; /* Hook to replace login link */
}
}
function authjoomla_StaticUserLogout() {
$dbname = $GLOBALS['wgDBname'];
$dbprefix = $GLOBALS['wgDBprefix'];
$path = $GLOBALS['wgCookiePath'];
$domain = $GLOBALS['wgCookieDomain'];
$cookie_secure = $GLOBALS['wgCookieSecure'];
$prefix = $dbname . '_' . $dbprefix;
$GLOBALS['wgCookiePrefix'] = $prefix; // not sure this is necessary
setcookie( $prefix . '_session', '', time() - 3600, $path, $domain, $cookie_secure );
setcookie( $prefix . 'UserName', '', time() - 3600, $path, $domain, $cookie_secure );
setcookie( $prefix . 'UserID', '', time() - 3600, $path, $domain, $cookie_secure );
setcookie( $prefix . 'Token', '', time() - 3600, $path, $domain, $cookie_secure );
// Remember when the user logged out, to prevent seeing cached pages
$ts_now = gmdate('YmdHis', time()); // emulates wfTimestampNow()
setcookie( $prefix . 'LoggedOut', $ts_now, time() + 86400, $path, $domain, $cookie_secure );
}
/**
* Function that handles MW AutoAuthenticate hook
*
* Use info passed by Joomla in MWJoomla (MD5 hashed) cookie to log the user in.
*
* the $return_user arg will normally be a reference to $wgUser
* Not expected to return anything.
*/
function Auth_joomla_autologin_hook($user, &$return_user ) {
global $wgUser;
global $wgAuth;
global $wgContLang;
wfSetupSession();
// Now lets check for joomla cookie
$name = getCurrentJoomlaUsername();
if ( empty( $name ) ) {
return false;
}
$user = User::newFromName( $name );
// is it a new user?
if ( 0 == $user->getID() ) {
// we have a new user to add...
$joomla_user = $wgAuth->getJoomlaUser( $name );
if ( empty( $joomla_user ) ) {
wfDebug( __FUNCTION__ . " AuthJoomla ERROR: " . $name . " not found in Joomla DB \n" );
return false;
}
//!dbg wfDebug( "AuthJoomla2: logging in NEW user " . $name . "\n" );
// this mimicks what LoginForm::initUser() does (code identical to
// regular login moved down to common code)
$user->setName( $wgContLang->ucfirst( $joomla_user->username ) );
$user->addToDatabase();
// Update user count in site stats (stolen from SpecialUserlogin)
$ssUpdate = new SiteStatsUpdate( 0, 0, 0, 0, 1 );
$ssUpdate->doUpdate();
// LoginForm::initUser() calls $wgAuth->initUser, but I don't see the point
// $wgAuth->initUser( $u );
} else {
//!dbg wfDebug( "AuthJoomla2: logging in existing user " . $name . "\n" );
}
// update email, real name, etc.
$wgAuth->updateUser( $user );
// Go ahead and log 'em in
//$user->setToken();
$user->saveSettings();
wfSetupSession();
$user->setCookies();
$message = 'MediaWiki session (cookie) opened for <em>' . $name . '</em>.';
$wgAuth->joomla_uid = $user->getID();
return true;
}
/**
* Hook function to rewrite login link to point to Joomla instance
*/
function Auth_joomla_loginlink_hook( & $personal_urls, & $title ) {
//correct?
if ( $GLOBALS['wgShowIPinHeader'] && isset( $_COOKIE[ini_get( "session.name" )] ) ) {
// shown for anonymous users without a session?
$personal_urls['anonlogin'] = array (
'text' => wfMessage( 'userlogin' )->text(),
'href' => $GLOBALS['wgAuthJoomla_LoginURL'] );
} else {
// shown for anonymous users with a session?
$personal_urls['login'] = array (
'text' => wfMessage('userlogin' )->text(),
'href' => $GLOBALS['wgAuthJoomla_LoginURL'] );
}
return true;
}
/**
* Hook function to rewrite logout link to point to Joomla instance
*/
function Auth_joomla_logoutlink_hook(& $personal_urls, & $title) {
$personal_urls['logout'] = array (
'text' => wfMessage('userlogout' )->text(),
'href' => $GLOBALS['wgAuthJoomla_LogoutURL'] );
return true;
}
/**
* Replacement login class which checks for a logged in Joomla user
*/
class AuthJoomla2 extends AuthPlugin {
// Database Settings initialized in constructor
/* private */
var $db_table;
/* private */
var $db_prefix;
/* private */
var $joomla_users_table;
/* private */
var $joomla_log_table;
var $joomla_uid;
var $my_dbr = NULL; // either the MW db or a separate db
/**
* Constructor
*/
function AuthJoomla2() {
global $wgAuthJoomla_TablePrefix;
global $wgAuthJoomla_UID;
if (! empty( $wgAuthJoomla_UID) ) {
$joomla_uid = $wgAuthJoomla_UID;
}
$this->db_prefix = $wgAuthJoomla_TablePrefix;
$this->joomla_users_table = $this->makeJoomlaTableName('users');
return;
}
/**
* Returns a handle to the Joomla database, and creates one if it doesn't exist
*/
function getDB() {
if ( empty( $this->my_dbr ) ) {
$this->connectToDB();
}
return $this->my_dbr;
}
/**
* Connects to the Joomla database
*/
function connectToDB() {
if ($GLOBALS['wgAuthJoomla_UseExtDatabase']) {
// Drupal tables are in a separate DB from MW tables, create
// a separate DB connection
$this->my_dbr = DatabaseBase::factory('mysql', array(
'host' => $GLOBALS['wgAuthJoomla_MySQL_Host'],
'user' => $GLOBALS['wgAuthJoomla_MySQL_Username'],
'password' => $GLOBALS['wgAuthJoomla_MySQL_Password'],
'dbname' => $GLOBALS['wgAuthJoomla_MySQL_Database'],
'flags' => '0',
'tablePrefix' => ''));
} else {
$this->my_dbr = & wfGetDB(DB_SLAVE);
}
if (!$this->my_dbr->isOpen()) {
wfDebug("AuthJoomla::connectToDB() : DB failed to open\n");
}
}
/**
* Return entire user record from Joomla user table, so we can get at email, etc.
*
* @param string $username the name of the user to retrieve from the Joomla database
*/
function getJoomlaUser($username) {
$dbr = $this->getDB();
$qUsername = $dbr->addQuotes($username);
return $dbr->selectRow( $this->joomla_users_table,
"*",
"LCase(username)=LCase(CONVERT($qUsername USING latin1))",
"AuthJoomla::getJoomlaUser" );
}
/**
* BELOW HERE CODE IS STANDARD AuthPlugin CLASS METHODS
*
* Functions that we do not need to override are not included here, they
* can be found in includes/AuthPlugin.php
*
* Comments above each function are from AuthPlugin.php.
* I've documented my understanding of the use of each function--Maarten.
*
*/
/**
* Check whether there exists a user account with the given name.
* The name will be normalized to MediaWiki's requirements, so
* you might need to munge it (for instance, for lowercase initial
* letters).
*
* @param $username String: username.
* @return bool
* @public
*/
function userExists($username) {
// Dit is niet nodig omdat we niet meer inloggen op de wiki, Joomla controleert dit zelf.
//!dbg wfDebug("##" . __METHOD__ . "\n");
return true;
}
/**
* Het inloggen gebeurt niet meer op de wiki, maar een veiligheidscontrole is hier wel belangrijk.
*
* @param $username String: username.
* @param $password String: user password.
* @return bool
* @public
*/
function authenticate($username, $password) {
//!dbg wfDebug("##" . __METHOD__ . "\n");
// as a sanity check, we'll re-check that the user getting logged in is
// the same that was passed by Joomla in its cookie
$name = getCurrentJoomlaUsername();
// ignore case since wiki wants first letter upcase and Joomla does not
$same = (0 === strcasecmp($username, $name));
if (!$same) {
wfDebug("AuthJoomla: ERROR: authenticate() called with mismatched username: "
. "wiki=" . $username . " vs cookie=" . $name . "\n");
}
return $same;
}
/**
* When a user logs in, optionally fill in preferences and such.
* For instance, you might pull the email address or real name from the
* external user database.
*
* The User object is passed by reference so it can be modified; don't
* forget the & on your function declaration.
*
* Maarten: this is our chance to pull info out of the Joomla database
* and update it in MW's user table, e.g. in case the user's email address
* or real name has changed
* @param User $user
* @public
*/
function updateUser(& $user) {
// wfDebug("##" . __METHOD__ . "\n"); //!dbg
$user->load();
$name = $user->getName();
$joomla_user = $this->getJoomlaUser($name);
if ( empty( $joomla_user ) ) {
wfDebug( __FUNCTION__ . " AuthJoomla ERROR: " . $name . " not found in Joomla DB \n" );
return;
}
//$user->mPassword = 'isLeeg'; // not something a hash will match
//$user->mNewpassword = '';
$user->mNewpassTime = null;
$user->setRealName($joomla_user->name );
$user->setEmail( $joomla_user->email );
$user->mEmailAuthenticated = wfTimestampNow();
$user->saveSettings();
return true;
}
/**
* Return true if the wiki should create a new local account automatically
* when asked to login a user who doesn't exist locally but does in the
* external auth database.
*
* If you don't automatically create accounts, you must still create
* accounts in some way. It's not possible to authenticate without
* a local account.
*
* This is just a question, and shouldn't perform any actions.
*
* Maarten: not sure if this is necessary since we explicitly add new users
* to the MW database in the AuthAuthenticate hook handler
*
* @return bool
* @public
*/
function autoCreate() {
//!dbg wfDebug("##" . __METHOD__ . "\n");
return true;
}
/**
* Can users change certain preferences?
*
* NOTE: to block user from changing password, return false from
* AuthPlugin::allowPasswordChange()
*
* Value set to true means "disallow editing of this field"
* Assumes fields are editable unless specified otherwise.
*
* e.g.: return array( 'wpRealName' => true );
*
* Returns all disallowed fields at once to avoid having to call this
* once for each field on the prefs form.
*
* @return array ( $key => boolean )
*/
function disallowPrefsEditByUser() {
return array (
'wpRealName' => true,
'wpUserEmail' => true,
'wpNick' => true
);
}
/**
* Can users change their passwords?
* Maarten: we force users to do this on the Joomla side.
*
* @return bool
*/
function allowPasswordChange() {
//!dbg wfDebug("##" . __METHOD__ . "\n");
return false;
}
/**
* Set the given password in the authentication database.
* As a special case, the password may be set to null to request
* locking the password to an unusable value, with the expectation
* that it will be set later through a mail reset or other method.
*
* Maarten: we do not allow password changes to originate in the wiki and
* propagate back to Joomla. Note that returning false here will make
* User::setPassword fail to complete as well, at least in 1.9.x
*
* Return true if successful.
*
* @param $user User object.
* @param $password String: password.
* @return bool
* @public
*/
function setPassword( $user, $password ) {
return false;
}
/**
* Return true to prevent logins that don't authenticate here from being
* checked against the local database's password fields.
*
* This is just a question, and shouldn't perform any actions.
*
* Maarten: in no case do we want to authenticate against MW's user table,
* so this should return true
*
* @return bool
* @public
*/
function strict() {
//!dbg wfDebug("##" . __METHOD__ . "\n");
return true;
}
/**
* When creating a user account, optionally fill in preferences and such.
* For instance, you might pull the email address or real name from the
* external user database.
*
* The User object is passed by reference so it can be modified; don't
* forget the & on your function declaration.
*
* @param $user User object.
* @public
*/
function initUser(&$user, $autocreate = false) {
//!dbg wfDebug("##" . __METHOD__ . "\n");
// XXX TODO: set notification defaults and such
}
/**
* If you want to munge the case of an account name before the final
* check, now is your chance.
*/
function getCanonicalName( $username ) {
//!dbg wfDebug("##" . __METHOD__ . "\n");
global $wgContLang;
return $wgContLang->ucfirst($username);
}
function makeJoomlaTableName($table) {
return "`" . $this->db_prefix . $table . "`";
}
}
/**
* Database error callback function
*/
function auth_joomla_db_error_callback($db_obj, $error) {
wgDebug( __FUNC__ . " - ERROR: " . $error . "\n" );
}
/**
* Utility functions for decoding cookie with username
*
* Does a check against an obfuscated version to verify that the username
* was actually set by our code on the Joomla side, and not being spoofed
* by a malicious end user.
*
*/
function getCurrentJoomlaUsername() {
$plaintext_name = explode("|", base64_decode($_COOKIE['MW'.md5('Joomla')]));
if (MD5($plaintext_name[0] . $GLOBALS['wgAuthJoomla_security_key']) == $plaintext_name[1] ) {
return $plaintext_name[0];
}
else {
return null;
}
}
?>