================================================================================
-VERSION 0.9.16 XX XX 2008
+VERSION 0.9.17 XX XX 2008
+
+
+================================================================================
+VERSION 0.9.16 31 03 2008
New:
* Emails:
- Imap mail storage can be activated/deactivated from interface -VZA
+ - Mail storage backends are now integrated with redirections -VZA
* Lists:
- Unsure mails are moderated -FRU
Bug/Wish:
+ * Carnet:
+ - #734: Fix notification emails and carnet for female users -VZA
+
* Emails:
- #726: Don't send the email if an attachment can't be downloaded -FRU
- #750: Fix email list in test email -FRU
- #802: Fix upload content type checking on some buggy PHP -FRU
+ - #803: Prevents UI from allowing 'last active alias deletion' -Car
* Lists:
- #793: Show broken members on ML -FRU
- #728: Update CSV -FRU
- #743: Don't show a warning when subscriber has no forlife -FRU
- #730: XnetEvents are not synchronized with aliases -VZA
+ - #772: Indicate there are members-only events for non-members -JAC
* XnetGrp:
- #732: Adapt subscription text to sex -FRU
- #735: Encoding of list description in member edition form -FRU
- #740: Can add a picture in the announces -FRU
+ - #799: Improve asked inscription interface -JAC
From 0.9.15 branch:
* CAT: Florian El Ahdab (LeChat) <florian.el-ahdab@m4x.org>
* FAL: Raphaël Marichez (Falco) <raphael.marichez@m4x.org>
* FRU: Florent Bruneau (Fruneau) <florent.bruneau@m4x.org>
+ * JAC: Stéphane Jacob (jacou) <stephane.jacob@m4x.org>
* JS : Jean Sébastien Bedo <jean-sebastien.bedo@m4x.org>
* MC : Pierre Habouzit (MadCoder) <pierre.habouzit@m4x.org>
* mYk: Aymeric Augustin (mYk) <aymeric.augustin@m4x.org>
## core
##
-core: spool/templates_c spool/mails_c include/globals.inc.php configs/platal.cron htdocs/.htaccess spool/conf
+core: spool/templates_c spool/mails_c include/globals.inc.php configs/platal.cron htdocs/.htaccess spool/conf spool/tmp
-spool/templates_c spool/mails_c spool/uploads spool/conf spool/uploads/temp:
+spool/templates_c spool/mails_c spool/uploads spool/conf spool/tmp:
mkdir -p $@
chmod o+w $@
-spool/uploads/temp/.htaccess: spool/uploads/temp Makefile
- echo "Order deny,allow" > $@
- echo "Deny from all" >> $@
-
htdocs/.htaccess: htdocs/.htaccess.in Makefile
@REWRITE_BASE="/~$$(id -un)"; \
test "$$REWRITE_BASE" = "/~web" && REWRITE_BASE="/"; \
build-wiki: $(WIKI_NEEDS) | get-wiki
-htdocs/uploads: spool/uploads/temp/.htaccess
+htdocs/uploads:
cd htdocs && ln -sf ../spool/uploads
htdocs/wiki:
check("select uid from adresses where pub != 'private' and pub !='ax' and pub != 'public'", "Utiliseur n'ayant pas de flag de publicite pour une adresse");
check("select uid from tels where tel_pub != 'private' and tel_pub !='ax' and tel_pub != 'public'", "Utiliseur n'ayant pas de flag de publicite pour un numero de telephone");
-/* validite de adresses */
-check("select uid, count(adrid) from adresses group by uid having count(adrid) > 7", "Utilisateurs ayant trop d'adresses");
-
-/* Validite des tables de langues, competences, mentoring*/
-check("select uid, count(lid) from langues_ins group by uid having count(lid) > 10","Utilisateurs ayant trop de langues");
-check("select uid, count(cid) from competences_ins group by uid having count(cid) > 20","Utilisateurs ayant trop de competences");
-
/* validite de aliases */
check("SELECT a.*
FROM aliases AS a
WHERE matricule_ax != '0'
GROUP BY matricule_ax
having c > 1", "à chaque personne de l'annuaire de l'AX (identification_ax) doit correspondre AU PLUS UNE personne de notre annuaire (auth_user_md5) -> si ce n'est pas le cas il faut regarder en manuel ce qui ne va pas !");
+
+/* verifie qu'il n'y a pas d'utilisateurs ayant un compte Google Apps désactivé et une redirection encore active vers Google Apps */
+check("SELECT a.alias, g.g_status, u.mail_storage
+ FROM auth_user_md5 AS u
+ INNER JOIN aliases AS a ON (a.id = u.user_id AND a.type = 'a_vie')
+ INNER JOIN gapps_accounts AS g ON (g.l_userid = u.user_id)
+ WHERE FIND_IN_SET('googleapps', u.mail_storage) > 0 AND g.g_status != 'active'",
+ "utilisateurs ayant une redirection vers Google Apps alors que leur compte GApps n'est pas actif");
+
// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
?>
--- /dev/null
+#!/bin/sh
+
+find /var/lib/php5 -maxdepth 1 -name 'sess_*' -type f -delete
}
$val = call_user_func_array($hook['hook'], $args);
- if ($val & PL_DO_AUTH) {
+ if ($val == PL_DO_AUTH) {
// The handler need a better auth with the current args
if (!call_user_func(array($globals->session, 'doAuth'))) {
$this->force_login($page);
private function makeFilename($file_id)
{
global $globals;
- $filename = $globals->spoolroot . '/spool/uploads/temp/';
+ $filename = $globals->spoolroot . '/spool/tmp/';
if (!file_exists($filename)) {
if (!mkdir($filename)) {
trigger_error('can\'t create upload directory: ' . $filename, E_USER_ERROR);
static public function listRawFiles($forlife = '*', $category = '*', $uniq = false, $basename = false)
{
global $globals;
- $filename = $globals->spoolroot . '/spool/uploads/temp/';
+ $filename = $globals->spoolroot . '/spool/tmp/';
$filename .= $forlife . '--' . $category;
if (!$uniq) {
$filename .= '--*';
--- /dev/null
+/activity-monthly.png
+/activity-yearly.png
{
var val = document.forms.prof_annu.countries_sel.value;
var show = true;
- if (val == '') {
+ if (val == '' || val == '00') {
show = false;
}
if (document.getElementById('countries_' + val) != null) {
var val = cb.value;
var text = cb.options[cb.selectedIndex].text;
var html = '<div id="countries_' + val + '" style="clear: both; margin-bottom: 0.7em">'
- + ' <div style="float: left; width: 50%">' + text + '</div>'
- + ' <input type="hidden" name="countries[' + val + ']" value="' + text + '" />'
- + ' <a href="javascript:removeCountry(\'' + val + '\')">'
+ + ' <a href="javascript:removeCountry(\'' + val + '\')" style="display: block; float:right">'
+ ' <img src="images/icons/cross.gif" alt="" title="Supprimer ce pays" />'
+ ' </a>'
+ + ' <div style="float: left; width: 50%">' + text + '</div>'
+ + ' <input type="hidden" name="countries[' + val + ']" value="' + text + '" />'
+ '</div>';
$('#countries').append(html);
updateCountry();
var secteur = document.forms.prof_annu.secteur_sel.value;
if (secteur == '') {
secteur = '-1';
+ document.getElementById('ss_secteur_sel').innerHTML = '';
+ return;
}
$.get(platal_baseurl + 'profile/ajax/secteur/-1/' + secteur,
function(data) {
}
}
+function disableGoodiesPopups() {
+ __goodies_active = false;
+}
+
+var __goodies_active = true;
var __goodies_ical_sites = [
{'url_prefix': '',
'img': 'images/icons/calendar_view_day.gif',
function __goodies_popup(node, sites, default_title) {
var mouseover_cb = function() {
- var rss_text = __goodies_popupText(node.href, sites);
- var rss_title = (node.title ? node.title : default_title);
- return overlib(rss_text, CAPTION, rss_title, CLOSETEXT, 'Fermer', DELAY, 800, STICKY, WIDTH, 150);
+ if (__goodies_active) {
+ var rss_text = __goodies_popupText(node.href, sites);
+ var rss_title = (node.title ? node.title : default_title);
+ return overlib(rss_text, CAPTION, rss_title, CLOSETEXT, 'Fermer', DELAY, 800, STICKY, WIDTH, 150);
+ }
}
var mouseout_cb = function() {
nd();
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)
{
- $res = XDB::query("SELECT COUNT(*) FROM aliases WHERE id={?} AND FIND_IN_SET('bestalias',flags) AND type!='homonyme'", $uid);
- if ($n = $res->fetchOneCell()) {
+ $res = XDB::query("SELECT COUNT(*)
+ FROM aliases
+ WHERE id = {?} AND FIND_IN_SET('bestalias', flags) AND type != 'homonyme'",
+ $uid);
+ if ($res->fetchOneCell()) {
return;
}
+
XDB::execute("UPDATE aliases
SET flags=CONCAT(flags,',','bestalias')
WHERE id={?} AND type!='homonyme'
}
// function valide_email() {{{1
-
+// Returns a cleaned-up version of the @p email string. It removes garbage
+// characters, and determines the canonical form (without _ and +) for
+// Polytechnique.org email addresses.
function valide_email($str)
{
global $globals;
}
// class Bogo {{{1
-
+// The Bogo class represents a spam filtering level in plat/al architecture.
class Bogo
{
// properties {{{2
+ private $uid;
private $state;
private $_states = Array('let_spams', 'tag_spams', 'tag_and_drop_spams', 'drop_spams');
if (!$uid) {
return;
}
+
+ $this->uid = $uid;
$res = XDB::query('SELECT email FROM emails WHERE uid={?} AND flags="filter"', $uid);
if ($res->numRows()) {
$this->state = $res->fetchOneCell();
// public function change() {{{2
- public function change($uid, $state)
+ 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, $uid);
+ $this->state, $this->uid);
}
// pubic function level() {{{2
}
// class Email {{{1
-
-class Email
+// Represents an "email address" used as final recipient for plat/al-managed
+// addresses; it can be subclasses a Redirection emails (third-party) or as
+// Storage emails (Polytechnique.org).
+abstract class Email
{
- // properties {{{2
+ protected $uid;
+ // Basic email properties; $sufficient indicates if the email can be used as
+ // an unique redirection; $email contains the delivery email address.
+ public $type;
+ public $sufficient;
public $email;
+ public $display_email;
+
+ // Redirection status properties.
public $active;
public $broken;
public $disabled;
public $rewrite;
+
+ // Redirection bounces stats.
public $panne;
public $last;
public $panne_level;
+ // Activates the email address as a redirection.
+ public abstract function activate();
+
+ // Deactivates the email address as a redirection.
+ public abstract function deactivate();
+
+ // Sets the rewrite rule for the given address.
+ public abstract function set_rewrite($rewrite);
+
+ // Resets the error counts associated with the redirection.
+ public abstract function clean_errors();
+
+ // Email backend capabilities ('rewrite' refers to From: rewrite for mails
+ // forwarded by Polytechnique.org's MXs; 'removable' indicates if the email
+ // can be definitively removed; 'disable' indicates if the email has a third
+ // status 'disabled' in addition to 'active' and 'inactive').
+ public abstract function has_rewrite();
+ public abstract function is_removable();
+ public abstract function has_disable();
+}
+
+// class EmailRedirection {{{1
+// Implementation of Email for third-party redirection (redirection of emails to
+// external user-supplied addresses).
+class EmailRedirection extends Email
+{
// constructor {{{2
- public function __construct($row)
+ public function __construct($uid, $row)
{
+ $this->uid = $uid;
+ $this->sufficient = true;
+
list($this->email, $flags, $this->rewrite, $this->panne, $this->last, $this->panne_level) = $row;
+ $this->display_email = $this->email;
$this->active = ($flags == 'active');
$this->broken = ($flags == 'panne');
$this->disabled = ($flags == 'disable');
// public function activate() {{{2
- public function activate($uid)
+ public function activate()
{
if (!$this->active) {
XDB::execute("UPDATE emails
SET panne_level = IF(flags = 'panne', panne_level - 1, panne_level),
flags = 'active'
- WHERE uid={?} AND email={?}", $uid, $this->email);
- $_SESSION['log']->log("email_on", $this->email.($uid!=S::v('uid') ? "(admin on $uid)" : ""));
+ WHERE uid={?} AND email={?}", $this->uid, $this->email);
+ $_SESSION['log']->log("email_on", $this->email.($this->uid!=S::v('uid') ? "(admin on {$this->uid})" : ""));
$this->active = true;
$this->broken = false;
}
// public function deactivate() {{{2
- public function deactivate($uid)
+ public function deactivate()
{
if ($this->active) {
XDB::execute("UPDATE emails SET flags =''
- WHERE uid={?} AND email={?}", $uid, $this->email);
- $_SESSION['log']->log("email_off",$this->email.($uid!=S::v('uid') ? "(admin on $uid)" : "") );
+ WHERE uid={?} AND email={?}", $this->uid, $this->email);
+ $_SESSION['log']->log("email_off",$this->email.($this->uid != S::v('uid') ? "(admin on {$this->uid})" : "") );
$this->active = false;
}
}
- // public function rewrite() {{{2
+ // public function set_rewrite() {{{2
- public function rewrite($rew, $uid)
+ public function set_rewrite($rewrite)
{
- if ($this->rewrite == $rew) {
+ if ($this->rewrite == $rewrite) {
return;
}
- if (!$rew || !isvalid_email($rew)) {
- $rew = '';
+ if (!$rewrite || !isvalid_email($rewrite)) {
+ $rewrite = '';
}
- XDB::execute('UPDATE emails SET rewrite={?} WHERE uid={?} AND email={?}', $rew, $uid, $this->email);
- $this->rewrite = $rew;
+ XDB::execute('UPDATE emails SET rewrite={?} WHERE uid={?} AND email={?}', $rewrite, $this->uid, $this->email);
+ $this->rewrite = $rewrite;
return;
}
- // function cleanErrors() {{{2
+ // public function clean_errors() {{{2
- public function cleanErrors($uid)
+ public function clean_errors()
{
if (!S::has_perms()) {
return false;
return XDB::execute("UPDATE emails
SET panne_level = 0, panne = 0, last = 0
WHERE uid = {?} AND email = {?}",
- $uid, $this->email);
+ $this->uid, $this->email);
+ }
+
+ // public function has_rewrite() {{{2
+
+ public function has_rewrite()
+ {
+ return true;
+ }
+
+ // public function is_removable() {{{2
+
+ public function is_removable()
+ {
+ return true;
+ }
+
+ // public function has_disable() {{{2
+
+ public function has_disable()
+ {
+ return true;
}
}
-// class Redirect {{{1
+// class EmailStorage {{{1
+// Implementation of Email for email storage backends from Polytechnique.org.
+class EmailStorage extends Email
+{
+ // Shortname to realname mapping for known mail storage backends.
+ private $display_names = array(
+ 'imap' => 'Accès de secours aux emails (IMAP)',
+ 'googleapps' => 'Compte GMail / Google Apps',
+ );
+
+ // Retrieves the current list of actives storages.
+ private function get_storages()
+ {
+ $res = XDB::query("SELECT mail_storage
+ FROM auth_user_md5
+ WHERE user_id = {?}", $this->uid);
+ return new FlagSet($res->fetchOneCell());
+ }
+
+ // Updates the list of active storages.
+ private function set_storages($storages)
+ {
+ XDB::execute("UPDATE auth_user_md5
+ SET mail_storage = {?}
+ WHERE user_id = {?}", $storages->flags(), $this->uid);
+ }
+ // Returns the list of allowed storages for the @p user.
+ static public function get_allowed_storages($uid)
+ {
+ 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') {
+ $storages[] = 'googleapps';
+ }
+
+ // IMAP storage is always visible to administrators, and is allowed for
+ // everyone when the service is marked as 'active'.
+ if ($globals->mailstorage->imap_active || S::has_perms()) {
+ $storages[] = 'imap';
+ }
+
+ return $storages;
+ }
+
+
+ public function __construct($uid, $name)
+ {
+ $this->uid = $uid;
+ $this->email = $name;
+ $this->display_email = (isset($this->display_names[$name]) ? $this->display_names[$name] : $name);
+
+ $storages = $this->get_storages();
+ $this->sufficient = ($name == 'googleapps');
+ $this->active = $storages->hasFlag($name);
+ $this->broken = false;
+ $this->disabled = false;
+ $this->rewrite = '';
+ $this->panne = $this->last = $this->panne_level = 0;
+ }
+
+ public function activate()
+ {
+ if (!$this->active) {
+ $storages = $this->get_storages();
+ $storages->addFlag($this->email);
+ $this->set_storages($storages);
+ $this->active = true;
+ }
+ }
+
+ public function deactivate()
+ {
+ if ($this->active) {
+ $storages = $this->get_storages();
+ $storages->rmFlag($this->email);
+ $this->set_storages($storages);
+ $this->active = false;
+ }
+
+ }
+
+ // Source rewrite can't be enabled for email storage addresses.
+ public function set_rewrite($rewrite) {}
+
+ // Email storage are not supposed to be broken, hence not supposed to be
+ // cleaned-up.
+ public function clean_errors() {}
+
+ // Capabilities.
+ public function has_rewrite() { return false; }
+ public function is_removable() { return false; }
+ public function has_disable() { return false; }
+}
+
+// class Redirect {{{1
+// Redirect is a placeholder class for an user's active redirections (third-party
+// redirection email, or Polytechnique.org mail storages).
class Redirect
{
// properties {{{2
public function __construct($_uid)
{
- $this->uid=$_uid;
+ $this->uid = $_uid;
+ $this->bogo = new Bogo($_uid);
+
+ // Adds third-party email redirections.
$res = XDB::iterRow("SELECT email, flags, rewrite, panne, last, panne_level
FROM emails
WHERE uid = {?} AND flags != 'filter'", $_uid);
- $this->emails=Array();
+ $this->emails = Array();
while ($row = $res->next()) {
- $this->emails[] = new Email($row);
+ $this->emails[] = new EmailRedirection($_uid, $row);
+ }
+
+ // Adds local email storage backends.
+ foreach (EmailStorage::get_allowed_storages($_uid) as $storage) {
+ $this->emails[] = new EmailStorage($_uid, $storage);
}
- $this->bogo = new Bogo($_uid);
}
// public function other_active() {{{2
public function other_active($email)
{
foreach ($this->emails as $mail) {
- if ($mail->email!=$email && $mail->active) {
+ if ($mail->email != $email && $mail->active && $mail->sufficient) {
return true;
}
}
}
XDB::execute('DELETE FROM emails WHERE uid={?} AND email={?}', $this->uid, $email);
$_SESSION['log']->log('email_del',$email.($this->uid!=S::v('uid') ? " (admin on {$this->uid})" : ""));
- foreach ($this->emails as $i=>$mail) {
- if ($email==$mail->email) {
+ foreach ($this->emails as $i => $mail) {
+ if ($email == $mail->email) {
unset($this->emails[$i]);
}
}
return SUCCESS;
}
}
- $this->emails[] = new Email(array($email, 'active', '', '0000-00-00', '0000-00-00', 0));
+ $this->emails[] = new EmailRedirection($this->uid, array($email, 'active', '', '0000-00-00', '0000-00-00', 0));
// security stuff
check_email($email, "Ajout d'une adresse surveillée aux redirections de " . $this->uid);
{
foreach ($this->emails as &$mail) {
if (in_array($mail->email, $emails_actifs)) {
- $mail->activate($this->uid);
+ $mail->activate();
} else {
- $mail->deactivate($this->uid);
+ $mail->deactivate();
}
- $mail->rewrite($emails_rewrite[$mail->email], $this->uid);
+ $mail->set_rewrite($emails_rewrite[$mail->email]);
}
check_redirect($this);
}
if ($mail->email == $email) {
$thisone = $i;
}
- $allinactive &= !$mail->active || $mail->email == $email;
+ $allinactive &= !$mail->active || !$mail->sufficient || $mail->email == $email;
}
if ($thisone === false) {
return ERROR_INVALID_EMAIL;
}
if ($allinactive || $activate) {
- $this->emails[$thisone]->activate($this->uid);
+ $this->emails[$thisone]->activate();
} else {
- $this->emails[$thisone]->deactivate($this->uid);
+ $this->emails[$thisone]->deactivate();
}
check_redirect($this);
if ($allinactive && !$activate) {
{
foreach ($this->emails as &$mail) {
if ($mail->email == $email) {
- $mail->rewrite($redirect, $this->uid);
+ $mail->set_rewrite($redirect);
check_redirect($this);
return;
}
}
}
- // function cleanErrors() {{{2
+ // function clean_errors() {{{2
- public function cleanErrors($email)
+ public function clean_errors($email)
{
foreach ($this->emails as &$mail) {
if ($mail->email == $email) {
check_redirect($this);
- return $mail->cleanErrors($this->uid);
+ return $mail->clean_errors();
}
}
return false;
SET flags = 'disable'
WHERE flags = 'active' AND uid = {?}", $this->uid);
foreach ($this->emails as &$mail) {
- if ($mail->active) {
+ if ($mail->active && $mail->has_disable()) {
$mail->disabled = true;
$mail->active = false;
}
$mxs = $res->fetchAllAssoc();
$mails = array();
foreach ($this->emails as &$mail) {
- if ($mail->active) {
+ if ($mail->active && strstr($mail->email, '@') !== false) {
list(,$domain) = explode('@', $mail->email);
getmxrr($domain, $lcl_mxs);
if (empty($lcl_mxs)) {
}
return $mails;
}
-}
-
-// class MailStorage {{{1
-class MailStorage {
- protected $uid;
- protected $name;
- protected $storage;
-
- public function __construct($_uid, $_name)
- {
- $this->uid = $_uid;
- $this->name = $_name;
-
- $res = XDB::query("SELECT mail_storage
- FROM auth_user_md5
- WHERE user_id = {?}", $this->uid);
- $this->storages = new FlagSet($res->fetchOneCell());
- }
- public function disable()
- {
- $this->storages->rmFlag($this->name);
- XDB::execute("UPDATE auth_user_md5
- SET mail_storage = {?}
- WHERE user_id = {?}", $this->storages->flags(), $this->uid);
- return true;
- }
-
- public function enable()
- {
- $this->storages->addFlag($this->name);
- XDB::execute("UPDATE auth_user_md5
- SET mail_storage = {?}
- WHERE user_id = {?}", $this->storages->flags(), $this->uid);
- return true;
- }
+ // function active_emails() {{{2
- public function active()
+ public function active_emails()
{
- return $this->storages->hasFlag($this->name);
+ $emails = array();
+ foreach ($this->emails as $mail) {
+ if ($mail->active) {
+ $emails[] = $mail;
+ }
+ }
+ return $emails;
}
-}
-class MailStorageIMAP extends MailStorage {
- public function __construct($_uid)
- {
- parent::__construct($_uid, 'imap');
- }
-}
+ // function get_uid() {{{2
-class MailStorageGoogleApps extends MailStorage {
- public function __construct($_uid)
+ public function get_uid()
{
- parent::__construct($_uid, 'googleapps');
- }
-
- public function disable() {
- $redirect = new Redirect(S::v('uid'));
- if (!$redirect->other_active(NULL)) {
- return false;
- }
-
- return parent::disable();
+ return $this->uid;
}
}
/** paths */
public $baseurl;
+ public $baseurl_http;
public $spoolroot;
public $locale;
$this->read_config();
if (isset($_SERVER) && isset($_SERVER['SERVER_NAME'])) {
$base = empty($_SERVER['HTTPS']) ? 'http://' : 'https://';
- $this->baseurl = @trim($base.$_SERVER['SERVER_NAME'].dirname($_SERVER['PHP_SELF']), '/');
+ $this->baseurl = @trim($base .$_SERVER['SERVER_NAME'].dirname($_SERVER['PHP_SELF']), '/');
+ $this->baseurl_http = @trim('http://'.$_SERVER['SERVER_NAME'].dirname($_SERVER['PHP_SELF']), '/');
}
$this->setlocale();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
***************************************************************************/
-// Checks the admin status of the @p account_name.
-function is_google_apps_administrator($account_name) {
- static $last_account_name = null;
- static $last_result = null;
-
- if ($last_account_name == $account_name) {
- return $last_result;
- }
-
- $res = XDB::query(
- "SELECT g_admin
- FROM gapps_accounts
- WHERE g_account_name = {?} AND g_status = 'active'",
- $account_name);
- $last_account_name = $account_name;
- $last_result = ($res->numRows() > 0 ? (bool)$res->fetchOneRow() : false);
- return $last_result;
-}
-
-// Post-queue job cleanup functions; they are used to update the plat/al database
-// when a specific Google Apps queue job enters 'success' state.
+// Post-processes the successful Google Apps account creation queue job.
function post_queue_u_create($job) {
global $globals;
return;
}
- // Adds a redirection to the Google Apps delivery address.
+ // Adds a redirection to the Google Apps delivery address, if requested by
+ // the user at creation time.
$account = new GoogleAppsAccount($userid, $forlife);
if ($account->activate_mail_redirection) {
require_once('emails.inc.php');
- $storage = new MailStorageGoogleApps($userid);
- $storage->enable();
+ $storage = new EmailStorage($userid, 'googleapps');
+ $storage->activate();
}
- // Sends an email to the account owner.
+ // Sends the 'account created' email to the user, with basic documentation.
$res = XDB::query(
"SELECT FIND_IN_SET('femme', u.flags), prenom
FROM auth_user_md5 AS u
$mailer->send();
}
+// Post-processes the successful Google Apps account update queue job.
function post_queue_u_update($job) {
global $globals;
if (isset($parameters['suspended']) && $parameters['suspended'] == false) {
require_once('emails.inc.php');
$account = new GoogleAppsAccount($userid, $forlife);
- if ($account->g_status == 'active') {
+ if ($account->active()) {
// Re-adds the email redirection (if the user did request it).
if ($account->activate_mail_redirection) {
- $storage = new MailStorageGoogleApps($userid);
- $storage->enable();
+ $storage = new EmailStorage($userid, 'googleapps');
+ $storage->activate();
}
// Sends an email to the account owner.
}
// Reprensentation of an SQL-stored Google Apps account.
+// This class is the interface with the gappsd SQL tables: gappsd is the python
+// daemon which deals with Google Apps provisioning APIs.
+// TODO(vincent.zanotti): add the url of gappsd, when available.
class GoogleAppsAccount
{
+ // User identification: user id, and forlife.
private $uid;
public $g_account_name;
+ // Local account parameters.
public $sync_password;
public $activate_mail_redirection;
+
+ // Account status, obtained from Google Apps provisioning & reporting APIs.
+ public $g_account_id;
public $g_status;
public $g_suspension;
public $r_disk_usage;
public $r_last_webmail;
public $reporting_date;
+ // Pending requests in the gappsd job queue (cf. top note).
public $pending_create;
public $pending_delete;
public $pending_update;
public $pending_update_password;
public $pending_update_suspension;
+ // Pending requests in plat/al validation queue.
public $pending_validation_unsuspend;
- public function __construct($uid, $account_name)
+ // Constructs the account object, by retrieving all informations from the
+ // GApps account table, from GApps job queue, and from plat/al validation queue.
+ public function __construct($uid, $account_name = NULL)
{
+ if ($account_name == NULL) {
+ require_once 'user.func.inc.php';
+ $account_name = get_user_forlife($uid, '_silent_user_callback');
+ }
+
$this->uid = $uid;
$this->g_account_name = $account_name;
$this->g_status = NULL;
$res = XDB::query(
"SELECT l_sync_password, l_activate_mail_redirection,
- g_account_name, g_status, g_suspension, r_disk_usage,
+ g_account_name, g_account_id, g_status, g_suspension, r_disk_usage,
UNIX_TIMESTAMP(r_creation) as r_creation,
UNIX_TIMESTAMP(r_last_login) as r_last_login,
UNIX_TIMESTAMP(r_last_webmail) as r_last_webmail
if ($account = $res->fetchOneAssoc()) {
$this->sync_password = $account['l_sync_password'];
$this->activate_mail_redirection = $account['l_activate_mail_redirection'];
+ $this->g_account_id = $account['g_account_id'];
$this->g_status = $account['g_status'];
$this->g_suspension = $account['g_suspension'];
$this->r_disk_usage = $account['r_disk_usage'];
}
}
- // Account object initialization methods.
+ // Determines if changes to the Google Account are currently waiting in the
+ // GApps job queue, and initializes the local values accordingly.
private function load_pending_counts()
{
- // Determines if changes to the Google Account are currently waiting
- // in the Google Apps queue.
$res = XDB::query(
"SELECT SUM(j_type = 'u_create') AS pending_create,
SUM(j_type = 'u_update') AS pending_update,
$this->pending_update_suspension = false;
}
+ // Checks for unsuspend requests waiting for validation in plat/al
+ // validation queue.
private function load_pending_validations()
{
require_once('validations.inc.php');
Validate::get_typed_requests_count($this->uid, 'gapps-unsuspend');
}
+ // Retrieves all the pending update job in the gappsd queue for the current
+ // user, and analyzes the scope of the update (ie. the fields in the user
+ // account which are going to be updated).
private function load_pending_updates()
{
- // If updates are pending, determines their nature (more specifically:
- // determines which part of the account is concerned).
$res = XDB::iterator(
"SELECT j_parameters
FROM gapps_queue
}
// Creates a queue job of the @p type, for the user represented by this
- // GoogleAppsAccount object, using @p parameters.
+ // GoogleAppsAccount object, using @p parameters. @p parameters is supposed
+ // to be a one-dimension array of key-value mappings.
+ // The created job as a 'normal' priority, and is scheduled for immediate
+ // execution.
private function create_queue_job($type, $parameters) {
$parameters["username"] = $this->g_account_name;
XDB::execute(
json_encode($parameters));
}
+
+ // Returns true if the account is currently active.
+ public function active()
+ {
+ return $this->g_status == 'active';
+ }
+
+ // Returns true if the account exists in Google Apps.
+ public function provisioned()
+ {
+ return $this->g_status == 'active' or $this->g_status == 'disabled';
+ }
+
+ // Returns true if the account exists, but cannot be used (user-requested
+ // suspension, or Google-requested suspension).
+ public function suspended()
+ {
+ return $this->g_status == 'disabled';
+ }
+
+
// Changes the GoogleApps password.
public function set_password($password) {
- if ($this->g_status == NULL || $this->g_status == 'unprovisioned') {
+ if (!$this->provisioned()) {
return;
}
if (!$this->pending_update_password) {
$this->create_queue_job('u_update', array('password' => $password));
+ $this->pending_update_password = true;
}
}
+
// Changes the password synchronization status ("sync = true" means that the
// Polytechnique.org password will be replicated to the Google Apps account).
public function set_password_sync($sync) {
- if ($this->g_status == NULL || $this->g_status == 'unprovisioned') {
+ if (!$this->provisioned()) {
return;
}
// Suspends the Google Apps account.
public function suspend() {
- if ($this->g_status == NULL || $this->g_status == 'unprovisioned') {
+ if (!$this->provisioned()) {
return;
}
if (!$this->pending_update_suspension) {
$this->create_queue_job('u_update', array('suspended' => true));
$this->pending_update_suspension = true;
+ XDB::execute(
+ "UPDATE gapps_accounts
+ SET g_status = 'disabled'
+ WHERE g_account_name = {?} AND g_status = 'active'",
+ $this->g_account_name);
}
}
// Adds an unsuspension request to the validation queue (used on user-request).
public function unsuspend($activate_mail_redirection = NULL) {
- if ($this->g_status == NULL || $this->g_status == 'unprovisioned') {
+ if (!$this->provisioned()) {
return;
}
if ($activate_mail_redirection !== NULL) {
"UPDATE gapps_accounts
SET l_activate_mail_redirection = {?}
WHERE g_account_name = {?}",
- $activate_mail_redirection);
+ $activate_mail_redirection,
+ $this->g_account_name);
}
if (!$this->pending_update_suspension && !$this->pending_validation_unsuspend) {
// Unsuspends the Google Apps account (used on admin-request, or on validation of
// an user-request).
public function do_unsuspend() {
- if ($this->g_status == NULL || $this->g_status == 'unprovisioned') {
+ if (!$this->provisioned()) {
return;
}
return false;
}
- // Adds a creation request in the job queue.
+ // Creates a new Google Apps account with the @p local parameters.
public function create($password_sync, $password, $redirect_mails) {
if ($this->g_status != NULL) {
return;
$this->uid);
list($nom, $nom_usage, $prenom) = $res->fetchOneRow();
- // Adds an entry in the gapps_accounts table.
+ // Adds an 'unprovisioned' entry in the gapps_accounts table.
XDB::execute(
"INSERT INTO gapps_accounts
SET l_userid = {?},
$this->__construct($this->uid, $this->g_account_name);
}
}
+
+
+ // Returns the status of the Google Apps account for @p user, or false
+ // when no account exists.
+ static public function account_status($uid) {
+ $res = XDB::query(
+ "SELECT g_status
+ FROM gapps_accounts
+ WHERE l_userid = {?}", $uid);
+ return ($res->numRows() > 0 ? $res->fetchOneCell() : false);
+ }
+
+ // Returns true if the @p user is an administrator of the Google Apps domain.
+ static public function is_administrator($uid) {
+ $res = XDB::query(
+ "SELECT g_admin
+ FROM gapps_accounts
+ WHERE l_userid = {?} AND g_status = 'active'", $uid);
+ return ($res->numRows() > 0 ? (bool)$res->fetchOneRow() : false);
+ }
}
// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
$sql = "
(
SELECT u.promo, u.prenom, IF(u.nom_usage='',u.nom,u.nom_usage) AS nom,
- u.deces != 0 AS dcd,
+ u.deces != 0 AS dcd, (u.flags = 'femme') AS sexe,
a.alias AS bestalias,
wo.*,
{$our['contact_sql']} AS contact,
if ($mail) {
$sql.=",
w.uid AS aid, v.prenom AS aprenom, IF(v.nom_usage='',v.nom,v.nom_usage) AS anom,
- b.alias AS abestalias, (v.flags='femme') AS sexe, q.core_mail_fmt AS mail_fmt";
+ b.alias AS abestalias, (v.flags='femme') AS asexe, q.core_mail_fmt AS mail_fmt";
}
$sql .= "
$aid = $tmp['aid'];
if (empty($this->_data[$aid])) {
$this->_data[$aid] = Array("prenom" => $tmp['aprenom'], 'nom' => $tmp['anom'],
- 'bestalias'=>$tmp['abestalias'], 'sexe' => $tmp['sexe'], 'mail_fmt' => $tmp['mail_fmt'],
+ 'bestalias'=>$tmp['abestalias'], 'sexe' => $tmp['asexe'], 'mail_fmt' => $tmp['mail_fmt'],
'dcd'=>$tmp['dcd']);
}
- unset($tmp['aprenom'], $tmp['anom'], $tmp['abestalias'], $tmp['aid'], $tmp['sexe'], $tmp['mail_fmt'], $tmp['dcd']);
+ unset($tmp['aprenom'], $tmp['anom'], $tmp['abestalias'], $tmp['aid'], $tmp['asexe'], $tmp['mail_fmt'], $tmp['dcd']);
$this->_data[$aid]['data'][$tmp['cid']][] = $tmp;
}
}
$res = XDB::query(
'SELECT a.id
FROM aliases AS a
- INNER JOIN auth_user_quick AS q ON ( a.id = q.user_id AND q.core_rss_hash = {?} )
+ INNER JOIN auth_user_md5 AS u ON (a.id = u.user_id AND u.perms IN ("admin", "user"))
+ INNER JOIN auth_user_quick AS q ON (a.id = q.user_id AND q.core_rss_hash = {?})
WHERE a.alias = {?} AND a.type != "homonyme"', $hash, $alias);
$uid = $res->fetchOneCell();
$tables_to_clear['contact'] = array('contacts');
XDB::execute("UPDATE auth_user_md5
SET date_ins = 0, promo_sortie = 0, nom_usage = '', password = '', perms = 'pending',
- nationalite = '', cv = '', section = 0, date = 0, smtppass = ''
+ nationalite = '', cv = '', section = 0, date = 0, smtppass = '', mail_storage = ''
WHERE user_id = {?}", $uid);
XDB::execute("DELETE virtual.* FROM virtual INNER JOIN virtual_redirect AS r USING(vid) WHERE redirect = {?}",
$alias.'@'.$globals->mail->domain);
s.text AS section, p.x, p.y, p.pub AS photo_pub,
u.matricule_ax,
m.expertise != '' AS is_referent,
- COUNT(e.email) > 0 AS actif
+ (COUNT(e.email) > 0 OR FIND_IN_SET('googleapps', u.mail_storage) > 0) AS actif
FROM auth_user_md5 AS u
INNER JOIN auth_user_quick AS q USING(user_id)
INNER JOIN aliases AS a ON (u.user_id=a.id AND a.type='a_vie')
ad1.text AS app1text, ad1.url AS app1url, ai1.type AS app1type,
adr.city, gp.a2, gp.pays AS countrytxt, gr.name AS region,
IF(u.nom_usage<>'',u.nom_usage,u.nom) AS sortkey,
- COUNT(em.email) > 0 AS actif" . (S::logged() ? ", c.contact AS contact" : '');
+ (COUNT(em.email) > 0 OR FIND_IN_SET('googleapps', u.mail_storage) > 0) AS actif" .
+ (S::logged() ? ", c.contact AS contact" : '');
}
public function joins()
if ($this->nom_usage) {
$res .= "\n\n Les alias {$this->alias}@{$globals->mail->domain} et @{$globals->mail->domain2} sont maintenant à ta disposition !";
}
+ if ($globals->mailstorage->googleapps_domain) {
+ require_once 'googleapps.inc.php';
+ $account = new GoogleAppsAccount(S::v('uid'), S::v('forlife'));
+ if ($account->active()) {
+ $res .= "\n\n Si tu utilises Google Apps, tu peux changer ton nom d'usage sur https://mail.google.com/a/polytechnique.org/#settings/accounts";
+ }
+ }
return $res;
} else {
return " La demande de changement de nom d'usage que tu avais faite a été refusée.";
static $convVIn, $convVOut, $convGuIn, $convGuOut, $accents;
if (!isset($convGuIn)) {
global $uc_convert, $lc_convert;
- $convGuIn = array( 'GUI', 'GUE', 'GA', 'GO', 'GU', 'SC', 'CA', 'CO', 'CU', 'QU', 'Q', 'CC', 'CK', 'G', 'ST', 'PH');
- $convGuOut = array( 'KI', 'KE', 'KA', 'KO', 'KU', 'SK', 'KA', 'KO', 'KU', 'K', 'K', 'K', 'K', 'J', 'T', 'F');
+ $convGuIn = array( 'GUI', 'GUE', 'GA', 'GO', 'GU', 'SCI', 'SCE', 'SC', 'CA', 'CO',
+ 'CU', 'QU', 'Q', 'CC', 'CK', 'G', 'ST', 'PH');
+ $convGuOut = array( 'KI', 'KE', 'KA', 'KO', 'K', 'SI', 'SE', 'SK', 'KA', 'KO',
+ 'KU', 'K', 'K', 'K', 'K', 'J', 'T', 'F');
$convVIn = array( '/E?(AU)/', '/([EA])?[UI]([NM])([^EAIOUY]|$)/', '/[AE]O?[NM]([^AEIOUY]|$)/',
'/[EA][IY]([NM]?[^NM]|$)/', '/(^|[^OEUIA])(OEU|OE|EU)([^OEUIA]|$)/', '/OI/',
'/(ILLE?|I)/', '/O(U|W)/', '/O[NM]($|[^EAOUIY])/', '/(SC|S|C)H/',
- '/([^AEIOUY1])[^AEIOUYLKTP]([UAO])([^AEIOUY])/', '/([^AEIOUY]|^)([AUO])[^AEIOUYLKTP]([^AEIOUY1])/', '/^KN/',
+ '/([^AEIOUY1])[^AEIOUYLKTPNR]([UAO])([^AEIOUY])/', '/([^AEIOUY]|^)([AUO])[^AEIOUYLKTP]([^AEIOUY1])/', '/^KN/',
'/^PF/', '/C([^AEIOUY]|$)/',
'/C/', '/Z$/', '/(?<!^)Z+/', '/ER$/', '/H/', '/W/');
$convVOut = array( 'O', '1\3', 'A\1',
// on réinterprète les voyelles
$sIn = preg_replace( $convVIn, $convVOut, $sIn);
// on supprime les terminaisons T, D, S, X (et le L qui précède si existe)
- $sIn = preg_replace( '`L?[TDSX]$`', '', $sIn );
+ $sIn = preg_replace( '`L?[TDX]S?$`', '', $sIn );
// on supprime les E, A et Y qui ne sont pas en première position
$sIn = preg_replace( '`(?!^)Y([^AEOU]|$)`', '\1', $sIn);
$sIn = preg_replace( '`(?!^)[EA]`', '', $sIn);
*/
function ip_to_uint($ip)
{
- return ip2long($ip);
+ $part = explode('.', $ip);
+ $v = 0;
+ $fact = 0x1000000;
+ for ($i = 0 ; $i < 4 ; ++$i) {
+ $v += $fact * $part[$i];
+ $fact >>= 8;
+ }
+ return $v;
}
/** Convert uint to ip (to build a human understandable ip)
}
$ips[] = $_SERVER['REMOTE_ADDR'];
foreach ($ips as &$ip) {
- $ip = "ip = " . ip_to_uint($ip);
+ $ip = '(ip & mask) = (' . ip_to_uint($ip) . '& mask)';
}
- $res = XDB::query('SELECT state
+ $res = XDB::query('SELECT state, description
FROM ip_watch
WHERE ' . implode(' OR ', $ips) . '
ORDER BY state DESC');
if ($res->numRows()) {
- $_SESSION['check_ip'] = $res->fetchOneCell();
+ $state = $res->fetchOneAssoc();
+ $_SESSION['check_ip'] = $state['state'];
+ $_SESSION['check_ip_desc'] = $state['description'];
} else {
$_SESSION['check_ip'] = 'safe';
}
if (is_null($red)) {
$red = new Redirect(S::v('uid'));
}
- $_SESSION['no_redirect'] = !$red->other_active('');
- $_SESSION['mx_failures'] = $red->get_broken_mx();
+ if ($red->get_uid() == S::v('uid')) {
+ $_SESSION['no_redirect'] = !$red->other_active('');
+ $_SESSION['mx_failures'] = $red->get_broken_mx();
+ }
}
function send_warning_mail($title)
$mailer->send();
}
+function kill_sessions()
+{
+ assert(S::has_perms());
+ shell_exec('sudo -u root ' . dirname(dirname(__FILE__)) . '/bin/kill_sessions.sh');
+}
+
/******************************************************************************
* Dynamic configuration update/edition stuff
function set_skin()
{
global $globals;
- if (S::logged() && !S::has('skin')) {
+ if (S::logged() && (!S::has('skin') || S::has('suid'))) {
$uid = S::v('uid');
- $res = XDB::query("SELECT skin_tpl
- FROM auth_user_quick AS a
- INNER JOIN skins AS s ON a.skin = s.id
- WHERE user_id = {?} AND skin_tpl != ''", $uid);
- if ($_SESSION['skin'] = $res->fetchOneCell()) {
+ $res = XDB::query("SELECT skin_tpl
+ FROM auth_user_quick AS a
+ INNER JOIN skins AS s ON a.skin = s.id
+ WHERE user_id = {?} AND skin_tpl != ''", $uid);
+ if ($_SESSION['skin'] = $res->fetchOneCell()) {
return;
}
}
break;
case "clean_fwd":
if (!empty($val)) {
- $redirect->cleanErrors($val);
+ $redirect->clean_errors($val);
}
break;
case "add_alias":
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']);
$mailer->assign('old', $old_fields);
$mailer->assign('new', $new_fields);
$mailer->send();
-
+
// update number of subscribers (perms or deceased may have changed)
update_NbIns();
if ($globals->mailstorage->googleapps_domain && Env::v('newpass_clair') != "********") {
require_once 'googleapps.inc.php';
$account = new GoogleAppsAccount($mr['user_id'], $mr['forlife']);
- if ($account->g_status == 'active' && $account->sync_password) {
+ if ($account->active() && $account->sync_password) {
$account->set_password($pass_encrypted);
}
}
switch (Post::v('action')) {
case 'create':
if (trim(Post::v('ipN')) != '') {
- Xdb::execute('INSERT IGNORE INTO ip_watch (ip, state, detection, last, uid, description)
- VALUES ({?}, {?}, CURDATE(), NOW(), {?}, {?})',
- ip_to_uint(trim(Post::v('ipN'))), Post::v('stateN'), S::i('uid'), Post::v('descriptionN'));
+ Xdb::execute('INSERT IGNORE INTO ip_watch (ip, mask, state, detection, last, uid, description)
+ VALUES ({?}, {?}, {?}, CURDATE(), NOW(), {?}, {?})',
+ ip_to_uint(trim(Post::v('ipN'))), ip_to_uint(trim(Post::v('maskN'))),
+ Post::v('stateN'), S::i('uid'), Post::v('descriptionN'));
};
break;
case 'edit':
Xdb::execute('UPDATE ip_watch
- SET state = {?}, last = NOW(), uid = {?}, description = {?}
+ SET state = {?}, last = NOW(), uid = {?}, description = {?}, mask = {?}
WHERE ip = {?}', Post::v('stateN'), S::i('uid'), Post::v('descriptionN'),
- ip_to_uint(Post::v('ipN')));
+ ip_to_uint(Post::v('maskN')), ip_to_uint(Post::v('ipN')));
break;
default:
$sql = "SELECT w.ip, IF(s.ip IS NULL,
IF(w.ip = s2.ip, s2.host, s2.forward_host),
IF(w.ip = s.ip, s.host, s.forward_host)),
- w.detection, w.state, a.alias AS forlife
+ w.mask, w.detection, w.state, a.alias AS forlife
FROM ip_watch AS w
LEFT JOIN logger.sessions AS s ON (s.ip = w.ip)
LEFT JOIN logger.sessions AS s2 ON (s2.forward_ip = w.ip)
$table = array();
$props = array();
- while (list($ip, $host, $date, $state, $forlife) = $it->next()) {
+ while (list($ip, $host, $mask, $date, $state, $forlife) = $it->next()) {
$ip = uint_to_ip($ip);
+ $mask = uint_to_ip($mask);
if (count($props) == 0 || $props['ip'] != $ip) {
if (count($props) > 0) {
$table[] = $props;
}
$props = array('ip' => $ip,
+ 'mask' => $mask,
'host' => $host,
'detection' => $date,
'state' => $state,
}
$page->assign('table', $table);
} elseif ($action == 'edit') {
- $sql = "SELECT w.detection, w.state, w.last, w.description,
+ $sql = "SELECT w.detection, w.state, w.last, w.description, w.mask,
a1.alias AS edit, a2.alias AS forlife, s.host
FROM ip_watch AS w
LEFT JOIN aliases AS a1 ON (a1.id = w.uid AND a1.type = 'a_vie')
$it = Xdb::iterRow($sql, ip_to_uint($ip));
$props = array();
- while (list($detection, $state, $last, $description, $edit, $forlife, $host) = $it->next()) {
+ while (list($detection, $state, $last, $description, $mask, $edit, $forlife, $host) = $it->next()) {
if (count($props) == 0) {
$props = array('ip' => $ip,
+ 'mask' => uint_to_ip($mask),
'host' => $host,
'detection' => $detection,
'state' => $state,
'login' => $this->make_hook('login', AUTH_COOKIE),
'send_bug' => $this->make_hook('bug', AUTH_COOKIE),
'purge_cache' => $this->make_hook('purge_cache', AUTH_COOKIE, 'admin'),
+ 'kill_sessions' => $this->make_hook('kill_sessions', AUTH_COOKIE, 'admin'),
'get_rights' => $this->make_hook('get_rights', AUTH_MDP, 'admin'),
'wiki_help' => $this->make_hook('wiki_help', AUTH_PUBLIC),
http_redirect(empty($_SERVER['HTTP_REFERER']) ? './' : $_SERVER['HTTP_REFERER']);
}
+ function handler_kill_sessions(&$page)
+ {
+ kill_sessions();
+ }
+
function handler_get_rights(&$page, $level)
{
if (S::has('suid')) {
function handler_emails(&$page, $action = null, $email = null)
{
global $globals;
+ require_once 'emails.inc.php';
$page->changeTpl('emails/index.tpl');
$page->assign('xorg_title','Polytechnique.org - Mes emails');
ORDER BY LENGTH(alias)";
$page->assign('aliases', XDB::iterator($sql, $uid));
- $homonyme = XDB::query("SELECT alias FROM aliases INNER JOIN homonymes ON (id = homonyme_id) WHERE user_id = {?} AND type = 'homonyme'", $uid);
- $page->assign('homonyme', $homonyme->fetchOneCell());
+ $homonyme = XDB::query("SELECT alias FROM aliases INNER JOIN homonymes ON (id = homonyme_id) WHERE user_id = {?} AND type = 'homonyme'", $uid);
+ $page->assign('homonyme', $homonyme->fetchOneCell());
// Affichage des redirections de l'utilisateur.
- $sql = "SELECT email
- FROM emails
- WHERE uid = {?} AND FIND_IN_SET('active', flags)";
- $page->assign('mails', XDB::iterator($sql, $uid));
-
- // Affichage des backends actifs de stockage des emails.
- $sql = "SELECT mail_storage
- FROM auth_user_md5
- WHERE user_id = {?}";
- $storages = XDB::query($sql, $uid)->fetchOneCell();
- $page->assign('storage', explode(',', $storages));
+ $redirect = new Redirect($uid);
+ $page->assign('mails', $redirect->active_emails());
// on regarde si l'utilisateur a un alias et si oui on l'affiche !
$forlife = S::v('forlife');
$redirect->modify_one_email_redirect($email, $rewrite);
}
- if ($action == 'storage') {
- if ($email == 'imap') {
- $storage = new MailStorageIMAP(S::v('uid'));
- } else if ($email == 'googleapps') {
- $storage = new MailStorageGoogleApps(S::v('uid'));
- } else {
- $storage = NULL;
- }
-
- if ($storage) {
- $subaction = @func_get_arg(3);
- if ($subaction == 'active') {
- $storage->enable();
- }
- if ($subaction == 'inactive') {
- $storage->disable();
- }
- }
- }
-
if (Env::has('emailop')) {
$actifs = Env::v('emails_actifs', Array());
print_r(Env::v('emails_rewrite'));
$page->assign('alias', $res->fetchAllAssoc());
$page->assign('emails',$redirect->emails);
- $res = XDB::query(
- "SELECT mail_storage
- FROM auth_user_md5
- WHERE user_id = {?}", $uid);
- $page->assign('storage', explode(',', $res->fetchOneCell()));
-
- $res = XDB::query(
- "SELECT g_status
- FROM gapps_accounts
- WHERE l_userid = {?}", $uid);
- $page->assign('googleapps', ($res->numRows() > 0 ? $res->fetchOneCell() : false));
+ require_once 'googleapps.inc.php';
+ $page->assign('googleapps', GoogleAppsAccount::account_status($uid));
}
function handler_antispam(&$page, $statut_filtre = null)
$bogo = new Bogo(S::v('uid'));
if (isset($statut_filtre)) {
- $bogo->change(S::v('uid'), $statut_filtre + 0);
+ $bogo->change($statut_filtre + 0);
}
$page->assign('filtre',$bogo->level());
}
function handler_test(&$page, $forlife = null)
{
global $globals;
+ require_once 'emails.inc.php';
+
if (!S::has_perms() || !$forlife) {
$forlife = S::v('bestalias');
}
- $mailer = new PlMailer('emails/test.mail.tpl');
- $mailer->assign('email', $forlife . '@' . $globals->mail->domain);
- $iterator = XDB::iterator("SELECT email
- FROM emails AS e
- INNER JOIN aliases AS a ON (e.uid = a.id)
- WHERE FIND_IN_SET('active', e.flags) AND a.alias = {?}",
- $forlife);
- $mailer->assign('redirects', $iterator);
- $res = XDB::query("SELECT FIND_IN_SET('femme', u.flags), prenom
+
+ $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) = $res->fetchOneRow();
+ list($sexe, $prenom, $uid) = $res->fetchOneRow();
+ $redirect = new Redirect($uid);
+
+ $mailer = new PlMailer('emails/test.mail.tpl');
+ $mailer->assign('email', $forlife . '@' . $globals->mail->domain);
+ $mailer->assign('redirects', $redirect->active_emails());
$mailer->assign('sexe', $sexe);
$mailer->assign('prenom', $prenom);
$mailer->send();
$page->changeTpl('emails/lost.tpl');
$page->assign('lost_emails', XDB::iterator('
- SELECT u.user_id, a.alias
- 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 u.deces = 0
- ORDER BY u.promo DESC, u.nom, u.prenom'));
+ SELECT u.user_id, a.alias
+ 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'));
}
}
$page->assign('xorg_title','Polytechnique.org - Administration - Bannissements des forums');
$page->assign('title', 'Gestion des mises au ban');
$table_editor = new PLTableEditor('admin/forums','forums.innd','id_innd');
- $table_editor->describe('ipmin','min plage IP',true);
- $table_editor->describe('ipmax','max plage IP',true);
- $table_editor->describe('uid','utilisateur',true);
- $table_editor->describe('write_perm','perm. poster',true);
- $table_editor->describe('read_perm','perm. lire',true);
- $table_editor->describe('priority','priorite',true);
+ $table_editor->add_sort_field('priority', true, true);
+ $table_editor->describe('read_perm','lecture',true);
+ $table_editor->describe('write_perm','écriture',true);
+ $table_editor->describe('priority','priorité',true);
$table_editor->describe('comment','commentaire',true);
$table_editor->apply($page, $action, $id);
+ $page->changeTpl('forums/admin.tpl');
+ $page->addJsLink('jquery.js');
}
static function run_banana(&$page, $params = null)
}
return array(
- 'googleapps' => $this->make_hook('index', AUTH_MDP),
+ 'googleapps' => $this->make_hook('index', AUTH_MDP),
+ 'admin/googleapps' => $this->make_hook('admin', AUTH_MDP. 'admin'),
+ 'admin/googleapps/job' => $this->make_hook('admin_job', AUTH_MDP, 'admin'),
+ 'admin/googleapps/user' => $this->make_hook('admin_user', AUTH_MDP, 'admin'),
);
}
$page->assign('redirect_active', false);
$page->assign('redirect_unique', true);
- if ($account->g_status == 'active') {
+ if ($account->active()) {
$redirect = new Redirect(S::v('uid'));
- $page->assign('redirect_unique', !$redirect->other_active(NULL));
+ $page->assign('redirect_unique', !$redirect->other_active('googleapps'));
- $storage = new MailStorageGoogleApps(S::v('uid'));
- $page->assign('redirect_active', $storage->active());
+ $storage = new EmailStorage(S::v('uid'), 'googleapps');
+ $page->assign('redirect_active', $storage->active);
}
// Updates the Google Apps account as required.
}
}
- if ($action == 'suspend' && Post::has('suspend') && $account->g_status == 'active') {
+ if ($action == 'suspend' && Post::has('suspend') && $account->active()) {
if ($account->pending_update_suspension) {
$page->trig("Ton compte est déjà en cours de désactivation.");
} else {
- $storage = new MailStorageGoogleApps(S::v('uid'));
- if ($storage->disable()) {
+ if ($redirect->modify_one_email('googleapps', false) == SUCCESS) {
$account->suspend();
$page->trig("Ton compte Google Apps est dorénavant désactivé.");
} else {
$page->trig("Ton compte Google Apps est ta seule adresse de redirection. Ton compte ne peux pas être désactivé.");
}
}
- } elseif ($action == 'unsuspend' && Post::has('unsuspend') && $account->g_status == 'disabled') {
+ } elseif ($action == 'unsuspend' && Post::has('unsuspend') && $account->suspended()) {
$account->unsuspend(Post::b('redirect_mails', true));
$page->trig("Ta demande de réactivation a bien été prise en compte.");
}
$page->assign('account', $account);
}
+
+ function handler_admin(&$page, $action = null) {
+ require_once("googleapps.inc.php");
+ $page->changeTpl('googleapps/admin.tpl');
+ $page->assign('xorg_title', 'Polytechnique.org - Administration Google Apps');
+ $page->assign('googleapps_admin', GoogleAppsAccount::is_administrator(S::v('uid')));
+
+ if ($action == 'ack') {
+ $qid = @func_get_arg(2);
+ if ($qid) {
+ XDB::execute(
+ "DELETE FROM gapps_queue
+ WHERE q_id = {?} AND p_status = 'hardfail'", $qid);
+ $page->trig("La requête échouée a bien été retirée.");
+ }
+ }
+
+ // Retrieves latest pending administrative requests from the gappsd queue.
+ $res = XDB::iterator(
+ "SELECT q_id, q_recipient_id, a.alias, j_type, j_parameters,
+ UNIX_TIMESTAMP(q.p_entry_date) AS p_entry_date
+ FROM gapps_queue AS q
+ LEFT JOIN aliases AS a ON (a.id = q_recipient_id AND a.type = 'a_vie')
+ WHERE p_status IN ('idle', 'active', 'softfail') AND
+ p_admin_request IS TRUE
+ ORDER BY p_entry_date");
+ while ($request = $res->next()) {
+ $j_parameters = json_decode($request['j_parameters'], true);
+ unset($j_parameters['username']);
+ $parameters = array_keys($j_parameters);
+ $request['parameters'] = implode(', ', $parameters);
+
+ $page->append('admin_requests', $request);
+ }
+
+ // Retrieves latest failed requests from the gappsd queue.
+ $res = XDB::iterator(
+ "SELECT q.q_id, q.q_recipient_id, a.alias, q.j_type, q.r_result,
+ UNIX_TIMESTAMP(q.p_entry_date) AS p_entry_date
+ FROM gapps_queue AS q
+ LEFT JOIN aliases AS a ON (a.id = q.q_recipient_id AND a.type = 'a_vie')
+ WHERE q.p_status = 'hardfail'
+ ORDER BY p_entry_date DESC
+ LIMIT 20");
+ $page->assign('failed_requests', $res);
+ }
+
+ function handler_admin_job(&$page, $job = null) {
+ require_once("googleapps.inc.php");
+ $page->changeTpl('googleapps/admin.job.tpl');
+ $page->assign('xorg_title', 'Polytechnique.org - Administration Google Apps');
+ $page->assign('googleapps_admin', GoogleAppsAccount::is_administrator(S::v('uid')));
+
+ if ($job) {
+ $res = XDB::query(
+ "SELECT q.*, ao.alias AS q_owner, ar.alias AS q_recipient
+ FROM gapps_queue AS q
+ LEFT JOIN aliases AS ao ON (ao.id = q.q_owner_id AND ao.type = 'a_vie')
+ LEFT JOIN aliases AS ar ON (ar.id = q.q_recipient_id AND ar.type = 'a_vie')
+ WHERE q_id = {?}", $job);
+ $sql_job = $res->fetchOneAssoc();
+ $sql_job['decoded_parameters'] = var_export(json_decode($sql_job['j_parameters'], true), true);
+ $page->assign('job', $sql_job);
+ }
+ }
+
+ function handler_admin_user(&$page, $user = null, $action = null) {
+ require_once("emails.inc.php");
+ require_once("googleapps.inc.php");
+ $page->changeTpl('googleapps/admin.user.tpl');
+ $page->assign('xorg_title', 'Polytechnique.org - Administration Google Apps');
+ $page->assign('googleapps_admin', GoogleAppsAccount::is_administrator(S::v('uid')));
+
+ if (!$user && Post::has('login')) {
+ $user = Post::v('login');
+ }
+ if ($user && !is_numeric($user)) {
+ $res = XDB::query("SELECT id FROM aliases WHERE alias = {?} AND type != 'homonyme'", $user);
+ $user = $res->fetchOneCell();
+ }
+
+ if ($user) {
+ $account = new GoogleAppsAccount($user);
+ $storage = new EmailStorage($user, 'googleapps');
+
+ // Force synchronization of plat/al and Google Apps passwords.
+ if ($action == 'forcesync' && $account->sync_password) {
+ $res = XDB::query("SELECT password FROM auth_user_md5 WHERE user_id = {?}", $user);
+ $account->set_password($res->fetchOneCell());
+ $page->trig('Le mot de passe a été synchronisé.');
+ }
+
+ // Displays basic account information.
+ $page->assign('account', $account);
+ $page->assign('admin_account', GoogleAppsAccount::is_administrator($user));
+ $page->assign('googleapps_storage', $storage->active);
+ $page->assign('user', $user);
+
+ // Retrieves user's pending requests.
+ $res = XDB::iterator(
+ "SELECT q_id, q_recipient_id, p_status, j_type, UNIX_TIMESTAMP(p_entry_date) AS p_entry_date
+ FROM gapps_queue
+ WHERE q_recipient_id = {?}
+ ORDER BY p_entry_date DESC", $user);
+ $page->assign('requests', $res);
+ }
+ }
}
// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
foreach($members as $mem) {
list($m, $dom) = explode('@',$mem);
if ($dom == $globals->mail->domain || $dom == $globals->mail->domain2) {
- $res = XDB::query('SELECT prenom, IF(nom_usage="", nom, nom_usage), promo, e.uid IS NULL
+ $res = XDB::query('SELECT prenom, IF(nom_usage="", nom, nom_usage), promo,
+ (e.uid IS NULL AND FIND_IN_SET("googleapps", u.mail_storage) = 0)
FROM auth_user_md5 AS u
INNER JOIN aliases AS a ON u.user_id = a.id
- LEFT JOIN emails AS e ON ( e.flags = \'active\' AND e.uid = u.user_id)
+ LEFT JOIN emails AS e ON (e.flags = "active" AND e.uid = u.user_id)
WHERE a.alias = {?}
GROUP BY u.user_id', $m);
if(list($prenom, $nom, $promo, $broken) = $res->fetchOneRow()) {
$res = Xdb::query("SELECT u.nom, u.prenom, u.promo, FIND_IN_SET('femme', u.flags) AS sexe,
u.deces = '0000-00-00' AS alive, a.alias AS forlife, b.alias AS bestalias,
- e.email, e.last
+ IF(e.email IS NOT NULL, e.email, IF(FIND_IN_SET('googleapps', u.mail_storage), 'googleapps', NULL)) AS email, e.last
FROM auth_user_md5 AS u
INNER JOIN aliases AS a ON (a.id = u.user_id AND a.type = 'a_vie')
INNER JOIN aliases AS b ON (b.id = u.user_id AND FIND_IN_SET('bestalias', b.flags))
if ($globals->mailstorage->googleapps_domain) {
require_once 'googleapps.inc.php';
$account = new GoogleAppsAccount(S::v('uid'), S::v('forlife'));
- if ($account->g_status == 'active' && $account->sync_password) {
+ if ($account->active() && $account->sync_password) {
$account->set_password($password);
}
}
// updates the Google Apps password as well.
if ($globals->mailstorage->googleapps_domain) {
require_once 'googleapps.inc.php';
- require_once 'user.func.inc.php';
- $forlife = get_user_forlife($uid, '_silent_user_callback');
- $account = new GoogleAppsAccount($uid, $forlife);
- if ($account->g_status == 'active' && $account->sync_password) {
+ $account = new GoogleAppsAccount($uid);
+ if ($account->active() && $account->sync_password) {
$account->set_password($password);
}
}
WHERE matricule={?}", $x);
$login = $res->fetchOneCell();
} else {
- $login = get_user_forlife($x);
+ $login = get_user_forlife($x, S::logged() ? '_default_user_callback'
+ : '_silent_user_callback');
}
if (empty($login)) {
- if (preg_match('/([-a-z]+)\.([-a-z]+)\.([0-9]{4})/i', $x, $matches)) {
- $matches = str_replace('-', '_', $matches);
- $res = XDB::query("SELECT user_id
- FROM auth_user_md5
- WHERE prenom LIKE {?} AND nom LIKE {?} AND promo = {?}
- AND perms = 'pending'",
- $matches[1], $matches[2], $matches[3]);
- if ($res->numRows() == 1) {
- $uid = $res->fetchOneCell();
- pl_redirect('marketing/public/' . $uid);
- }
+ $user = get_not_registered_user($x, true);
+ if ($user->total() != 1) {
+ return PL_NOT_FOUND;
}
- return PL_NOT_FOUND;
+ $user = $user->next();
+ if (S::logged()) {
+ pl_redirect('marketing/public/' . $user['user_id']);
+ }
+ $user['forlife'] = $x;
+ } else {
+ $new = Env::v('modif') == 'new';
+ $user = get_user_details($login, S::v('uid'), $view);
+ }
+
+ if (S::logged()) {
+ $_SESSION['log']->log('view_profile', $login);
}
- $new = Env::v('modif') == 'new';
- $user = get_user_details($login, S::v('uid'), $view);
$title = $user['prenom'] . ' ' . ( empty($user['nom_usage']) ? $user['nom'] : $user['nom_usage'] );
$page->assign('xorg_title', $title);
$user['forlife'].'@'.$globals->mail->domain,
$user['forlife'].'@'.$globals->mail->domain2);
$page->assign('virtualalias', $res->fetchOneCell());
+ $page->assign('view', $view);
$page->addJsLink('close_on_esc.js');
header('Last-Modified: ' . date('r', strtotime($user['date'])));
}
// Check if the given email is known as dangerous
- $res = Xdb::iterRow("SELECT w.state, w.description, a.alias
- FROM emails AS e
- INNER JOIN emails_watch AS w ON (e.email = w.email AND w.state != 'safe')
- INNER JOIN aliases AS a ON (e.uid = a.id AND a.type = 'a_vie')
- WHERE e.email = {?}
- ORDER BY a.alias", Post::v('email'));
- $aliases = array();
- while(list($gstate, $gdescription, $alias) = $res->next()) {
- $state = $gstate;
- $description = $gdescription;
- $aliases[] = $alias;
- }
- if (count($aliases) != 0) {
+ $res = XDB::query("SELECT w.state, w.description
+ FROM emails_watch AS w
+ WHERE w.email = {?} AND w.state != 'safe'",
+ Post::v('email'));
+ $email_banned = false;
+ if ($res->numRows()) {
+ list($state, $description) = $res->fetchOneRow();
$alert .= "Email surveille propose a l'inscription - ";
+ $sub_state['email_desc'] = $description;
+ if ($state == 'dangerous') {
+ $email_banned = true;
+ }
}
if ($sub_state['watch']) {
$alter .= "Inscription d'un utilisateur surveillé - ";
$alert .= "Date de naissance incorrecte à l'inscription - ";
}
$sub_state['email'] = Post::v('email');
- if (check_ip('unsafe')) {
+ $ip_banned = check_ip('unsafe');
+ if ($ip_banned) {
+ $alert .= "Tentative d'inscription depuis une IP surveillee";
+ }
+ if ($email_banned || $ip_banned) {
$err = "Une erreur s'est produite lors de l'inscription."
. " Merci de contacter <a href='mailto:register@{$globals->mail->domain}>"
. " register@{$globals->mail->domain}</a>"
. " pour nous faire part de cette erreur";
- $alert .= "Tentative d'inscription depuis une IP surveillee";
} else {
$sub_state['step'] = 4;
if (count($sub_state['backs']) >= 3) {
if ($globals->mailstorage->googleapps_domain) {
require_once 'googleapps.inc.php';
$account = new GoogleAppsAccount(S::v('uid'), S::v('forlife'));
- if ($account->g_status == 'active' && $account->sync_password) {
+ if ($account->active() && $account->sync_password) {
$account->set_password($password);
}
}
}
if (Post::v('imap')) {
require_once 'emails.inc.php';
- $storage = new MailStorageIMAP(S::v('uid'));
- $storage->enable();
+ $storage = new EmailStorage(S::v('uid'), 'imap');
+ $storage->activate();
}
pl_redirect('profile/edit');
if (Env::has('quick') || $action == 'geoloc') {
$quick = trim(Env::v('quick'));
+ if (S::logged() && !Env::has('page')) {
+ $_SESSION['log']->log('search', 'quick=' . $quick);
+ }
$list = 'profile|prf|fiche|fic|referent|ref|mentor';
if (S::has_perms()) {
$list .= '|admin|adm|ax';
'school' => array('field' => 'id', 'table' => 'applis_def', 'text' => 'text', 'exact' => false),
'city' => array('table' => 'geoloc_city', 'text' => 'name', 'exact' => false)
);
+ if (!Env::has('page')) {
+ $_SESSION['log']->log('search', 'adv=' . var_export($_GET, true));
+ }
foreach ($textFields as $field=>&$query) {
if (!Env::v($field) && Env::v($field . 'Txt')) {
$res = XDB::query("SELECT {$query['field']}
ad1.text AS app1text, ad1.url AS app1url, ai1.type AS app1type,
es.label AS secteur, ef.fonction_fr AS fonction,
IF(n.nat=\'\',n.pays,n.nat) AS nat, n.a2 AS iso3166,
- COUNT(em.email) > 0 AS actif,';
+ (COUNT(em.email) > 0 OR FIND_IN_SET("googleapps", u.mail_storage) > 0) AS actif,';
// hide private information if not logged
if (S::logged())
$globals->search->result_fields .='
'stats/graph/evolution'
=> $this->make_hook('graph_evo', AUTH_COOKIE),
'stats/promos' => $this->make_hook('promos', AUTH_COOKIE),
+ 'stats/profile' => $this->make_hook('profile', AUTH_COOKIE),
'stats/coupures' => $this->make_hook('coupures', AUTH_PUBLIC),
);
$page->assign('mxs', $res);
}
}
+
+ function handler_profile(&$page, $period = 'overall')
+ {
+ $page->changeTpl('stats/profile.tpl');
+
+ $time = '';
+ switch ($period) {
+ case 'week': case 'month': case 'year':
+ $time = ' AND e.stamp > DATE_SUB(CURDATE(), INTERVAL 1 ' . strtoupper($period) . ')';
+ break;
+ }
+ $rows = XDB::iterator("SELECT IF(u.nom_usage != '', u.nom_usage, u.nom) AS nom,
+ u.prenom, u.promo, e.data AS forlife, COUNT(*) AS count
+ FROM logger.events AS e
+ INNER JOIN logger.actions AS act ON (e.action = act.id)
+ INNER JOIN aliases AS a ON (a.alias = e.data)
+ INNER JOIN auth_user_md5 AS u ON (u.user_id = a.id)
+ WHERE act.text = 'view_profile' $time
+ GROUP BY e.data
+ ORDER BY count DESC
+ LIMIT 10");
+ $page->assign('profiles', $rows);
+ $page->assign('period', $period);
+ }
}
// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
LEFT JOIN groupex.evenements_participants AS ep ON (ep.eid = e.eid AND ep.uid = {?})
WHERE asso_id = {?}
AND archive = " . ($archive ? "1 " : "0 ")
- . (is_member() || may_update() ? "" : " AND accept_nonmembre != 0 ")
. "GROUP BY e.eid
ORDER BY inscr_open DESC, debut DESC", S::v('uid'), $globals->asso('id'));
$evts = array();
+ $undisplayed_events = 0;
while ($e = $evenements->next()) {
+ if (!is_member() && !may_update() && !$e['accept_nonmembre']) {
+ $undisplayed_events ++;
+ continue;
+ }
+
$e['show_participants'] = ($e['show_participants'] && (is_member() || may_update()));
$res = XDB::query(
"SELECT titre, details, montant, ei.item_id, nb, ep.paid
}
$page->assign('evenements', $evts);
+ $page->assign('undisplayed_events', $undisplayed_events);
}
function handler_sub(&$page, $eid = null)
global $globals;
$site = $globals->asso('site');
if (!$site) {
- $page->trig('Le groupe n\'a pas de site web');
+ $page->trig('Le groupe n\'a pas de site web.');
return $this->handler_index($page);
}
http_redirect($site);
m.perms='admin' AS admin,
m.origine='X' AS x,
u.perms!='pending' AS inscrit,
- m.uid, IF(e.email IS NULL,NULL,1) AS actif
+ m.uid, IF(e.email IS NULL AND FIND_IN_SET('googleapps', u.mail_storage) = 0, NULL, 1) AS actif
FROM groupex.membres AS m
LEFT JOIN auth_user_md5 AS u ON ( u.user_id = m.uid )
LEFT JOIN aliases AS a ON ( a.id = m.uid AND a.type='a_vie' )
. "j'ai le plaisir de t'annoncer que ton inscription a été validée !\n"
. "\n"
. "Bien cordialement,\n"
+ . "-- \n"
. "{$_SESSION["prenom"]} {$_SESSION["nom"]}.";
$mailer->setTxtBody($message);
$mailer->send();
- $page->kill("$prenom $nom a bien été inscrit" . ($sexe ? 'e' : '') . ".");
+ pl_redirect("member/$u");
}
elseif (Env::has('refuse'))
{
$mailer->setSubject('['.$globals->asso('nom').'] Demande d\'inscription annulée');
$mailer->setTxtBody(Env::v('motif'));
$mailer->send();
- $page->kill("la demande $prenom $nom a bien été refusée");
+ $page->kill("La demande de $prenom $nom a bien été refusée.");
} else {
$page->assign('show_form', true);
$page->assign('prenom', $prenom);
}
if (is_member()) {
- $page->kill("tu es déjà membre !");
+ $page->kill("Tu es déjà membre !");
return;
}
pl_redirect("member/$email");
}
} else {
- $page->trig("« <strong>$email</strong> » n'est pas une adresse mail valide");
+ $page->trig("« <strong>$email</strong> » n'est pas une adresse mail valide.");
}
}
}
if ($res->numRows() == 0) {
$x = get_not_registered_user($login);
if (!$x) {
- $page->trig("Le login $login ne correspond à aucun X");
+ $page->trig("Le login $login ne correspond à aucun X.");
return false;
} else if (count($x) > 1) {
- $page->trig("Le login $login correspond a plusieurs camarades");
+ $page->trig("Le login $login correspond a plusieurs camarades.");
return false;
}
$uid = $x[0]['user_id'];
$perms ? 'admin' : 'membre',
$user['uid'], $globals->asso('id'));
$user['perms'] = $perms;
- $page->trig('permissions modifiées');
+ $page->trig('Permissions modifiées !');
}
// Update ML subscriptions
if ($ask == $state) {
if ($state && $email_changed) {
$mmlist->replace_email($ml, $from_email, $user['email2']);
- $page->trig("L'abonnement de {$user['prenom']} {$user['nom']} à $ml@ a été mis à jour");
+ $page->trig("L'abonnement de {$user['prenom']} {$user['nom']} à $ml@ a été mis à jour.");
}
continue;
}
."cours sur <strong>$ml@</strong> !!!");
} elseif ($ask) {
$mmlist->mass_subscribe($ml, Array($user['email2']));
- $page->trig("{$user['prenom']} {$user['nom']} a été abonné à $ml@");
+ $page->trig("{$user['prenom']} {$user['nom']} a été abonné à $ml@.");
} else {
if ($email_changed) {
$mmlist->mass_unsubscribe($ml, Array($from_email));
} else {
$mmlist->mass_unsubscribe($ml, Array($user['email2']));
}
- $page->trig("{$user['prenom']} {$user['nom']} a été désabonné de $ml@");
+ $page->trig("{$user['prenom']} {$user['nom']} a été désabonné de $ml@.");
}
}
XDB::query("INSERT INTO virtual_redirect (vid,redirect)
SELECT vid,{?} FROM virtual WHERE alias={?}",
$user['email'], $ml);
- $page->trig("{$user['prenom']} {$user['nom']} a été abonné à $ml");
+ $page->trig("{$user['prenom']} {$user['nom']} a été abonné à $ml.");
} else {
XDB::query("DELETE FROM virtual_redirect
USING virtual_redirect
INNER JOIN virtual USING(vid)
WHERE redirect={?} AND alias={?}",
$user['email'], $ml);
- $page->trig("{$user['prenom']} {$user['nom']} a été désabonné de $ml");
+ $page->trig("{$user['prenom']} {$user['nom']} a été désabonné de $ml.");
}
}
}
($art['promo_min'] != 0 && ($art['promo_min'] <= 1900 || $art['promo_min'] >= 2020)) ||
($art['promo_max'] != 0 && ($art['promo_max'] <= 1900 || $art['promo_max'] >= 2020))))
{
- $page->trig("L'intervalle de promotions est invalide");
+ $page->trig("L'intervalle de promotions est invalide.");
Post::kill('valid');
}
if (!trim($art['titre']) || !trim($art['texte'])) {
- $page->trig("L'article doit avoir un titre et un contenu");
+ $page->trig("L'article doit avoir un titre et un contenu.");
Post::kill('valid');
}
$art['promo_min'], $art['promo_max'], $art['peremption'], "", S::v('uid'),
$upload);
$article->submit();
- $page->trig("L'affichage sur la page d'accueil de Polytechnique.org est en attente de validation");
+ $page->trig("L'affichage sur la page d'accueil de Polytechnique.org est en attente de validation.");
} else if ($upload && $upload->exists()) {
$upload->rm();
}
$article = new NLReq(S::v('uid'), $globals->asso('nom') . " : " .$art['titre'],
$art['texte'], $art['contact_html']);
$article->submit();
- $page->trig("La parution dans la Lettre Mensuelle est en attente de validation");
+ $page->trig("La parution dans la Lettre Mensuelle est en attente de validation.");
}
} else {
XDB::query("UPDATE groupex.announces
$art = $res->fetchOneAssoc();
$art['contact_html'] = $art['contacts'];
} else {
- $page->kill("Aucun article correspond à l'identifiant indiqué");
+ $page->kill("Aucun article correspond à l'identifiant indiqué.");
}
}
--- /dev/null
+<?php
+/***************************************************************************
+ * 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 *
+ ***************************************************************************/
+require_once 'platal.inc.php';
+
+function smarty_function_make_forlife($params, &$smarty)
+{
+ return make_forlife($params['nom'], $params['prenom'], $params['promo']);
+}
+
+/* vim: set expandtab enc=utf-8: */
+?>
{foreach from=$table item=ip}
<tr class="{cycle values="pair,impair"}">
<td>
- <strong>{$ip.ip}</strong><br />
+ <strong>{$ip.ip}/{$ip.mask}</strong><br />
<small>{$ip.host}</small><br />
Ajoutée le {$ip.detection|date_format}
</td>
{/if}
</tr>
<tr class="pair">
+ <td class="titre">Masque d'influence</td>
+ <td><input type="text" name="maskN" value="{$ip.mask}" /></td>
+ </tr>
+ <tr class="pair">
<td class="titre">Danger</td>
<td>
<select name="stateN">
</table>
</form>
+<p><strong>* à ne modifier qu'avec l'accord express de l'utilisateur !!!</strong></p>
+
<form id="bans" method="post" action="admin/user">
<table cellspacing="0" cellpadding="2" class="tinybicol">
<tr>
</tr>
<tr class="impair">
<td class="titre">
- Poster :
+ Poster
</td>
<td>
- <input type="text" name="write_perm" size="40" maxlength="255" value="{$bans.write_perm}" />
+ <input type="text" name="write_perm" size="32" maxlength="255" value="{$bans.write_perm}" />
</td>
<td class="action">
<a href="javascript:ban_write()">Bannir</a>
</tr>
<tr class="pair">
<td class="titre">
- Lire :
+ Lire
</td>
<td>
- <input type="text" name="read_perm" size="40" maxlength="255" value="{$bans.read_perm}" />
+ <input type="text" name="read_perm" size="32" maxlength="255" value="{$bans.read_perm}" />
</td>
<td class="action">
<a href="javascript:ban_read()">Bannir</a>
<td class="titre">
Commentaire
</td>
- <td>
+ <td colspan="2">
<input type="text" name="comment" size="40" maxlength="255" value="{$bans.comment}" />
</td>
- <td/>
</tr>
<tr class="center">
<td colspan="3">
</table>
</form>
-<p>
-<strong>* à ne modifier qu'avec l'accord express de l'utilisateur !!!</strong>
-</p>
-
{javascript name="ajax"}
{test_email forlife=$mr.forlife}
Redirections
</th>
</tr>
- {assign var=actives value=false}
- {assign var=disabled value=false}
+ {assign var=actives value=false}
+ {assign var=disabled value=false}
{foreach item=mail from=$emails}
{cycle assign=class values="impair,pair"}
<tr class="{$class}">
- {if $mail->active}
+ {if $mail->active && $mail->has_disable()}
{assign var=actives value=true}
- {elseif $mail->disabled}
+ {elseif $mail->disabled && $mail->has_disable()}
{assign var=disabled value=true}
{/if}
<td class="titre">
</td>
<td>
{if $mail->broken}<span style="color: #f00">{/if}
- {$mail->email}
+ {$mail->display_email}
{if $mail->broken}<em> (en panne)</em></span>{/if}
</td>
<td class="action">
+ {if $mail->is_removable()}
<a href="javascript:del_fwd('{$mail->email}')">delete</a>
+ {/if}
</td>
</tr>
{if $mail->panne && $mail->panne neq "0000-00-00"}
<tr class="{$class}">
<td colspan="3" class="smaller" style="color: #f00">
{icon name=error title="Panne"}
- Panne de {$mail->email} le {$mail->panne|date_format}
+ Panne de {$mail->display_email} le {$mail->panne|date_format}
{if $mail->panne neq $mail->last}confirmée le {$mail->last|date_format}{/if}
</td>
<td class="action">
{javascript name="jquery"}
<script type="text/javascript">//<![CDATA[
{literal}
-function activateField(name, id, obj) {
- $("#" + name + "_" + id).show();
- return true;
+function toggleField(name, id, obj) {
+ $("#" + name + "_" + id).toggle();
}
{/literal}
//]]></script>
</tr>
{include file=$valid->formu()}
{if $valid->editor()}
- <tr>
+ <tr onclick="toggleField('edit', '{$valid->id()}')" style="cursor: pointer">
<th colspan="2">
- {if $preview_id neq $valid->id()}
+ {if $preview_id neq $valid->id()}
<div style="float: left">
- <a href="javascript:activateField('edit', '{$valid->id()}')">{icon name="add"}</a>
+ {icon name="add"}
</div>
{/if}
- Editer
+ Éditer
</th>
</tr>
<tr {if $preview_id neq $valid->id()}style="display: none"{/if} id="edit_{$valid->id()}">
<input type="hidden" name="type" value="{$valid->type}" />
<input type="hidden" name="stamp" value="{$valid->stamp}" />
<br />
- <input type="submit" name="edit" value="Editer" />
+ <input type="submit" name="edit" value="Éditer" />
</div>
</form>
</td>
</tr>
{/if}
- <tr>
+ <tr onclick="toggleField('comment', '{$valid->id()}')" style="cursor: pointer">
<th colspan='2'>
{if $valid->comments|@count eq 0}
<div style="float: left">
- <a href="javascript:activateField('comment', '{$valid->id()}')">{icon name="add"}</a>
+ {icon name="add"}
</div>
{/if}
Commentaires
</form>
</td>
</tr>
- <tr><th colspan='2'>Réponse</th></tr>
+ <tr>
+ <th colspan='2'>
+ {if $preview_id neq $valid->id()}
+ <div style="float: left">
+ {icon name="null"}
+ </div>
+ {/if}
+ Réponse
+ </th>
+ </tr>
<tr>
<td colspan='2' {popup caption="Règles de validation" text=$valid->ruleText()}>
<form action="admin/validate" method="post">
<option value="{$automatic_answer.answer}">{$automatic_answer.title}</option>
{/foreach}
</select>
- <a href="admin/validate/answers">{icon name="page_edit" title="Editer les réponses automatiques"}</a>
+ <a href="admin/validate/answers">{icon name="page_edit" title="Éditer les réponses automatiques"}</a>
</div>
<div class='center'>
Ajouté dans l'email :<br />
--------------------------------------------------------------------
Cette lettre est envoyée par l'AX grâce aux outils de Polytechnique.org.
+{if $is_mail}
archives : <https://www.polytechnique.org/ax>
ne plus recevoir : <https://www.polytechnique.org/ax/out{if $hash}/{$hash}{/if}>
+{else}
+archives : <https://www.polytechnique.org/ax>
+ne plus recevoir : <https://www.polytechnique.org/ax/out{if $hash}/{$hash}{/if}>
+{/if}
{if !$is_mail}
</pre>
<tr><th>{$am->title(true)}</th></tr>
<tr>
<td>
- {include file="axletter/letter.tpl"}
+ {include file="axletter/letter.mail.tpl"}
</td>
</tr>
</table>
{foreach from=$u.data key=cid item=d}
-!{if $d|@count eq 1}{$cats[$cid].mail_sg}{else}{$cats[$cid].mail}{/if} :
+!{if $d|@count eq 1}{if $d[0].sexe}{$cats[$cid].mail_sg_xette}{else}{$cats[$cid].mail_sg}{/if}{else}{$cats[$cid].mail}{/if}:
-{foreach from=$d key=promo item=x}
-* (X{$x.promo}), le {$x.date|date_format:"%d %b %Y"}, [[https://www.polytechnique.org/profile/private/{$x.bestalias}|{$x.prenom} {$x.nom}]]
+{foreach from=$d item=x}
+* (X{$x.promo}), le {$x.date|date_format:"%d %B %Y"}, [[https://www.polytechnique.org/profile/private/{$x.bestalias}|{$x.prenom} {$x.nom}]]
{/foreach}
{/foreach}
---
+--
L'Équipe de Polytechnique.org
-'''''Note :''''' Tu reçois ce mail ce mail car tu as activé la notification automatique par mail des événements que tu surveilles.\\
+'''''Note:''''' Tu reçois ce mail ce mail car tu as activé la notification automatique par mail des événements que tu surveilles.\\
Tu peux changer cette options sur la [[https://www.polytechnique.org/carnet/notifs|page de configuration des notifications]].
{/if}
{if ($promo|@count) > 1}
{$notifs->_cats[$cid].mail} :
{else}
- {$notifs->_cats[$cid].mail_sg} :
+ {if $promo[0].sexe}
+ {$notifs->_cats[$cid].mail_sg_xette} :
+ {else}
+ {$notifs->_cats[$cid].mail_sg} :
+ {/if}
{/if}
{/foreach}
{/if}</h2>
{$promo[row].date|date_format}
</td>
{if $promo[row].data}
- <tr><td>{$promo[row].data|smarty:nodefaults}</td></tr>
+ </tr><tr><td>{$promo[row].data|smarty:nodefaults}</td>
{/if}
</tr>
{/section}
</p>
{/if}
-{if !$smarty.session.auth}
-<p>
-<strong>Tu ne connais pas ton mot de passe ?</strong>
-</p>
-<ul>
- <li>
- Si tu viens de terminer ta pré-inscription, <strong>il est dans le mail</strong> que
- nous t'avons envoyé (expéditeur pre-inscription@{#globals.mail.domain#}).
- </li>
- <li>
- Si tu n'es jamais venu sur le site, <strong>il faut t'enregistrer auprès de
- nous</strong> pour obtenir un accès. {#globals.core.sitename#} c'est l'e-mail des X,
- l'annuaire en ligne, plus un tas d'autres services. Nous te fournirons un accès le plus
- rapidement possible. <strong> <a href="register/">Clique ici pour nous demander tes
- paramètres personnels.</a></strong>
- </li>
-</ul>
-{/if}
-
{if $smarty.request.response}<!-- failed login code //-->
-<br />
<div class="erreur">
Erreur d'identification. Essaie à nouveau !
</div>
-{/if}
-
<br />
+{/if}
<form action="{$smarty.server.REQUEST_URI}" method="post" id="login" onsubmit="doChallengeResponse(); return false;" style="display: none">
<table class="bicol" cellpadding="4" summary="Formulaire de login">
<tr>
<td></td>
<td>
- <input type="checkbox" name="remember" id="remember" /><label for="remember">Garder l'accès aux services après déconnexion</label>
- </td>
- </tr>
- <tr>
- <td></td>
- <td>
- Coche la case ci-dessus pour être automatiquement reconnu lors de ta prochaine connexion depuis cet ordinateur.
- Il n'est pas conseillé de la cocher si cette machine n'est pas <b>strictement</b> personnelle.
+ <script type="text/javascript">{literal}
+ function confirm_remember(input) {
+ if (input.checked && !confirm('Cocher cette case te permet d\'être automatiquement reconnu à ta prochaine connexion depuis cet ordinateur. '
+ + 'Il n\'est pas conseillé de cocher la case si cette machine n\'est pas strictement personnelle.\n\nVeux-tu vraiment cocher cette case ?')) {
+ input.checked = false;
+ return false;
+ }
+ return true;
+ }
+ {/literal}</script>
+ <input type="checkbox" name="remember" id="remember" onchange="return confirm_remember(this);" /><label for="remember">Garder l'accès aux services après déconnexion</label>
</td>
</tr>
<tr>
</td>
</tr>
</table>
- <p>
- Problème de connexion ? <a href="Xorg/FAQ?display=light#connect" class="popup2">La réponse est là.</a>
- </p>
</form>
+{if !$smarty.session.auth}
+<p>
+<strong>Tu ne connais pas ton mot de passe ?</strong>
+</p>
+<ul>
+ <li>
+ Si tu viens de terminer ta pré-inscription, <strong>il est dans le mail</strong> que
+ nous t'avons envoyé (expéditeur pre-inscription@{#globals.mail.domain#}).
+ </li>
+ <li>
+ Si tu n'es jamais venu sur le site, <strong>il faut t'enregistrer auprès de
+ nous</strong> pour obtenir un accès. {#globals.core.sitename#} c'est l'e-mail des X,
+ l'annuaire en ligne, plus un tas d'autres services. Nous te fournirons un accès le plus
+ rapidement possible. <strong> <a href="register/">Clique ici pour nous demander tes
+ paramètres personnels.</a></strong>
+ </li>
+</ul>
+{/if}
+
<div id="nologin" style="background: #fcc; color: red">
Pour assurer la confidentialité de ton mot de passe, il est chiffré sur ta machine
avant de nous être transmis. Pour cela, il faut
</div>
</div>
+<p>
+ <strong>Problème de connexion ?</strong> <a href="Xorg/FAQ?display=light#connect" class="popup2">La réponse est là.</a>
+</p>
+
<script type="text/javascript">
document.getElementById('login').style.display="";
document.getElementById('nologin').style.display="none";
</tr>
<tr class="impair">
<td>
- {if $mails->total() eq 0}
+ {if count($mails) eq 0}
<p class="erreur">
Tu n'as actuellement aucune adressse de redirection. Tout courrier électronique qui t'es adresses
ci-dessus génère une erreur. Modifie au plus vite ta liste de redirection.<br/>
</p>
{else}
Actuellement, tout courrier électronique qui t'y est adressé, est envoyé
- {if $mails->total() eq 1} à l'adresse{else} aux adresses{/if} :
+ {if count($mails) eq 1} à l'adresse{else} aux adresses{/if} :
<ul>
- {iterate from=$mails item=m}
- <li><strong>{$m.email}</strong></li>
- {/iterate}
- </ul>
- {/if}
- {if count($storage) neq 0}
- Ton courrier est également stocké sur {if count($storage) eq 1}le compte suivant{else} les comptes suivants{/if} :
- <ul>
- {if in_array('googleapps', $storage)}
- <li><a href="googleapps"><strong>Compte Google Apps / GMail de Polytechnique.org</strong></a></li>
- {/if}
- {if in_array('imap', $storage)}
- <li><a href="Xorg/IMAP"><strong>Accès de secours aux emails (IMAP)</strong></a></li>
- {/if}
+ {foreach from=$mails item=m}
+ <li><strong>{$m->display_email}</strong></li>
+ {/foreach}
</ul>
{/if}
{test_email}
var remove = $(".active_email:checked");
if (remove.length <= 1) {
remove.attr("disabled", "disabled");
+ remove.parent('td').parent('tr').children('td').children('.remove_email').hide();
} else {
remove.removeAttr("disabled");
+ $('.remove_email').show();
}
}
$.get(link.href, {},function() {
$('tr[@id=line_' + email.replace('@', '_at_') + ']').remove();
showRemove();
+ activeEnable();
});
}
return false;
}
}
+ function updateRedirect(checked, email)
+ {
+ activeEnable();
+ Ajax.update_html(null, 'emails/redirect/' + (checked ? '' : 'in') + 'active/' + email, redirectUpdate);
+ }
+
{/literal}
//]]></script>
{javascript name="jquery"}
<div class="center">
<table class="bicol" summary="Adresses de redirection">
<tr>
- <th>Email</th>
+ <th>Redirection</th>
<th>Actif</th>
<th>Réécriture</th>
<th> </th>
<strong>
{if $e->broken}<span class="erreur">{assign var="erreur" value="1"}{/if}
{if $e->panne neq '0000-00-00'}{assign var="panne" value="1"}{icon name=error title="En panne"}{/if}
- {$e->email}
+ {$e->display_email}
{if $e->broken}</span>{/if}
</strong>
</td>
<td>
- <input type="checkbox" value="{$e->email}" class="active_email"
+ <input type="checkbox" value="{$e->email}" {if $e->sufficient}class="active_email"{/if}
{if $e->active}checked="checked"{/if}
{if $smarty.foreach.redirect.total eq 1}disabled="disabled"{/if}
- onchange="Ajax.update_html(null,'{$globals->baseurl}/emails/redirect/'+(this.checked?'':'in')+'active/{$e->email}', redirectUpdate)" /></td>
+ onchange="updateRedirect(this.checked, '{$e->email}')" /></td>
<td>
+ {if $e->has_rewrite()}
<select onchange="Ajax.update_html(null,'emails/redirect/rewrite/{$e->email}/'+this.value, redirectUpdate)">
<option value=''>--- aucune ---</option>
{assign var=dom1 value=#globals.mail.domain#}
value='{$a.alias}@{#globals.mail.domain2#}'>{$a.alias}@{#globals.mail.domain2#}</option>
{/foreach}
</select>
+ {else}
+ <em>pas de réécriture</em>
+ {/if}
</td>
<td>
+ {if $e->is_removable()}
<a href="emails/redirect/remove/{$e->email}"
class="remove_email"
onclick="return removeRedirect(this, "{$e->email}");" >
{icon name=cross title="Supprimer"}
</a>
+ {else}
+ {if $e->sufficient}<span class="remove_email"></span>{/if}
+ <a href="emails/redirect#{$e->email}">{icon name=information title="Plus d'informations"}</a>
+ {/if}
</td>
</tr>
{/foreach}
- {if $googleapps eq 'active'}
- <tr class="{cycle values="pair,impair"}">
- <td><strong>Compte GMail / Google Apps</strong></td>
- <td>
- <input type="checkbox" value="googleapps" disabled="disabled"
- {if in_array('googleapps', $storage)}checked="checked"{/if} />
- </td>
- <td>-</td>
- <td>
- <a href="emails/redirect#googleapps">{icon name=information title="Plus d'informations"}</a>
- </td>
- </tr>
- {/if}
- <script type="text/javascript">activeEnable(); showRemove();</script>
<tr class="{cycle values="pair,impair"}"><td colspan="4">
<form action="emails/redirect" method="post">
<div>
</form>
</td></tr>
</table>
+ <script type="text/javascript">activeEnable(); showRemove();</script>
</div>
{if $panne}
<p class="smaller">
</fieldset>
{/if}
-{* TODO(vincent.zanotti): remove the following block of code when both IMAP and GApps will be active. *}
-{if in_array('imap', $storage) neq 0 or #globals.mailstorage.imap_active# or hasPerm('admin')}
- {assign var=has_imap value=true}
-{else}
- {assign var=has_imap value=false}
-{/if}
-{if $googleapps or #globals.mailstorage.googleapps_active# or hasPerm('admin')}
- {assign var=has_googleapps value=true}
-{else}
- {assign var=has_googleapps value=false}
-{/if}
-
-{if $has_imap or $has_googleapps}
+{if #globals.mailstorage.googleapps_active# or #globals.mailstorage.imap_active# or hasPerm('admin') or $googleapps}
<h1>Tes comptes de stockage de courrier</h1>
{/if}
-{if $has_imap}
+{if #globals.mailstorage.imap_active# or hasPerm('admin')}
<p>
Polytechnique.org te propose de conserver les mails que tu reçois, pendant une durée limitée (environ 30 jours).
Grâce à ce service, tu disposes d'une sauvegarde de tes mails en secours, au cas où, par exemple, tu effacerais
</p>
<table class="bicol" summary="Compte de stockage">
- <col width="75%" />
- <col width="25%" />
+ <col width="55%" />
+ <col width="45%" />
<tr>
<th colspan="2">Compte de stockage</th>
</tr>
</a><br />Hébergé par Polytechnique.org
</td>
<td style="text-align: center; vertical-align: middle">
- <form action="emails/redirect/storage/imap/{if in_array('imap', $storage)}inactive{else}active{/if}" method="post">
- {if in_array('imap', $storage)}
- <input type="submit" value="Désactiver" />
- {else}
- <input type="submit" value="Activer" />
- {/if}
- </form>
+ <a href="emails/redirect#line_imap">Voir l'état de la redirection vers l'IMAP</a>
</td>
</tr>
</table>
{/if}
-{if $has_googleapps}
+{if #globals.mailstorage.googleapps_active# or hasPerm('admin') or $googleapps}
<br />
<p>
Grâce à un partenariat avec Google, Polytechnique.org te propose également un compte
</p>
<table class="bicol" summary="Compte de stockage" id="googleapps">
- <col width="75%" />
- <col width="25%" />
+ <col width="55%" />
+ <col width="45%" />
<tr>
<th colspan="2">Compte de stockage</th>
</tr>
{if $googleapps eq 'active'}
<td>
<a href="googleapps">
- <strong>Redirection des emails vers GMail / Google Apps</strong>
+ <strong>Compte GMail / Google Apps</strong>
</a><br />Hébergé par Google
</td>
<td style="text-align: center; vertical-align: middle">
- <form action="emails/redirect/storage/googleapps/{if in_array('googleapps', $storage)}inactive{else}active{/if}" method="post">
- {if in_array('googleapps', $storage)}
- <input type="submit" value="Désactiver" />
- {else}
- <input type="submit" value="Activer" />
- {/if}
- </form>
+ Ton compte Google Apps est actif.<br />
+ <a href="emails/redirect#line_googleapps">Voir l'état de la redirection vers GMail</a>
</td>
{else}
<td colspan="2">
{if $sexe}Chère{else}Cher{/if} {$prenom},
Tu reçois ce mail car tu as demandé la confirmation du bon fonctionnement de ton adresse polytechnicienne {$email}.
-{if $redirects->total() gt 1}Si toutes tes redirections fonctionnent correctement tu devrais recevoir une copie de ce mail
+{if count($redirects) gt 1}Si toutes tes redirections fonctionnent correctement tu devrais recevoir une copie de ce mail
dans les boîtes suivantes :
-{iterate from=$redirects item=mail}
-* {$mail.email}
-{/iterate}
+{foreach from=$redirects item=mail}
+* {$mail->display_email}
+{/foreach}
{/if}
Tu trouveras sur le site divers outils pour gérer ton adresse email :
{/foreach}
{if !$has_evts}
<tr>
- <td class="half">Aucun article actuellement</td>
+ <td class="half">
+ {if $smarty.session.core_rss_hash}
+ <a href="rss/{$smarty.session.forlife}/{$smarty.session.core_rss_hash}/rss.xml" style="display:block;float:right" title="Annonces">
+ {icon name=feed title='fil rss'}
+ </a>
+ {else}
+ <a href='prefs/rss?referer=events' style="display:block;float:right">
+ {icon name=feed_add title='Activer mon fil rss'}
+ </a>
+ {/if}
+ Aucun article actuellement
+ </td>
</tr>
{/if}
</table>
--- /dev/null
+{**************************************************************************}
+{* *}
+{* 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 *}
+{* *}
+{**************************************************************************}
+
+Le tableau suivant permet de gérer la mise au ban (le bannissement) de certains utilisateurs aux forums.
+
+Chaque ligne permet de gérer les accès limités à :
+<ul>
+<li>une plage d'adresses IP donnée (entre ipmin et ipmax),</li>
+<li>à tout le monde (uid=0) ou seulement à un utilisateur donné,</li>
+<li>en restreignant l'accès en lecture à un ensemble de forums décrits par un masque,</li>
+<li>en restreignant l'accès en écriture à un ensemble de forums décrits par un masque.</li>
+</ul>
+
+<p>
+Dans les masques le <strong>*</strong> remplace n'importe quel texte et le <strong>!</strong> bloque l'accès au lieu de l'autoriser. Par exemple : <code>xorg.*,!xorg.prive.*</code> autorise tous les forums xorg sauf ceux qui s'appellent xorg.prive.qqchose.
+</p>
+
+<p>
+Les différentes règles sont appliquées par ordre de priorité décroissante.
+</p>
+
+{include file="core/table-editor.tpl"}
+
+{literal}
+<script type="text/javascript">
+ $('#body td table tr').each(function() {
+ var uidcell = $('td:eq(3)',this);
+ if (uidcell.length != 1) {
+ return;
+ }
+ var uid = uidcell.text().replace(/^\s+/g,'').replace(/\s+$/g,'');
+ uidcell.replaceWith('<'+'a href="admin/user/'+uid+'">'+uid+'</'+'a>');
+ });
+</script>
+{/literal}
+
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
+
--- /dev/null
+{**************************************************************************}
+{* *}
+{* 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 *}
+{* *}
+{**************************************************************************}
+
+<h1>Requête de la queue Google Apps</h1>
+
+{if $job}
+<table class="bicol">
+ <col width="50%" />
+ <col width="50%" />
+ <tr>
+ <th style="text-align: left" colspan="2">Queue id: {$job.q_id}</th>
+ </tr>
+
+ <tr class="impair">
+ <td class="titre">Propriétaire</td><td>{if $job.q_owner}{$job.q_owner}{else}<em>none</em>{/if}</td>
+ </tr>
+ <tr class="impair">
+ <td class="titre">Destinataire</td><td>{if $job.q_recipient}{$job.q_recipient}{else}<em>none</em>{/if}</td>
+ </tr>
+
+ <tr class="pair">
+ <td class="titre">Statut</td><td><code>{$job.p_status}</code></td>
+ </tr>
+ <tr class="pair">
+ <td class="titre">Priorité</td><td><code>{$job.p_priority}</code></td>
+ </tr>
+ <tr class="pair">
+ <td class="titre">Requête administrateur ?</td><td>{if $job.p_admin_request}oui{else}non{/if}</td>
+ </tr>
+
+ <tr class="impair">
+ <td class="titre">Entrée dans la queue</td><td>{$job.p_entry_date}</td>
+ </tr>
+ <tr class="impair">
+ <td class="titre">Date d'activation</td><td>{$job.p_notbefore_date}</td>
+ </tr>
+ <tr class="impair">
+ <td class="titre">Début de traitement</td><td>{if $job.p_start_date}{$job.p_start_date}{else}<em>none</em>{/if}</td>
+ </tr>
+ <tr class="impair">
+ <td class="titre">Fin de traitement</td><td>{if $job.p_end_date}{$job.p_end_date}{else}<em>none</em>{/if}</td>
+ </tr>
+
+ <tr class="pair">
+ <td class="titre">Erreurs récupérables</td><td>{$job.r_softfail_count}</td>
+ </tr>
+ <tr class="pair">
+ <td class="titre">Dernière erreur récupérable</td><td><code>{if $job.r_softfail_date}{$job.r_softfail_date}{else}<em>none</em>{/if}</code></td>
+ </tr>
+ <tr class="pair">
+ <td class="titre">Résultat du traitement</td><td><code>{if $job.r_result}{$job.r_result}{else}<em>none</em>{/if}</code></td>
+ </tr>
+
+ <tr class="impair">
+ <td class="titre">Type de requête</td><td><code>{$job.j_type}</code></td>
+ </tr>
+ <tr class="impair">
+ <td class="titre">Paramètres</td><td><pre>{$job.decoded_parameters}</pre></td>
+ </tr>
+</table>
+{else}
+<p><strong>Aucune requête n'a été trouvée.</strong></p>
+{/if}
+
+<p>Retourner à la <a href="admin/googleapps">page d'administration de Google Apps</a>.</p>
+
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
--- /dev/null
+{**************************************************************************}
+{* *}
+{* 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 *}
+{* *}
+{**************************************************************************}
+
+<h1>Gestion des utilisateurs</h1>
+
+<form method="post" action="admin/googleapps/user">
+<table class="tinybicol" cellspacing="0" cellpadding="2">
+ <tr>
+ <th>Administrer un utilisateur (Google Apps)</th>
+ </tr>
+ <tr>
+ <td class="center"><input type="text" name="login" size="40" maxlength="255" value="" /></td>
+ </tr>
+ <tr>
+ <td class="center"><input type="submit" value="Valider" /></td>
+ </tr>
+</table>
+</form>
+
+<h1>Queue de requêtes vers Google Apps</h1>
+
+<p>
+ Requête nécessitant <a href="Equipe/Infra-GoogleApps#admin-cli">l'intervention manuelle</a>
+ d'un administrateur Google Apps {if $googleapps_admin}(tu en es un){/if} :
+</p>
+<table class="bicol" style="text-align: center">
+ <tr>
+ <th>qid</th>
+ <th>date</th>
+ <th>recipient</th>
+ <th>type</th>
+ <th>parameters</th>
+ </tr>
+ {foreach from=$admin_requests item=r}
+ <tr class="{cycle values="impair,pair"}">
+ <td><a href="admin/googleapps/job/{$r.q_id}">{$r.q_id}</a></td>
+ <td>{$r.p_entry_date|date_format:"%Y-%m-%d %H:%M"}</td>
+ <td>{if $r.alias}<a href="admin/googleapps/user/{$r.alias}">{$r.alias}</a>{else}-{/if}</td>
+ <td>{$r.j_type}</td>
+ <td>{$r.parameters}</td>
+ </tr>
+ {/foreach}
+</table>
+
+<p>
+ Requêtes ayant échoué récemment (plus d'information dans la <a href="Equipe/Infra-GoogleApps">documentation</a>) :
+</p>
+<table class="bicol" style="text-align: center">
+ <tr>
+ <th>qid</th>
+ <th>date</th>
+ <th>recipient</th>
+ <th>type</th>
+ <th>reason</th>
+ <th></th>
+ </tr>
+ {iterate from=$failed_requests item=r}
+ <tr class="{cycle values="impair,pair"}">
+ <td><a href="admin/googleapps/job/{$r.q_id}">{$r.q_id}</a></td>
+ <td>{$r.p_entry_date|date_format:"%Y-%m-%d %H:%M"}</td>
+ <td>{if $r.alias}<a href="admin/googleapps/user/{$r.alias}">{$r.alias}</a>{else}-{/if}</td>
+ <td>{$r.j_type}</td>
+ <td><code>{$r.r_result}</code></td>
+ <td><a href="admin/googleapps/ack/{$r.q_id}">{icon name=cross title="Retirer cet échec"}</a></td>
+ </tr>
+ {/iterate}
+</table>
+
+<h1>Statistiques d'utilisation de Google Apps</h1>
+
+<div style="text-align: center">
+ <img src="images/googleapps/activity-monthly.png" alt="Activité Google Apps - 1 mois" width="500 height="250" />
+ <br /><em>Utilisation des comptes Google Apps sur les 31 derniers jours</em>.
+</div>
+
+<div style="text-align: center">
+ <img src="images/googleapps/activity-yearly.png" alt="Activité Google Apps - 1 an" width="500 height="250" />
+ <br /><em>Utilisation des comptes Google Apps sur les 12 derniers mois</em>.
+</div>
+
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
--- /dev/null
+{**************************************************************************}
+{* *}
+{* 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 *}
+{* *}
+{**************************************************************************}
+
+<h1>Compte Google Apps</h1>
+
+{if $account}
+{assign var=a value=$account}
+<table class="bicol">
+ <col width="50%" />
+ <col width="50%" />
+ <tr>
+ <th colspan="2" style="text-align: left">
+ <div style="float: left; text-align: left">
+ Compte = {$a->g_account_name}
+ </div>
+ <div style="float: right; text-align: right">
+ Google id = {$a->g_account_id}<br />
+ Plat/al id = {$user}
+ </div>
+ </th>
+ </tr>
+
+ <tr class="impair">
+ <td class="titre">Statut du compte</td>
+ <td>
+ <strong>{$a->g_status}</strong>
+ {if $admin_account}<br /><strong>Compte administrateur de Google Apps</strong>{/if}
+ </td>
+ </tr>
+ {if $a->suspended()}
+ <tr class="impair">
+ <td class="titre">Raison de suspension</td><td>{$a->g_suspension}</td>
+ </tr>
+ {/if}
+ <tr class="impair">
+ <td class="titre">Mots de passes synchronisés</td>
+ <td>
+ {if $a->sync_password}
+ oui (<a href="admin/googleapps/user/{$a->g_account_name}/forcesync">lancer une synchronisation</a>)
+ {else}non{/if}
+ </td>
+ </tr>
+ <tr class="impair">
+ <td class="titre">Redirection des mails</td><td>{if $googleapps_storage}activée{else}désactivee{/if}</td>
+ </tr>
+
+ <tr class="pair">
+ <td class="titre">Date de création</td><td>{$a->r_creation|date_format:"%Y-%m-%d"}</td>
+ </tr>
+ <tr class="pair">
+ <td class="titre">Dernière connexion</td><td>{$a->r_last_login|date_format:"%Y-%m-%d"}</td>
+ </tr>
+ <tr class="pair">
+ <td class="titre">Dernière utilisation du webmail</td><td>{$a->r_last_webmail|date_format:"%Y-%m-%d"}</td>
+ </tr>
+ <tr class="pair">
+ <td class="titre">Utilisation du quota mail</td><td>{$a->r_disk_usage/1024/1024|string_format:"%.2f"}MB</td>
+ </tr>
+</table><br />
+
+<table class="bicol" style="text-align: center">
+ <tr>
+ <th colspan="4" style="text-align: left">Requêtes en attente</th>
+ </tr>
+ <tr>
+ <th>qid</th>
+ <th>date</th>
+ <th>statut</th>
+ <th>type</th>
+ </tr>
+ {iterate from=$requests item=r}
+ <tr class="{cycle values="impair,pair"}">
+ <td><a href="admin/googleapps/job/{$r.q_id}">{$r.q_id}</a></td>
+ <td>{$r.p_entry_date|date_format:"%Y-%m-%d %H:%M"}</td>
+ <td>{$r.p_status}</td>
+ <td>{$r.j_type}</td>
+ </tr>
+ {/iterate}
+</table>
+{else}
+<p><strong>Aucun utilisateur n'a été trouvé.</strong></p>
+{/if}
+
+<p>Retourner à la <a href="admin/googleapps">page d'administration de Google Apps</a>.</p>
+
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
</tr>
</table>
-{elseif $account->g_status eq 'disabled' or $account->pending_update_suspension}
+{elseif $account->suspended() or $account->pending_update_suspension}
<br />
<table class="bicol" id="status">
<tr>
message sur ce compte.
</td>
</tr>
- {if $account->pending_validation_unsuspend or ($account->g_status eq 'disabled' and $account->pending_update_suspension)}
+ {if $account->pending_validation_unsuspend or ($account->suspended() and $account->pending_update_suspension)}
<tr class="pair">
<td>
La réactivation de ton compte est en attente de validation.<br />
Tu recevras un email dès que l'opération sera terminée.
</td>
</tr>
- {elseif $account->g_status neq 'disabled' and $account->pending_update_suspension}
+ {elseif !$account->suspended() and $account->pending_update_suspension}
<tr class="pair">
<td>
Les opérations de désactivation de ton compte Google Apps ne sont pas terminées, tu ne peux donc pas encore demander sa réactivation.
<form action="googleapps/password#password" method="post" id="changepass2">
<input type="hidden" name="response2" value="" />
</form><br />
- Pour une sécurité optimale, ton mot de passe circule de manière cryptée (https) et est stocké crypté irréversiblement sur nos serveurs, ainsi que sur ceux de Google.
+ Pour une sécurité optimale, ton mot de passe circule de manière sécurisée (https).
+ Il est chiffré irréversiblement sur nos serveurs, ainsi que sur ceux de Google.
</li>
</ul>
</td>
{* *}
{**************************************************************************}
-
-{if !$c.inscrit || $c.dcd}<div class='grayed'>{/if}
+{if (!$c.inscrit && $smarty.session.auth ge AUTH_COOKIE) || $c.dcd}<div class='grayed'>{/if}
<div class="contact" {if $c.inscrit}{if $smarty.session.auth ge AUTH_COOKIE}title="fiche mise à jour le {$c.date|date_format}"{/if}{/if}>
<div class="nom">
{if $c.sexe}•{/if}
- {if !$c.dcd && $c.inscrit}<a href="profile/{$c.forlife}" class="popup2">{/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.nom_usage}{$c.nom_usage} {$c.prenom}<br />({$c.nom}){else}{$c.nom} {$c.prenom}{/if}
- {if !$c.dcd && $c.inscrit}</a>{/if}
+ {if !$c.dcd && ($c.inscrit || $smarty.session.auth eq AUTH_PUBLIC)}</a>{/if}
</div>
<div class="appli">
</div>
</div>
-{if !$c.inscrit || $c.dcd}</div>{/if}
+{if (!$c.inscrit && $smarty.session.auth ge AUTH_COOKIE) || $c.dcd}</div>{/if}
{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
Cette lettre est envoyée à tous les Polytechniciens sur Internet par
l'intermédiaire de Polytechnique.org.
+{if $is_mail}
archives : <https://www.polytechnique.org/nl>
écrire : <https://www.polytechnique.org/nl/submit>
ne plus recevoir : <https://www.polytechnique.org/nl/out>
-
+{else}
+archives : <https://www.polytechnique.org/nl>
+écrire : <https://www.polytechnique.org/nl/submit>
+ne plus recevoir : <https://www.polytechnique.org/nl/out>
+{/if}
{if !$is_mail}
</pre>
{/if}
<tr><th>{$nl->title(true)}</th></tr>
<tr>
<td>
- {include file="newsletter/nl.mail.tpl"}
+ {include file="newsletter/nl.mail.tpl" escape=true}
</td>
</tr>
</table>
{/if}
<form action="nl/submit" method='post'>
- <table class='tinybicol'>
+ <table class='bicol'>
<tr><th>Version texte</th></tr>
<tr id='text'>
<td><pre>{$art->toText()}</pre></td>
</tr>
- {if $art->check()}
<tr><th>Version html</th></tr>
<tr id='html'>
<td>
</div>
</td>
</tr>
+ {if $art->check()}
<tr>
<th>Soumettre</th>
</tr>
{icon name=information title="Syntaxe wiki"} Voir les marqueurs de mise en forme autorisés
</a>
</td>
- <tr>
+ </tr>
<tr class='pair'>
<td colspan='2' class='center'>
<input type='submit' name='see' value='visualiser' />
{* *}
{**************************************************************************}
+<p>{icon name=information title="Afficher ma fiche référent"}Tu peux consulter ta <a class="popup2" href="referent/{$smarty.session.forlife}">fiche référent</a> qui n'est accessible que par les X.
+</p>
<p>
Si tu acceptes que ceux des camarades te contactent afin de te demander
conseil, dans les domaines que tu connais bien, et pour lesquels tu pourrais
<p>
Tu peux mentionner ici les domaines de compétences, les expériences
notamment internationales sur la base desquels tu seras identifiable depuis
- <a href="referent/search">la page de recherche d'un conseil professionnel</a>.<br />
+ <a href="referent/search#mentors">la page de recherche d'un conseil professionnel</a>.<br />
</p>
<p>Le mentoring est particulièrement important pour les camarades :</p>
<ul>
{$x.cv|miniwiki:title|smarty:nodefaults}
</div>
{/if}
- {if !$logged}
+ {if $view eq 'public'}
<div class="part">
<small>
Cette fiche est publique et visible par tout internaute,<br />
vous pouvez aussi voir <a href="profile/private/{$x.forlife}?display=light">celle réservée aux X</a>.
</small>
</div>
+ {elseif $view eq 'ax'}
+ <div class="part">
+ <small>
+ Cette fiche est privée et ne recense que les informations transmises à l'AX.
+ </small>
+ </div>
{/if}
<div class="spacer"></div>
</div>
{include wiki=Docs.Emploi}
{/if}
+<a name="mentors"></a>
+
<p>
Actuellement, {$mentors_number} mentors et référents se sont déclarés sur {#globals.core.sitename#}.
</p>
<td style="width: 78%">
<input type="checkbox" name="with_soundex" id="with_soundex" value="1" {if $smarty.request.with_soundex}checked="checked"{/if} /> <label for="with_soundex">Activer la recherche par proximité sonore.</label>
<br /><input type='checkbox' name='order' id="order" value='date_mod' {if $smarty.request.order eq "date_mod"}checked='checked'{/if} /> <label for="order">Mettre les fiches modifiées récemment en premier.</label>
- <br /><input type='checkbox' name='nonins' id="nonins" readonly="readonly" {if $smarty.request.nonins}checked='checked'{/if} value='1' /> <label for="nonins">Chercher uniquement des non inscrits.</label>
+ <br /><input type='checkbox' name='nonins' id="nonins" {if $smarty.request.nonins}checked='checked'{/if} value='1' /> <label for="nonins">Chercher uniquement des non inscrits.</label>
</td>
{else}
<tr class="noprint">
<li><a href="stats/evolution">Nombre d'inscrits au cours du temps</a></li>
<li><a href="stats/promos/{$smarty.session.promo}">Nombre d'inscrits dans ta promotion</a></li>
<li><a href="stats/promos">Nombre d'inscrits par promotion</a></li>
+<li><a href="stats/profile">Consultations des fiches de l'annuaire</a></li>
</ul>
{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
--- /dev/null
+{**************************************************************************}
+{* *}
+{* 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 *}
+{* *}
+{**************************************************************************}
+
+
+<h1>
+ Fiches les plus consultées
+</h1>
+
+<ul>
+ <li>
+ {if $period neq 'overall'}<a href="stats/profile/overall">{/if}
+ Classement de tous les temps
+ {if $period neq 'overall'}</a>{/if}
+ </li>
+ <li>
+ {if $period neq 'year'}<a href="stats/profile/year">{/if}
+ Classement sur l'année écoulée
+ {if $period neq 'year'}</a>{/if}
+ </li>
+ <li>
+ {if $period neq 'month'}<a href="stats/profile/month">{/if}
+ Classement sur le mois écoulé
+ {if $period neq 'month'}</a>{/if}
+ </li>
+ <li>
+ {if $period neq 'week'}<a href="stats/profile/week">{/if}
+ Classement sur la semaine écoulée
+ {if $period neq 'week'}</a>{/if}
+ </li>
+
+</ul>
+
+<table class="tinybicol">
+ <tr>
+ <th>Nom</th>
+ {if hasPerms('admin')}<th>Consultations</th>{/if}
+ </tr>
+ {iterate from=$profiles item=profile}
+ <tr class="{cycle values="pair,impair"}">
+ <td><a href="profile/{$profile.forlife}" class="popup">{$profile.prenom} {$profile.nom} (X{$profile.promo})</a></td>
+ {if hasPerms('admin')}<td class="right">{$profile.count}</td>{/if}
+ </tr>
+ {/iterate}
+</table>
+
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
- <a href="send_bug" class="popup_840x600">signaler un bug</a>
{/if}
<br />
- © Copyright 2000-2008 <a href="http://x-org.polytechnique.org/">Association Polytechnique.org</a>
+ Plat/al {#globals.version#} - © Copyright 2000-2008 <a href="http://x-org.polytechnique.org/">Association Polytechnique.org</a>
</td>
</tr>
{/if}
{foreachelse}
-
<p class="descr">
{if $archive}
Aucun événement n'a été archivé par les animateurs du groupe.
{/foreach}
+{if $undisplayed_events neq 0}
+<p class="descr">
+ Il y a {$undisplayed_events} événement{if $undisplayed_events > 1}s non affichés car ils sont réservés
+ {else} non affiché car il est réservé{/if} aux membres de ce groupe.
+</p>
+{/if}
+
{if $evenements}
<p class="descr">
En cliquant sur l'icône {icon name=calendar_view_day title="Événement iCal"} associée à un événement,
DROP PRIMARY KEY,
DROP COLUMN ip,
CHANGE COLUMN ip2 ip INT(11) UNSIGNED NOT NULL,
-ADD PRIMARY KEY ip (ip);
+ADD COLUMN mask int(11) unsigned NOT NULL DEFAULT 4294967295,
+ADD PRIMARY KEY ip (ip),
+ADD INDEX network (ip, mask);
# vim:set syntax=mysql:
-CREATE TABLE `forums.innd` (
+USE forums;
+
+CREATE TABLE IF NOT EXISTS `innd` (
`id_innd` int(10) unsigned NOT NULL auto_increment,
`ipmin` int(10) unsigned default '0' COMMENT 'ip_address',
`ipmax` int(10) unsigned default '4294967295' COMMENT 'ip_address',
PRIMARY KEY (`id_innd`)
) DEFAULT CHARSET=utf8;
-INSERT INTO `forums.innd` VALUES (1,0,4294967295,NULL,'xorg.*,!xorg.prive.*','xorg.*,!xorg.prive.*,!xorg.pa.emploi',0,'par defaut pour tous');
+INSERT INTO `innd` VALUES (1,0,4294967295,NULL,'xorg.*,!xorg.prive.*','xorg.*,!xorg.prive.*,!xorg.pa.emploi',0,'par defaut pour tous');
--- /dev/null
+ALTER TABLE watch_cat ADD COLUMN mail_sg_xette varchar(80) DEFAULT NULL AFTER mail_sg;
+UPDATE watch_cat SET mail_sg_xette = 'Cette camarade a mis sa fiche à jour' WHERE id = 1;
+UPDATE watch_cat SET mail_sg_xette = 'Cette camarade s\'est inscrite' WHERE id = 2;
+UPDATE watch_cat SET mail_sg_xette = 'Cette camarade nous a quittés' WHERE id = 3;
+UPDATE watch_cat SET mail_sg_xette = 'Cette camarade fête son anniversaire cette semaine' WHERE id = 4;
+
+# vim:set syntax=mysql:
--- /dev/null
+INSERT INTO logger.actions (text, description)
+ VALUES ('view_profile', 'Consultation d\'une fiche'),
+ ('search', 'Réalisation d\'une recherche');
+
+use logger;
+ALTER TABLE events ADD INDEX action (action);
+
+use x4dat;
+
+# vim:set syntax=mysql: