Adds content caching for static content (css, images, javascript).
[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
FB
71 } else if (!@$GLOBALS['IS_XNET_SITE']) {
72 pl_redirect('review');
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
89 function handler_changelog(&$page)
90 {
8b1f8e12 91 $page->changeTpl('platal/changeLog.tpl');
5de0b7e1 92
493b6abe 93 $clog = pl_entities(file_get_contents(dirname(__FILE__).'/../ChangeLog'));
8249b26c 94 $clog = preg_replace('/===+\s*/', '</pre><hr /><pre>', $clog);
4e95f720 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'),
100 array(
101 '<a href="\\0">\\0</a>',
102 '\\1<a href="http://www.\\2">www.\\2</a>',
103 '<a href="mailto:\\0">\\0</a>'),
104 $clog);
5de0b7e1 105 $clog = preg_replace('!(#[0-9]+(,[0-9]+)*)!e', 'bugize("\1")', $clog);
9408f155 106 $clog = preg_replace('!vim:.*$!', '', $clog);
02722b9d 107 $clog = preg_replace("!(<hr />(\\s|\n)*)?<pre>(\s|\n)*</pre>((\\s|\n)*<hr />)?!m", "", "<pre>$clog</pre>");
5de0b7e1 108 $page->assign('ChangeLog', $clog);
109 }
110
7927d719 111 function __set_rss_state($state)
112 {
7927d719 113 if ($state) {
114 $_SESSION['core_rss_hash'] = rand_url_id(16);
08cce2ff 115 XDB::execute('UPDATE auth_user_quick
7927d719 116 SET core_rss_hash={?} WHERE user_id={?}',
cab08090 117 S::v('core_rss_hash'), S::v('uid'));
7927d719 118 } else {
08cce2ff 119 XDB::execute('UPDATE auth_user_quick
7927d719 120 SET core_rss_hash="" WHERE user_id={?}',
cab08090 121 S::v('uid'));
122 S::kill('core_rss_hash');
7927d719 123 }
124 }
125
e59506eb 126 function handler_prefs(&$page)
127 {
8b1f8e12 128 $page->changeTpl('platal/preferences.tpl');
46f272fe 129 $page->setTitle('Mes préférences');
e59506eb 130
bee33d93 131 if (Post::has('mail_fmt')) {
5e2307dc 132 $fmt = Post::v('mail_fmt');
e59506eb 133 if ($fmt != 'texte') $fmt = 'html';
08cce2ff 134 XDB::execute("UPDATE auth_user_quick
e59506eb 135 SET core_mail_fmt = '$fmt'
136 WHERE user_id = {?}",
cab08090 137 S::v('uid'));
e59506eb 138 $_SESSION['mail_fmt'] = $fmt;
e59506eb 139 }
140
bee33d93 141 if (Post::has('rss')) {
5e2307dc 142 $this->__set_rss_state(Post::b('rss'));
e59506eb 143 }
e67b4436
VZ
144
145 # FIXME: this code is not multi-domain compatible. We should decide how
146 # carva will extend to users not in the main domain.
147 $res = XDB::query("SELECT alias
148 FROM aliases
149 WHERE id = {?} AND FIND_IN_SET('bestalias', flags)",
150 S::user()->id());
151 $page->assign('bestalias', $res->fetchOneCell());
e59506eb 152 }
9bae6004 153
bce2f8eb 154 function handler_webredir(&$page)
155 {
8b1f8e12 156 $page->changeTpl('platal/webredirect.tpl');
bce2f8eb 157
46f272fe 158 $page->setTitle('Redirection de page WEB');
bce2f8eb 159
cab08090 160 $log =& S::v('log');
5e2307dc 161 $url = Env::v('url');
bce2f8eb 162
5e2307dc 163 if (Env::v('submit') == 'Valider' and Env::has('url')) {
08cce2ff 164 XDB::execute('UPDATE auth_user_quick
bce2f8eb 165 SET redirecturl = {?} WHERE user_id = {?}',
cab08090 166 $url, S::v('uid'));
732e5855 167 S::logger()->log('carva_add', 'http://'.Env::v('url'));
a7d35093 168 $page->trigSuccess("Redirection activée vers <a href='http://$url'>$url</a>");
5e2307dc 169 } elseif (Env::v('submit') == "Supprimer") {
08cce2ff 170 XDB::execute("UPDATE auth_user_quick
bce2f8eb 171 SET redirecturl = ''
172 WHERE user_id = {?}",
cab08090 173 S::v('uid'));
732e5855 174 S::logger()->log("carva_del", $url);
bce2f8eb 175 Post::kill('url');
a7d35093 176 $page->trigSuccess('Redirection supprimée');
bce2f8eb 177 }
178
08cce2ff 179 $res = XDB::query('SELECT redirecturl
bce2f8eb 180 FROM auth_user_quick
181 WHERE user_id = {?}',
cab08090 182 S::v('uid'));
bce2f8eb 183 $page->assign('carva', $res->fetchOneCell());
e67b4436
VZ
184
185 # FIXME: this code is not multi-domain compatible. We should decide how
186 # carva will extend to users not in the main domain.
187 $res = XDB::query("SELECT alias
188 FROM aliases
189 WHERE id = {?} AND FIND_IN_SET('bestalias', flags)",
190 S::user()->id());
191 $page->assign('bestalias', $res->fetchOneCell());
bce2f8eb 192 }
193
4da0b8d7 194 function handler_prefs_rss(&$page)
7927d719 195 {
8b1f8e12 196 $page->changeTpl('platal/filrss.tpl');
7927d719 197
5e2307dc 198 $page->assign('goback', Env::v('referer', 'login'));
7927d719 199
5e2307dc 200 if (Env::v('act_rss') == 'Activer') {
7927d719 201 $this->__set_rss_state(true);
a7d35093 202 $page->trigSuccess("Ton Fil RSS est activé.");
7927d719 203 }
7927d719 204 }
205
7c77c3ee 206 function handler_password(&$page)
207 {
84270653
VZ
208 global $globals;
209
40d428d8 210 if (Post::has('response2')) {
7c77c3ee 211 require_once 'secure_hash.inc.php';
40d428d8 212 S::assert_xsrf_token();
7c77c3ee 213
5e2307dc 214 $_SESSION['password'] = $password = Post::v('response2');
7c77c3ee 215
eaf30d86 216 XDB::execute('UPDATE auth_user_md5
9ffe0e77 217 SET password={?}
218 WHERE user_id={?}', $password,
219 S::v('uid'));
7c77c3ee 220
84270653
VZ
221 // If GoogleApps is enabled, and the user did choose to use synchronized passwords,
222 // updates the Google Apps password as well.
223 if ($globals->mailstorage->googleapps_domain) {
224 require_once 'googleapps.inc.php';
d56cb887 225 $account = new GoogleAppsAccount(S::user());
f5c4bf30 226 if ($account->active() && $account->sync_password) {
84270653
VZ
227 $account->set_password($password);
228 }
229 }
230
604dfd58
FB
231 S::logger()->log('passwd');
232 Platal::session()->setAccessCookie(true);
7c77c3ee 233
8b1f8e12 234 $page->changeTpl('platal/motdepasse.success.tpl');
7c77c3ee 235 $page->run();
236 }
237
8b1f8e12 238 $page->changeTpl('platal/motdepasse.tpl');
c99ef281 239 $page->addJsLink('motdepasse.js');
46f272fe 240 $page->setTitle('Mon mot de passe');
7c77c3ee 241 }
242
1a5da857 243 function handler_smtppass(&$page)
244 {
8b1f8e12 245 $page->changeTpl('platal/acces_smtp.tpl');
46f272fe 246 $page->setTitle('Acces SMTP/NNTP');
eaf30d86 247
8f201b69
FB
248 $wp = new PlWikiPage('Xorg.SMTPSécurisé');
249 $wp->buildCache();
250 $wp = new PlWikiPage('Xorg.NNTPSécurisé');
251 $wp->buildCache();
1a5da857 252
cab08090 253 $uid = S::v('uid');
5e2307dc 254 $pass = Env::v('smtppass1');
cab08090 255 $log = S::v('log');
1a5da857 256
eaf30d86
PH
257 if (Env::v('op') == "Valider" && strlen($pass) >= 6
258 && Env::v('smtppass1') == Env::v('smtppass2'))
1a5da857 259 {
08cce2ff 260 XDB::execute('UPDATE auth_user_md5 SET smtppass = {?}
1a5da857 261 WHERE user_id = {?}', $pass, $uid);
a7d35093 262 $page->trigSuccess('Mot de passe enregistré');
732e5855 263 S::logger()->log("passwd_ssl");
5e2307dc 264 } elseif (Env::v('op') == "Supprimer") {
08cce2ff 265 XDB::execute('UPDATE auth_user_md5 SET smtppass = ""
1a5da857 266 WHERE user_id = {?}', $uid);
a7d35093 267 $page->trigSuccess('Compte SMTP et NNTP supprimé');
732e5855 268 S::logger()->log("passwd_del");
1a5da857 269 }
270
eaf30d86 271 $res = XDB::query("SELECT IF(smtppass != '', 'actif', '')
1a5da857 272 FROM auth_user_md5
273 WHERE user_id = {?}", $uid);
274 $page->assign('actif', $res->fetchOneCell());
1a5da857 275 }
276
8858cfc1 277 function handler_recovery(&$page)
278 {
279 global $globals;
280
8b1f8e12 281 $page->changeTpl('platal/recovery.tpl');
8858cfc1 282
283 if (!Env::has('login') || !Env::has('birth')) {
fd8f77de 284 return;
8858cfc1 285 }
286
5e2307dc 287 if (!ereg('[0-3][0-9][0-1][0-9][1][9]([0-9]{2})', Env::v('birth'))) {
a7d35093 288 $page->trigError('Date de naissance incorrecte ou incohérente');
c9110c6c 289 return;
8858cfc1 290 }
c9110c6c 291
292 $birth = sprintf('%s-%s-%s',
5e2307dc 293 substr(Env::v('birth'), 4, 4),
294 substr(Env::v('birth'), 2, 2),
295 substr(Env::v('birth'), 0, 2));
8858cfc1 296
5e2307dc 297 $mailorg = strtok(Env::v('login'), '@');
8858cfc1 298
a7de4ef7 299 // paragraphe rajouté : si la date de naissance dans la base n'existe pas, on l'update
300 // avec celle fournie ici en espérant que c'est la bonne
8858cfc1 301
08cce2ff 302 $res = XDB::query(
8858cfc1 303 "SELECT user_id, naissance
304 FROM auth_user_md5 AS u
3a5c1551 305 INNER JOIN aliases AS a ON (u.user_id=a.id AND type != 'homonyme')
8858cfc1 306 WHERE a.alias={?} AND u.perms IN ('admin','user') AND u.deces=0", $mailorg);
307 list($uid, $naissance) = $res->fetchOneRow();
308
309 if ($naissance == $birth) {
8c28edc9 310 $res = XDB::query("SELECT COUNT(*)
311 FROM emails
312 WHERE uid = {?} AND flags != 'panne' AND flags != 'filter'", $uid);
313 $count = intval($res->fetchOneCell());
314 if ($count == 0) {
315 $page->assign('no_addr', true);
316 return;
317 }
318
8858cfc1 319 $page->assign('ok', true);
320
eaf30d86
PH
321 $url = rand_url_id();
322 XDB::execute('INSERT INTO perte_pass (certificat,uid,created)
a4d5829b 323 VALUES ({?},{?},NOW())', $url, $uid);
324 $res = XDB::query('SELECT email
325 FROM emails
326 WHERE uid = {?} AND email = {?}',
327 $uid, Post::v('email'));
328 if ($res->numRows()) {
329 $mails = $res->fetchOneCell();
330 } else {
be88a8f6
SJ
331 $user = User::getSilent($uid);
332 $mails = $user->bestEmail();
333 $res = XDB::query("SELECT email
a4d5829b 334 FROM emails
be88a8f6
SJ
335 WHERE uid = {?} AND NOT FIND_IN_SET('filter', flags)
336 AND NOT FIND_IN_SET('active', flags)",
337 $uid);
338 if ($res->numRows() > 0) {
339 $mails .= ', ' . implode(', ', $res->fetchColumn());
340 }
a4d5829b 341 }
1e33266a 342 $mymail = new PlMailer();
1d55fe45 343 $mymail->setFrom('"Gestion des mots de passe" <support+password@' . $globals->mail->domain . '>');
8858cfc1 344 $mymail->addTo($mails);
345 $mymail->setSubject('Ton certificat d\'authentification');
346 $mymail->setTxtBody("Visite la page suivante qui expire dans six heures :
347{$globals->baseurl}/tmpPWD/$url
348
e887e90d 349Si 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 350
eaf30d86 351--
8858cfc1 352Polytechnique.org
3bf63218 353\"Le portail des élèves & anciens élèves de l'École polytechnique\"
8858cfc1 354
faefdbb7 355Email envoyé à ".Env::v('login') . (Post::has('email') ? "
a4d5829b 356Adresse de secours : " . Post::v('email') : ""));
8858cfc1 357 $mymail->send();
358
359 // on cree un objet logger et on log l'evenement
b482a0b5 360 S::logger($uid)->log('recovery', $mails);
8858cfc1 361 } else {
a7d35093 362 $page->trigError('Les informations que tu as rentrées ne permettent pas de récupérer ton mot de passe.<br />'.
3a5c1551 363 'Si tu as un homonyme, utilise prenom.nom.promo comme login');
8858cfc1 364 }
8858cfc1 365 }
366
6c49d0af 367 function handler_tmpPWD(&$page, $certif = null)
368 {
84270653 369 global $globals;
08cce2ff 370 XDB::execute('DELETE FROM perte_pass
6c49d0af 371 WHERE DATE_SUB(NOW(), INTERVAL 380 MINUTE) > created');
372
08cce2ff 373 $res = XDB::query('SELECT uid FROM perte_pass WHERE certificat={?}', $certif);
6c49d0af 374 $ligne = $res->fetchOneAssoc();
375 if (!$ligne) {
8b1f8e12 376 $page->changeTpl('platal/index.tpl');
6c49d0af 377 $page->kill("Cette adresse n'existe pas ou n'existe plus sur le serveur.");
378 }
379
380 $uid = $ligne["uid"];
381 if (Post::has('response2')) {
5e2307dc 382 $password = Post::v('response2');
08cce2ff 383 XDB::query('UPDATE auth_user_md5 SET password={?}
6c49d0af 384 WHERE user_id={?} AND perms IN("admin","user")',
385 $password, $uid);
08cce2ff 386 XDB::query('DELETE FROM perte_pass WHERE certificat={?}', $certif);
84270653
VZ
387
388 // If GoogleApps is enabled, and the user did choose to use synchronized passwords,
389 // updates the Google Apps password as well.
390 if ($globals->mailstorage->googleapps_domain) {
391 require_once 'googleapps.inc.php';
d56cb887 392 $account = new GoogleAppsAccount(User::getSilent($uid));
f5c4bf30 393 if ($account->active() && $account->sync_password) {
84270653
VZ
394 $account->set_password($password);
395 }
396 }
397
cf40e1ae 398 S::logger($uid)->log("passwd", "");
8b1f8e12 399 $page->changeTpl('platal/tmpPWD.success.tpl');
6c49d0af 400 } else {
8b1f8e12 401 $page->changeTpl('platal/motdepasse.tpl');
c99ef281 402 $page->addJsLink('motdepasse.js');
6c49d0af 403 }
6c49d0af 404 }
405
9bae6004 406 function handler_skin(&$page)
407 {
408 global $globals;
409
8b1f8e12 410 $page->changeTpl('platal/skins.tpl');
46f272fe 411 $page->setTitle('Skins');
9bae6004 412
a7de4ef7 413 if (Env::has('newskin')) { // formulaire soumis, traitons les données envoyées
08cce2ff 414 XDB::execute('UPDATE auth_user_quick
63528107 415 SET skin={?} WHERE user_id={?}',
5e2307dc 416 Env::i('newskin'), S::v('uid'));
92e6a287 417 S::kill('skin');
47fa97fe 418 Platal::session()->setSkin();
9bae6004 419 }
420
92e6a287 421 $res = XDB::query('SELECT id FROM skins WHERE skin_tpl={?}', S::v('skin'));
422 $page->assign('skin_id', $res->fetchOneCell());
423
9bae6004 424 $sql = "SELECT s.*,auteur,count(*) AS nb
425 FROM skins AS s
426 LEFT JOIN auth_user_quick AS a ON s.id=a.skin
427 WHERE skin_tpl != '' AND ext != ''
428 GROUP BY id ORDER BY s.date DESC";
a3afa47c 429 $page->assign('skins', XDB::iterator($sql));
9bae6004 430 }
4da0b8d7 431
5de0b7e1 432 function handler_exit(&$page, $level = null)
433 {
cab08090 434 if (S::has('suid')) {
e74411f7 435 $suid = S::v('suid');
436 $log = S::v('log');
ae277b9f 437 S::logger()->log("suid_stop", S::user()->login() . " by " . $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?>