Current File : /home/jvzmxxx/wiki1/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;	
	}
}
?>