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