Merge commit 'origin/master' into hruid
authorVincent Zanotti <vincent.zanotti@polytechnique.org>
Sun, 21 Sep 2008 20:24:50 +0000 (22:24 +0200)
committerVincent Zanotti <vincent.zanotti@polytechnique.org>
Sun, 21 Sep 2008 20:24:50 +0000 (22:24 +0200)
Conflicts:
include/emails.inc.php

Signed-off-by: Vincent Zanotti <vincent.zanotti@polytechnique.org>
1  2 
include/emails.inc.php
include/userset.inc.php
modules/admin.php
modules/email.php
modules/xnetevents.php
modules/xnetevents/xnetevents.inc.php
modules/xnetgrp.php
templates/emails/redirect.tpl
templates/emails/rewrite-in.mail.tpl
templates/include/minifiche.tpl

diff --combined include/emails.inc.php
@@@ -27,12 -27,12 +27,12 @@@ define("ERROR_LOOP_EMAIL", 4)
  // function fix_bestalias() {{{1
  // Checks for an existing 'bestalias' among the the current user's aliases, and
  // eventually selects a new bestalias when required.
 -function fix_bestalias($uid)
 +function fix_bestalias(User &$user)
  {
      $res = XDB::query("SELECT  COUNT(*)
                           FROM  aliases
                          WHERE  id = {?} AND FIND_IN_SET('bestalias', flags) AND type != 'homonyme'",
 -                      $uid);
 +                      $user->id());
      if ($res->fetchOneCell()) {
          return;
      }
@@@ -41,7 -41,7 +41,7 @@@
                       SET  flags=CONCAT(flags,',','bestalias')
                     WHERE  id={?} AND type!='homonyme'
                  ORDER BY  !FIND_IN_SET('usage',flags),alias LIKE '%.%', LENGTH(alias)
 -                   LIMIT  1", $uid);
 +                   LIMIT  1", $user->id());
  }
  
  // function valide_email() {{{1
@@@ -80,28 -80,26 +80,28 @@@ class Bog
  {
      // properties {{{2
  
 -    private $uid;
 +    private $user;
      private $state;
      private $_states = Array('let_spams', 'tag_spams', 'tag_and_drop_spams', 'drop_spams');
  
      // constructor {{{2
  
 -    public function __construct($uid)
 +    public function __construct(User &$user)
      {
 -        if (!$uid) {
 +        if (!$user) {
              return;
          }
  
 -        $this->uid = $uid;
 -        $res = XDB::query('SELECT email FROM emails WHERE uid={?} AND flags="filter"', $uid);
 +        $this->user = &$user;
 +        $res = XDB::query('SELECT email FROM emails WHERE uid = {?} AND flags = "filter"', $user->id());
          if ($res->numRows()) {
              $this->state = $res->fetchOneCell();
          } else {
              $this->state = 'tag_and_drop_spams';
 -            $res = XDB::query("INSERT INTO emails (uid,email,rewrite,panne,flags)
 -                                    VALUES ({?},'tag_and_drop_spams','','0000-00-00','filter')", $uid);
 +            $res = XDB::query(
 +                    "INSERT INTO  emails (uid, email, rewrite, panne, flags)
 +                          VALUES  ({?}, 'tag_and_drop_spams', '', '0000-00-00', 'filter')",
 +                    $user->id());
          }
      }
  
      public function change($state)
      {
          $this->state = is_int($state) ? $this->_states[$state] : $state;
 -        XDB::execute('UPDATE emails SET email={?} WHERE uid={?} AND flags = "filter"',
 -                     $this->state, $this->uid);
 +        XDB::execute('UPDATE emails SET email = {?} WHERE uid = {?} AND flags = "filter"',
 +                     $this->state, $this->user->id());
      }
  
      // pubic function level() {{{2
  // Storage emails (Polytechnique.org).
  abstract class Email
  {
 -    protected $uid;
 +    protected $user;
  
      // Basic email properties; $sufficient indicates if the email can be used as
      // an unique redirection; $email contains the delivery email address.
      public $broken;
      public $disabled;
      public $rewrite;
+     public $allow_rewrite;
+     public $hash;
  
      // Redirection bounces stats.
      public $panne;
@@@ -176,12 -176,12 +178,12 @@@ class EmailRedirection extends Emai
  {
      // constructor {{{2
  
 -    public function __construct($uid, $row)
 +    public function __construct(User &$user, $row)
      {
 -        $this->uid = $uid;
 +        $this->user = &$user;
          $this->sufficient = true;
  
-         list($this->email, $flags, $this->rewrite, $this->panne, $this->last, $this->panne_level) = $row;
+         list($this->email, $flags, $this->rewrite, $this->allow_rewrite, $this->hash, $this->panne, $this->last, $this->panne_level) = $row;
          $this->display_email = $this->email;
          $this->active   = ($flags == 'active');
          $this->broken   = ($flags == 'panne');
              XDB::execute("UPDATE  emails
                               SET  panne_level = IF(flags = 'panne', panne_level - 1, panne_level),
                                    flags = 'active'
 -                           WHERE  uid={?} AND email={?}", $this->uid, $this->email);
 -            S::logger()->log("email_on", $this->email.($this->uid!=S::v('uid') ? "(admin on {$this->uid})" : ""));
 +                           WHERE  uid = {?} AND email = {?}", $this->user->id(), $this->email);
 +            S::logger()->log("email_on", $this->email . ($this->user->id() != S::v('uid') ? "(admin on {$this->user->login()})" : ""));
              $this->active = true;
              $this->broken = false;
          }
      {
          if ($this->active) {
              XDB::execute("UPDATE  emails SET flags =''
 -                           WHERE  uid={?} AND email={?}", $this->uid, $this->email);
 -            S::logger()->log("email_off",$this->email.($this->uid != S::v('uid') ? "(admin on {$this->uid})" : "") );
 +                           WHERE  uid = {?} AND email = {?}", $this->user->id(), $this->email);
 +            S::logger()->log("email_off", $this->email . ($this->user->id() != S::v('uid') ? "(admin on {$this->user->login()})" : "") );
              $this->active = false;
          }
      }
          if (!$rewrite || !isvalid_email($rewrite)) {
              $rewrite = '';
          }
 -        XDB::execute('UPDATE emails SET rewrite={?} WHERE uid={?} AND email={?}', $rewrite, $this->uid, $this->email);
 +        XDB::execute('UPDATE emails SET rewrite = {?} WHERE uid = {?} AND email = {?}', $rewrite, $this->user->id(), $this->email);
          $this->rewrite = $rewrite;
 -                               WHERE uid = {?} AND email = {?}", $this->hash, $this->uid, $this->email);
+         if (!$this->allow_rewrite) {
+             global $globals;
+             if (empty($this->hash)) {
+                 $this->hash = rand_url_id();
+                 XDB::execute("UPDATE emails
+                                  SET hash = {?}
 -            $res = XDB::query("SELECT  IF(u.nom_usage = '', u.nom, u.nom_usage) AS nom, u.prenom, FIND_IN_SET('femme', u.flags) AS sex,
 -                                       q.core_mail_fmt, a.alias AS forlife, a2.alias AS bestalias
 -                                 FROM  auth_user_md5 AS u
 -                           INNER JOIN  auth_user_quick AS q ON (u.user_id = q.user_id)
 -                           INNER JOIN  aliases         AS a ON (a.id = u.user_id AND a.type = 'a_vie')
 -                           INNER JOIN  aliases         AS a2 ON (a2.id = u.user_id AND FIND_IN_SET('bestalias', a2.flags))
 -                                WHERE  u.user_id = {?}", $this->uid);
 -            list($nom, $prenom, $sexe, $fmt, $forlife, $bestalias) = $res->fetchOneRow();
++                               WHERE uid = {?} AND email = {?}", $this->hash, $this->user->id(), $this->email);
+             }
 -            $mail->assign('nom', $nom);
 -            $mail->assign('prenom', $prenom);
 -            $mail->assign('sexe', $sexe);
 -            $mail->assign('forlife', $forlife);
+             $mail = new PlMailer('emails/rewrite-in.mail.tpl');
+             $mail->assign('mail', $this);
 -            $mail->send($fmt == 'html');
++            $mail->assign('user', $this->user);
+             $mail->assign('baseurl', $globals->baseurl);
+             $mail->assign('sitename', $globals->core->sitename);
+             $mail->assign('to', $this->email);
++            $mail->send($this->user->isEmailFormatHtml());
+         }
          return;
      }
  
          return XDB::execute("UPDATE  emails
                                  SET  panne_level = 0, panne = 0, last = 0
                                WHERE  uid = {?} AND email = {?}",
 -                            $this->uid, $this->email);
 +                            $this->user->id(), $this->email);
      }
  
      // public function has_rewrite() {{{2
@@@ -283,7 -310,7 +301,7 @@@ class EmailStorage extends Emai
      {
          $res = XDB::query("SELECT  mail_storage
                               FROM  auth_user_md5
 -                            WHERE  user_id = {?}", $this->uid);
 +                            WHERE  user_id = {?}", $this->user->id());
          return new PlFlagSet($res->fetchOneCell());
      }
  
      {
          XDB::execute("UPDATE  auth_user_md5
                           SET  mail_storage = {?}
 -                       WHERE  user_id = {?}", $storages, $this->uid);
 +                       WHERE  user_id = {?}", $storages, $this->user->id());
      }
  
      // Returns the list of allowed storages for the @p user.
 -    static public function get_allowed_storages($uid)
 +    static public function get_allowed_storages(User &$user)
      {
          global $globals;
          $storages = array();
          // Google Apps storage is available for users with valid Google Apps account.
          require_once 'googleapps.inc.php';
          if ($globals->mailstorage->googleapps_domain &&
 -            GoogleAppsAccount::account_status($uid) == 'active') {
 +            GoogleAppsAccount::account_status($user->id()) == 'active') {
              $storages[] = 'googleapps';
          }
  
      }
  
  
 -    public function __construct($uid, $name)
 +    public function __construct(User &$user, $name)
      {
 -        $this->uid = $uid;
 +        $this->user = &$user;
          $this->email = $name;
          $this->display_email = (isset($this->display_names[$name]) ? $this->display_names[$name] : $name);
  
@@@ -375,30 -402,30 +393,30 @@@ class Redirec
      // properties {{{2
  
      private $flag_active = 'active';
 -    private $uid;
 +    private $user;
  
      public $emails;
      public $bogo;
  
      // constructor {{{2
  
 -    public function __construct($_uid)
 +    public function __construct(User &$user)
      {
 -        $this->uid = $_uid;
 -        $this->bogo = new Bogo($_uid);
 +        $this->user = &$user;
 +        $this->bogo = new Bogo($user);
  
          // Adds third-party email redirections.
-         $res = XDB::iterRow("SELECT  email, flags, rewrite, panne, last, panne_level
+         $res = XDB::iterRow("SELECT  email, flags, rewrite, allow_rewrite, hash, panne, last, panne_level
                                 FROM  emails
 -                              WHERE  uid = {?} AND flags != 'filter'", $_uid);
 +                              WHERE  uid = {?} AND flags != 'filter'", $user->id());
          $this->emails = Array();
          while ($row = $res->next()) {
 -            $this->emails[] = new EmailRedirection($_uid, $row);
 +            $this->emails[] = new EmailRedirection($user, $row);
          }
  
          // Adds local email storage backends.
 -        foreach (EmailStorage::get_allowed_storages($_uid) as $storage) {
 -            $this->emails[] = new EmailStorage($_uid, $storage);
 +        foreach (EmailStorage::get_allowed_storages($user) as $storage) {
 +            $this->emails[] = new EmailStorage($user, $storage);
          }
      }
  
          if (!$this->other_active($email)) {
              return ERROR_INACTIVE_REDIRECTION;
          }
 -        XDB::execute('DELETE FROM emails WHERE uid={?} AND email={?}', $this->uid, $email);
 -        S::logger()->log('email_del',$email.($this->uid!=S::v('uid') ? " (admin on {$this->uid})" : ""));
 +        XDB::execute('DELETE FROM emails WHERE uid = {?} AND email = {?}', $this->user->id(), $email);
 +        S::logger()->log('email_del', $email . ($this->user->id() != S::v('uid') ? " (admin on {$this->user->login()})" : ""));
          foreach ($this->emails as $i => $mail) {
              if ($email == $mail->email) {
                  unset($this->emails[$i]);
          if (!isvalid_email_redirection($email_stripped)) {
              return ERROR_LOOP_EMAIL;
          }
 -        XDB::execute('REPLACE INTO emails (uid,email,flags) VALUES({?},{?},"active")', $this->uid, $email);
 +        XDB::execute('REPLACE INTO emails (uid,email,flags) VALUES({?},{?},"active")', $this->user->id(), $email);
          if ($logger = S::v('log', null)) { // may be absent --> step4.php
 -            S::logger()->log('email_add',$email.($this->uid!=S::v('uid') ? " (admin on {$this->uid})" : ""));
 +            S::logger()->log('email_add', $email . ($this->user->id() != S::v('uid') ? " (admin on {$this->user->login()})" : ""));
          }
          foreach ($this->emails as $mail) {
              if ($mail->email == $email_stripped) {
                  return SUCCESS;
              }
          }
-         $this->emails[] = new EmailRedirection($this->user, array($email, 'active', '', '0000-00-00', '0000-00-00', 0));
 -        $this->emails[] = new EmailRedirection($this->uid, array($email, 'active', '', 0, null, '0000-00-00', '0000-00-00', 0));
++        $this->emails[] = new EmailRedirection($this->user, array($email, 'active', '', 0, null, '0000-00-00', '0000-00-00', 0));
  
          // security stuff
 -        check_email($email, "Ajout d'une adresse surveillée aux redirections de " . $this->uid);
 +        check_email($email, "Ajout d'une adresse surveillée aux redirections de " . $this->user->login());
          check_redirect($this);
          return SUCCESS;
      }
      {
          XDB::execute("UPDATE  emails
                           SET  flags = 'disable'
 -                       WHERE  flags = 'active' AND uid = {?}", $this->uid);
 +                       WHERE  flags = 'active' AND uid = {?}", $this->user->id);
          foreach ($this->emails as &$mail) {
              if ($mail->active && $mail->has_disable()) {
                  $mail->disabled = true;
      {
          XDB::execute("UPDATE  emails
                           SET  flags = 'active'
 -                       WHERE  flags = 'disable' AND uid = {?}", $this->uid);
 +                       WHERE  flags = 'disable' AND uid = {?}", $this->user->id);
          foreach ($this->emails as &$mail) {
              if ($mail->disabled) {
                  $mail->active   = true;
  
      public function get_uid()
      {
 -        return $this->uid;
 +        return $this->user->id();
      }
  }
  
diff --combined include/userset.inc.php
@@@ -137,7 -137,7 +137,7 @@@ class ArraySet extends UserSe
      {
          $where = $this->getUids($users);
          if ($where) {
 -            $where = "a.alias IN ($where)";
 +            $where = "u.hruid IN ($where)";
          } else {
              $where = " 0 ";
          }
  
      private function getUids(array $users)
      {
 -        $users = get_users_forlife_list($users, true, '_silent_user_callback');
 +        $users = User::getBulkHruid($users, array('User', '_silent_user_callback'));
          if (is_null($users)) {
              return '';
          }
@@@ -178,7 -178,7 +178,7 @@@ class MinificheView extends MultipageVi
                  u.perms != 'pending' AS wasinscrit,
                  u.deces != 0 AS dcd, u.deces, u.matricule_ax,
                  FIND_IN_SET('femme', u.flags) AS sexe,
-                 e.entreprise, es.label AS secteur, ef.fonction_fr AS fonction,
+                 e.entreprise, e.web AS job_web, es.label AS secteur, ef.fonction_fr AS fonction,
                  IF(n.nat='',n.pays,n.nat) AS nat, n.a2 AS iso3166,
                  ad0.text AS app0text, ad0.url AS app0url, ai0.type AS app0type,
                  ad1.text AS app1text, ad1.url AS app1url, ai1.type AS app1type,
diff --combined modules/admin.php
@@@ -356,342 -356,330 +356,342 @@@ class AdminModule extends PLModul
          $page->changeTpl('admin/utilisateurs.tpl');
          $page->setTitle('Administration - Edit/Su/Log');
          require_once("emails.inc.php");
 -        require_once("user.func.inc.php");
  
          if (S::has('suid')) {
              $page->kill("Déjà en SUID !!!");
          }
  
 -        if (Env::has('user_id')) {
 -            $login = get_user_forlife(Env::i('user_id'));
 -            if (empty($login)) {
 -                $login = Env::i('user_id');
 -            }
 -        } elseif (Env::has('login')) {
 -            $login = get_user_forlife(Env::v('login'));
 +        // Loads the user identity using the environment.
 +        if ($login) {
 +            $user = User::get($login);
 +        } else if (Env::has('user_id')) {
 +            $user = User::get(Env::i('user_id'));
 +        } else if (Env::has('login')) {
 +            $user = User::get(Env::v('login'));
          }
  
 -        if(Env::has('logs_button') && $login) {
 -            pl_redirect("admin/logger?loguser=$login&year=".date('Y')."&month=".date('m'));
 +        if ($user) {
 +            $login = $user->login();
 +            $registered = ($user->forlifeEmail() != null);
 +        } else {
 +            return;
          }
  
 -        if (Env::has('ax_button') && $login) {
 -            pl_redirect("admin/synchro_ax/$login");
 +        // Handles specific requests (AX sync, su, ...).
 +        if(Env::has('logs_button') && $registered) {
 +            pl_redirect("admin/logger?loguser=$login&year=".date('Y')."&month=".date('m'));
          }
  
 -        if(Env::has('suid_button') && $login) {
 -            S::logger()->log("suid_start", "login by ".S::v('forlife'));
 -            $r = XDB::query("SELECT  id
 -                               FROM  aliases
 -                              WHERE  alias={?}", $login);
 -            if($uid = $r->fetchOneCell()) {
 -                if (!Platal::session()->startSUID($uid)) {
 -                    $page->trigError('Impossible d\'effectuer un SUID sur ' . $uid);
 -                } else {
 -                    $page->kill("coucou");
 -                    pl_redirect("");
 -                }
 -            }
 +        if (Env::has('ax_button') && $registered) {
 +            pl_redirect("admin/synchro_ax/" . $user->login());
          }
  
 -        if ($login) {
 -            if (is_numeric($login)) {
 -                $r = XDB::query("SELECT *, a.alias AS forlife,
 -                                        FIND_IN_SET('watch', u.flags) AS watch, FIND_IN_SET('femme', u.flags) AS sexe,
 -                                        (year(naissance) > promo - 15 or year(naissance) < promo - 25) AS naiss_err
 -                                   FROM auth_user_md5 AS u
 -                              LEFT JOIN aliases       AS a ON (a.id = u.user_id AND type= 'a_vie')
 -                                  WHERE u.user_id = {?}", $login);
 +        if(Env::has('suid_button') && $registered) {
 +            S::logger()->log("suid_start", "login on " . $user->login());
 +            if (!Platal::session()->startSUID($user->id())) {
 +                $page->trigError('Impossible d\'effectuer un SUID sur ' . $user->id());
              } else {
 -                $r  = XDB::query("SELECT  *, a.alias AS forlife,
 -                                          FIND_IN_SET('watch', u.flags) AS watch, FIND_IN_SET('femme', u.flags) AS sexe,
 -                                          (year(naissance) > promo - 15 or year(naissance) < promo - 25) AS naiss_err
 -                                    FROM  auth_user_md5 AS u
 -                              INNER JOIN  aliases       AS a ON ( a.id = u.user_id AND a.alias={?} AND type!='homonyme' )", $login);
 +                pl_redirect("");
              }
 -            $mr = $r->fetchOneAssoc();
 +        }
  
 -            // Checks the user has a forlife, as non-registered user can't have redirections.
 -            if ($mr['forlife']) {
 -                $redirect = new Redirect($mr['user_id']);
 -            }
 +        // Fetches user data.
 +        $userinfo_query = "SELECT  *, FIND_IN_SET('watch', flags) AS watch, FIND_IN_SET('femme', flags) AS sexe,
 +                                   (year(naissance) > promo - 15 or year(naissance) < promo - 25) AS naiss_err
 +                             FROM  auth_user_md5
 +                            WHERE  user_id = {?}";
 +        $mr = XDB::query($userinfo_query, $user->id())->fetchOneAssoc();
 +        $redirect = ($registered ? new Redirect($user) : null);
  
 -            // Check if there was a submission
 -            foreach($_POST as $key => $val) {
 -                S::assert_xsrf_token();
 +        // Processes admin requests, if any.
 +        foreach($_POST as $key => $val) {
 +            S::assert_xsrf_token();
  
 -                switch ($key) {
 -                    case "add_fwd":
 -                        $email = trim(Env::v('email'));
 -                        if (!isvalid_email_redirection($email)) {
 -                            $page->trigError("Email non valide: $email");
 -                        } else {
 -                            $redirect->add_email($email);
 -                            $page->trigSuccess("Ajout de $email effectué");
 -                        }
 -                        break;
 +            switch ($key) {
 +                // Email redirection actions.
 +                case "add_fwd":
 +                    $email = trim(Env::v('email'));
 +                    if (!isvalid_email_redirection($email)) {
 +                        $page->trigError("Email non valide: $email");
 +                    } else {
 +                        $redirect->add_email($email);
 +                        $page->trigSuccess("Ajout de $email effectué");
 +                    }
 +                    break;
  
 -                    case "del_fwd":
 -                        if (!empty($val)) {
 -                            $redirect->delete_email($val);
 -                        }
 -                        break;
 +                case "del_fwd":
 +                    if (!empty($val)) {
 +                        $redirect->delete_email($val);
 +                    }
 +                    break;
  
 -                    case "del_alias":
 -                        if (!empty($val)) {
 -                            XDB::execute("DELETE FROM aliases
 -                                                WHERE id={?} AND alias={?}
 -                                                      AND type!='a_vie' AND type!='homonyme'", $mr['user_id'], $val);
 -                            XDB::execute("UPDATE emails
 -                                             SET rewrite = ''
 -                                           WHERE uid = {?} AND rewrite LIKE CONCAT({?}, '@%')",
 -                                         $mr['user_id'], $val);
 -                            fix_bestalias($mr['user_id']);
 -                            $page->trigSuccess($val." a été supprimé");
 -                        }
 -                        break;
 -                    case "activate_fwd":
 -                        if (!empty($val)) {
 -                            $redirect->modify_one_email($val, true);
 -                        }
 -                        break;
 -                    case "deactivate_fwd":
 -                        if (!empty($val)) {
 -                            $redirect->modify_one_email($val, false);
 -                        }
 -                        break;
 -                    case "disable_fwd":
 -                        $redirect->disable();
 -                        break;
 -                    case "enable_fwd":
 -                        $redirect->enable();
 -                        break;
 -                    case "clean_fwd":
 -                        if (!empty($val)) {
 -                            $redirect->clean_errors($val);
 -                        }
 -                        break;
 -                    case "add_alias":
 -                        global $globals;
 -                        $alias = trim(Env::v('email'));
 -                        if (strpos($alias, '@') !== false) {
 -                            list($alias, $domain) = explode('@', $alias);
 +                case "activate_fwd":
 +                    if (!empty($val)) {
 +                        $redirect->modify_one_email($val, true);
 +                    }
 +                    break;
 +                case "deactivate_fwd":
 +                    if (!empty($val)) {
 +                        $redirect->modify_one_email($val, false);
 +                    }
 +                    break;
 +                case "disable_fwd":
 +                    $redirect->disable();
 +                    break;
 +                case "enable_fwd":
 +                    $redirect->enable();
 +                    break;
 +                case "clean_fwd":
 +                    if (!empty($val)) {
 +                        $redirect->clean_errors($val);
 +                    }
 +                    break;
 +
 +                // Alias actions.
 +                case "add_alias":
 +                    global $globals;
 +
 +                    // Splits new alias in user and fqdn.
 +                    $alias = trim(Env::v('email'));
 +                    if (strpos($alias, '@') !== false) {
 +                        list($alias, $domain) = explode('@', $alias);
 +                    } else {
 +                        $domain = $globals->mail->domain;
 +                    }
 +
 +                    // Checks for alias' user validity.
 +                    if (!preg_match('/[-a-z0-9\.]+/s', $alias)) {
 +                        $page->trigError("'$alias' n'est pas un alias valide");
 +                    }
 +
 +                    // Eventually adds the alias to the right domain.
 +                    if ($domain == $globals->mail->alias_dom || $domain == $globals->mail->alias_dom2) {
 +                        $req = new AliasReq($user, $alias, 'Admin request', false);
 +                        if ($req->commit()) {
 +                            $page->trigSuccess("Nouvel alias '$alias@$domain' attribué");
                          } else {
 -                            $domain = $globals->mail->domain;
 -                        }
 -                        if (!preg_match('/[-a-z0-9\.]+/s', $alias)) {
 -                            $page->trigError("'$alias' n'est pas un alias valide");
 +                            $page->trigError("Impossible d'ajouter l'alias '$alias@$domain', il est probablement déjà attribué");
                          }
 -                        if ($domain == $globals->mail->alias_dom || $domain == $globals->mail->alias_dom2) {
 -                            $req = new AliasReq($mr['user_id'], $alias, 'Admin request', false);
 -                            if ($req->commit()) {
 -                                $page->trigSuccess("Nouvel alias '$alias@$domain' attribué");
 -                            } else {
 -                                $page->trigError("Impossible d'ajouter l'alias '$alias@$domain', il est probablement déjà attribué");
 -                            }
 -                        } elseif ($domain == $globals->mail->domain || $domain == $globals->mail->domain2) {
 -                            if (XDB::execute("INSERT INTO  aliases (id,alias,type) VALUES  ({?}, {?}, 'alias')",
 -                                    $mr['user_id'], $alias)) {
 -                                $page->trigSuccess("Nouvel alias '$alias' ajouté");
 -                            } else {
 -                                $page->trigError("Impossible d'ajouter l'alias '$alias', il est probablement déjà attribué");
 -                            }
 +                    } elseif ($domain == $globals->mail->domain || $domain == $globals->mail->domain2) {
 +                        $res = XDB::execute("INSERT INTO aliases (id,alias,type) VALUES ({?}, {?}, 'alias')",
 +                                            $user->id(), $alias);
 +                        if ($res) {
 +                            $page->trigSuccess("Nouvel alias '$alias' ajouté");
                          } else {
 -                            $page->trigError("Le domaine '$domain' n'est pas valide");
 -                        }
 -                        break;
 -
 -                    case "best":
 -                        // 'bestalias' is the first bit of the set : 1
 -                        // 255 is the max for flags (8 sets max)
 -                        XDB::execute("UPDATE  aliases SET flags= flags & (255 - 1) WHERE id={?}", $mr['user_id']);
 -                        XDB::execute("UPDATE  aliases
 -                                                   SET  flags= flags | 1
 -                                                WHERE  id={?} AND alias={?}", $mr['user_id'], $val);
 -                        break;
 -
 -
 -                    // Editer un profil
 -                    case "u_edit":
 -                        require_once('secure_hash.inc.php');
 -                        $pass_encrypted = Env::v('newpass_clair') != "********" ? hash_encrypt(Env::v('newpass_clair')) : Env::v('passw');
 -                        $naiss    = Env::v('naissanceN');
 -                        $deces    = Env::v('decesN');
 -                        $perms    = Env::v('permsN');
 -                        $prenm    = Env::v('prenomN');
 -                        $nom      = Env::v('nomN');
 -                        $nomusage = Env::v('nomusageN');
 -                        $promo    = Env::i('promoN');
 -                        $sexe     = Env::v('sexeN');
 -                        $comm     = trim(Env::v('commentN'));
 -                        $watch    = Env::v('watchN');
 -                        $flags    = '';
 -                        if ($sexe) {
 -                            $flags = 'femme';
 -                        }
 -                        if ($watch) {
 -                            if ($flags) {
 -                                $flags .= ',';
 -                            }
 -                            $flags .= 'watch';
 -                        }
 -
 -                        if ($watch && !$comm) {
 -                            $page->trigError("Il est nécessaire de mettre un commentaire pour surveiller un compte");
 -                            break;
 +                            $page->trigError("Impossible d'ajouter l'alias '$alias', il est probablement déjà attribué");
                          }
 +                    } else {
 +                        $page->trigError("Le domaine '$domain' n'est pas valide");
 +                    }
 +                    break;
  
 -                        $watch = 'SELECT naissance, deces, password, perms, nom_usage,
 -                                         prenom, nom, flags, promo, comment
 -                                    FROM auth_user_md5
 -                                   WHERE user_id = ' . $mr['user_id'];
 -                        $res = XDB::query($watch);
 -                        $old_fields = $res->fetchOneAssoc();
 -                        $query = "UPDATE auth_user_md5 SET
 -                                         naissance = '$naiss',
 -                                         deces     = '$deces',
 -                                         password  = '$pass_encrypted',
 -                                         perms     = '$perms',
 -                                         prenom    = '".addslashes($prenm)."',
 -                                         nom       = '".addslashes($nom)."',
 -                                         nom_usage = '".addslashes($nomusage)."',
 -                                         flags     = '$flags',
 -                                         promo     = $promo,
 -                                         comment   = '".addslashes($comm)."'
 -                                   WHERE user_id = '{$mr['user_id']}'";
 -                        if ($perms == 'disabled' && $old_fields['perms'] != 'disabled') {
 -                            // A user has been banned ==> ensure his php session has been killed
 -                            // This solution is ugly and overkill, but, it should be efficient.
 -                            kill_sessions();
 -                        }
 -                        if (XDB::execute($query)) {
 -                            user_reindex($mr['user_id']);
 +                case "del_alias":
 +                    if (!empty($val)) {
 +                        XDB::execute("DELETE FROM  aliases
 +                                            WHERE  id = {?} AND alias = {?} AND
 +                                                   type NOT IN ('a_vie', 'homonyme')",
 +                                     $user->id(), $val);
 +                        XDB::execute("UPDATE  emails
 +                                         SET  rewrite = ''
 +                                       WHERE  uid = {?} AND rewrite LIKE CONCAT({?}, '@%')",
 +                                     $user->id(), $val);
 +                        fix_bestalias($user);
 +                        $page->trigSuccess("L'alias '$val' a été supprimé");
 +                    }
 +                    break;
  
 -                            $res = XDB::query($watch);
 -                            $new_fields = $res->fetchOneAssoc();
 +                case "best":
 +                    XDB::execute("UPDATE  aliases
 +                                     SET  flags = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', flags, ','), ',bestalias,', ','))
 +                                   WHERE  id = {?}", $user->id());
 +                    XDB::execute("UPDATE  aliases
 +                                     SET  flags = CONCAT_WS(',', IF(flags = '', NULL, flags), 'bestalias')
 +                                   WHERE  id = {?} AND alias = {?}", $user->id(), $val);
 +
 +                    // As having a non-null bestalias value is critical in
 +                    // plat/al's code, we do an a posteriori check on the
 +                    // validity of the bestalias.
 +                    fix_bestalias($user);
 +                    break;
  
 -                            $mailer = new PlMailer("admin/useredit.mail.tpl");
 -                            $mailer->assign("admin", S::v('forlife'));
 -                            $mailer->assign("user", $mr['forlife']);
 -                            $mailer->assign('old', $old_fields);
 -                            $mailer->assign('new', $new_fields);
 -                            $mailer->send();
 +                // Profile edition.
 +                case "u_edit":
 +                    // Loads new values from environment.
 +                    require_once('secure_hash.inc.php');
 +                    $pass_encrypted = Env::v('newpass_clair') != "********" ? hash_encrypt(Env::v('newpass_clair')) : Env::v('passw');
 +                    $naiss    = Env::v('naissanceN');
 +                    $deces    = Env::v('decesN');
 +                    $perms    = Env::v('permsN');
 +                    $prenom    = Env::v('prenomN');
 +                    $nom      = Env::v('nomN');
 +                    $nomusage = Env::v('nomusageN');
 +                    $promo    = Env::i('promoN');
 +                    $sexe     = Env::v('sexeN');
 +                    $comm     = trim(Env::v('commentN'));
 +                    $watch    = Env::v('watchN');
 +
 +                    $flags    = ($sexe ? 'femme' : '');
 +                    if ($watch) {
 +                        $flags .= ($flags ? ',watch' : 'watch');
 +                    }
 +                    if ($watch && !$comm) {
 +                        $page->trigError("Il est nécessaire de mettre un commentaire pour surveiller un compte");
 +                        break;
 +                    }
 +
 +                    // Fetches fields to watch for changes.
 +                    $watch_query = "SELECT  naissance, deces, password, perms, nom_usage,
 +                                           prenom, nom, flags, promo, comment
 +                                      FROM  auth_user_md5
 +                                     WHERE user_id = {?}";
 +                    $old_fields = XDB::query($watch_query, $user->id())->fetchOneAssoc();
 +
 +                    // If user was newly banned, we need to ensure her php session
 +                    // is killed. This hack is ugly (and largely overkill); it should
 +                    // however suits our needs.
 +                    if ($perms == 'disabled' && $old_fields['perms'] != 'disabled') {
 +                        kill_sessions();
 +                    }
 +
 +                    // Updates the user profile with the new values.
 +                    $res = XDB::execute("UPDATE  auth_user_md5
 +                                            SET  naissance = {?}, deces = {?}, password = {?},
 +                                                 perms = {?}, prenom = {?}, nom = {?}, nom_usage = {?},
 +                                                 flags = {?}, promo = {?}, comment = {?}
 +                                          WHERE  user_id = {?}",
 +                                        $naiss, $deces, $pass_encrypted,
 +                                        $perms, $prenom, $nom, $nomusage,
 +                                        $flags, $promo, $comm, $user->id());
 +                    if ($res) {
 +                        require_once("user.func.inc.php");
 +                        user_reindex($user->id());
 +                        $new_fields = XDB::query($watch_query, $user->id())->fetchOneAssoc();
  
 -                            // update number of subscribers (perms or deceased may have changed)
 -                            $globals->updateNbIns();
 +                        $mailer = new PlMailer("admin/useredit.mail.tpl");
 +                        $mailer->assign("admin", S::user()->login());
 +                        $mailer->assign("user", $user->login());
 +                        $mailer->assign('old', $old_fields);
 +                        $mailer->assign('new', $new_fields);
 +                        $mailer->send();
  
 -                            $page->trigSuccess("updaté correctement.");
 -                        }
 -                        if (Env::v('nomusageN') != $mr['nom_usage']) {
 -                            set_new_usage($mr['user_id'], Env::v('nomusageN'), make_username(Env::v('prenomN'), Env::v('nomusageN')));
 -                        }
 -                        if (Env::v('decesN') != $mr['deces']) {
 -                            require_once 'notifs.inc.php';
 -                            register_watch_op($mr['user_id'], WATCH_DEATH, $mr['deces']);
 -                            user_clear_all_subs($mr['user_id'], false);
 -                        }
 -                        $r = XDB::query("SELECT *, a.alias AS forlife,
 -                                                FIND_IN_SET('watch', u.flags) AS watch, FIND_IN_SET('femme', u.flags) AS sexe
 -                                           FROM auth_user_md5 AS u
 -                                      LEFT JOIN aliases       AS a ON (a.id = u.user_id AND type= 'a_vie')
 -                                          WHERE u.user_id = {?}", $mr['user_id']);
 -                        $mr = $r->fetchOneAssoc();
 -
 -                        // If GoogleApps is enabled, the user did choose to use synchronized passwords,
 -                        // and the password was changed, updates the Google Apps password as well.
 -                        if ($globals->mailstorage->googleapps_domain && Env::v('newpass_clair') != "********") {
 +                        $globals->updateNbIns();
 +                        $page->trigSuccess("Update was successful.");
 +                    } else {
 +                        $page->trigError("Update failed, please double check your values.");
 +                    }
 +
 +                    // Checks for changes, and updates other tables of plat/al.
 +                    if (Env::v('nomusageN') != $mr['nom_usage']) {
 +                        set_new_usage($user->id(), Env::v('nomusageN'), make_username(Env::v('prenomN'), Env::v('nomusageN')));
 +                    }
 +                    if (Env::v('decesN') != $mr['deces']) {
 +                        require_once 'notifs.inc.php';
 +                        register_watch_op($user->id(), WATCH_DEATH, $mr['deces']);
 +                        user_clear_all_subs($user->id(), false);
 +                    }
 +
 +                    // Eventually updates the Google Apps account.
 +                    if ($globals->mailstorage->googleapps_domain) {
 +                        // If the user did choose to use synchronized passwords,
 +                        // and the password was changed, updates the Google Apps
 +                        // password as well.
 +                        if (Env::v('newpass_clair') != "********") {
                              require_once 'googleapps.inc.php';
 -                            $account = new GoogleAppsAccount($mr['user_id'], $mr['forlife']);
 +                            $account = new GoogleAppsAccount($user);
                              if ($account->active() && $account->sync_password) {
                                  $account->set_password($pass_encrypted);
                              }
                          }
  
 -                        // If GoogleApps is enabled, and the user is now disabled, disables the Google Apps account as well.
 -                        if ($globals->mailstorage->googleapps_domain &&
 -                            $new_fields['perms'] == 'disabled' &&
 -                            $new_fields['perms'] != $old_fields['perms']) {
 +                        // If the update did disable the user account, disables
 +                        // the Google Apps account as well.
 +                        if ($new_fields['perms'] == 'disabled' && $new_fields['perms'] != $old_fields['perms']) {
                              require_once 'googleapps.inc.php';
 -                            $account = new GoogleAppsAccount($mr['user_id'], $mr['forlife']);
 +                            $account = new GoogleAppsAccount($user);
                              $account->suspend();
                          }
 -                        break;
 +                    }
  
 -                    // DELETE FROM auth_user_md5
 -                    case "u_kill":
 -                        user_clear_all_subs($mr['user_id']);
 -                        // update number of subscribers (perms or deceased may have changed)
 -                        $globals->updateNbIns();
 -                        $page->trigSuccess("'{$mr['user_id']}' a été désinscrit !");
 -                        $mailer = new PlMailer("admin/useredit.mail.tpl");
 -                        $mailer->assign("admin", S::v('forlife'));
 -                        $mailer->assign("user", $mr['forlife']);
 -                        $mailer->assign("deletion", true);
 -                        $mailer->send();
 -                        break;
  
 -                    case "b_edit":
 -                        XDB::execute("DELETE FROM forums.innd WHERE uid = {?}", $mr['user_id']);
 -                        if (Env::v('write_perm') != "" || Env::v('read_perm') != ""  || Env::v('commentaire') != "" ) {
 -                          XDB::execute("INSERT INTO forums.innd
 -                                                SET ipmin = '0',
 -                                                    ipmax = '4294967295',
 -                                                    write_perm = {?},
 -                                                    read_perm = {?},
 -                                                    comment = {?},
 -                                                    priority = '200',
 -                                                    uid = {?}",
 -                                       Env::v('write_perm'), Env::v('read_perm'), Env::v('comment'), $mr['user_id']);
 -                        }
 -                        break;
 -                }
 -            }
 +                    // Reloads the user profile, to ensure the latest version will
 +                    // be served to the administrator.
 +                    $mr = XDB::query($userinfo_query, $user->id())->fetchOneAssoc();
 +
 +                    break;
  
 -            $res = XDB::query("SELECT  start, host
 -                                 FROM  logger.sessions
 -                                WHERE  uid={?} AND suid=0
 -                             ORDER BY  start DESC
 -                                LIMIT  1", $mr['user_id']);
 -            list($lastlogin,$host) = $res->fetchOneRow();
 -            $page->assign('lastlogin', $lastlogin);
 -            $page->assign('host', $host);
 -
 -            $res = XDB::iterator("SELECT  alias
 -                                    FROM  virtual
 -                              INNER JOIN  virtual_redirect USING(vid)
 -                                   WHERE  type = 'user' AND redirect LIKE '" . $mr['forlife'] . "@%'");
 -            $page->assign('virtuals', $res);
 -
 -            $page->assign('aliases', XDB::iterator(
 -                        "SELECT  alias, type='a_vie' AS for_life,FIND_IN_SET('bestalias',flags) AS best,expire
 -                           FROM  aliases
 -                          WHERE  id = {?} AND type!='homonyme'
 -                       ORDER BY  type!= 'a_vie'", $mr["user_id"]));
 -            if ($mr['perms'] != 'pending' && isset($redirect)) {
 -                $page->assign('emails', $redirect->emails);
 +                // User re-registration.
 +                case "u_kill":
 +                    user_clear_all_subs($user->id());
 +                    $globals->updateNbIns();
 +                    $page->trigSuccess("'" . $user->id() . "' a été désinscrit !");
 +
 +                    $mailer = new PlMailer("admin/useredit.mail.tpl");
 +                    $mailer->assign("admin", S::user()->login());
 +                    $mailer->assign("user", $user->login());
 +                    $mailer->assign("deletion", true);
 +                    $mailer->send();
 +                    break;
 +
 +                // Forum ban update.
 +                case "b_edit":
 +                    XDB::execute("DELETE FROM forums.innd WHERE uid = {?}", $user->id());
 +                    if (Env::v('write_perm') != "" || Env::v('read_perm') != ""  || Env::v('commentaire') != "" ) {
 +                        XDB::execute("INSERT INTO  forums.innd
 +                                              SET  ipmin = '0', ipmax = '4294967295',
 +                                                   write_perm = {?}, read_perm = {?},
 +                                                   comment = {?}, priority = '200', uid = {?}",
 +                                     Env::v('write_perm'), Env::v('read_perm'), Env::v('comment'), $user->id());
 +                    }
 +                    break;
              }
 +        }
 +
 +        // Displays last login and last host information.
 +        $res = XDB::query("SELECT  start, host
 +                             FROM  logger.sessions
 +                            WHERE  uid = {?} AND suid = 0
 +                         ORDER BY  start DESC
 +                            LIMIT  1", $user->id());
 +        list($lastlogin,$host) = $res->fetchOneRow();
 +        $page->assign('lastlogin', $lastlogin);
 +        $page->assign('host', $host);
 +
 +        // Display active aliases.
 +        $page->assign('virtuals', XDB::iterator(
 +                "SELECT  alias
 +                   FROM  virtual
 +             INNER JOIN  virtual_redirect USING (vid)
 +                  WHERE  type = 'user' AND redirect LIKE CONCAT({?}, '@%')", $user->id()));
 +
 +        $page->assign('aliases', XDB::iterator(
 +                "SELECT  alias, type='a_vie' AS for_life,FIND_IN_SET('bestalias',flags) AS best,expire
 +                   FROM  aliases
 +                  WHERE  id = {?} AND type != 'homonyme'
 +               ORDER BY  type != 'a_vie'", $user->id()));
 +
 +        // Displays email redirection and the general profile.
 +        if ($registered && $redirect) {
 +            $page->assign('emails', $redirect->emails);
 +        }
  
 -            $page->assign('mr',$mr);
 +        $page->assign('mr', $mr);
 +        $page->assign('user', $user);
  
 -            // Bans forums
 -            $res = XDB::query("SELECT  write_perm, read_perm, comment
 -                                 FROM  forums.innd
 -                                WHERE  uid = {?}", $mr['user_id']);
 -            $bans = $res->fetchOneAssoc();
 -            $page->assign('bans', $bans);
 +        // Displays forum bans.
 +        $res = XDB::query("SELECT  write_perm, read_perm, comment
 +                             FROM  forums.innd
 +                            WHERE  uid = {?}", $user->id());
 +        $bans = $res->fetchOneAssoc();
 +        $page->assign('bans', $bans);
 +    }
 +
 +    function getHruid($line, $key)
 +    {
 +        var_dump($line);
 +        if (!isset($line['nom']) || !isset($line['prenom']) || !isset($line['promo'])) {
 +            return null;
          }
 +        return make_forlife($line['prenom'], $line['nom'], $line['promo']);
      }
  
      function getMatricule($line, $key)
          }
  
          $importer = new CSVImporter('auth_user_md5', 'matricule');
 -        $importer->registerFunction('matricule', 'matricle Ecole vers X.org', array($this, 'getMatricule'));
 +        $importer->registerFunction('matricule', 'matricule Ecole vers X.org', array($this, 'getMatricule'));
          switch ($action) {
            case 'add':
 -            $fields = array('nom', 'nom_ini', 'prenom', 'naissance_ini',
 +            $fields = array('hruid', 'nom', 'nom_ini', 'prenom', 'naissance_ini',
                              'prenom_ini', 'promo', 'promo_sortie', 'flags',
                              'matricule', 'matricule_ax', 'perms');
 +            $importer->forceValue('hruid', array($this, 'getHruid'));
              $importer->forceValue('promo', $promo);
              $importer->forceValue('promo_sortie', $promo + 3);
              break;
          $importer->apply($page, "admin/promo/$action/$promo", $fields);
      }
  
 -    function handler_homonyms(&$page, $op = 'list', $target = null) {
 +    function handler_homonyms(&$page, $op = 'list', $target = null)
 +    {
          $page->changeTpl('admin/homonymes.tpl');
          $page->setTitle('Administration - Homonymes');
          require_once("homonymes.inc.php");
          $page->assign('dead', $res);
      }
  
 -    function handler_synchro_ax(&$page, $user = null, $action = null) {
 +    function handler_synchro_ax(&$page, $login = null, $action = null) {
          $page->changeTpl('admin/synchro_ax.tpl');
          $page->setTitle('Administration - Synchro AX');
  
 +        // Checks for synchronization requirements.
          require_once('synchro_ax.inc.php');
 -
          if (is_ax_key_missing()) {
              $page->assign('no_private_key', true);
              $page->run();
          }
  
 -        require_once('user.func.inc.php');
 -
 -        if ($user)
 -            $login = get_user_forlife($user);
 -
 -        if (Env::has('user')) {
 -            $login = get_user_forlife(Env::v('user'));
 -            if ($login === false) {
 -                return;
 -            }
 +        // Determines user identity using environment.
 +        if ($login) {
 +            $user = User::get($login);
 +        } else if (Env::has('user')) {
 +            $user = User::get(Env::v('user'));
 +        } else if (Env::has('mat')) {
 +            $res = XDB::query("SELECT user_id FROM auth_user_md5 WHERE matricule = {?}", Env::i('mat'));
 +            $user = User::get($res->fetchOneCell());
 +        } else {
 +            return;
          }
  
 -        if (Env::has('mat')) {
 -            $res = XDB::query(
 -                    "SELECT  alias
 -                       FROM  aliases       AS a
 -                 INNER JOIN  auth_user_md5 AS u ON (a.id=u.user_id AND a.type='a_vie')
 -                      WHERE  matricule={?}", Env::i('mat'));
 -            $login = $res->fetchOneCell();
 +        // Finally synchronizes the AX and plat/al information.
 +        if ($action == 'import') {
 +            ax_synchronize($user->login(), S::v('uid'));
          }
  
 -        if ($login) {
 -            if ($action == 'import') {
 -                ax_synchronize($login, S::v('uid'));
 -            }
 -            // get details from user, but looking only info that can be seen by ax
 -            $user  = get_user_details($login, S::v('uid'), 'ax');
 -            $userax= get_user_ax($user['matricule_ax']);
 -            require_once 'profil.func.inc.php';
 -            $diff = diff_user_details($userax, $user, 'ax');
 -
 -            $page->assign('x', $user);
 -            $page->assign('diff', $diff);
 -        }
 +        require_once 'profil.func.inc.php';
 +        $userxorg = get_user_details($user->login(), S::v('uid'), 'ax');
 +        $userax = get_user_ax($userxorg['matricule_ax']);
 +        $diff = diff_user_details($userax, $userxorg, 'ax');
 +
 +        $page->assign('x', $userxorg);
 +        $page->assign('diff', $diff);
      }
  
      function handler_validate(&$page, $action = 'list', $id = null)
              S::assert_xsrf_token();
  
              $req = Validate::get_typed_request(Env::v('uid'), Env::v('type'), Env::v('stamp'));
-             $req->handle_formu();
+             if ($req) {
+                 $req->handle_formu();
+             } else {
+                 $page->trigWarning('La validation a déjà été effectuée.');
+             }
          }
  
          $r = XDB::iterator('SHOW COLUMNS FROM requests_answers');
diff --combined modules/email.php
@@@ -33,6 -33,9 +33,9 @@@ class EmailModule extends PLModul
              'emails/antispam/submit'  => $this->make_hook('submit', AUTH_COOKIE),
              'emails/test'     => $this->make_hook('test', AUTH_COOKIE, 'user', NO_AUTH),
  
+             'emails/rewrite/in' => $this->make_hook('rewrite_in', AUTH_PUBLIC),
+             'emails/rewrite/out' => $this->make_hook('rewrite_out', AUTH_PUBLIC),
              'emails/imap/in'  => $this->make_hook('imap_in', AUTH_PUBLIC),
  
              'admin/emails/duplicated' => $this->make_hook('duplicated', AUTH_MDP, 'admin'),
          $page->changeTpl('emails/index.tpl');
          $page->setTitle('Mes emails');
  
 -        $uid = S::v('uid');
 +        $user = S::user();
  
 +        // Apply the bestalias change request.
          if ($action == 'best' && $email) {
              if (!S::has_xsrf_token()) {
                  return PL_FORBIDDEN;
              }
  
 -            // bestalias is the first bit : 1
 -            // there will be maximum 8 bits in flags : 255
 -            XDB::execute("UPDATE  aliases SET flags=flags & (255 - 1) WHERE id={?}", $uid);
 -            XDB::execute("UPDATE  aliases SET flags=flags | 1 WHERE id={?} AND alias={?}",
 -                                   $uid, $email);
 +            XDB::execute("UPDATE  aliases
 +                             SET  flags = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', flags, ','), ',bestalias,', ','))
 +                           WHERE  id = {?}", $user->id());
 +            XDB::execute("UPDATE  aliases
 +                             SET  flags = CONCAT_WS(',', IF(flags = '', NULL, flags), 'bestalias')
 +                           WHERE  id = {?} AND alias = {?}", $user->id(), $email);
 +
 +            // As having a non-null bestalias value is critical in
 +            // plat/al's code, we do an a posteriori check on the
 +            // validity of the bestalias.
 +            fix_bestalias($user);
          }
  
 -        // on regarde si on a affaire à un homonyme
 +        // Fetch and display aliases.
          $sql = "SELECT  alias, (type='a_vie') AS a_vie,
                          (alias REGEXP '\\\\.[0-9]{2}$') AS cent_ans,
                          FIND_IN_SET('bestalias',flags) AS best, expire
                    FROM  aliases
                   WHERE  id = {?} AND type!='homonyme'
                ORDER BY  LENGTH(alias)";
 -        $page->assign('aliases', XDB::iterator($sql, $uid));
 +        $page->assign('aliases', XDB::iterator($sql, $user->id()));
  
 -        $homonyme = XDB::query("SELECT alias FROM aliases INNER JOIN homonymes ON (id = homonyme_id) WHERE user_id = {?} AND type = 'homonyme'", $uid);
 +        // Check for homonyms.
 +        $homonyme = XDB::query(
 +                "SELECT  alias
 +                   FROM  aliases
 +             INNER JOIN  homonymes ON (id = homonyme_id)
 +                  WHERE  user_id = {?} AND type = 'homonyme'", $user->id());
          $page->assign('homonyme', $homonyme->fetchOneCell());
  
 -        // Affichage des redirections de l'utilisateur.
 -        $redirect = new Redirect($uid);
 +        // Display active redirections.
 +        $redirect = new Redirect($user);
          $page->assign('mails', $redirect->active_emails());
  
 -        // on regarde si l'utilisateur a un alias et si oui on l'affiche !
 -        $forlife = S::v('forlife');
 +        // Display, when available, the @alias_dom email alias.
          $res = XDB::query(
                  "SELECT  alias
                     FROM  virtual          AS v
               INNER JOIN  virtual_redirect AS vr USING(vid)
                    WHERE  (redirect={?} OR redirect={?})
                           AND alias LIKE '%@{$globals->mail->alias_dom}'",
 -                $forlife.'@'.$globals->mail->domain, $forlife.'@'.$globals->mail->domain2);
 +                $user->forlifeEmail(),
 +                // TODO: remove this über-ugly hack. The issue is that you need
 +                // to remove all @m4x.org addresses in virtual_redirect first.
 +                $user->login() . '@' . $globals->mail->domain2);
          $page->assign('melix', $res->fetchOneCell());
      }
  
          $page->changeTpl('emails/alias.tpl');
          $page->setTitle('Alias melix.net');
  
 -        $uid     = S::v('uid');
 -        $forlife = S::v('forlife');
 -
 -        $page->assign('demande', AliasReq::get_request($uid));
 +        $user = S::user();
 +        $page->assign('demande', AliasReq::get_request($user->id()));
  
 +        // Remove the email alias.
          if ($action == 'delete' && $value) {
              S::assert_xsrf_token();
  
 -            //Suppression d'un alias
              XDB::execute(
 -                'DELETE virtual, virtual_redirect
 -                   FROM virtual
 -             INNER JOIN virtual_redirect USING (vid)
 -                  WHERE alias = {?} AND (redirect = {?} OR redirect = {?})', $value,
 -                $forlife.'@'.$globals->mail->domain, $forlife.'@'.$globals->mail->domain2);
 +                    "DELETE  virtual, virtual_redirect
 +                       FROM  virtual
 +                 INNER JOIN  virtual_redirect USING (vid)
 +                      WHERE  alias = {?} AND (redirect = {?} OR redirect = {?})",
 +                    $value, $user->forlifeEmail(),
 +                    // TODO: remove this über-ugly hack. The issue is that you need
 +                    // to remove all @m4x.org addresses in virtual_redirect first.
 +                    $user->login() . '@' . $globals->mail->domain2);
          }
  
 -        //Récupération des alias éventuellement existants
 +        // Fetch existing @alias_dom aliases.
          $res = XDB::query(
                  "SELECT  alias, emails_alias_pub
                     FROM  auth_user_quick, virtual
               INNER JOIN  virtual_redirect USING(vid)
 -                   WHERE ( redirect={?} OR redirect= {?} )
 +                  WHERE  (redirect = {?} OR redirect = {?})
                           AND alias LIKE '%@{$globals->mail->alias_dom}' AND user_id = {?}",
 -                $forlife.'@'.$globals->mail->domain,
 -                $forlife.'@'.$globals->mail->domain2, S::v('uid'));
 +                $user->forlifeEmail(),
 +                // TODO: remove this über-ugly hack. The issue is that you need
 +                // to remove all @m4x.org addresses in virtual_redirect first.
 +                $user->login() . '@' . $globals->mail->domain2, $user->id());
          list($alias, $visibility) = $res->fetchOneRow();
          $page->assign('actuel', $alias);
  
                  }
  
                  //Insertion de la demande dans la base, écrase les requêtes précédente
 -                $myalias = new AliasReq($uid, $alias, $raison, $public);
 +                $myalias = new AliasReq($user, $alias, $raison, $public);
                  $myalias->submit();
                  $page->assign('success',$alias);
                  return;
  
              if ($value == 'public') {
                  XDB::execute("UPDATE auth_user_quick SET emails_alias_pub = 'public'
 -                                         WHERE user_id = {?}", S::v('uid'));
 +                                         WHERE user_id = {?}", $user->id());
              } else {
                  XDB::execute("UPDATE auth_user_quick SET emails_alias_pub = 'private'
 -                                         WHERE user_id = {?}", S::v('uid'));
 +                                         WHERE user_id = {?}", $user->id());
              }
  
              $visibility = $value;
  
          $page->changeTpl('emails/redirect.tpl');
  
 -        $uid     = S::v('uid');
 -        $forlife = S::v('forlife');
 -
 -        $page->assign('eleve', S::i('promo') >= date("Y") - 5);
 +        $user = S::user();
 +        $page->assign_by_ref('user', $user);
 +        $page->assign('eleve', $user->promo() >= date("Y") - 5);
  
 -        $redirect = new Redirect(S::v('uid'));
 +        $redirect = new Redirect($user);
  
          // FS#703 : $_GET is urldecoded twice, hence
          // + (the data) => %2B (in the url) => + (first decoding) => ' ' (second decoding)
          // Since there can be no spaces in emails, we can fix this with :
          $email = str_replace(' ', '+', $email);
  
 +        // Apply email redirection change requests.
          if ($action == 'remove' && $email) {
              $retour = $redirect->delete_email($email);
              $page->assign('retour', $retour);
              }
          }
  
 +        // Fetch the @alias_dom email alias, if any.
          $res = XDB::query(
                  "SELECT  alias
                     FROM  virtual
               INNER JOIN  virtual_redirect USING(vid)
                    WHERE  (redirect={?} OR redirect={?})
                           AND alias LIKE '%@{$globals->mail->alias_dom}'",
 -                $forlife.'@'.$globals->mail->domain, $forlife.'@'.$globals->mail->domain2);
 +                $user->forlifeEmail(),
 +                // TODO: remove this über-ugly hack. The issue is that you need
 +                // to remove all @m4x.org addresses in virtual_redirect first.
 +                $user->login() . '@' . $globals->mail->domain2);
          $melix = $res->fetchOneCell();
          if ($melix) {
              list($melix) = explode('@', $melix);
              $page->assign('melix',$melix);
          }
  
 +        // Fetch existing email aliases.
          $res = XDB::query(
                  "SELECT  alias,expire
                     FROM  aliases
                    WHERE  id={?} AND (type='a_vie' OR type='alias')
 -               ORDER BY  !FIND_IN_SET('usage',flags), LENGTH(alias)", $uid);
 -
 +               ORDER BY  !FIND_IN_SET('usage',flags), LENGTH(alias)", $user->id());
          $page->assign('alias', $res->fetchAllAssoc());
 -        $page->assign('emails',$redirect->emails);
 +        $page->assign('emails', $redirect->emails);
  
 +        // Display GoogleApps acount information.
          require_once 'googleapps.inc.php';
 -        $page->assign('googleapps', GoogleAppsAccount::account_status($uid));
 +        $page->assign('googleapps', GoogleAppsAccount::account_status($user->id()));
      }
  
      function handler_antispam(&$page, $statut_filtre = null)
  
          $page->changeTpl('emails/antispam.tpl');
  
 -        $bogo = new Bogo(S::v('uid'));
 +        $bogo = new Bogo(S::user());
          if (isset($statut_filtre)) {
              $bogo->change($statut_filtre + 0);
          }
 -        $page->assign('filtre',$bogo->level());
 +        $page->assign('filtre', $bogo->level());
      }
  
      function handler_submit(&$page)
          if (Post::has('send_email')) {
              S::assert_xsrf_token();
  
 -            $upload = PlUpload::get($_FILES['mail'], S::v('forlife'), 'spam.submit', true);
 +            $upload = PlUpload::get($_FILES['mail'], S::user()->login(), 'spam.submit', true);
              if (!$upload) {
                  $page->trigError('Une erreur a été rencontrée lors du transfert du fichier');
                  return;
                  $page->trigError('Le fichier ne contient pas un email complet');
                  return;
              }
 +            $type = (Post::v('type') == 'spam' ? 'spam' : 'nonspam');
 +
              global $globals;
 -            $box    = Post::v('type') . '@' . $globals->mail->domain;
 +            $box    = $type . '@' . $globals->mail->domain;
              $mailer = new PlMailer();
              $mailer->addTo($box);
 -            $mailer->setFrom('"' . S::v('prenom') . ' ' . S::v('nom') . '" <web@' . $globals->mail->domain . '>');
 -            $mailer->setTxtBody(Post::v('type') . ' soumis par ' . S::v('forlife') . ' via le web');
 -            $mailer->addUploadAttachment($upload, Post::v('type') . '.mail');
 +            $mailer->setFrom('"' . S::user()->fullName() . '" <web@' . $globals->mail->domain . '>');
 +            $mailer->setTxtBody($type . ' soumis par ' . S::user()->login() . ' via le web');
 +            $mailer->addUploadAttachment($upload, $type . '.mail');
              $mailer->send();
              $page->trigSuccess('Le message a été transmis à ' . $box);
              $upload->clear();
  
      function handler_send(&$page)
      {
 -        global $globals;
          $page->changeTpl('emails/send.tpl');
          $page->addJsLink('ajax.js');
  
  
              $error = false;
              foreach ($_FILES as &$file) {
 -                if ($file['name'] && !PlUpload::get($file, S::v('forlife'), 'emails.send', false)) {
 +                if ($file['name'] && !PlUpload::get($file, S::user()->login(), 'emails.send', false)) {
                      $page->trigError(PlUpload::$lastError);
                      $error = true;
                      break;
  
                  if (empty($to) && empty($cc) && empty($to2) && empty($bcc) && empty($cc2)) {
                      $page->trigError("Indique au moins un destinataire.");
 -                    $page->assign('uploaded_f', PlUpload::listFilenames(S::v('forlife'), 'emails.send'));
 +                    $page->assign('uploaded_f', PlUpload::listFilenames(S::user()->login(), 'emails.send'));
                  } else {
                      $mymail = new PlMailer();
                      $mymail->setFrom($from);
                      if (!empty($bcc)) { $mymail->addBcc($bcc); }
                      if (!empty($to2)) { $mymail->addTo($to2); }
                      if (!empty($cc2)) { $mymail->addCc($cc2); }
 -                    $files =& PlUpload::listFiles(S::v('forlife'), 'emails.send');
 +                    $files =& PlUpload::listFiles(S::user()->login(), 'emails.send');
                      foreach ($files as $name=>&$upload) {
                          $mymail->addUploadAttachment($upload, $name);
                      }
                      }
                      if ($mymail->send()) {
                          $page->trigSuccess("Ton email a bien été envoyé.");
 -                        $_REQUEST = array('bcc' => S::v('bestalias').'@'.$globals->mail->domain);
 -                        PlUpload::clear(S::v('forlife'), 'emails.send');
 +                        $_REQUEST = array('bcc' => S::user()->bestEmail());
 +                        PlUpload::clear(S::user()->login(), 'emails.send');
                      } else {
                          $page->trigError("Erreur lors de l'envoi du courriel, réessaye.");
 -                        $page->assign('uploaded_f', PlUpload::listFilenames(S::v('forlife'), 'emails.send'));
 +                        $page->assign('uploaded_f', PlUpload::listFilenames(S::user()->login(), 'emails.send'));
                      }
                  }
              }
                                   FROM  email_send_save
                                  WHERE  uid = {?}", S::i('uid'));
              if ($res->numRows() == 0) {
 -                PlUpload::clear(S::v('forlife'), 'emails.send');
 -                $_REQUEST['bcc'] = S::v('bestalias').'@'.$globals->mail->domain;
 +                PlUpload::clear(S::user()->login(), 'emails.send');
 +                $_REQUEST['bcc'] = S::user()->bestEmail();
              } else {
                  $data = unserialize($res->fetchOneCell());
                  $_REQUEST = array_merge($_REQUEST, $data);
                   ORDER BY u.nom, u.prenom", S::v('uid'));
          $page->assign('contacts', $res->fetchAllAssoc());
          $page->assign('maxsize', ini_get('upload_max_filesize') . 'o');
 +        $page->assign('user', S::user());
      }
  
 -    function handler_test(&$page, $forlife = null)
 +    function handler_test(&$page, $hruid = null)
      {
 -        global $globals;
          require_once 'emails.inc.php';
  
          if (!S::has_xsrf_token()) {
              return PL_FORBIDDEN;
          }
 -        if (!S::has_perms() || !$forlife) {
 -            $forlife = S::v('bestalias');
 +
 +        // Retrieves the User object for the test email recipient.
 +        if (S::has_perms() && $hruid) {
 +            $user = User::getSilent($hruid);
 +        } else {
 +            $user = S::user();
 +        }
 +        if (!$user) {
 +            return PL_NOT_FOUND;
          }
  
 -        $res = XDB::query("SELECT  FIND_IN_SET('femme', u.flags), prenom, user_id
 -                             FROM  auth_user_md5 AS u
 -                       INNER JOIN  aliases AS a ON (a.id = u.user_id)
 -                            WHERE  a.alias = {?}", $forlife);
 -        list($sexe, $prenom, $uid) = $res->fetchOneRow();
 -        $redirect = new Redirect($uid);
 +        // Sends the test email.
 +        $redirect = new Redirect($user);
  
          $mailer = new PlMailer('emails/test.mail.tpl');
 -        $mailer->assign('email', $forlife . '@' . $globals->mail->domain);
 +        $mailer->assign('email', $user->bestEmail());
          $mailer->assign('redirects', $redirect->active_emails());
 -        $mailer->assign('sexe', $sexe);
 -        $mailer->assign('prenom', $prenom);
 -        $mailer->send();
 +        $mailer->assign('display_name', $user->displayName());
 +        $mailer->assign('sexe', $user->isFemale());
 +        $mailer->send($user->isEmailFormatHtml());
          exit;
      }
  
+     function handler_rewrite_in(&$page, $mail, $hash)
+     {
+         $page->changeTpl('emails/rewrite.tpl');
+         $page->assign('option', 'in');
+         if (empty($mail) || empty($hash)) {
+             return PL_NOT_FOUND;
+         }
+         $pos = strrpos($mail, '_');
+         if ($pos === false) {
+             return PL_NOT_FOUND;
+         }
+         $mail{$pos} = '@';
+         $res = XDB::query("SELECT  COUNT(*)
+                              FROM  emails
+                             WHERE  email = {?} AND hash = {?}",
+                           $mail, $hash);
+         $count = intval($res->fetchOneCell());
+         if ($count > 0) {
+             XDB::query("UPDATE  emails
+                            SET  allow_rewrite = true, hash = NULL
+                          WHERE  email = {?} AND hash = {?}",
+                          $mail, $hash);
+             $page->trigSuccess("Réécriture activée pour l'adresse " . $mail);
+             return;
+         }
+         return PL_NOT_FOUND;
+     }
+     function handler_rewrite_out(&$page, $mail, $hash)
+     {
+         $page->changeTpl('emails/rewrite.tpl');
+         $page->assign('option', 'out');
+         if (empty($mail) || empty($hash)) {
+             return PL_NOT_FOUND;
+         }
+         $pos = strrpos($mail, '_');
+         if ($pos === false) {
+             return PL_NOT_FOUND;
+         }
+         $mail{$pos} = '@';
+         $res = XDB::query("SELECT  COUNT(*)
+                              FROM  emails
+                             WHERE  email = {?} AND hash = {?}",
+                           $mail, $hash);
+         $count = intval($res->fetchOneCell());
+         if ($count > 0) {
+             global $globals;
+             $res = XDB::query("SELECT  e.email, e.rewrite, a.alias
+                                  FROM  emails AS e
+                            INNER JOIN  aliases AS a ON (a.id = e.uid AND a.type = 'a_vie')
+                                 WHERE  e.email = {?} AND e.hash = {?}",
+                               $mail, $hash);
+             XDB::query("UPDATE  emails
+                            SET  allow_rewrite = false, hash = NULL
+                          WHERE  email = {?} AND hash = {?}",
+                         $mail, $hash);
+             list($mail, $rewrite, $forlife) = $res->fetchOneRow();
+             $mail = new PlMailer();
+             $mail->setFrom("webmaster@" . $globals->mail->domain);
+             $mail->addTo("support@" .  $globals->mail->domain);
+             $mail->setSubject("Tentative de détournement de correspondance via le rewrite");
+             $mail->setTxtBody("$forlife a tenté un rewrite de $mail vers $rewrite. Cette demande a été rejetée via le web");
+             $mail->send();
+             $page->trigWarning("Un mail d'alerte a été envoyé à l'équipe de " . $globals->core->sitename);
+             return;
+         }
+         return PL_NOT_FOUND;
+     }
      function handler_imap_in(&$page, $hash = null, $login = null)
      {
          $page->changeTpl('emails/imap_register.tpl');
 -        $id = null;
 +        $user = null;
          if (!empty($hash) || !empty($login)) {
 -            $req = XDB::query("SELECT  u.prenom, FIND_IN_SET('femme', u.flags) AS sexe, a.id
 -                                 FROM  aliases AS a
 -                           INNER JOIN  newsletter_ins AS ni ON (a.id = ni.user_id)
 -                           INNER JOIN  auth_user_md5 AS u ON (u.user_id = a.id)
 -                                WHERE  a.alias = {?} AND ni.hash = {?}", $login, $hash);
 -            list($prenom, $sexe, $id) = $req->fetchOneRow();
 +            $user = User::getSilent($login);
 +            if ($user) {
 +                $req = XDB::query("SELECT 1 FROM newsletter_ins WHERE user_id = {?} AND hash = {?}", $user->id(), $hash);
 +                if ($req->numRows() == 0) {
 +                    $user = null;
 +                }
 +            }
          }
  
          require_once('emails.inc.php');
          $page->assign('ok', false);
 -        if (S::logged() && (is_null($id) || $id == S::i('uid'))) {
 -            $storage = new EmailStorage(S::i('uid'), 'imap');
 +        if (S::logged() && (is_null($user) || $user->id() == S::i('uid'))) {
 +            $storage = new EmailStorage(S::user(), 'imap');
              $storage->activate();
              $page->assign('ok', true);
              $page->assign('prenom', S::v('prenom'));
              $page->assign('sexe', S::v('femme'));
 -        } else if (!S::logged() && $id) {
 -            $storage = new EmailStorage($id, 'imap');
 +        } else if (!S::logged() && $user) {
 +            $storage = new EmailStorage($user, 'imap');
              $storage->activate();
              $page->assign('ok', true);
 -            $page->assign('prenom', $prenom);
 -            $page->assign('sexe', $sexe);
 +            $page->assign('prenom', $user->displayName());
 +            $page->assign('sexe', $user->isFemale());
          }
      }
  
  
              $email = valide_email($email);
              // vérifications d'usage
 -            $sel = XDB::query(
 -                    "SELECT  e.uid, a.alias
 -                       FROM  emails        AS e
 -                 INNER JOIN  aliases       AS a ON (e.uid = a.id AND type!='homonyme'
 -                                                    AND FIND_IN_SET('bestalias',a.flags))
 -                      WHERE  e.email={?}", $email);
 -
 -            if (list($uid, $dest) = $sel->fetchOneRow()) {
 +            $sel = XDB::query("SELECT uid FROM emails WHERE email = {?}", $email);
 +            if (($uid = $sel->fetchOneCell())) {
 +                $dest = User::getSilent($uid);
 +
                  // envoi du mail
                  $message = "Bonjour !
  
  Cet email a été généré automatiquement par le service de patte cassée de
 -Polytechnique.org car un autre utilisateur, ".S::v('prenom').' '.S::v('nom').",
 +Polytechnique.org car un autre utilisateur, " . S::user()->fullName() . ",
  nous a signalé qu'en t'envoyant un email, il avait reçu un message d'erreur
  indiquant que ton adresse de redirection $email
  ne fonctionnait plus !
@@@ -564,7 -613,7 +636,7 @@@ L'équipe d'administration <support@" 
  
                  $mail = new PlMailer();
                  $mail->setFrom('"Polytechnique.org" <support@' . $globals->mail->domain . '>');
 -                $mail->addTo("$dest@" . $globals->mail->domain);
 +                $mail->addTo($dest->bestEmail());
                  $mail->setSubject("Une de tes adresse de redirection Polytechnique.org ne marche plus !!");
                  $mail->setTxtBody($message);
                  $mail->send();
                  $sel = XDB::query(
                          "SELECT  e1.uid, e1.panne != 0 AS panne,
                                   (count(e2.uid) + IF(FIND_IN_SET('googleapps', u.mail_storage), 1, 0)) AS nb_mails,
 -                                 u.nom, u.prenom, u.promo, a.alias AS forlife
 +                                 u.nom, u.prenom, u.promo, u.hruid
                             FROM  emails as e1
                        LEFT JOIN  emails as e2 ON(e1.uid = e2.uid
                                                   AND FIND_IN_SET('active', e2.flags)
                                                   AND e1.email != e2.email)
                       INNER JOIN  auth_user_md5 as u ON(e1.uid = u.user_id)
 -                     INNER JOIN  aliases AS a ON (a.id = e1.uid AND a.type = 'a_vie')
                            WHERE  e1.email = {?}
                         GROUP BY  e1.uid", $email);
                  if ($x = $sel->fetchOneAssoc()) {
      {
          $page->changeTpl('emails/lost.tpl');
  
 -        $page->assign('lost_emails', XDB::iterator('
 -            SELECT  u.user_id, a.alias
 +        $page->assign('lost_emails', XDB::iterator("
 +            SELECT  u.user_id, u.hruid
                FROM  auth_user_md5 AS u
 -        INNER JOIN  aliases AS a ON (a.id = u.user_id AND a.type = "a_vie")
 -         LEFT JOIN  emails  AS e ON (u.user_id=e.uid AND FIND_IN_SET("active",e.flags))
 -             WHERE  e.uid IS NULL AND
 -                    FIND_IN_SET("googleapps", u.mail_storage) = 0 AND
 -                    u.deces = 0
 -          ORDER BY  u.promo DESC, u.nom, u.prenom'));
 +         LEFT JOIN  emails        AS e ON (u.user_id = e.uid AND FIND_IN_SET('active', e.flags))
 +             WHERE  e.uid IS NULL AND FIND_IN_SET('googleapps', u.mail_storage) = 0 AND
 +                    u.deces = 0 AND u.perms IN ('user', 'admin', 'disabled')
 +          ORDER BY  u.promo DESC, u.nom, u.prenom"));
      }
  }
  
diff --combined modules/xnetevents.php
@@@ -183,9 -183,18 +183,18 @@@ class XnetEventsModule extends PLModul
          $page->changeTpl('xnetevents/subscribe.tpl');
  
          $evt = get_event_detail($eid);
-         if (!$evt) {
+         if (is_null($evt)) {
              return PL_NOT_FOUND;
          }
+         if ($evt === false) {
+             global $globals, $platal;
+             $url = $globals->asso('sub_url');
+             if (empty($url)) {
+                 $url = $platal->ns . 'subscribe';
+             }
+             $page->kill('Cet événement est reservé aux membres du groupe ' . $globals->asso('nom') .
+                         '. Pour devenir membre, rends-toi sur la page de <a href="' . $url . '">demande d\'inscripton</a>.');
+         }
  
          if (!$evt['inscr_open']) {
              $page->kill('Les inscriptions pour cet événement sont closes');
              // request for a new payment
              if (Post::v('paiement_id') == -1 && $money_defaut >= 0) {
                  require_once 'validations.inc.php';
 -                $p = new PayReq(S::v('uid'),
 +                $p = new PayReq(S::user(),
                                  Post::v('intitule')." - ".$globals->asso('nom'),
                                  Post::v('site'), $money_defaut,
                                  Post::v('confirmation'), 0, 999,
@@@ -51,9 -51,12 +51,12 @@@ function get_event_detail($eid, $item_i
  
      $evt = $res->fetchOneAssoc();
  
-     if (!$evt || ($GLOBALS['IS_XNET_SITE'] && $evt['accept_nonmembre'] == 0 && !is_member() && !may_update())) {
+     if (!$evt) {
          return null;
      }
+     if ($GLOBALS['IS_XNET_SITE'] && $evt['accept_nonmembre'] == 0 && !is_member() && !may_update()) {
+         return false;
+     }
  
      // smart calculation of the total number
      if (!$item_id) {
@@@ -201,15 -204,17 +204,15 @@@ function get_event_participants(&$evt, 
  //  {{{ function subscribe_lists_event()
  function subscribe_lists_event($participate, $uid, $evt)
  {
 -    require_once('user.func.inc.php');
      global $globals;
      $page =& Platal::page();
  
      $participant_list = $evt['participant_list'];
      $absent_list      = $evt['absent_list'];
  
 -    $email = get_user_forlife($uid, '_silent_user_callback');
 -
 -    if ($email) {
 -        $email .= '@'.$globals->mail->domain;
 +    $user = User::getSilent($uid);
 +    if ($user) {
 +        $email = $user->forlifeEmail();
      } else {
          $res = XDB::query("SELECT email
                               FROM groupex.membres
diff --combined modules/xnetgrp.php
@@@ -137,10 -137,11 +137,10 @@@ class XnetGrpModule extends PLModul
                              Env::i('unread'), S::i('uid'));
                  pl_redirect("#art" . Env::i('unread'));
              }
 -            $arts = XDB::iterator("SELECT a.*, u.nom, u.prenom, u.promo, l.alias AS forlife,
 +            $arts = XDB::iterator("SELECT a.*, u.nom, u.prenom, u.promo, u.hruid,
                                            FIND_IN_SET('photo', a.flags) AS photo
                                       FROM groupex.announces AS a
                                 INNER JOIN auth_user_md5 AS u USING(user_id)
 -                               INNER JOIN aliases AS l ON (u.user_id = l.id AND l.type = 'a_vie')
                                  LEFT JOIN groupex.announces_read AS r ON (r.user_id = {?} AND r.announce_id = a.id)
                                      WHERE asso_id = {?} AND peremption >= CURRENT_DATE()
                                            AND (promo_min = 0 OR promo_min <= {?})
                                $platal->ns . "rss/rss.xml");
          } else {
              $page->setRssLink("Polytechnique.net :: {$globals->asso("nom")} :: News",
 -                              $platal->ns . 'rss/'.S::v('forlife') .'/'.S::v('core_rss_hash').'/rss.xml');
 +                              $platal->ns . 'rss/'.S::v('hruid') .'/'.S::v('core_rss_hash').'/rss.xml');
          }
  
          $page->assign('articles', $arts);
              if (Post::has('notif_unsub') && Post::i('notif_unsub') == 1) {
                  $flags->addFlag('notif_unsub');
              }
+             $site = trim(Post::v('site'));
+             if ($site && ($site != "http://")) {
+                 $scheme = parse_url($site, PHP_URL_SCHEME);
+                 if (!$scheme) {
+                     $site = "http://" . $site;
+                 }
+             } else {
+                 $site = "";
+             }
              if (S::has_perms()) {
                  if (Post::v('mail_domain') && (strstr(Post::v('mail_domain'), '.') === false)) {
                      $page->trigError("le domaine doit être un FQDN (aucune modif effectuée) !!!");
                        WHERE  id={?}",
                        Post::v('nom'), Post::v('diminutif'),
                        Post::v('cat'), Post::i('dom'),
-                       Post::v('descr'), Post::v('site'),
+                       Post::v('descr'), $site,
                        Post::v('mail'), Post::v('resp'),
                        Post::v('forum'), Post::v('mail_domain'),
                        Post::has('ax'), Post::v('pub'),
                               forum={?}, ax={?}, pub= {?}, sub_url={?},
                               unsub_url={?},flags={?}
                        WHERE  id={?}",
-                       Post::v('descr'), Post::v('site'),
+                       Post::v('descr'), $site,
                        Post::v('mail'), Post::v('resp'),
                        Post::v('forum'), Post::has('ax'),
                        Post::v('pub'),
              $this->load('mail.inc.php');
              set_time_limit(120);
              $tos = get_all_redirects($mbr,  $mls, $mmlist);
 -            $upload = PlUpload::get($_FILES['uploaded'], S::v('forlife'), 'xnet.emails', true);
 +            $upload = PlUpload::get($_FILES['uploaded'], S::user()->login(), 'xnet.emails', true);
              send_xnet_mails($from, $sujet, $body, Env::v('wiki'), $tos, Post::v('replyto'), $upload, @$_FILES['uploaded']['name']);
              if ($upload) {
                  $upload->rm();
                       $globals->asso('id'), $uid);
      }
  
 -    private function validSubscription($nom, $prenom, $sexe, $uid, $forlife)
 +    private function validSubscription(User &$user)
      {
          global $globals;
 -        $this->removeSubscriptionRequest($uid);
 +        $this->removeSubscriptionRequest($user->id());
          XDB::execute("INSERT INTO  groupex.membres (asso_id, uid)
                             VALUES  ({?}, {?})",
 -                     $globals->asso('id'), $uid);
 +                     $globals->asso('id'), $user->id());
          $mailer = new PlMailer();
 -        $mailer->addTo("$forlife@polytechnique.org");
 -        $mailer->setFrom('"' . S::v('prenom') . ' ' . S::v('nom')
 -                         . '" <' . S::v('forlife') . '@polytechnique.org>');
 +        $mailer->addTo($user->forlifeEmail());
 +        $mailer->setFrom('"' . S::user()->fullName() . '" <' . S::user()->forlifeEmail() . '>');
          $mailer->setSubject('[' . $globals->asso('nom') . '] Demande d\'inscription');
 -        $message = ($sexe ? 'Chère' : 'Cher') . " Camarade,\n"
 +        $message = ($user->isFemale() ? 'Chère' : 'Cher') . " Camarade,\n"
                   . "\n"
                   . "  Suite à ta demande d'adhésion à " . $globals->asso('nom') . ",\n"
                   . "j'ai le plaisir de t'annoncer que ton inscription a été validée !\n"
                   . "\n"
                   . "Bien cordialement,\n"
                   . "-- \n"
 -                 . S::s('prenom') . ' ' . S::s('nom') . '.';
 +                 . S::user()->fullName() . '.';
          $mailer->setTxtBody($message);
          $mailer->send();
      }
                              ."sur la page de présentation.");
  
          if (!is_null($u) && may_update()) {
 -            $page->assign('u', $u);
 -            $res = XDB::query("SELECT  u.nom, u.prenom, u.promo, u.user_id, FIND_IN_SET('femme', u.flags), s.reason
 -                                 FROM  auth_user_md5 AS u
 -                           INNER JOIN  aliases AS al ON (al.id = u.user_id AND al.type != 'liste')
 -                            LEFT JOIN  groupex.membres_sub_requests AS s ON (u.user_id = s.uid AND s.asso_id = {?})
 -                                WHERE  al.alias = {?}", $globals->asso('id'), $u);
 -
 -            if (list($nom, $prenom, $promo, $uid, $sexe, $reason) = $res->fetchOneRow()) {
 -                $res = XDB::query("SELECT  COUNT(*)
 -                                     FROM  groupex.membres AS m
 -                               INNER JOIN  aliases  AS a ON (m.uid = a.id AND a.type != 'homonyme')
 -                                    WHERE  a.alias = {?} AND m.asso_id = {?}",
 -                                  $u, $globals->asso('id'));
 -                $n   = $res->fetchOneCell();
 -                if ($n) {
 -                    $this->removeSubscriptionRequest($uid);
 -                    $page->kill("$prenom $nom est déjà membre du groupe !");
 -                    return;
 -                } elseif (Env::has('accept')) {
 -                    S::assert_xsrf_token();
 -
 -                    $this->validSubscription($nom, $prenom, $sexe, $uid, $u);
 -                    pl_redirect("member/$u");
 -                } elseif (Env::has('refuse')) {
 -                    S::assert_xsrf_token();
 -
 -                    $this->removeSubscriptionRequest($uid);
 -                    $mailer = new PlMailer();
 -                    $mailer->addTo("$u@polytechnique.org");
 -                    $mailer->setFrom('"'.S::v('prenom').' '.S::v('nom')
 -                                     .'" <'.S::v('forlife').'@polytechnique.org>');
 -                    $mailer->setSubject('['.$globals->asso('nom').'] Demande d\'inscription annulée');
 -                    $mailer->setTxtBody(Env::v('motif'));
 -                    $mailer->send();
 -                    $page->kill("La demande de $prenom $nom a bien été refusée.");
 -                } else {
 -                    $page->assign('show_form', true);
 -                    $page->assign('prenom', $prenom);
 -                    $page->assign('nom', $nom);
 -                    $page->assign('promo', $promo);
 -                    $page->assign('uid', $uid);
 -                    $page->assign('reason', $reason);
 -                }
 -                return;
 +            $user = User::get($u);
 +            if (!$user) {
 +                return PL_NOT_FOUND;
 +            } else {
 +                $page->assign('user', $user);
              }
 -            return PL_NOT_FOUND;
 +
 +            // Retrieves the subscription status, and the reason.
 +            $res = XDB::query("SELECT  reason
 +                                 FROM  groupex.membres_sub_requests
 +                                WHERE  asso_id = {?} AND uid = {?}",
 +                              $globals->asso('id'), $user->id());
 +            $reason = ($res->numRows() ? $res->fetchOneCell() : null);
 +
 +            $res = XDB::query("SELECT  COUNT(*)
 +                                 FROM  groupex.membres
 +                                WHERE  asso_id = {?} AND uid = {?}",
 +                              $globals->asso('id'), $user->id());
 +            $already_member = ($res->fetchOneCell() > 0);
 +
 +            // Handles the membership request.
 +            if ($already_member) {
 +                $this->removeSubscriptionRequest($user->id());
 +                $page->kill($user->fullName() . " est déjà membre du groupe !");
 +            } elseif (Env::has('accept')) {
 +                S::assert_xsrf_token();
 +
 +                $this->validSubscription($user);
 +                pl_redirect("member/" . $user->login());
 +            } elseif (Env::has('refuse')) {
 +                S::assert_xsrf_token();
 +
 +                $this->removeSubscriptionRequest($user->id());
 +                $mailer = new PlMailer();
 +                $mailer->addTo($user->forlifeEmail());
 +                $mailer->setFrom('"' . S::user()->fullName() . '" <' . S::user()->forlifeEmail() . '>');
 +                $mailer->setSubject('['.$globals->asso('nom').'] Demande d\'inscription annulée');
 +                $mailer->setTxtBody(Env::v('motif'));
 +                $mailer->send();
 +                $page->kill("La demande de {$user->fullName()} a bien été refusée.");
 +            } else {
 +                $page->assign('show_form', true);
 +                $page->assign('reason', $reason);
 +            }
 +            return;
          }
  
          if (is_member()) {
              $append = "\n"
                      . "-- \n"
                      . "Ce message a été envoyé suite à la demande d'inscription de\n"
 -                    . S::v('prenom').' '.S::v('nom').' (X'.S::v('promo').")\n"
 +                    . S::user()->fullName() . ' (X' . S::v('promo') . ")\n"
                      . "Via le site www.polytechnique.net. Tu peux choisir de valider ou\n"
                      . "de refuser sa demande d'inscription depuis la page :\n"
 -                    .
 -                    "http://www.polytechnique.net/".$globals->asso("diminutif")."/subscribe/"
 -                        .S::v('forlife')."\n"
 +                    . "http://www.polytechnique.net/" . $globals->asso("diminutif") . "/subscribe/" . S::user()->login() . "\n"
                      . "\n"
                      . "En cas de problème, contacter l'équipe de Polytechnique.org\n"
                      . "à l'adresse : support@polytechnique.org\n";
  
              $mailer = new PlMailer();
              $mailer->addTo($to);
 -            $mailer->setFrom('"'.S::v('prenom').' '.S::v('nom')
 -                             .'" <'.S::v('forlife').'@polytechnique.org>');
 +            $mailer->setFrom('"' . S::user()->fullName() . '" <' . S::user()->forlifeEmail() . '>');
              $mailer->setSubject('['.$globals->asso('nom').'] Demande d\'inscription');
              $mailer->setTxtBody(Post::v('message').$append);
              $mailer->send();
              $subs = Post::v('subs');
              if (is_array($subs)) {
                  $users = array();
 -                foreach ($subs as $forlife => $val) {
 +                foreach ($subs as $hruid => $val) {
                      if ($val == '1') {
 -                        $res = XDB::query("SELECT  IF(u.nom_usage != '', u.nom_usage, u.nom) AS u,
 -                                                   u.prenom, FIND_IN_SET('femme', u.flags) AS sexe,
 -                                                   u.user_id
 -                                             FROM  auth_user_md5 AS u
 -                                       INNER JOIN  aliases AS a ON (a.id = u.user_id)
 -                                            WHERE  a.alias = {?}", $forlife);
 -                        if ($res->numRows() == 1) {
 -                            list($nom, $prenom, $sexe, $uid) = $res->fetchOneRow();
 -                            $this->validSubscription($nom, $prenom, $sexe, $uid, $forlife);
 +                        $user = User::get($hruid);
 +                        if ($user) {
 +                            $this->validSubscription($user);
                          }
                      }
                  }
          }
  
          $it = XDB::iterator("SELECT  IF(u.nom_usage != '', u.nom_usage, u.nom) AS nom,
 -                                     u.prenom, u.promo, a.alias AS forlife, s.ts AS date
 +                                     u.prenom, u.promo, u.hruid, s.ts AS date
                                 FROM  groupex.membres_sub_requests AS s
                           INNER JOIN  auth_user_md5 AS u ON (s.uid = u.user_id)
 -                         INNER JOIN  aliases AS a ON (a.id = s.uid AND a.type = 'a_vie')
                                WHERE  asso_id = {?}
                             ORDER BY  nom, prenom",
                             $globals->asso('id'));
              S::assert_xsrf_token();
          }
  
 -        if (strpos($email, '@') === false) {
 -            $x = true;
 -        } else {
 -            list(,$fqdn) = explode('@', $email, 2);
 -            $fqdn = strtolower($fqdn);
 -            $x = ($fqdn == 'polytechnique.org' || $fqdn == 'melix.org' ||
 -                  $fqdn == 'm4x.org' || $fqdn == 'melix.net');
 -        }
 -        if ($x) {
 -            require_once 'user.func.inc.php';
 -            if ($forlife = get_user_forlife($email)) {
 -                XDB::execute(
 -                    'INSERT INTO  groupex.membres (uid,asso_id,origine)
 -                          SELECT  user_id,{?},"X"
 -                            FROM  auth_user_md5 AS u
 -                      INNER JOIN  aliases       AS a ON (u.user_id = a.id)
 -                           WHERE  a.alias={?}', $globals->asso('id'), $forlife);
 -                pl_redirect("member/$forlife");
 -            } else {
 -                $page->trigError($email." n'est pas un alias polytechnique.org valide.");
 +        if (!User::isForeignEmailAddress($email)) {
 +            $user = User::get($email);
 +            if ($user) {
 +                XDB::execute("REPLACE INTO  groupex.membres (uid, asso_id, origine)
 +                                    VALUES  ({?}, {?}, 'X')",
 +                             $user->id(), $globals->asso('id'));
 +                pl_redirect("member/" . $user->login());
              }
          } else {
              if (isvalid_email($email)) {
      function handler_unsubscribe(&$page)
      {
          $page->changeTpl('xnetgrp/membres-del.tpl');
 -        $user = get_infos(S::v('forlife'));
 +        $user = get_infos(S::user()->id());
          if (empty($user)) {
              return PL_NOT_FOUND;
          }
                  exit;
              }
          } else {
 -            $upload = new PlUpload(S::v('forlife'), 'xnetannounce');
 +            $upload = new PlUpload(S::user()->login(), 'xnetannounce');
              if ($upload->exists() && $upload->isType('image')) {
                  header('Content-Type: ' . $upload->contentType());
                  echo $upload->getContents();
              $art['nom']        = S::v('nom');
              $art['prenom']     = S::v('prenom');
              $art['promo']      = S::v('promo');
 -            $art['forlife']    = S::v('forlife');
 +            $art['hruid']      = S::user()->login();
              $art['peremption'] = Post::v('peremption');
              $art['public']     = Post::has('public');
              $art['xorg']       = Post::has('xorg');
              $art['nl']         = Post::has('nl');
              $art['event']      = Post::v('event');
 -            $upload     = new PlUpload(S::v('forlife'), 'xnetannounce');
 +            $upload     = new PlUpload(S::user()->login(), 'xnetannounce');
              $this->upload_image($page, $upload);
  
              $art['contact_html'] = $art['contacts'];
                  $post = null;/*
                  if ($globals->asso('forum')) {
                      require_once 'banana/forum.inc.php';
 -                    $banana = new ForumsBanana(S::v('forlife'));
 +                    $banana = new ForumsBanana(S::user());
                      $post = $banana->post($globals->asso('forum'), null,
                                            $art['titre'], MiniWiki::wikiToText($fulltext, false, 0, 80));
                  }*/
                  if ($art['xorg']) {
                      require_once('validations.inc.php');
                      $article = new EvtReq("[{$globals->asso('nom')}] " . $art['titre'], $fulltext,
 -                                    $art['promo_min'], $art['promo_max'], $art['peremption'], "", S::v('uid'),
 +                                    $art['promo_min'], $art['promo_max'], $art['peremption'], "", S::user(),
                                      $upload);
                      $article->submit();
                      $page->trigWarning("L'affichage sur la page d'accueil de Polytechnique.org est en attente de validation.");
                  }
                  if ($art['nl']) {
                      require_once('validations.inc.php');
 -                    $article = new NLReq(S::v('uid'), $globals->asso('nom') . " : " .$art['titre'],
 +                    $article = new NLReq(S::user(), $globals->asso('nom') . " : " .$art['titre'],
                                           $art['texte'], $art['contact_html']);
                      $article->submit();
                      $page->trigWarning("La parution dans la Lettre Mensuelle est en attente de validation.");
          }
  
          if (empty($art) && !is_null($aid)) {
 -            $res = XDB::query("SELECT a.*, u.nom, u.prenom, u.promo, l.alias AS forlife,
 +            $res = XDB::query("SELECT a.*, u.nom, u.prenom, u.promo, u.hruid,
                                        FIND_IN_SET('public', a.flags) AS public,
                                        FIND_IN_SET('photo', a.flags) AS photo
                                   FROM groupex.announces AS a
                             INNER JOIN auth_user_md5 AS u USING(user_id)
 -                           INNER JOIN aliases AS l ON (l.id = u.user_id AND l.type = 'a_vie')
                                  WHERE asso_id = {?} AND a.id = {?}",
                                $globals->asso('id'), $aid);
              if ($res->numRows()) {
@@@ -23,7 -23,7 +23,7 @@@
  {if $retour == $smarty.const.ERROR_INACTIVE_REDIRECTION}
    <p class="erreur">
    Tu ne peux pas avoir aucune adresse de redirection active, sinon ton adresse
 -  {$smarty.session.forlife}@{#globals.mail.domain#} ne fonctionnerait plus.
 +  {$user->forlifeEmail()} ne fonctionnerait plus.
    </p>
  {/if}
  {if $retour == $smarty.const.ERROR_INVALID_EMAIL}
@@@ -33,8 -33,8 +33,8 @@@
  {/if}
  {if $retour == $smarty.const.ERROR_LOOP_EMAIL}
    <p class="erreur">
 -  Erreur&nbsp;: {$smarty.session.forlife}@{#globals.mail.domain#} ne doit pas être renvoyé
 -  vers lui-même, ni vers son équivalent en {#globals.mail.domain2#} ni vers polytechnique.edu.
 +  Erreur&nbsp;: {$user->forlifeEmail()} ne doit pas être renvoyé vers lui-même,
 +  ni vers son équivalent en {#globals.mail.domain2#} ni vers polytechnique.edu.
    </p>
  {/if}
    <h1>
          Ajax.update_html(null, 'emails/redirect/' + (checked ? '' : 'in') + 'active/' + email, redirectUpdate);
      }
  
+     function rewriteUpdate(mail, allow, box)
+     {
+         return function() {
+                   if (!allow) {
+                       if (box.value != '') {
+                           alert("Un mail de validation vient d'être envoyer sur " + mail
+                                + ". La réécriture ne sera active que lorsque tu auras cliqué sur le lien indiqué dans ce mail.");
+                       }
+                   }
+                   redirectUpdate();
+               };
+     }
      {/literal}
    //]]></script>
    {test_email}
                   {if $e->active}checked="checked"{/if}
                   {if $smarty.foreach.redirect.total eq 1}disabled="disabled"{/if}
                   onchange="updateRedirect(this.checked, '{$e->email}')" /></td>
-         <td>
+         <td style="text-align: left">
            {if $e->has_rewrite()}
-           <select onchange="Ajax.update_html(null,'emails/redirect/rewrite/{$e->email}/'+this.value, redirectUpdate)">
+           <select onchange="Ajax.update_html(null,'emails/redirect/rewrite/{$e->email}/'+this.value, rewriteUpdate('{$e->email}', {$e->allow_rewrite|default:"0"}, this))">
              <option value=''>--- aucune ---</option>
              {assign var=dom1 value=#globals.mail.domain#}
              {assign var=dom2 value=#globals.mail.domain2#}
                value='{$a.alias}@{#globals.mail.domain2#}'>{$a.alias}@{#globals.mail.domain2#}</option>
              {/foreach}
            </select>
+           {if $e->rewrite neq '' && !$e->allow_rewrite}{icon name="error" title="en attente de validation"}{/if}
            {else}
            <em>pas de réécriture</em>
            {/if}
    L'X te fournit aussi une adresse à vie en <strong>«prenom.nom»@polytechnique.edu</strong> qui par défaut est
    une redirection vers «login»@poly.polytechnique.fr. <a href="https://www.mail.polytechnique.edu/">
    Tu peux modifier cette redirection</a> et la faire pointer vers ton adresse
 -  {$smarty.session.forlife}@{#globals.mail.domain#} (attention, cela demande de la concentration).
 +  {$user->forlifeEmail()} (attention, cela demande de la concentration).
  </p>
  <p>
    Si tu utilises le service POP de poly pour récupérer tes emails dans ton logiciel de courrier,
    l'équipe de Polytechnique.org te conseille de rediriger&nbsp;:
  </p>
  <ul>
 -  <li>«prenom.nom»@polytechnique.edu vers {$smarty.session.forlife}@{#globals.mail.domain#}&nbsp;;</li>
 -  <li>{$smarty.session.forlife}@{#globals.mail.domain#} vers «login»@poly.polytechnique.fr.</li>
 +  <li>«prenom.nom»@polytechnique.edu vers {$user->forlifeEmail()}&nbsp;;</li>
 +  <li>{$user->forlifeEmail()} vers «login»@poly.polytechnique.fr.</li>
  </ul>
  <p>
    Attention à ne pas faire une boucle quand tu manipules tes redirections ! Tes emails seraient
index 0000000,38dfc0c..c9f0a35
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,48 +1,48 @@@
 -{if $sexe}Chère{else}Cher{/if} {$prenom},
+ {**************************************************************************}
+ {*                                                                        *}
+ {*  Copyright (C) 2003-2008 Polytechnique.org                             *}
+ {*  http://opensource.polytechnique.org/                                  *}
+ {*                                                                        *}
+ {*  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               *}
+ {*                                                                        *}
+ {**************************************************************************}
+ {config_load file="mails.conf" section="rewrite_email"}
+ {if $mail_part eq 'head'}
+ {from full=#from#}
+ {to addr=$to}
+ {subject text="Validation de la demande de réécriture pour l'adresse `$mail->email`"}
+ {elseif $mail_part eq 'wiki'}
++{if $user->isFemale()}Chère{else}Cher{/if} {$user->displayName()},
+ Tu reçois cet email car une demande de réécriture vient d'être effectuée sur {$sitename} pour que les mails
+ l'adresse {$mail->email} soit automatiquement réécrite en {$mail->rewrite}.
+ Si tu es à l'origine de cette demande, clique sur le lien suivant pour activer la réécriture :
+ * {$baseurl}/emails/rewrite/in/{$mail->email|replace:'@':'_'}/{$mail->hash}
+ Si tu n'est pas à l'origine de cette demande, il peut s'agir d'une tentative de détournement de ta correspondance par un
+ camarade mal intentionné. Dans ce cas, clique sur le lien suivant pour avertir l'équipe de {$sitename} :
+ * {$baseurl}/emails/rewrite/out/{$mail->email|replace:'@':'_'}/{$mail->hash}
+ Merci encore de la confiance que tu portes à nos services.
+ -- \\
+ Très Cordialement,\\
+ L'Équipe de Polytechnique.org
+ {/if}
+ {* vim:set et sw=2 sts=2 sws=2: *}
    <div class="identity">
      {if $smarty.session.auth ge AUTH_COOKIE}
      <div class="photo">
 -      <img src="photo/{if $c.inscrit}{$c.forlife}{else}{make_forlife nom=$c.nom prenom=$c.prenom promo=$c.promo}{/if}"
 +      <img src="photo/{$c.hruid}"
             alt="{$c.prenom} {$c.nom}" />
      </div>
      {/if}
  
      <div class="nom">
        {if $c.sexe}&bull;{/if}
 -      {if !$c.dcd && ($c.inscrit || $smarty.session.auth eq AUTH_PUBLIC)}<a href="profile/{if $c.inscrit}{$c.forlife}{else}{make_forlife nom=$c.nom prenom=$c.prenom promo=$c.promo}{/if}" class="popup2">{/if}
 +      {if !$c.dcd && ($c.inscrit || $smarty.session.auth eq AUTH_PUBLIC)}<a href="profile/{$c.hruid}" class="popup2">{/if}
        {if $c.nom_usage}{$c.nom_usage} {$c.prenom}<br />({$c.nom}){else}{$c.nom} {$c.prenom}{/if}
        {if !$c.dcd && ($c.inscrit || $smarty.session.auth eq AUTH_PUBLIC)}</a>{/if}
      </div>
      *}{icon name=cross title="Retirer de la liste de mes surveillances"}</a>
          {/if}
        {elseif $c.wasinscrit}
 -    <a href="profile/{$c.forlife}" class="popup2">{*
 +    <a href="profile/{$c.hruid}" class="popup2">{*
      *}{icon name=user_suit title="Afficher la fiche"}</a>
          {if !$c.dcd}
 -    <a href="vcard/{$c.forlife}.vcf">{*
 +    <a href="vcard/{$c.hruid}.vcf">{*
      *}{icon name=vcard title="Afficher la carte de visite"}</a>
+     <a href="mailto:{$c.forlife}@{#globals.mail.domain#}">{*
+     *}{icon name=email title="Envoyer un email"}</a>
            {if $show_action eq ajouter}
 -    <a href="carnet/contacts?action={$show_action}&amp;user={$c.forlife}&amp;token={xsrf_token}">{*
 +    <a href="carnet/contacts?action={$show_action}&amp;user={$c.hruid}&amp;token={xsrf_token}">{*
      *}{icon name=add title="Ajouter à mes contacts"}</a>
            {else}
 -    <a href="carnet/contacts?action={$show_action}&amp;user={$c.forlife}&amp;token={xsrf_token}">{*
 +    <a href="carnet/contacts?action={$show_action}&amp;user={$c.hruid}&amp;token={xsrf_token}">{*
      *}{icon name=cross title="Retirer de mes contacts"}</a>
            {/if}
          {/if}
      {if hasPerm('admin')}
      <div>
        [{if !$c.wasinscrit && !$c.dcd}
 -      <a href="marketing/private/{$c.user_id}">{*
 +      <a href="marketing/private/{$c.hruid}">{*
          *}{icon name=email title="marketter user"}</a>
        {/if}
 -      <a href="admin/user/{if $c.wasinscrit}{$c.forlife}{else}{$c.user_id}{/if}">{*
 +      <a href="admin/user/{$c.hruid}">{*
        *}{icon name=wrench title="administrer user"}</a>
        <a href="http://www.polytechniciens.com/?page=AX_FICHE_ANCIEN&amp;anc_id={$c.matricule_ax}">{*
        *}{icon name=user_gray title="fiche AX"}</a>]
        <tr>
          <td class="lt">Profession&nbsp;:</td>
          <td class="rt">
-           {$c.entreprise} {if $c.secteur}({$c.secteur}){/if}
-           {if $c.fonction}<br />{$c.fonction}{/if}
+           {if $c.job_web}<a href="{$c.job_web}">{$c.entreprise}</a>{else}{$c.entreprise}{/if}
+           {if $c.secteur}({$c.secteur}){/if} {if $c.fonction}<br />{$c.fonction}{/if}
          </td>
        </tr>
        {/if}
          <td class="smaller" colspan="2">
            {if !$c.wasinscrit}
            Ce{if $c.sexe}tte{/if} camarade n'est pas inscrit{if $c.sexe}e{/if}.
 -          <a href="marketing/public/{$c.user_id}" class='popup'>Si tu connais son adresse email,
 +          <a href="marketing/public/{$c.hruid}" class='popup'>Si tu connais son adresse email,
            <strong>n'hésite pas à nous la transmettre !</a>
            {elseif !$c.actif}
            Ce{if $c.sexe}tte{/if} camarade n'a plus d'adresse de redirection valide.
 -          <a href="marketing/broken/{$c.forlife}">
 +          <a href="marketing/broken/{$c.hruid}">
              Si tu en connais une, <strong>n'hésite pas à nous la transmettre</strong>.
            </a>
            {/if}