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