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