Topic: Login Integration

I've been searching the forums on how to integrate punbb with my current site's login and registration system.  I've successfully integrated the registrations, but I can't get the login process to integrate.  I am trying to have users login at mysite.com, and have them automatically logged in to mysite.com/punbb.  I've tried adapting the code found here: http://punbb.informer.com/forums/topic/ … and-punbb/.

I can log in via my site, but it won't log in to the punbb forums.  Here is my entire code:

<?php 

defined('C5_EXECUTE') or die(_("Access Denied."));
Loader::library('authentication/open_id');
//Punbb code
define('FORUM_ROOT', './punbb/');



class LoginController extends Controller { 
    
    public $helpers = array('form');
    private $openIDReturnTo;
    public function on_start() {
        $this->error = Loader::helper('validation/error');
        if (USER_REGISTRATION_WITH_EMAIL_ADDRESS == true) {
            $this->set('uNameLabel', t('Email Address'));
        } else {
            $this->set('uNameLabel', t('Username'));
        }
        if (strlen($_GET['uName'])) { // pre-populate the username if supplied
            $this->set("uName",$_GET['uName']);
        }
        
        $this->openIDReturnTo = BASE_URL . View::url("/login", "complete_openid"); 
    }
    
    /* automagically run by the controller once we're done with the current method */
    /* method is passed to this method, the method that we were just finished running */
    public function on_before_render() {
        if ($this->error->has()) {
            $this->set('error', $this->error);
        }
    }
    
    public function complete_openid_email() {
        $email = $this->post('uEmail');
        $vals = Loader::helper('validation/strings');
        $valc = Loader::helper('concrete/validation');
        if (!$vals->email($email)) {
            $this->error->add(t('Invalid email address provided.'));
        } else if (!$valc->isUniqueEmail($email)) {
            $this->error->add(t("The email address %s is already in use. Please choose another.", $_POST['uEmail']));
        }    
    
        if (!$this->error->has()) {
            // complete the openid record with the provided email
            if (isset($_SESSION['uOpenIDRequested'])) {
                $oa = new OpenIDAuth();
                $ui = $oa->registerUser($_SESSION['uOpenIDRequested'], $email);
                User::loginByUserID($ui->getUserID());
                $this->finishLogin();
            }
        }
    }
    
    public function view() {
        $this->clearOpenIDSession();
    }
    
    private function clearOpenIDSession() {
        unset($_SESSION['uOpenIDError']);
        unset($_SESSION['uOpenIDRequested']);
        unset($_SESSION['uOpenIDExistingUser']);
    }
    
    public function complete_openid() {
        $v = Loader::helper('validation/numbers');
        $oa = new OpenIDAuth();
        $oa->setReturnURL($this->openIDReturnTo);
        $oa->complete();
        $response = $oa->getResponse();
        if ($response->code == OpenIDAuth::E_CANCEL) {
            $this->error->add(t('OpenID Verification Cancelled'));
            $this->clearOpenIDSession();
        } else if ($response->code == OpenIDAuth::E_FAILURE) {
            $this->error->add(t('OpenID Authentication Failed: %s', $response->message));
            $this->clearOpenIDSession();
        } else {
            switch($response->code) {
                case OpenIDAuth::S_USER_CREATED:
                case OpenIDAuth::S_USER_AUTHENTICATED:
                    if ($v->integer($response->message)) {
                        User::loginByUserID($response->message);
                        $this->finishLogin();
                    }
                    break;
                case OpenIDAuth::E_REGISTRATION_EMAIL_INCOMPLETE:
                    // we don't have an email address, but the account is valid
                    // valid display identifier comes back in message
                    $_SESSION['uOpenIDRequested'] = $response->message;
                    $_SESSION['uOpenIDError'] = OpenIDAuth::E_REGISTRATION_EMAIL_INCOMPLETE;
                    break; 
                case OpenIDAuth::E_REGISTRATION_EMAIL_EXISTS:
                    // an email address came back with us from the openid server
                    // but that email already exists
                    $_SESSION['uOpenIDRequested'] = $response->openid;
                    $_SESSION['uOpenIDExistingUser'] = $response->user;
                    $_SESSION['uOpenIDError'] = OpenIDAuth::E_REGISTRATION_EMAIL_EXISTS;
                    break;
            }
        }
        $this->set('oa', $oa);        
    }
    
    public function account_deactivated() {
        $this->error->add(t('This user is inactive. Please contact us regarding this account.'));
    }
    
    public function do_login() { 
        $ip = Loader::helper('validation/ip');
        $vs = Loader::helper('validation/strings');
        
        $loginData['success']=0;
        
        try {
            if (!$ip->check()) {                
                throw new Exception($ip->getErrorMessage());
            }
            if (OpenIDAuth::isEnabled() && $vs->notempty($this->post('uOpenID'))) {
                $oa = new OpenIDAuth();
                $oa->setReturnURL($this->openIDReturnTo);
                $return = $oa->request($this->post('uOpenID'));
                $resp = $oa->getResponse();
                if ($resp->code == OpenIDAuth::E_INVALID_OPENID) {
                    throw new Exception(t('Invalid OpenID.'));
                }
            }
            
            if ((!$vs->notempty($this->post('uName'))) || (!$vs->notempty($this->post('uPassword')))) {
                if (USER_REGISTRATION_WITH_EMAIL_ADDRESS) {
                    throw new Exception(t('An email address and password are required.'));
                } else {
                    throw new Exception(t('A username and password are required.'));
                }
            }
            
            $u = new User($this->post('uName'), $this->post('uPassword'));
            if ($u->isError()) {
                switch($u->getError()) {
                    case USER_NON_VALIDATED:
                        throw new Exception(t('This account has not yet been validated. Please check the email associated with this account and follow the link it contains.'));
                        break;
                    case USER_INVALID:
                        if (USER_REGISTRATION_WITH_EMAIL_ADDRESS) {
                            throw new Exception(t('Invalid email address or password.'));
                        } else {
                            throw new Exception(t('Invalid username or password.'));                        
                        }
                        break;
                    case USER_INACTIVE:
                        throw new Exception(t('This user is inactive. Please contact us regarding this account.'));
                        break;
                }
            } else {
            
                if (OpenIDAuth::isEnabled() && $_SESSION['uOpenIDExistingUser'] > 0) {
                    $oa = new OpenIDAuth();
                    if ($_SESSION['uOpenIDExistingUser'] == $u->getUserID()) {
                        // the account we logged in with is the same as the existing user from the open id. that means
                        // we link the account to open id and keep the user logged in.
                        $oa->linkUser($_SESSION['uOpenIDRequested'], $u);
                    } else {
                        // The user HAS logged in. But the account they logged into is NOT the same as the one
                        // that links to their OpenID. So we log them out and tell them so.
                        $u->logout();
                        throw new Exception(t('This account does not match the email address provided.'));
                    }

//Punbb Code
include 'punbb/include/common.php';    //Include this file so that $pun_user['is_guest'] can be used and that (some?) functions from punbb/include/functions.php can also be used in this script


if (($websitelogin==true) && ($forum_user['is_guest'])) {

    
 $username =$this->post('uEmail');  //Get the username of the logged in user and put it in a variable     ($user->Username comes from code from the website which is intended to get login integration with punbb through this script)
    
    $queryFromPunbb = "SELECT * FROM pun1_users WHERE username='$username'";    //get the row with the id from the logged in user. This id is the primary key of the punbb_users table in the punbb database
    $result = mysql_query($queryFromPunbb, $conn) or die (mysql_error());    //Run the query
    $row = mysql_fetch_array($result) or die(mysql_error());    //Put the result of the query in an array called $row  
    
    $user_id = $row['id'];    //Put the id from the $row array into the variable $user_id
    $hashedPassword = forum_hash($this->post('uPassword'));    //hash the user's password using the punbb hash function 
    $expirationTime = time()+24*60*60;
    
    forum_setcookie($user_id, $hashedPassword, $expirationTime); //Set the punBB cookie, which is called punbb_cookie
    

}

                }
                
                $loginData['success']=1;
                $loginData['msg']=t('Login Successful');    
                $loginData['uID'] = intval($u->getUserID());
                if($_REQUEST['remote'] && intval($_REQUEST['timestamp'])){ 
                    $loginData['auth_token'] =     UserInfo::generateAuthToken( $u->getUserName(), intval($_REQUEST['timestamp']) );
                    //is this user in a support group? 
                    foreach( RemoteMarketplaceHelper::getSupportGroups() as $group){
                        if($u->inGroup($group)){
                            $inValidSupportGroup=1;
                            break;
                        }

    


                    }
                    $loginData['in_support_group'] = intval($inValidSupportGroup);
                }
            }

            $loginData = $this->finishLogin($loginData);





            
        } catch(Exception $e) {
            $ip->logSignupRequest();
            if ($ip->signupRequestThreshholdReached()) {
                $ip->createIPBan();
            }
            $this->error->add($e);
            $loginData['error']=$e->getMessage();
        }
        
        if( $_REQUEST['format']=='JSON' ){
            $jsonHelper=Loader::helper('json'); 
            echo $jsonHelper->encode($loginData);
            die;
        }



    }



    protected function finishLogin( $loginData=array() ) {
        $u = new User();
        if ($this->post('uMaintainLogin')) {
            $u->setUserForeverCookie();
        }
        $rcID = $this->post('rcID');
        $nh = Loader::helper('validation/numbers');

        //set redirect url
        if ($nh->integer($rcID)) {
            $nh = Loader::helper('navigation');
            $rc = Page::getByID($rcID);
            $url = $nh->getLinkToCollection($rc, true);
            $loginData['redirectURL'] = $url;
        }elseif( strlen($rcID) ){
            $loginData['redirectURL'] = $rcID;
        }
        
        //full page login redirect (non-ajax login)
        if( strlen($loginData['redirectURL']) && $_REQUEST['format']!='JSON' ){ 
            header('Location: ' . $loginData['redirectURL']);
            exit;    
        }
        
        //not sure why there's this second redirect approach, but oh well...
        if ($this->post('redirect') != '' && $this->isValidExternalUrl($this->post('redirect'))) {
            $loginData['redirectURL']=$this->post('redirect');
        }
        
        $dash = Page::getByPath("/dashboard", "RECENT");
        $dbp = new Permissions($dash);        
        
        Events::fire('on_user_login',$this);
        
        //End JSON Login
        if($_REQUEST['format']=='JSON') 
            return $loginData;        
        
        //should administrator be redirected to dashboard?  defaults to yes if not set. 
        $adminToDash=intval(Config::get('LOGIN_ADMIN_TO_DASHBOARD'));      
        
        //Full page login, standard redirection            
        if ($loginData['redirectURL']) {
            //make double secretly sure there's no caching going on
            header("Cache-Control: no-store, no-cache, must-revalidate");
            header("Pragma: no-cache");
            header('Expires: Fri, 30 Oct 1998 14:19:41 GMT'); //in the past        
            $this->externalRedirect( $loginData['redirectURL'] );
        }else if ( $dbp->canRead() && $adminToDash ) {
            $this->redirect('/dashboard');
        } else {
            //options set in dashboard/users/registration
            $login_redirect_cid=intval(Config::get('LOGIN_REDIRECT_CID'));
            $login_redirect_mode=Config::get('LOGIN_REDIRECT');        
            
            //redirect to user profile
            if( $login_redirect_mode=='PROFILE' && ENABLE_USER_PROFILES ){             
                $this->redirect( '/profile/', $u->uID );                 
                
            //redirect to custom page    
            }elseif( $login_redirect_mode=='CUSTOM' && $login_redirect_cid > 0 ){ 
                $redirectTarget = Page::getByID( $login_redirect_cid ); 
                if(intval($redirectTarget->cID)>0) $this->redirect( $redirectTarget->getCollectionPath() );
                else $this->redirect('/home');        
                        
            //redirect home
            }else $this->redirect('/home');
        }
    }

    public function password_sent() {
        $this->set('intro_msg', $this->getPasswordSentMsg() );
    }
    
    public function getPasswordSentMsg(){
        return t('An email containing instructions on reseting your password has been sent to your account address.');
    }
    
    public function logout() {
        $u = new User();
        $u->logout();
        $this->redirect('/');

    }
    
    public function forward($cID) {
        $this->set('rcID', $cID);
    }
    
    // responsible for validating a user's email address
    public function v($hash) {
        $ui = UserInfo::getByValidationHash($hash);
        if (is_object($ui)) {
            $ui->markValidated();
            $this->set('uEmail', $ui->getUserEmail());
            $this->set('validated', true);
        }
    }
    
    // responsible for validating a user's email address
    public function change_password($uHash) {
        $db = Loader::db();
        $h = Loader::helper('validation/identifier');
        $e = Loader::helper('validation/error');
        
        $ui = UserInfo::getByValidationHash($uHash);        
        if (is_object($ui)){
            $hashCreated = $db->GetOne("select uDateGenerated FROM UserValidationHashes where uHash=?", array($uHash));
            if($hashCreated < (time()-(USER_CHANGE_PASSWORD_URL_LIFETIME))) {
                $h->deleteKey('UserValidationHashes','uHash',$uHash);
                throw new Exception( t('Key Expired. Please visit the forgot password page again to have a new key generated.') );
            }else{    
            
                if(strlen($_POST['uPassword'])){
                
                    $userHelper = Loader::helper('concrete/user');
                    $userHelper->validNewPassword($_POST['uPassword'],$e);
                    
                    if(strlen($_POST['uPassword']) && $_POST['uPasswordConfirm']!=$_POST['uPassword']){            
                        $e->add(t('The two passwords provided do not match.'));
                    }
                    
                    if (!$e->has()){ 
                        $ui->changePassword( $_POST['uPassword'] );                        
                        $h->deleteKey('UserValidationHashes','uHash',$uHash);                    
                        $this->set('passwordChanged', true);
                        
                        $u = $ui->getUserObject();
                        $_POST['uName'] =  $u->getUserName();
                        $this->do_login();
                            
                        return;
                    }else{
                        $this->set('uHash', $uHash);
                        $this->set('changePasswordForm', true);                    
                        $this->set('errorMsg', join( '<br>', $e->getList() ) );                    
                    }
                }else{                 
                    $this->set('uHash', $uHash);
                    $this->set('changePasswordForm', true);
                }
            }        
        }else{
            throw new Exception( t('Invalid Key. Please visit the forgot password page again to have a new key generated.') );
        }
    }    
    
    public function forgot_password() {
        $loginData['success']=0;
    
        $vs = Loader::helper('validation/strings');
        $em = $this->post('uEmail');
        try {
            if (!$vs->email($em)) {
                throw new Exception(t('Invalid email address.'));
            }
            
            $oUser = UserInfo::getByEmail($em);
            if (!$oUser) {
                throw new Exception(t('We have no record of that email address.'));
            }            
            
            $mh = Loader::helper('mail');
            //$mh->addParameter('uPassword', $oUser->resetUserPassword());
            $mh->addParameter('uName', $oUser->getUserName());            
            $mh->to($oUser->getUserEmail());
            
            //generate hash that'll be used to authenticate user, allowing them to change their password
            $h = Loader::helper('validation/identifier');
            $uHash = $h->generate('UserValidationHashes', 'uHash');    
            $db = Loader::db();
            $db->Execute("DELETE FROM UserValidationHashes WHERE uID=?", array( $oUser->uID ) );            
            $db->Execute("insert into UserValidationHashes (uID, uHash, uDateGenerated, type) values (?, ?, ?, ?)", array($oUser->uID, $uHash, time(),intval(UVTYPE_CHANGE_PASSWORD)));        
            $changePassURL=BASE_URL . View::url('/login', 'change_password', $uHash);         
            $mh->addParameter('changePassURL', $changePassURL);
            
            if (defined('EMAIL_ADDRESS_FORGOT_PASSWORD')) {
                $mh->from(EMAIL_ADDRESS_FORGOT_PASSWORD,  t('Forgot Password'));
            } else {
                $adminUser = UserInfo::getByID(USER_SUPER_ID);
                if (is_object($adminUser)) {
                    $mh->from($adminUser->getUserEmail(),  t('Forgot Password'));
                } else {
                    $mh->from('info@concrete5.org', t('Forgot Password'));
                }
            }
            $mh->load('forgot_password');
            @$mh->sendMail();
            
            $loginData['success']=1;
            $loginData['msg']=$this->getPasswordSentMsg();

        } catch(Exception $e) {
            $this->error->add($e);
            $loginData['error']=$e->getMessage();
        }
        
        if( $_REQUEST['format']=='JSON' ){
            $jsonHelper=Loader::helper('json'); 
            echo $jsonHelper->encode($loginData);
            die;
        }        
        
        if($loginData['success']==1)
            $this->redirect('/login', 'password_sent');    
    }

}

I'm using punbb 1.3.4 and trying to integrate with Concrete5 cms.  Thanks to anyone who can help.

Re: Login Integration

I think this could be the issue, I tried to do the same once before but I ran into an error about this

<input type="hidden" name="csrf_token" value="5d6873d60498923b36391b783160d6370eec5daf" />

If im correct each login creates a different value and no matter if your session is correct unless you have the same csrf_token script you will not be logged in,

I'm not sure the developers want us to post how to hack the login on the forum so If and when you figure it out message me :-)

Re: Login Integration

if you find out the code, can u please post. i want the same thing.

thanks

MyFootballCafe.com  is Now Online!

Re: Login Integration

Hi, please can you explain step by step how you integrated the registrations? Thank you.

5 (edited by Clyd 2010-06-17 18:58)

Re: Login Integration

Bonjour.

Bien j'ai trouvé un morceau de code qui permets de disposer une boite de connexion sur toutes les pages du site, je ne suis pas l'auteur de ce code je l'ai trouvé sur une mod je ne sais plus laquelle mais cela fonctionne.

Son auteur se reconnaitra.


Avant le doctype de votre document  il fait ajouter les lignes suivantes.

<?php
 
// Add these lines in the very top of your code
define('FORUM_ROOT', './forum/');
require FORUM_ROOT.'include/common.php'; 
?>

Puis a l'endroit ou vous voulez voir apparaitre la case de connexion ajoutez le code suivant, les membres peuvent voir aussi l'avatar s'ils sont connectés.

<?php
// If user is logged display some informations about it
if (!$forum_user['is_guest'])
{
    require FORUM_ROOT.'lang/'.$forum_user['language'].'/index.php';
    if ($forum_config['o_users_online'] == '1')
    {
        // Fetch users online info and generate strings for output
        $query = array(
            'SELECT'    => 'o.user_id, o.ident',
            'FROM'        => 'online AS o',
            'WHERE'        => 'o.idle=0',
            'ORDER BY'    => 'o.ident'
        );
        $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
        $num_guests = 0;
        $users = array();

        while ($forum_user_online = $forum_db->fetch_assoc($result))
        {

            if ($forum_user_online['user_id'] > 1)
                $users[] = '<a href="'.forum_link($forum_url['user'], $forum_user_online['user_id']).'">'.forum_htmlencode($forum_user_online['ident']).'</a>';
            else
                ++$num_guests;
            
        }

        // If there are registered users logged in, list them
        if (count($users) > 0)
            //$users_online = '<p><strong>'.$forum_user['Online'].'</strong> '.implode(', ', $users).'</p>';<!--Décommenter cette ligne pour afficher les utilisateurs en ligne-->

        $stats_online[] = 'Membres en ligne: <strong>'.count($users).'</strong><br />';
        $stats_online[] = 'Visiteurs en ligne: <strong>'.$num_guests.'</strong>';
    }
    
    $avatar = generate_avatar_markup($forum_user['id']);
?>
<?php echo Bienvenue ?>: <strong><?php echo forum_htmlencode($forum_user['username']) ?>  </strong> <br />
<?php echo $links['logout'] = '<span id="navlogout"><a href="'.forum_link($forum_url['logout'], array($forum_user['id'], generate_form_token('logout'.$forum_user['id']))).'">'.$lang_common['Logout'].'</a></span> | ';?>
<?php echo $links['profile'] = '<span id="navprofile"'.((substr(FORUM_PAGE, 0, 7) == 'profile') ? ' class="isactive"' : '').'><a href="'.forum_link($forum_url['user'], $forum_user['id']).'">'.$lang_common['Profile'].'</a></span> | ';?>
<?php echo $links['userlist'] = '<span id="navuserlist"'.((FORUM_PAGE == 'userlist') ? ' class="isactive"' : '').'><a href="'.forum_link($forum_url['users']).'">'.$lang_common['User list'].'</a></span>';?>
<?php if ($avatar != '') : ?>
            <?php echo $avatar ?>
<?php else : ?>
<?php endif; ?>
            <ul class="stats-online">
                <?php echo implode("\n\t\t\t", $stats_online) ?>
            </ul>
        
            <?php //if (isset($users_online)) : echo $users_online; endif; ?><!--Décommenter cette ligne pour afficher les utilisateurs en ligne-->

<?php

}


// Else user is not logged, display login form
else
{
    $cur_panel['title'] = $lang_common['Login'];

    require_once FORUM_ROOT.'lang/'.$forum_user['language'].'/login.php';
    $form_action = forum_link($forum_url['login']);
?>
    <?php echo Bienvenue ?>: <strong><?php echo $lang_login['Guest'] ?></strong>    <br />
    <?php echo $lang_login['Please login'] ?><br />
    <a href="<?php echo forum_link($forum_url['register']) ?>"><?php echo $lang_login['Register'] ?></a>
    <a href="<?php echo forum_link($forum_url['request_password']) ?>"><?php echo $lang_login['New password'] ?></a><br />
    <form method="post" action="<?php echo $form_action ?>">
        <div class="hidden">
            <input type="hidden" name="form_sent" value="1" />
            <input type="hidden" name="redirect_url" value="<?php echo get_current_url() ?>" />
            <input type="hidden" name="csrf_token" value="<?php echo generate_form_token($form_action) ?>" />
        </div>
        <div class="panel-input">
            <?php echo $lang_login['Username'] ?>
            <input type="text" name="req_username" size="13" /><br />
        </div>
        <div class="panel-input">
            <?php echo $lang_login['Password'] ?>
            <input type="password" name="req_password" size="13" /><br />
        </div>
        <div>
            <label for="fld-remember-me"><span class="fld-label"><?php echo $lang_login['Remember me'] ?></span>&nbsp;<input type="checkbox" id="fld-remember-me" name="save_pass" value="1" /></label>
            <span class="submit"><input type="submit" name="login" value="<?php echo $lang_common['Login'] ?>" /></span>
        </div>
            
            
</form><?php

}

// this variable is also used for display statistics on forums page
unset($stats_list);

?>

Bien sur il faudrait ajouter a ce code les liens supplementaires contenus dans la navlinks, personellement je n'ais pas besoin de plus.

Ajouter au fichier login de votre pack langage les lignes suivantes (traduisez selon vos besoins)

'Guest'                                =>    'Visiteur',
'Welcome'                            =>    'Bienvenue',
'Please login'                        =>    'Déjà inscrit? Connectez-vous.',
'Register'                            =>    'S\'enregistrer',
'New password'                        =>    'Redéfinir mot de passe'

Enfin un code CSS devra etre creé selon les besoins de chacun,sur le thème du site.

Ce code fonctionne parfaitement, il est possible de faire un nettoyage de code approfondi car je n'y connais rien en php.

Re: Login Integration

(English translation)

Hello

I found some code to display a logon form on all the pages on a site. I'm not the author of this code; I simply found it on a mod; Can't recall which, but it works. Its author will know who he is.

Before the doctype of the document, add the following lines:

<?php
 
// Add these lines in the very top of your code
define('FORUM_ROOT', './forum/');
require FORUM_ROOT.'include/common.php'; 
?>

Next, where you want the logon form to be displayed, add the following code. Logged-on members can also see the avatar:

<?php
// If user is logged display some informations about it
if (!$forum_user['is_guest'])
{
    require FORUM_ROOT.'lang/'.$forum_user['language'].'/index.php';
    if ($forum_config['o_users_online'] == '1')
    {
        // Fetch users online info and generate strings for output
        $query = array(
            'SELECT'    => 'o.user_id, o.ident',
            'FROM'        => 'online AS o',
            'WHERE'        => 'o.idle=0',
            'ORDER BY'    => 'o.ident'
        );
        $result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
        $num_guests = 0;
        $users = array();

        while ($forum_user_online = $forum_db->fetch_assoc($result))
        {

            if ($forum_user_online['user_id'] > 1)
                $users[] = '<a href="'.forum_link($forum_url['user'], $forum_user_online['user_id']).'">'.forum_htmlencode($forum_user_online['ident']).'</a>';
            else
                ++$num_guests;
            
        }

        // If there are registered users logged in, list them
        if (count($users) > 0)
            //$users_online = '<p><strong>'.$forum_user['Online'].'</strong> '.implode(', ', $users).'</p>';<!--Décommenter cette ligne pour afficher les utilisateurs en ligne-->

        $stats_online[] = 'Membres en ligne: <strong>'.count($users).'</strong><br />';
        $stats_online[] = 'Visiteurs en ligne: <strong>'.$num_guests.'</strong>';
    }
    
    $avatar = generate_avatar_markup($forum_user['id']);
?>
<?php echo Bienvenue ?>: <strong><?php echo forum_htmlencode($forum_user['username']) ?>  </strong> <br />
<?php echo $links['logout'] = '<span id="navlogout"><a href="'.forum_link($forum_url['logout'], array($forum_user['id'], generate_form_token('logout'.$forum_user['id']))).'">'.$lang_common['Logout'].'</a></span> | ';?>
<?php echo $links['profile'] = '<span id="navprofile"'.((substr(FORUM_PAGE, 0, 7) == 'profile') ? ' class="isactive"' : '').'><a href="'.forum_link($forum_url['user'], $forum_user['id']).'">'.$lang_common['Profile'].'</a></span> | ';?>
<?php echo $links['userlist'] = '<span id="navuserlist"'.((FORUM_PAGE == 'userlist') ? ' class="isactive"' : '').'><a href="'.forum_link($forum_url['users']).'">'.$lang_common['User list'].'</a></span>';?>
<?php if ($avatar != '') : ?>
            <?php echo $avatar ?>
<?php else : ?>
<?php endif; ?>
            <ul class="stats-online">
                <?php echo implode("\n\t\t\t", $stats_online) ?>
            </ul>
        
            <?php //if (isset($users_online)) : echo $users_online; endif; ?><!--Décommenter cette ligne pour afficher les utilisateurs en ligne-->

<?php

}


// Else user is not logged, display login form
else
{
    $cur_panel['title'] = $lang_common['Login'];

    require_once FORUM_ROOT.'lang/'.$forum_user['language'].'/login.php';
    $form_action = forum_link($forum_url['login']);
?>
    <?php echo Bienvenue ?>: <strong><?php echo $lang_login['Guest'] ?></strong>    <br />
    <?php echo $lang_login['Please login'] ?><br />
    <a href="<?php echo forum_link($forum_url['register']) ?>"><?php echo $lang_login['Register'] ?></a>
    <a href="<?php echo forum_link($forum_url['request_password']) ?>"><?php echo $lang_login['New password'] ?></a><br />
    <form method="post" action="<?php echo $form_action ?>">
        <div class="hidden">
            <input type="hidden" name="form_sent" value="1" />
            <input type="hidden" name="redirect_url" value="<?php echo get_current_url() ?>" />
            <input type="hidden" name="csrf_token" value="<?php echo generate_form_token($form_action) ?>" />
        </div>
        <div class="panel-input">
            <?php echo $lang_login['Username'] ?>
            <input type="text" name="req_username" size="13" /><br />
        </div>
        <div class="panel-input">
            <?php echo $lang_login['Password'] ?>
            <input type="password" name="req_password" size="13" /><br />
        </div>
        <div>
            <label for="fld-remember-me"><span class="fld-label"><?php echo $lang_login['Remember me'] ?></span>&nbsp;<input type="checkbox" id="fld-remember-me" name="save_pass" value="1" /></label>
            <span class="submit"><input type="submit" name="login" value="<?php echo $lang_common['Login'] ?>" /></span>
        </div>
            
            
</form><?php

}

// this variable is also used for display statistics on forums page
unset($stats_list);

?>

Obviously, this code requires adding the extra links contained in the navlinks. Personally, I don't need more than that.

To the login file of your "language pack" (?), add the following lines (translate according to your needs):

'Guest'                                =>    'Visiteur',
'Welcome'                            =>    'Bienvenue',
'Please login'                        =>    'Déjà inscrit? Connectez-vous.',
'Register'                            =>    'S\'enregistrer',
'New password'                        =>    'Redéfinir mot de passe'

Finally, you'll have to create some CSS based on the theme of your site. This code works fine. It could require some thorough code inspection, but I don't know PHP.