481b4c4cbd81d6f01d33257babcc1e76f65854f0
2 /***************************************************************************
3 * Copyright (C) 2003-2013 Polytechnique.org *
4 * http://opensource.polytechnique.org/ *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
20 ***************************************************************************/
22 function bugize($list)
24 $list = preg_split('/,/', $list, -1, PREG_SPLIT_NO_EMPTY
);
27 foreach ($list as $bug) {
28 $clean = str_replace('#', '', $bug);
29 $ans[] = "<a href='http://trackers.polytechnique.org/task/$clean'>$bug</a>";
32 return join(',', $ans);
36 class PlatalModule
extends PLModule
41 'index' => $this->make_hook('index', AUTH_PUBLIC
),
42 'cacert.pem' => $this->make_hook('cacert', AUTH_PUBLIC
),
43 'changelog' => $this->make_hook('changelog', AUTH_PUBLIC
),
45 // Preferences thingies
46 'prefs' => $this->make_hook('prefs', AUTH_COOKIE
, 'user,groups'),
47 'prefs/rss' => $this->make_hook('prefs_rss', AUTH_COOKIE
, 'user'),
48 'prefs/webredirect' => $this->make_hook('webredir', AUTH_PASSWD
, 'mail'),
49 'prefs/skin' => $this->make_hook('skin', AUTH_COOKIE
, 'user'),
50 'prefs/email' => $this->make_hook('prefs_email', AUTH_COOKIE
, 'mail'),
52 // password related thingies
53 'password' => $this->make_hook('password', AUTH_PASSWD
, 'user,groups'),
54 'password/smtp' => $this->make_hook('smtppass', AUTH_PASSWD
, 'mail'),
55 'tmpPWD' => $this->make_hook('tmpPWD', AUTH_PUBLIC
),
56 'recovery' => $this->make_hook('recovery', AUTH_PUBLIC
),
57 'recovery/ext' => $this->make_hook('recovery_ext', AUTH_PUBLIC
),
58 'register/ext' => $this->make_hook('register_ext', AUTH_PUBLIC
),
59 'exit' => $this->make_hook('exit', AUTH_PUBLIC
),
60 'review' => $this->make_hook('review', AUTH_PUBLIC
),
61 'deconnexion.php' => $this->make_hook('exit', AUTH_PUBLIC
),
63 'error' => $this->make_hook('test_error', AUTH_COOKIE
),
67 function handler_index($page)
69 // Include X-XRDS-Location response-header for Yadis discovery
71 header('X-XRDS-Location: ' . $globals->baseurl
. '/openid/xrds');
73 // Redirect to the suitable page
75 pl_redirect('events');
76 } else if (!@$GLOBALS['IS_XNET_SITE']) {
77 $this->handler_review($page);
81 function handler_cacert($page)
83 pl_cached_content_headers("application/x-x509-ca-cert");
84 readfile("/etc/ssl/xorgCA/cacert.pem");
88 function handler_changelog($page, $core = null
)
90 $page->changeTpl('platal/changeLog.tpl');
92 function formatChangeLog($file) {
93 $clog = pl_entities(file_get_contents($file));
94 $clog = preg_replace('/===+\s*/', '</pre><hr /><pre>', $clog);
95 // url catch only (not all wiki syntax)
96 $clog = preg_replace(array(
97 '/((?:https?|ftp):\/\/(?:\.*,*[\w@~%$£µ&i#\-+=_\/\?;])*)/ui',
98 '/(\s|^)www\.((?:\.*,*[\w@~%$£µ&i#\-+=_\/\?;])*)/iu',
99 '/(?:mailto:)?([a-z0-9.\-+_]+@([\-.+_]?[a-z0-9])+)/i'),
101 '<a href="\\0">\\0</a>',
102 '\\1<a href="http://www.\\2">www.\\2</a>',
103 '<a href="mailto:\\0">\\0</a>'),
105 $clog = preg_replace('!(#[0-9]+(,[0-9]+)*)!e', 'bugize("\1")', $clog);
106 $clog = preg_replace('!vim:.*$!', '', $clog);
107 return preg_replace("!(<hr />(\\s|\n)*)?<pre>(\s|\n)*</pre>((\\s|\n)*<hr />)?!m", "", "<pre>$clog</pre>");
109 if ($core != 'core') {
110 $page->assign('core', false
);
111 $page->assign('ChangeLog', formatChangeLog(dirname(__FILE__
).'/../ChangeLog'));
113 $page->assign('core', true
);
114 $page->assign('ChangeLog', formatChangeLog(dirname(__FILE__
).'/../core/ChangeLog'));
118 function __set_rss_state($state)
121 if (!S
::user()->token
) {
122 S
::user()->token
= rand_url_id(16);
123 S
::set('token', S
::user()->token
);
124 XDB
::execute('UPDATE accounts
126 WHERE uid = {?}', S
::user()->token
, S
::i('uid'));
130 S
::user()->token
= null
;
131 XDB
::execute('UPDATE accounts
133 WHERE uid = {?}', S
::i('uid'));
137 function handler_prefs($page)
139 $page->changeTpl('platal/preferences.tpl');
140 $page->setTitle('Mes préférences');
142 if (Post
::has('email_format')) {
143 S
::assert_xsrf_token();
144 $fmt = Post
::s('email_format');
145 S
::user()->setEmailFormat($fmt);
148 if (Post
::has('rss')) {
149 S
::assert_xsrf_token();
150 $this->__set_rss_state(Post
::s('rss') == 'on');
154 function handler_webredir($page)
156 $page->changeTpl('platal/webredirect.tpl');
157 $page->setTitle('Redirection de page WEB');
159 if (Env
::v('submit') == 'Valider' && !Env
::blank('url')) {
160 if (Env
::blank('url')) {
161 $page->trigError('URL invalide');
163 $url = Env
::t('url');
164 XDB
::execute('INSERT INTO carvas (uid, url)
166 ON DUPLICATE KEY UPDATE url = VALUES(url)',
168 S
::logger()->log('carva_add', 'http://' . $url);
169 $page->trigSuccess("Redirection activée vers <a href='http://$url'>$url</a>");
171 } elseif (Env
::v('submit') == 'Supprimer') {
172 XDB
::execute('DELETE FROM carvas
173 WHERE uid = {?}', S
::i('uid'));
175 S
::logger()->log('carva_del');
176 $page->trigSuccess('Redirection supprimée');
179 $url = XDB
::fetchOneCell('SELECT url
181 WHERE uid = {?}', S
::i('uid'));
182 $page->assign('carva', $url);
184 # FIXME: this code is not multi-domain compatible. We should decide how
185 # carva will extend to users not in the main domain.
186 $best = XDB
::fetchOneCell('SELECT email
187 FROM email_source_account
188 WHERE uid = {?} AND FIND_IN_SET(\'bestalias\', flags)',
190 $page->assign('bestalias', $best);
193 function handler_prefs_rss($page)
195 $page->changeTpl('platal/filrss.tpl');
197 $page->assign('goback', Env
::v('referer', 'login'));
199 if (Env
::v('act_rss') == 'Activer') {
200 $this->__set_rss_state(true
);
201 $page->trigSuccess("Ton Fil RSS est activé.");
205 function handler_prefs_email($page)
207 $page->changeTpl('platal/email_preferences.tpl');
209 if (Post
::has('submit')) {
210 S
::assert_xsrf_token();
212 $from_email = Post
::t('from_email');
213 $from_format = Post
::v('from_format');
216 $email_regex = '/^[a-z0-9.\-+_\$]+@([\-.+_]?[a-z0-9])+$/i';
217 if (!preg_match($email_regex, $from_email)) {
218 $full_regex = '/^[^<]*<[a-z0-9.\-+_\$]+@([\-.+_]?[a-z0-9])+>$/i';
219 if (!preg_match($full_regex, $from_email)) {
220 $page->trigError("L'adresse email est erronée.");
222 $page->assign('from_email', $from_email);
223 $page->assign('from_format', $from_format);
224 $page->assign('error', true
);
230 XDB
::execute('UPDATE accounts
231 SET from_email = {?}, from_format = {?}
233 $from_email, ($from_format == 'html' ?
'html' : 'text'), S
::user()->id());
234 $page->trigSuccess('Données enregistrées.');
237 $data = XDB
::fetchOneAssoc('SELECT from_email, from_format
241 $page->assign('from_email', $data['from_email']);
242 $page->assign('from_format', $data['from_format']);
243 $page->assign('error', false
);
246 function handler_password($page)
250 if (Post
::has('pwhash') && Post
::t('pwhash')) {
251 S
::assert_xsrf_token();
253 S
::set('password', $password = Post
::t('pwhash'));
254 XDB
::execute('UPDATE accounts
256 WHERE uid={?}', $password,
259 // If GoogleApps is enabled, and the user did choose to use synchronized passwords,
260 // updates the Google Apps password as well.
261 if ($globals->mailstorage
->googleapps_domain
) {
262 require_once 'googleapps.inc.php';
263 $account = new GoogleAppsAccount(S
::user());
264 if ($account->active() && $account->sync_password
) {
265 $account->set_password($password);
269 S
::logger()->log('passwd');
270 Platal
::session()->setAccessCookie(true
);
272 $page->changeTpl('platal/password.success.tpl');
276 $page->changeTpl('platal/password.tpl');
277 $page->setTitle('Mon mot de passe');
278 $page->assign('do_auth', 0);
281 function handler_smtppass($page)
283 $page->changeTpl('platal/acces_smtp.tpl');
284 $page->setTitle('Acces SMTP/NNTP');
286 $wp = new PlWikiPage('Xorg.SMTPSécurisé');
288 $wp = new PlWikiPage('Xorg.NNTPSécurisé');
292 $pass = Env
::v('smtppass1');
294 if (Env
::v('op') == "Valider" && strlen($pass) >= 6
295 && Env
::v('smtppass1') == Env
::v('smtppass2')) {
296 XDB
::execute('UPDATE accounts
297 SET weak_password = {?}
298 WHERE uid = {?}', $pass, $uid);
299 $page->trigSuccess('Mot de passe enregistré');
300 S
::logger()->log("passwd_ssl");
301 } elseif (Env
::v('op') == "Supprimer") {
302 XDB
::execute('UPDATE accounts
303 SET weak_password = NULL
304 WHERE uid = {?}', $uid);
305 $page->trigSuccess('Compte SMTP et NNTP supprimé');
306 S
::logger()->log("passwd_del");
309 $res = XDB
::query("SELECT weak_password IS NOT NULL
311 WHERE uid = {?}", $uid);
312 $page->assign('actif', $res->fetchOneCell());
315 function handler_recovery($page)
319 $page->changeTpl('platal/recovery.tpl');
321 if (!Env
::has('login') ||
!Env
::has('birth')) {
325 if (!preg_match('/^[0-3][0-9][0-1][0-9][1][9]([0-9]{2})$/', Env
::v('birth'))) {
326 $page->trigError('Date de naissance incorrecte ou incohérente');
330 $birth = sprintf('%s-%s-%s',
331 substr(Env
::v('birth'), 4, 4),
332 substr(Env
::v('birth'), 2, 2),
333 substr(Env
::v('birth'), 0, 2));
335 $mailorg = strtok(Env
::v('login'), '@');
337 $profile = Profile
::get(Env
::t('login'));
338 if (is_null($profile) ||
$profile->birthdate
!= $birth) {
339 $page->trigError('Les informations que tu as rentrées ne permettent pas de récupérer ton mot de passe.<br />'.
340 'Si tu as un homonyme, utilise prenom.nom.promo comme login');
344 $user = $profile->owner();
345 if ($user->state
!= 'active') {
346 $page->trigError('Ton compte n\'est pas activé.');
351 $page->assign('no_addr', true
);
355 $page->assign('ok', true
);
357 $url = rand_url_id();
358 XDB
::execute('INSERT INTO account_lost_passwords (certificat,uid,created)
359 VALUES ({?},{?},NOW())', $url, $user->id());
360 $to = XDB
::fetchOneCell('SELECT redirect
361 FROM email_redirect_account
362 WHERE uid = {?} AND redirect = {?}',
363 $user->id(), Post
::t('email'));
365 $emails = XDB
::fetchColumn('SELECT redirect
366 FROM email_redirect_account
367 WHERE uid = {?} AND flags = \'inactive\' AND type = \'smtp\'',
369 $inactives_to = implode(', ', $emails);
371 $mymail = new PlMailer();
372 $mymail->setFrom('"Gestion des mots de passe" <support+password@' . $globals->mail
->domain
. '>');
374 $mymail->addTo($user);
375 $log_to = $user->bestEmail();
376 if (!is_null($inactives_to)) {
377 $log_to = $inactives_to . ', ' . $log_to;
378 $mymail->addTo($inactives_to);
384 $mymail->setSubject("Ton certificat d'authentification");
385 $mymail->setTxtBody("Visite la page suivante qui expire dans six heures :
386 {$globals->baseurl}/tmpPWD/$url
388 Si en cliquant dessus tu n'y arrives pas, copie intégralement l'adresse dans la barre de ton navigateur. Si tu n'as pas utilisé ce lien dans six heures, tu peux tout simplement recommencer cette procédure.
392 \"Le portail des élèves & anciens élèves de l'École polytechnique\"
394 Email envoyé à ".Env
::v('login') . (is_null($to) ?
'' : '
395 Adresse de secours : ' . $to));
398 S
::logger($user->id())->log('recovery', $log_to);
401 function handler_recovery_ext($page)
403 $page->changeTpl('xnet/recovery.tpl');
405 if (!Post
::has('login')) {
409 $user = User
::getSilent(Post
::t('login'));
410 if (is_null($user)) {
411 $page->trigError('Le compte n\'existe pas.');
414 if ($user->state
!= 'active') {
415 $page->trigError('Ton compte n\'est pas activé.');
419 $page->assign('ok', true
);
421 $hash = rand_url_id();
422 XDB
::execute('INSERT INTO account_lost_passwords (uid, created, certificat)
423 VALUES ({?}, NOW(), {?})',
426 $mymail = new PlMailer('platal/password_recovery_xnet.mail.tpl');
427 $mymail->setTo($user);
428 $mymail->assign('hash', $hash);
429 $mymail->assign('email', Post
::t('login'));
432 S
::logger($user->id())->log('recovery', $user->bestEmail());
435 function handler_tmpPWD($page, $certif = null
)
438 XDB
::execute('DELETE FROM account_lost_passwords
439 WHERE DATE_SUB(NOW(), INTERVAL 380 MINUTE) > created');
441 if (Post
::has('pwhash') && Post
::t('pwhash')) {
442 $uid = XDB
::fetchOneCell('SELECT uid
445 Post
::t('username'));
446 $password = Post
::t('pwhash');
447 XDB
::query('UPDATE accounts
449 WHERE uid = {?} AND state = \'active\'',
451 XDB
::query('DELETE FROM account_lost_passwords
452 WHERE certificat = {?}', $certif);
454 // If GoogleApps is enabled, and the user did choose to use synchronized passwords,
455 // updates the Google Apps password as well.
456 if ($globals->mailstorage
->googleapps_domain
) {
457 require_once 'googleapps.inc.php';
458 $account = new GoogleAppsAccount(User
::getSilent($uid));
459 if ($account->active() && $account->sync_password
) {
460 $account->set_password($password);
464 S
::logger($uid)->log("passwd", "");
466 // Try to start a session (so the user don't have to log in); we will use
467 // the password available in Post:: to authenticate the user.
468 Platal
::session()->start(AUTH_PASSWD
);
470 $page->changeTpl('platal/tmpPWD.success.tpl');
472 $res = XDB
::query('SELECT uid
473 FROM account_lost_passwords
474 WHERE certificat = {?}', $certif);
475 $ligne = $res->fetchOneAssoc();
477 $page->changeTpl('platal/index.tpl');
478 $page->kill("Cette adresse n'existe pas ou n'existe plus sur le serveur.");
481 $hruid = XDB
::fetchOneCell('SELECT hruid
485 $page->changeTpl('platal/password.tpl');
486 $page->assign('hruid', $hruid);
487 $page->assign('do_auth', 1);
491 function handler_register_ext($page, $hash = null
)
493 XDB
::execute('DELETE FROM register_pending_xnet
494 WHERE DATE_SUB(NOW(), INTERVAL 1 MONTH) > date');
495 $res = XDB
::fetchOneAssoc('SELECT uid, hruid, email
496 FROM register_pending_xnet
500 if (is_null($hash) ||
is_null($res)) {
501 $page->trigErrorRedirect('Cette adresse n\'existe pas ou n\'existe plus sur le serveur.', '');
504 if (Post
::has('pwhash') && Post
::t('pwhash')) {
505 XDB
::startTransaction();
506 XDB
::query('UPDATE accounts
507 SET password = {?}, state = \'active\', registration_date = NOW()
508 WHERE uid = {?} AND state = \'pending\' AND type = \'xnet\'',
509 Post
::t('pwhash'), $res['uid']);
510 XDB
::query('DELETE FROM register_pending_xnet
515 S
::logger($res['uid'])->log('passwd', '');
517 // Try to start a session (so the user don't have to log in); we will use
518 // the password available in Post:: to authenticate the user.
520 Platal
::session()->startAvailableAuth();
522 $page->changeTpl('xnet/register.success.tpl');
523 $page->assign('email', $res['email']);
525 $page->changeTpl('platal/password.tpl');
526 $page->assign('xnet', true
);
527 $page->assign('hruid', $res['hruid']);
528 $page->assign('do_auth', 1);
532 function handler_skin($page)
536 $page->changeTpl('platal/skins.tpl');
537 $page->setTitle('Skins');
539 if (Env
::has('newskin')) { // formulaire soumis, traitons les données envoyées
540 XDB
::execute('UPDATE accounts
543 Env
::i('newskin'), S
::i('uid'));
545 Platal
::session()->setSkin();
548 $res = XDB
::query('SELECT id
550 WHERE skin_tpl = {?}', S
::v('skin'));
551 $page->assign('skin_id', $res->fetchOneCell());
553 $sql = 'SELECT s.*, auteur, COUNT(*) AS nb
555 LEFT JOIN accounts AS a ON (a.skin = s.id)
556 WHERE skin_tpl != \'\' AND ext != \'\'
557 GROUP BY id ORDER BY s.date DESC';
558 $page->assign('skins', XDB
::iterator($sql));
561 function handler_exit($page, $level = null
)
564 $old = S
::user()->login();
565 S
::logger()->log('suid_stop', $old . " by " . S
::suid('hruid'));
566 Platal
::session()->stopSUID();
567 $target = S
::s('suid_startpage');
568 S
::kill('suid_startpage');
569 if (!empty($target)) {
570 http_redirect($target);
572 pl_redirect('admin/user/' . $old);
575 if ($level == 'forget' ||
$level == 'forgetall') {
576 Platal
::session()->killAccessCookie();
579 if ($level == 'forgetuid' ||
$level == 'forgetall') {
580 Platal
::session()->killLoginFormCookies();
584 S
::logger()->log('deconnexion', @$_SERVER['HTTP_REFERER']);
585 Platal
::session()->destroy();
588 if (Get
::has('redirect')) {
589 http_redirect(rawurldecode(Get
::v('redirect')));
591 $page->changeTpl('platal/exit.tpl');
595 function handler_review($page, $action = null
, $mode = null
)
597 // Include X-XRDS-Location response-header for Yadis discovery
599 header('X-XRDS-Location: ' . $globals->baseurl
. '/openid/xrds');
601 $this->load('review.inc.php');
603 if (@$GLOBALS['IS_XNET_SITE']) {
606 $wp = new PlWikiPage($dom . '.Admin');
607 $conf = explode('%0a', $wp->getField('text'));
608 $wiz = new PlWizard('Tour d\'horizon', PlPage
::getCoreTpl('plwizard.tpl'), true
);
609 foreach ($conf as $line) {
610 $list = preg_split('/\s*[*|]\s*/', $line, -1, PREG_SPLIT_NO_EMPTY
);
611 $wiz->addPage('ReviewPage', $list[0], $list[1]);
613 $wiz->apply($page, 'review', $action, $mode);
616 function handler_test_error($page)
618 throw new Exception("Blih");
622 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: