'AuthP4',
'url' => 'http://public.perforce.com/wiki/index.php/AuthP4_%28MediaWiki_authentication_plugin%29',
'author' => 'Sam Stafford',
'description' => 'Authenticate via Perforce server',
);
class AuthP4 extends AuthPlugin
{
function AuthP4() { }
function userExists( $username )
{
$inf = array();
$err = array();
$user = escapeshellarg( wiki_to_p4( $username ) );
run_p4_s( "groups $user", $inf, $err );
return( count( $inf ) );
}
function authenticate( $username, $password )
{
global $wgP4EXEC;
global $wgP4PORT;
$inf = array();
$err = array();
$user = escapeshellarg( wiki_to_p4( $username ) );
$pass = $password; //passed thru pipe, not arg!
$descriptors = array
(
0 => array("pipe", "r"),
1 => array("pipe", "w")
);
$p4 = "$wgP4EXEC -p $wgP4PORT -u $user -s";
$loginproc = proc_open( "$p4 login -p", $descriptors, $pipes);
if ( !is_resource( $loginproc ) ) { return false; }
fwrite( $pipes[0], $pass );
fclose( $pipes[0] );
while ( !feof( $pipes[1] ) )
{
sort_p4_s_output( fgets( $pipes[1] ), $inf, $err );
}
fclose( $pipes[1] );
proc_close( $loginproc );
return( count( $inf ) );
}
function modifyUITemplate( &$template )
{
//Disable mail password (since it doesn't work), the
//account creation (since we want registration to always
//go through the Perforce account signup process), and the
//domain box (since it's irrelevant).
$template->set('useemail', false);
$template->set('create', false);
$template->set('domain', false);
$template->set('usedomain', false);
//Tweak "nologin" prompt to point at a custom page instead of
//the disabled "create account" special page.
global $wgP4PORT;
global $wgServer;
global $wgScriptPath;
$reglink = $wgServer.$wgScriptPath.'/index.php?title=Registration';
$template->set('link', "Log in with the user/password you use on $wgP4PORT.
Don't have a registered Public Depot account? Register here.");
}
function updateUser( &$user )
{
//Doesn't do anything, but needs to return true so MWiki
//doesn't think there was a problem.
return true;
}
function autoCreate()
{
//Create wiki accounts automagically if Perforce accounts
//exists. This eliminates the need to set up wiki accounts
//seperately.
return true;
}
//Make people use "p4 passwd" for now.
//This could be implemented with "p4 passwd $USER"
//at some point if desired.
function allowPasswordChange()
{
return false;
}
function setPassword( $user, $password )
{
return false;
}
function updateExternalDB( $user )
{
//Could be implemented with "p4 user -f USER", but
//we'll leave it alone for now. Still needs to return
//true or automatic account creation will fail.
return true;
}
//Not allowed to use local-only accounts or create Perforce
//accounts.
function canCreateAccounts()
{
return false;
}
function addUser( $user, $password, $email='', $realname='' )
{
return false;
}
function strict()
{
return true;
}
function initUser( &$user )
{
//Called on account creation.
//Pull fullname and email from Perforce. The user
//may change them later if desired.
$p4username = escapeshellarg( wiki_to_p4( $user->getName() ) );
$p4user = array();
run_p4_tag( "user -o $p4username", $p4user );
if ( isset( $p4user['Email'] ) )
{
$user->setEmail( $p4user['Email'] );
}
if ( isset( $p4user['FullName'] ) )
{
$user->setRealName( $p4user['FullName'] );
}
}
function getCanonicalName( $username )
{
//Force names to standard casing to prevent duplicates.
$user = trim( $username );
$user = str_replace( "_", " ", $user ); // 'JOHN_DOE' -> 'JOHN DOE'
$user = strtolower( $user ); // 'JOHN DOE' -> 'john doe'
$user = ucwords( $user ); // 'john doe' -> 'John Doe'
return $user;
}
} // end AuthPlugin class
//Things below this line aren't part of the AuthPlugin interface.
function run_p4_s( $command, &$info, &$error )
{
global $wgP4EXEC;
global $wgP4PORT;
global $wgP4USER;
global $wgP4PASSWD;
$p4 = "$wgP4EXEC -p $wgP4PORT -u $wgP4USER -P $wgP4PASSWD -s";
$exit = false;
$out = array();
exec( "$p4 $command", $out );
foreach( $out as $line )
{
if ( $line == "exit: 1" )
{
$exit = false;
}
elseif ( $line == "exit: 0" )
{
$exit = true;
}
else sort_p4_s_output( $line, $info, $error );
}
return $exit;
}
function run_p4_tag( $command, &$tagdict )
{
global $wgP4EXEC;
global $wgP4PORT;
global $wgP4USER;
global $wgP4PASSWD;
$p4 = "$wgP4EXEC -p $wgP4PORT -u $wgP4USER -P $wgP4PASSWD -Ztag";
$out = array();
exec( "$p4 $command", $out );
foreach( $out as $line )
{
sort_p4_tag_output( $line, $tagdict );
}
}
function sort_p4_s_output( $line, &$info, &$error )
{
if ( substr( $line, 0, 6 ) == "info: " )
{
array_push( $info, substr( $line, 6 ) );
}
elseif ( substr( $line, 0, 7 ) == "error: " )
{
array_push( $error, substr( $line, 7 ) );
}
}
function sort_p4_tag_output( $line, &$tagdict )
{
if ( !substr( $line, 0, 4 ) == "... " ) { return; }
$line = substr( $line, 4 );
$tagend = strpos( $line, " " );
$tag = substr( $line, 0, $tagend );
$data = substr( $line, $tagend + 1 );
$tagdict[$tag] = $data;
}
function wiki_to_p4( $user )
{
$user = trim( $user );
$user = str_replace( " ", "_", $user );
$user = strtolower( $user );
return $user;
}
function testUserExists( $user )
{
if ( AuthP4::userExists( $user ) )
{
print( "$user exists.\n" );
}
else
{
print( "$user does not exist.\n" );
}
}
function testAuthenticate( $user, $pass )
{
if ( AuthP4::authenticate( $user, $pass ) )
{
print( "$user authenticated with $pass\n" );
}
else
{
print( "$user failed authentication with $pass\n" );
}
}
$wgAuth = new AuthP4();
?>