<?php
/***************************************************************************
- * Copyright (C) 2003-2010 Polytechnique.org *
+ * Copyright (C) 2003-2011 Polytechnique.org *
* http://opensource.polytechnique.org/ *
* *
* This program is free software; you can redistribute it and/or modify *
function bugize($list)
{
- $list = split(',', $list);
+ $list = preg_split('/,/', $list, -1, PREG_SPLIT_NO_EMPTY);
$ans = array();
foreach ($list as $bug) {
function handlers()
{
return array(
- 'index' => $this->make_hook('index', AUTH_PUBLIC),
- 'cacert.pem' => $this->make_hook('cacert', AUTH_PUBLIC),
- 'changelog' => $this->make_hook('changelog', AUTH_PUBLIC),
+ 'index' => $this->make_hook('index', AUTH_PUBLIC),
+ 'cacert.pem' => $this->make_hook('cacert', AUTH_PUBLIC),
+ 'changelog' => $this->make_hook('changelog', AUTH_PUBLIC),
// Preferences thingies
- 'prefs' => $this->make_hook('prefs', AUTH_COOKIE),
- 'prefs/rss' => $this->make_hook('prefs_rss', AUTH_COOKIE),
- 'prefs/webredirect' => $this->make_hook('webredir', AUTH_MDP, 'mail'),
- 'prefs/skin' => $this->make_hook('skin', AUTH_COOKIE),
+ 'prefs' => $this->make_hook('prefs', AUTH_COOKIE, 'user,groups'),
+ 'prefs/rss' => $this->make_hook('prefs_rss', AUTH_COOKIE, 'user'),
+ 'prefs/webredirect' => $this->make_hook('webredir', AUTH_PASSWD, 'mail'),
+ 'prefs/skin' => $this->make_hook('skin', AUTH_COOKIE, 'user'),
+ 'prefs/email' => $this->make_hook('prefs_email', AUTH_COOKIE, 'mail'),
// password related thingies
- 'password' => $this->make_hook('password', AUTH_MDP),
- 'tmpPWD' => $this->make_hook('tmpPWD', AUTH_PUBLIC),
- 'password/smtp' => $this->make_hook('smtppass', AUTH_MDP, 'mail'),
- 'recovery' => $this->make_hook('recovery', AUTH_PUBLIC),
- 'exit' => $this->make_hook('exit', AUTH_PUBLIC),
- 'review' => $this->make_hook('review', AUTH_PUBLIC),
- 'deconnexion.php' => $this->make_hook('exit', AUTH_PUBLIC),
+ 'password' => $this->make_hook('password', AUTH_PASSWD, 'user,groups'),
+ 'password/smtp' => $this->make_hook('smtppass', AUTH_PASSWD, 'mail'),
+ 'tmpPWD' => $this->make_hook('tmpPWD', AUTH_PUBLIC),
+ 'recovery' => $this->make_hook('recovery', AUTH_PUBLIC),
+ 'recovery/ext' => $this->make_hook('recovery_ext', AUTH_PUBLIC),
+ 'register/ext' => $this->make_hook('register_ext', AUTH_PUBLIC),
+ 'exit' => $this->make_hook('exit', AUTH_PUBLIC),
+ 'review' => $this->make_hook('review', AUTH_PUBLIC),
+ 'deconnexion.php' => $this->make_hook('exit', AUTH_PUBLIC),
);
}
- function handler_index(&$page)
+ function handler_index($page)
{
// Include X-XRDS-Location response-header for Yadis discovery
global $globals;
}
}
- function handler_cacert(&$page)
+ function handler_cacert($page)
{
pl_cached_content_headers("application/x-x509-ca-cert");
readfile("/etc/ssl/xorgCA/cacert.pem");
exit;
}
- function handler_changelog(&$page, $core = null)
+ function handler_changelog($page, $core = null)
{
$page->changeTpl('platal/changeLog.tpl');
function __set_rss_state($state)
{
if ($state) {
- S::user()->token = rand_url_id(16);
- XDB::execute('UPDATE accounts
- SET token = {?}
- WHERE uid = {?}', S::user()->token, S::i('uid'));
+ if (!S::user()->token) {
+ S::user()->token = rand_url_id(16);
+ S::set('token', S::user()->token);
+ XDB::execute('UPDATE accounts
+ SET token = {?}
+ WHERE uid = {?}', S::user()->token, S::i('uid'));
+ }
} else {
S::kill('token');
+ S::user()->token = null;
XDB::execute('UPDATE accounts
SET token = NULL
WHERE uid = {?}', S::i('uid'));
}
}
- function handler_prefs(&$page)
+ function handler_prefs($page)
{
$page->changeTpl('platal/preferences.tpl');
$page->setTitle('Mes préférences');
if (Post::has('email_format')) {
+ S::assert_xsrf_token();
$fmt = Post::s('email_format');
S::user()->setEmailFormat($fmt);
}
if (Post::has('rss')) {
- $this->__set_rss_state(Post::b('rss'));
+ S::assert_xsrf_token();
+ $this->__set_rss_state(Post::s('rss') == 'on');
}
-
- # FIXME: this code is not multi-domain compatible. We should decide how
- # carva will extend to users not in the main domain.
- $res = XDB::query("SELECT alias
- FROM aliases
- WHERE uid = {?} AND FIND_IN_SET('bestalias', flags)",
- S::user()->id());
- $page->assign('bestalias', $res->fetchOneCell());
}
- function handler_webredir(&$page)
+ function handler_webredir($page)
{
$page->changeTpl('platal/webredirect.tpl');
$page->setTitle('Redirection de page WEB');
$page->trigError('URL invalide');
} else {
$url = Env::t('url');
- XDB::execute('REPLACE INTO carvas (uid, url)
- VALUES ({?}, {?})',
+ XDB::execute('INSERT INTO carvas (uid, url)
+ VALUES ({?}, {?})
+ ON DUPLICATE KEY UPDATE url = VALUES(url)',
S::i('uid'), $url);
S::logger()->log('carva_add', 'http://' . $url);
$page->trigSuccess("Redirection activée vers <a href='http://$url'>$url</a>");
# FIXME: this code is not multi-domain compatible. We should decide how
# carva will extend to users not in the main domain.
- $res = XDB::query("SELECT alias
- FROM aliases
- WHERE uid = {?} AND FIND_IN_SET('bestalias', flags)",
- S::user()->id());
- $page->assign('bestalias', $res->fetchOneCell());
+ $best = XDB::fetchOneCell('SELECT email
+ FROM email_source_account
+ WHERE uid = {?} AND FIND_IN_SET(\'bestalias\', flags)',
+ S::user()->id());
+ $page->assign('bestalias', $best);
}
- function handler_prefs_rss(&$page)
+ function handler_prefs_rss($page)
{
$page->changeTpl('platal/filrss.tpl');
}
}
- function handler_password(&$page)
+ function handler_prefs_email($page)
+ {
+ $page->changeTpl('platal/email_preferences.tpl');
+
+ if (Post::has('submit')) {
+ S::assert_xsrf_token();
+
+ $from_email = Post::t('from_email');
+ $from_format = Post::v('from_format');
+
+ // Checks email.
+ $email_regex = '/^[a-z0-9.\-+_\$]+@([\-.+_]?[a-z0-9])+$/i';
+ if (!preg_match($email_regex, $from_email)) {
+ $full_regex = '/^[^<]*<[a-z0-9.\-+_\$]+@([\-.+_]?[a-z0-9])+>$/i';
+ if (!preg_match($full_regex, $from_email)) {
+ $page->trigError("L'adresse email est erronée.");
+ $error = true;
+ $page->assign('from_email', $from_email);
+ $page->assign('from_format', $from_format);
+ $page->assign('error', true);
+ return;
+ }
+ }
+
+ // Saves data.
+ XDB::execute('UPDATE accounts
+ SET from_email = {?}, from_format = {?}
+ WHERE uid = {?}',
+ $from_email, ($from_format == 'html' ? 'html' : 'text'), S::user()->id());
+ $page->trigSuccess('Données enregistrées.');
+ }
+
+ $data = XDB::fetchOneAssoc('SELECT from_email, from_format
+ FROM accounts
+ WHERE uid = {?}',
+ S::user()->id());
+ $page->assign('from_email', $data['from_email']);
+ $page->assign('from_format', $data['from_format']);
+ $page->assign('error', false);
+ }
+
+ function handler_password($page)
{
global $globals;
}
$page->changeTpl('platal/password.tpl');
- $page->addJsLink('password.js');
$page->setTitle('Mon mot de passe');
+ $page->assign('do_auth', 0);
}
- function handler_smtppass(&$page)
+ function handler_smtppass($page)
{
$page->changeTpl('platal/acces_smtp.tpl');
$page->setTitle('Acces SMTP/NNTP');
$page->assign('actif', $res->fetchOneCell());
}
- function handler_recovery(&$page)
+ function handler_recovery($page)
{
global $globals;
return;
}
- if (!ereg('[0-3][0-9][0-1][0-9][1][9]([0-9]{2})', Env::v('birth'))) {
+ if (!preg_match('/^[0-3][0-9][0-1][0-9][1][9]([0-9]{2})$/', Env::v('birth'))) {
$page->trigError('Date de naissance incorrecte ou incohérente');
return;
}
return;
}
- $res = XDB::query("SELECT COUNT(*)
- FROM emails
- WHERE uid = {?} AND flags != 'panne' AND flags != 'filter'", $user->id());
- $count = intval($res->fetchOneCell());
- if ($count == 0) {
+ if ($user->lost) {
$page->assign('no_addr', true);
return;
}
$page->assign('ok', true);
- $url = rand_url_id();
+ $url = rand_url_id();
XDB::execute('INSERT INTO account_lost_passwords (certificat,uid,created)
VALUES ({?},{?},NOW())', $url, $user->id());
- $res = XDB::query('SELECT email
- FROM emails
- WHERE uid = {?} AND email = {?}',
- $user->id(), Post::v('email'));
- if ($res->numRows()) {
- $mails = $res->fetchOneCell();
- } else {
- $res = XDB::query("SELECT email
- FROM emails
- WHERE uid = {?} AND NOT FIND_IN_SET('filter', flags)", $user->id());
- $mails = implode(', ', $res->fetchColumn());
+ $to = XDB::fetchOneCell('SELECT redirect
+ FROM email_redirect_account
+ WHERE uid = {?} AND redirect = {?}',
+ $user->id(), Post::t('email'));
+ if (is_null($to)) {
+ $emails = XDB::fetchColumn('SELECT redirect
+ FROM email_redirect_account
+ WHERE uid = {?} AND flags = \'inactive\' AND type = \'smtp\'',
+ $user->id());
+ $inactives_to = implode(', ', $emails);
}
$mymail = new PlMailer();
$mymail->setFrom('"Gestion des mots de passe" <support+password@' . $globals->mail->domain . '>');
- $mymail->addTo($mails);
+ if (is_null($to)) {
+ $mymail->addTo($user);
+ $mymail->addTo($inactives_to);
+ } else {
+ $mymail->addTo($to);
+ }
$mymail->setSubject("Ton certificat d'authentification");
$mymail->setTxtBody("Visite la page suivante qui expire dans six heures :
{$globals->baseurl}/tmpPWD/$url
Polytechnique.org
\"Le portail des élèves & anciens élèves de l'École polytechnique\"
-Email envoyé à ".Env::v('login') . (Post::has('email') ? "
-Adresse de secours : " . Post::v('email') : ""));
+Email envoyé à ".Env::v('login') . (is_null($to) ? '' : '
+Adresse de secours : ' . $to));
$mymail->send();
- // on cree un objet logger et on log l'evenement
- S::logger($user->id())->log('recovery', $mails);
+ S::logger($user->id())->log('recovery', is_null($to) ? $inactives_to . ', ' . $user->bestEmail() : $to);
}
- function handler_tmpPWD(&$page, $certif = null)
+ function handler_recovery_ext($page)
+ {
+ $page->changeTpl('xnet/recovery.tpl');
+
+ if (!Post::has('login')) {
+ return;
+ }
+
+ $user = User::getSilent(Post::t('login'));
+ if (is_null($user)) {
+ $page->trigError('Le compte n\'existe pas.');
+ return;
+ }
+ if ($user->state != 'active') {
+ $page->trigError('Ton compte n\'est pas activé.');
+ return;
+ }
+
+ $page->assign('ok', true);
+
+ $hash = rand_url_id();
+ XDB::execute('INSERT INTO account_lost_passwords (uid, created, certificat)
+ VALUES ({?}, NOW(), {?})',
+ $user->id(), $hash);
+
+ $mymail = new PlMailer('platal/password_recovery_xnet.mail.tpl');
+ $mymail->setTo($user);
+ $mymail->assign('hash', $hash);
+ $mymail->assign('email', Post::t('login'));
+ $mymail->send();
+
+ S::logger($user->id())->log('recovery', $user->bestEmail());
+ }
+
+ function handler_tmpPWD($page, $certif = null)
{
global $globals;
- // XXX: recovery requires data from the profile
XDB::execute('DELETE FROM account_lost_passwords
WHERE DATE_SUB(NOW(), INTERVAL 380 MINUTE) > created');
- $res = XDB::query('SELECT uid
- FROM account_lost_passwords WHERE certificat={?}', $certif);
- $ligne = $res->fetchOneAssoc();
- if (!$ligne) {
- $page->changeTpl('platal/index.tpl');
- $page->kill("Cette adresse n'existe pas ou n'existe plus sur le serveur.");
- }
-
- $uid = $ligne["uid"];
if (Post::has('pwhash') && Post::t('pwhash')) {
+ $uid = XDB::fetchOneCell('SELECT uid
+ FROM accounts
+ WHERE hruid = {?}',
+ Post::t('username'));
$password = Post::t('pwhash');
XDB::query('UPDATE accounts
- SET password={?}
+ SET password = {?}
WHERE uid = {?} AND state = \'active\'',
$password, $uid);
XDB::query('DELETE FROM account_lost_passwords
- WHERE certificat={?}', $certif);
+ WHERE certificat = {?}', $certif);
// If GoogleApps is enabled, and the user did choose to use synchronized passwords,
// updates the Google Apps password as well.
}
S::logger($uid)->log("passwd", "");
+
+ // Try to start a session (so the user don't have to log in); we will use
+ // the password available in Post:: to authenticate the user.
+ Platal::session()->start(AUTH_PASSWD);
+
$page->changeTpl('platal/tmpPWD.success.tpl');
} else {
+ $res = XDB::query('SELECT uid
+ FROM account_lost_passwords
+ WHERE certificat = {?}', $certif);
+ $ligne = $res->fetchOneAssoc();
+ if (!$ligne) {
+ $page->changeTpl('platal/index.tpl');
+ $page->kill("Cette adresse n'existe pas ou n'existe plus sur le serveur.");
+ }
+
+ $hruid = XDB::fetchOneCell('SELECT hruid
+ FROM accounts
+ WHERE uid = {?}',
+ $ligne['uid']);
+ $page->changeTpl('platal/password.tpl');
+ $page->assign('hruid', $hruid);
+ $page->assign('do_auth', 1);
+ }
+ }
+
+ function handler_register_ext($page, $hash = null)
+ {
+ XDB::execute('DELETE FROM register_pending_xnet
+ WHERE DATE_SUB(NOW(), INTERVAL 1 MONTH) > date');
+ $res = XDB::fetchOneAssoc('SELECT uid, hruid, email
+ FROM register_pending_xnet
+ WHERE hash = {?}',
+ $hash);
+
+ if (is_null($hash) || is_null($res)) {
+ $page->trigErrorRedirect('Cette adresse n\'existe pas ou n\'existe plus sur le serveur.', '');
+ }
+
+ if (Post::has('pwhash') && Post::t('pwhash')) {
+ XDB::startTransaction();
+ XDB::query('UPDATE accounts
+ SET password = {?}, state = \'active\', registration_date = NOW()
+ WHERE uid = {?} AND state = \'pending\' AND type = \'xnet\'',
+ Post::t('pwhash'), $res['uid']);
+ XDB::query('DELETE FROM register_pending_xnet
+ WHERE uid = {?}',
+ $res['uid']);
+ XDB::commit();
+
+ S::logger($res['uid'])->log('passwd', '');
+
+ // Try to start a session (so the user don't have to log in); we will use
+ // the password available in Post:: to authenticate the user.
+ Post::kill('wait');
+ Platal::session()->startAvailableAuth();
+
+ $page->changeTpl('xnet/register.success.tpl');
+ $page->assign('email', $res['email']);
+ } else {
$page->changeTpl('platal/password.tpl');
- $page->addJsLink('password.js');
+ $page->assign('xnet', true);
+ $page->assign('hruid', $res['hruid']);
+ $page->assign('do_auth', 1);
}
}
- function handler_skin(&$page)
+ function handler_skin($page)
{
global $globals;
$page->assign('skins', XDB::iterator($sql));
}
- function handler_exit(&$page, $level = null)
+ function handler_exit($page, $level = null)
{
if (S::suid()) {
- S::logger()->log('suid_stop', S::user()->login() . " by " . S::suid('hruid'));
+ $old = S::user()->login();
+ S::logger()->log('suid_stop', $old . " by " . S::suid('hruid'));
Platal::session()->stopSUID();
- pl_redirect('admin/user/' . S::user()->login());
+ $target = S::s('suid_startpage');
+ S::kill('suid_startpage');
+ if (!empty($target)) {
+ http_redirect($target);
+ }
+ pl_redirect('admin/user/' . $old);
}
if ($level == 'forget' || $level == 'forgetall') {
}
}
- function handler_review(&$page, $action = null, $mode = null)
+ function handler_review($page, $action = null, $mode = null)
{
// Include X-XRDS-Location response-header for Yadis discovery
global $globals;