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