Merge remote branch 'origin/platal-0.10.2'
[platal.git] / modules / platal.php
CommitLineData
e59506eb 1<?php
2/***************************************************************************
9f5bd98e 3 * Copyright (C) 2003-2010 Polytechnique.org *
e59506eb 4 * http://opensource.polytechnique.org/ *
5 * *
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. *
10 * *
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. *
15 * *
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 *
18 * Foundation, Inc., *
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
20 ***************************************************************************/
21
5de0b7e1 22function bugize($list)
23{
24 $list = split(',', $list);
25 $ans = array();
26
27 foreach ($list as $bug) {
28 $clean = str_replace('#', '', $bug);
29 $ans[] = "<a href='http://trackers.polytechnique.org/task/$clean'>$bug</a>";
30 }
31
32 return join(',', $ans);
33}
34
35
e59506eb 36class PlatalModule extends PLModule
37{
38 function handlers()
39 {
40 return array(
eb5a266d
SJ
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),
5de0b7e1 44
4da0b8d7 45 // Preferences thingies
eb5a266d
SJ
46 'prefs' => $this->make_hook('prefs', AUTH_COOKIE),
47 'prefs/rss' => $this->make_hook('prefs_rss', AUTH_COOKIE),
48 'prefs/webredirect' => $this->make_hook('webredir', AUTH_MDP),
49 'prefs/skin' => $this->make_hook('skin', AUTH_COOKIE),
4da0b8d7 50
51 // password related thingies
eb5a266d
SJ
52 'password' => $this->make_hook('password', AUTH_MDP),
53 'tmpPWD' => $this->make_hook('tmpPWD', AUTH_PUBLIC),
54 'password/smtp' => $this->make_hook('smtppass', AUTH_MDP),
55 'recovery' => $this->make_hook('recovery', AUTH_PUBLIC),
56 'exit' => $this->make_hook('exit', AUTH_PUBLIC),
57 'review' => $this->make_hook('review', AUTH_PUBLIC),
58 'deconnexion.php' => $this->make_hook('exit', AUTH_PUBLIC),
e59506eb 59 );
60 }
61
c9178c75 62 function handler_index(&$page)
63 {
ab66bf7f 64 // Include X-XRDS-Location response-header for Yadis discovery
78507d96 65 global $globals;
34d91db6 66 header('X-XRDS-Location: ' . $globals->baseurl . '/openid/xrds');
ab66bf7f
AA
67
68 // Redirect to the suitable page
cab08090 69 if (S::logged()) {
8b00e0e0 70 pl_redirect('events');
ddb64990
FB
71 } else if (!@$GLOBALS['IS_XNET_SITE']) {
72 pl_redirect('review');
c9178c75 73 }
c9178c75 74 }
75
5de0b7e1 76 function handler_cacert(&$page)
77 {
3cb500d5
VZ
78 pl_cached_content_headers("application/x-x509-ca-cert");
79 readfile("/etc/ssl/xorgCA/cacert.pem");
5de0b7e1 80 exit;
81 }
82
83 function handler_changelog(&$page)
84 {
8b1f8e12 85 $page->changeTpl('platal/changeLog.tpl');
5de0b7e1 86
493b6abe 87 $clog = pl_entities(file_get_contents(dirname(__FILE__).'/../ChangeLog'));
8249b26c 88 $clog = preg_replace('/===+\s*/', '</pre><hr /><pre>', $clog);
4e95f720 89 // url catch only (not all wiki syntax)
90 $clog = preg_replace(array(
91 '/((?:https?|ftp):\/\/(?:\.*,*[\w@~%$£µ&i#\-+=_\/\?;])*)/ui',
92 '/(\s|^)www\.((?:\.*,*[\w@~%$£µ&i#\-+=_\/\?;])*)/iu',
93 '/(?:mailto:)?([a-z0-9.\-+_]+@([\-.+_]?[a-z0-9])+)/i'),
94 array(
95 '<a href="\\0">\\0</a>',
96 '\\1<a href="http://www.\\2">www.\\2</a>',
97 '<a href="mailto:\\0">\\0</a>'),
98 $clog);
5de0b7e1 99 $clog = preg_replace('!(#[0-9]+(,[0-9]+)*)!e', 'bugize("\1")', $clog);
9408f155 100 $clog = preg_replace('!vim:.*$!', '', $clog);
02722b9d 101 $clog = preg_replace("!(<hr />(\\s|\n)*)?<pre>(\s|\n)*</pre>((\\s|\n)*<hr />)?!m", "", "<pre>$clog</pre>");
5de0b7e1 102 $page->assign('ChangeLog', $clog);
103 }
104
7927d719 105 function __set_rss_state($state)
106 {
7927d719 107 if ($state) {
108 $_SESSION['core_rss_hash'] = rand_url_id(16);
08cce2ff 109 XDB::execute('UPDATE auth_user_quick
7927d719 110 SET core_rss_hash={?} WHERE user_id={?}',
cab08090 111 S::v('core_rss_hash'), S::v('uid'));
7927d719 112 } else {
08cce2ff 113 XDB::execute('UPDATE auth_user_quick
7927d719 114 SET core_rss_hash="" WHERE user_id={?}',
cab08090 115 S::v('uid'));
116 S::kill('core_rss_hash');
7927d719 117 }
118 }
119
e59506eb 120 function handler_prefs(&$page)
121 {
8b1f8e12 122 $page->changeTpl('platal/preferences.tpl');
46f272fe 123 $page->setTitle('Mes préférences');
e59506eb 124
bee33d93 125 if (Post::has('mail_fmt')) {
5e2307dc 126 $fmt = Post::v('mail_fmt');
e59506eb 127 if ($fmt != 'texte') $fmt = 'html';
08cce2ff 128 XDB::execute("UPDATE auth_user_quick
e59506eb 129 SET core_mail_fmt = '$fmt'
130 WHERE user_id = {?}",
cab08090 131 S::v('uid'));
e59506eb 132 $_SESSION['mail_fmt'] = $fmt;
e59506eb 133 }
134
bee33d93 135 if (Post::has('rss')) {
5e2307dc 136 $this->__set_rss_state(Post::b('rss'));
e59506eb 137 }
e67b4436
VZ
138
139 # FIXME: this code is not multi-domain compatible. We should decide how
140 # carva will extend to users not in the main domain.
141 $res = XDB::query("SELECT alias
142 FROM aliases
143 WHERE id = {?} AND FIND_IN_SET('bestalias', flags)",
144 S::user()->id());
145 $page->assign('bestalias', $res->fetchOneCell());
e59506eb 146 }
9bae6004 147
bce2f8eb 148 function handler_webredir(&$page)
149 {
8b1f8e12 150 $page->changeTpl('platal/webredirect.tpl');
bce2f8eb 151
46f272fe 152 $page->setTitle('Redirection de page WEB');
bce2f8eb 153
cab08090 154 $log =& S::v('log');
5e2307dc 155 $url = Env::v('url');
bce2f8eb 156
5e2307dc 157 if (Env::v('submit') == 'Valider' and Env::has('url')) {
08cce2ff 158 XDB::execute('UPDATE auth_user_quick
bce2f8eb 159 SET redirecturl = {?} WHERE user_id = {?}',
cab08090 160 $url, S::v('uid'));
732e5855 161 S::logger()->log('carva_add', 'http://'.Env::v('url'));
a7d35093 162 $page->trigSuccess("Redirection activée vers <a href='http://$url'>$url</a>");
5e2307dc 163 } elseif (Env::v('submit') == "Supprimer") {
08cce2ff 164 XDB::execute("UPDATE auth_user_quick
bce2f8eb 165 SET redirecturl = ''
166 WHERE user_id = {?}",
cab08090 167 S::v('uid'));
732e5855 168 S::logger()->log("carva_del", $url);
bce2f8eb 169 Post::kill('url');
a7d35093 170 $page->trigSuccess('Redirection supprimée');
bce2f8eb 171 }
172
08cce2ff 173 $res = XDB::query('SELECT redirecturl
bce2f8eb 174 FROM auth_user_quick
175 WHERE user_id = {?}',
cab08090 176 S::v('uid'));
bce2f8eb 177 $page->assign('carva', $res->fetchOneCell());
e67b4436
VZ
178
179 # FIXME: this code is not multi-domain compatible. We should decide how
180 # carva will extend to users not in the main domain.
181 $res = XDB::query("SELECT alias
182 FROM aliases
183 WHERE id = {?} AND FIND_IN_SET('bestalias', flags)",
184 S::user()->id());
185 $page->assign('bestalias', $res->fetchOneCell());
bce2f8eb 186 }
187
4da0b8d7 188 function handler_prefs_rss(&$page)
7927d719 189 {
8b1f8e12 190 $page->changeTpl('platal/filrss.tpl');
7927d719 191
5e2307dc 192 $page->assign('goback', Env::v('referer', 'login'));
7927d719 193
5e2307dc 194 if (Env::v('act_rss') == 'Activer') {
7927d719 195 $this->__set_rss_state(true);
a7d35093 196 $page->trigSuccess("Ton Fil RSS est activé.");
7927d719 197 }
7927d719 198 }
199
7c77c3ee 200 function handler_password(&$page)
201 {
84270653
VZ
202 global $globals;
203
40d428d8 204 if (Post::has('response2')) {
7c77c3ee 205 require_once 'secure_hash.inc.php';
40d428d8 206 S::assert_xsrf_token();
7c77c3ee 207
5e2307dc 208 $_SESSION['password'] = $password = Post::v('response2');
7c77c3ee 209
eaf30d86 210 XDB::execute('UPDATE auth_user_md5
9ffe0e77 211 SET password={?}
212 WHERE user_id={?}', $password,
213 S::v('uid'));
7c77c3ee 214
84270653
VZ
215 // If GoogleApps is enabled, and the user did choose to use synchronized passwords,
216 // updates the Google Apps password as well.
217 if ($globals->mailstorage->googleapps_domain) {
218 require_once 'googleapps.inc.php';
d56cb887 219 $account = new GoogleAppsAccount(S::user());
f5c4bf30 220 if ($account->active() && $account->sync_password) {
84270653
VZ
221 $account->set_password($password);
222 }
223 }
224
604dfd58
FB
225 S::logger()->log('passwd');
226 Platal::session()->setAccessCookie(true);
7c77c3ee 227
8b1f8e12 228 $page->changeTpl('platal/motdepasse.success.tpl');
7c77c3ee 229 $page->run();
230 }
231
8b1f8e12 232 $page->changeTpl('platal/motdepasse.tpl');
c99ef281 233 $page->addJsLink('motdepasse.js');
46f272fe 234 $page->setTitle('Mon mot de passe');
7c77c3ee 235 }
236
1a5da857 237 function handler_smtppass(&$page)
238 {
8b1f8e12 239 $page->changeTpl('platal/acces_smtp.tpl');
46f272fe 240 $page->setTitle('Acces SMTP/NNTP');
eaf30d86 241
8f201b69
FB
242 $wp = new PlWikiPage('Xorg.SMTPSécurisé');
243 $wp->buildCache();
244 $wp = new PlWikiPage('Xorg.NNTPSécurisé');
245 $wp->buildCache();
1a5da857 246
cab08090 247 $uid = S::v('uid');
5e2307dc 248 $pass = Env::v('smtppass1');
cab08090 249 $log = S::v('log');
1a5da857 250
eaf30d86
PH
251 if (Env::v('op') == "Valider" && strlen($pass) >= 6
252 && Env::v('smtppass1') == Env::v('smtppass2'))
1a5da857 253 {
08cce2ff 254 XDB::execute('UPDATE auth_user_md5 SET smtppass = {?}
1a5da857 255 WHERE user_id = {?}', $pass, $uid);
a7d35093 256 $page->trigSuccess('Mot de passe enregistré');
732e5855 257 S::logger()->log("passwd_ssl");
5e2307dc 258 } elseif (Env::v('op') == "Supprimer") {
08cce2ff 259 XDB::execute('UPDATE auth_user_md5 SET smtppass = ""
1a5da857 260 WHERE user_id = {?}', $uid);
a7d35093 261 $page->trigSuccess('Compte SMTP et NNTP supprimé');
732e5855 262 S::logger()->log("passwd_del");
1a5da857 263 }
264
eaf30d86 265 $res = XDB::query("SELECT IF(smtppass != '', 'actif', '')
1a5da857 266 FROM auth_user_md5
267 WHERE user_id = {?}", $uid);
268 $page->assign('actif', $res->fetchOneCell());
1a5da857 269 }
270
8858cfc1 271 function handler_recovery(&$page)
272 {
273 global $globals;
274
8b1f8e12 275 $page->changeTpl('platal/recovery.tpl');
8858cfc1 276
277 if (!Env::has('login') || !Env::has('birth')) {
fd8f77de 278 return;
8858cfc1 279 }
280
5e2307dc 281 if (!ereg('[0-3][0-9][0-1][0-9][1][9]([0-9]{2})', Env::v('birth'))) {
a7d35093 282 $page->trigError('Date de naissance incorrecte ou incohérente');
c9110c6c 283 return;
8858cfc1 284 }
c9110c6c 285
286 $birth = sprintf('%s-%s-%s',
5e2307dc 287 substr(Env::v('birth'), 4, 4),
288 substr(Env::v('birth'), 2, 2),
289 substr(Env::v('birth'), 0, 2));
8858cfc1 290
5e2307dc 291 $mailorg = strtok(Env::v('login'), '@');
8858cfc1 292
a7de4ef7 293 // paragraphe rajouté : si la date de naissance dans la base n'existe pas, on l'update
294 // avec celle fournie ici en espérant que c'est la bonne
8858cfc1 295
08cce2ff 296 $res = XDB::query(
8858cfc1 297 "SELECT user_id, naissance
298 FROM auth_user_md5 AS u
3a5c1551 299 INNER JOIN aliases AS a ON (u.user_id=a.id AND type != 'homonyme')
8858cfc1 300 WHERE a.alias={?} AND u.perms IN ('admin','user') AND u.deces=0", $mailorg);
301 list($uid, $naissance) = $res->fetchOneRow();
302
303 if ($naissance == $birth) {
8c28edc9 304 $res = XDB::query("SELECT COUNT(*)
305 FROM emails
306 WHERE uid = {?} AND flags != 'panne' AND flags != 'filter'", $uid);
307 $count = intval($res->fetchOneCell());
308 if ($count == 0) {
309 $page->assign('no_addr', true);
310 return;
311 }
312
8858cfc1 313 $page->assign('ok', true);
314
eaf30d86
PH
315 $url = rand_url_id();
316 XDB::execute('INSERT INTO perte_pass (certificat,uid,created)
a4d5829b 317 VALUES ({?},{?},NOW())', $url, $uid);
318 $res = XDB::query('SELECT email
319 FROM emails
320 WHERE uid = {?} AND email = {?}',
321 $uid, Post::v('email'));
322 if ($res->numRows()) {
323 $mails = $res->fetchOneCell();
324 } else {
be88a8f6
SJ
325 $user = User::getSilent($uid);
326 $mails = $user->bestEmail();
327 $res = XDB::query("SELECT email
a4d5829b 328 FROM emails
be88a8f6
SJ
329 WHERE uid = {?} AND NOT FIND_IN_SET('filter', flags)
330 AND NOT FIND_IN_SET('active', flags)",
331 $uid);
332 if ($res->numRows() > 0) {
333 $mails .= ', ' . implode(', ', $res->fetchColumn());
334 }
a4d5829b 335 }
1e33266a 336 $mymail = new PlMailer();
1d55fe45 337 $mymail->setFrom('"Gestion des mots de passe" <support+password@' . $globals->mail->domain . '>');
8858cfc1 338 $mymail->addTo($mails);
339 $mymail->setSubject('Ton certificat d\'authentification');
340 $mymail->setTxtBody("Visite la page suivante qui expire dans six heures :
341{$globals->baseurl}/tmpPWD/$url
342
e887e90d 343Si 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.
8858cfc1 344
eaf30d86 345--
8858cfc1 346Polytechnique.org
3bf63218 347\"Le portail des élèves & anciens élèves de l'École polytechnique\"
8858cfc1 348
faefdbb7 349Email envoyé à ".Env::v('login') . (Post::has('email') ? "
a4d5829b 350Adresse de secours : " . Post::v('email') : ""));
8858cfc1 351 $mymail->send();
352
353 // on cree un objet logger et on log l'evenement
b482a0b5 354 S::logger($uid)->log('recovery', $mails);
8858cfc1 355 } else {
a7d35093 356 $page->trigError('Les informations que tu as rentrées ne permettent pas de récupérer ton mot de passe.<br />'.
3a5c1551 357 'Si tu as un homonyme, utilise prenom.nom.promo comme login');
8858cfc1 358 }
8858cfc1 359 }
360
6c49d0af 361 function handler_tmpPWD(&$page, $certif = null)
362 {
84270653 363 global $globals;
08cce2ff 364 XDB::execute('DELETE FROM perte_pass
6c49d0af 365 WHERE DATE_SUB(NOW(), INTERVAL 380 MINUTE) > created');
366
08cce2ff 367 $res = XDB::query('SELECT uid FROM perte_pass WHERE certificat={?}', $certif);
6c49d0af 368 $ligne = $res->fetchOneAssoc();
369 if (!$ligne) {
8b1f8e12 370 $page->changeTpl('platal/index.tpl');
6c49d0af 371 $page->kill("Cette adresse n'existe pas ou n'existe plus sur le serveur.");
372 }
373
374 $uid = $ligne["uid"];
375 if (Post::has('response2')) {
5e2307dc 376 $password = Post::v('response2');
08cce2ff 377 XDB::query('UPDATE auth_user_md5 SET password={?}
6c49d0af 378 WHERE user_id={?} AND perms IN("admin","user")',
379 $password, $uid);
08cce2ff 380 XDB::query('DELETE FROM perte_pass WHERE certificat={?}', $certif);
84270653
VZ
381
382 // If GoogleApps is enabled, and the user did choose to use synchronized passwords,
383 // updates the Google Apps password as well.
384 if ($globals->mailstorage->googleapps_domain) {
385 require_once 'googleapps.inc.php';
d56cb887 386 $account = new GoogleAppsAccount(User::getSilent($uid));
f5c4bf30 387 if ($account->active() && $account->sync_password) {
84270653
VZ
388 $account->set_password($password);
389 }
390 }
391
cf40e1ae 392 S::logger($uid)->log("passwd", "");
8b1f8e12 393 $page->changeTpl('platal/tmpPWD.success.tpl');
6c49d0af 394 } else {
8b1f8e12 395 $page->changeTpl('platal/motdepasse.tpl');
c99ef281 396 $page->addJsLink('motdepasse.js');
6c49d0af 397 }
6c49d0af 398 }
399
9bae6004 400 function handler_skin(&$page)
401 {
402 global $globals;
403
8b1f8e12 404 $page->changeTpl('platal/skins.tpl');
46f272fe 405 $page->setTitle('Skins');
9bae6004 406
a7de4ef7 407 if (Env::has('newskin')) { // formulaire soumis, traitons les données envoyées
08cce2ff 408 XDB::execute('UPDATE auth_user_quick
63528107 409 SET skin={?} WHERE user_id={?}',
5e2307dc 410 Env::i('newskin'), S::v('uid'));
92e6a287 411 S::kill('skin');
47fa97fe 412 Platal::session()->setSkin();
9bae6004 413 }
414
92e6a287 415 $res = XDB::query('SELECT id FROM skins WHERE skin_tpl={?}', S::v('skin'));
416 $page->assign('skin_id', $res->fetchOneCell());
417
9bae6004 418 $sql = "SELECT s.*,auteur,count(*) AS nb
419 FROM skins AS s
420 LEFT JOIN auth_user_quick AS a ON s.id=a.skin
421 WHERE skin_tpl != '' AND ext != ''
422 GROUP BY id ORDER BY s.date DESC";
a3afa47c 423 $page->assign('skins', XDB::iterator($sql));
9bae6004 424 }
4da0b8d7 425
5de0b7e1 426 function handler_exit(&$page, $level = null)
427 {
cab08090 428 if (S::has('suid')) {
e74411f7 429 $suid = S::v('suid');
430 $log = S::v('log');
ae277b9f 431 S::logger()->log("suid_stop", S::user()->login() . " by " . $suid['hruid']);
47fa97fe 432 Platal::session()->stopSUID();
ae277b9f 433 pl_redirect('admin/user/' . S::user()->login());
5de0b7e1 434 }
435
436 if ($level == 'forget' || $level == 'forgetall') {
604dfd58 437 Platal::session()->killAccessCookie();
5de0b7e1 438 }
439
440 if ($level == 'forgetuid' || $level == 'forgetall') {
604dfd58 441 Platal::session()->killLoginFormCookies();
5de0b7e1 442 }
443
130b8708 444 if (S::logged()) {
59bec5bc
FB
445 S::logger()->log('deconnexion', @$_SERVER['HTTP_REFERER']);
446 Platal::session()->destroy();
130b8708 447 }
5de0b7e1 448
449 if (Get::has('redirect')) {
5e2307dc 450 http_redirect(rawurldecode(Get::v('redirect')));
5de0b7e1 451 } else {
8b1f8e12 452 $page->changeTpl('platal/exit.tpl');
5de0b7e1 453 }
5de0b7e1 454 }
ddb64990
FB
455
456 function handler_review(&$page, $action = null, $mode = null)
457 {
78507d96
AA
458 // Include X-XRDS-Location response-header for Yadis discovery
459 global $globals;
34d91db6 460 header('X-XRDS-Location: ' . $globals->baseurl . '/openid/xrds');
78507d96 461
460d8f55 462 $this->load('review.inc.php');
ddb64990
FB
463 $dom = 'Review';
464 if (@$GLOBALS['IS_XNET_SITE']) {
465 $dom .= 'Xnet';
466 }
8f201b69
FB
467 $wp = new PlWikiPage($dom . '.Admin');
468 $conf = explode('%0a', $wp->getField('text'));
6d20fb1d 469 $wiz = new PlWizard('Tour d\'horizon', PlPage::getCoreTpl('plwizard.tpl'), true);
ddb64990
FB
470 foreach ($conf as $line) {
471 $list = preg_split('/\s*[*|]\s*/', $line, -1, PREG_SPLIT_NO_EMPTY);
472 $wiz->addPage('ReviewPage', $list[0], $list[1]);
473 }
474 $wiz->apply($page, 'review', $action, $mode);
475 }
e59506eb 476}
477
a7de4ef7 478// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
e59506eb 479?>