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