Improves 59887c: uses global domain instead of polytechnique.org, improves javascript...
[platal.git] / modules / platal.php
1 <?php
2 /***************************************************************************
3 * Copyright (C) 2003-2008 Polytechnique.org *
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
22 function 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
36 class PlatalModule extends PLModule
37 {
38 function handlers()
39 {
40 return array(
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),
44
45 // Preferences thingies
46 'prefs' => $this->make_hook('prefs', AUTH_COOKIE),
47 'prefs/rss' => $this->make_hook('prefs_rss', AUTH_COOKIE),
48 'prefs/webredirect'
49 => $this->make_hook('webredir', AUTH_MDP),
50 'prefs/skin' => $this->make_hook('skin', AUTH_COOKIE),
51
52 // password related thingies
53 'password' => $this->make_hook('password', AUTH_MDP),
54 'tmpPWD' => $this->make_hook('tmpPWD', AUTH_PUBLIC),
55 'password/smtp' => $this->make_hook('smtppass', AUTH_MDP),
56 'recovery' => $this->make_hook('recovery', AUTH_PUBLIC),
57 'exit' => $this->make_hook('exit', AUTH_PUBLIC),
58 'review' => $this->make_hook('review', AUTH_PUBLIC),
59 'deconnexion.php' => $this->make_hook('exit', AUTH_PUBLIC),
60 );
61 }
62
63 function handler_index(&$page)
64 {
65 if (S::logged()) {
66 pl_redirect('events');
67 } else if (!@$GLOBALS['IS_XNET_SITE']) {
68 pl_redirect('review');
69 }
70 }
71
72 function handler_cacert(&$page)
73 {
74 $data = file_get_contents("/etc/ssl/xorgCA/cacert.pem","r");
75 header("Pragma:");
76 header("Set-Cookie:");
77 header("Cache-Control:");
78 header("Expires:");
79 header("Content-Type: application/x-x509-ca-cert");
80 header("Content-Length: ".strlen($data));
81 echo $data;
82 exit;
83 }
84
85 function handler_changelog(&$page)
86 {
87 $page->changeTpl('platal/changeLog.tpl');
88
89 $clog = pl_entities(file_get_contents(dirname(__FILE__).'/../ChangeLog'));
90 $clog = preg_replace('/=+\s*/', '</pre><hr /><pre>', $clog);
91 // url catch only (not all wiki syntax)
92 $clog = preg_replace(array(
93 '/((?:https?|ftp):\/\/(?:\.*,*[\w@~%$£µ&i#\-+=_\/\?;])*)/ui',
94 '/(\s|^)www\.((?:\.*,*[\w@~%$£µ&i#\-+=_\/\?;])*)/iu',
95 '/(?:mailto:)?([a-z0-9.\-+_]+@([\-.+_]?[a-z0-9])+)/i'),
96 array(
97 '<a href="\\0">\\0</a>',
98 '\\1<a href="http://www.\\2">www.\\2</a>',
99 '<a href="mailto:\\0">\\0</a>'),
100 $clog);
101 $clog = preg_replace('!(#[0-9]+(,[0-9]+)*)!e', 'bugize("\1")', $clog);
102 $clog = preg_replace('!vim:.*$!', '', $clog);
103 $clog = preg_replace("!(<hr />(\\s|\n)*)?<pre>(\s|\n)*</pre>((\\s|\n)*<hr />)?!m", "", "<pre>$clog</pre>");
104 $page->assign('ChangeLog', $clog);
105 }
106
107 function __set_rss_state($state)
108 {
109 if ($state) {
110 $_SESSION['core_rss_hash'] = rand_url_id(16);
111 XDB::execute('UPDATE auth_user_quick
112 SET core_rss_hash={?} WHERE user_id={?}',
113 S::v('core_rss_hash'), S::v('uid'));
114 } else {
115 XDB::execute('UPDATE auth_user_quick
116 SET core_rss_hash="" WHERE user_id={?}',
117 S::v('uid'));
118 S::kill('core_rss_hash');
119 }
120 }
121
122 function handler_prefs(&$page)
123 {
124 $page->changeTpl('platal/preferences.tpl');
125 $page->assign('xorg_title','Polytechnique.org - Mes préférences');
126
127 if (Post::has('mail_fmt')) {
128 $fmt = Post::v('mail_fmt');
129 if ($fmt != 'texte') $fmt = 'html';
130 XDB::execute("UPDATE auth_user_quick
131 SET core_mail_fmt = '$fmt'
132 WHERE user_id = {?}",
133 S::v('uid'));
134 $_SESSION['mail_fmt'] = $fmt;
135 }
136
137 if (Post::has('rss')) {
138 $this->__set_rss_state(Post::b('rss'));
139 }
140 }
141
142 function handler_webredir(&$page)
143 {
144 $page->changeTpl('platal/webredirect.tpl');
145
146 $page->assign('xorg_title','Polytechnique.org - Redirection de page WEB');
147
148 $log =& S::v('log');
149 $url = Env::v('url');
150
151 if (Env::v('submit') == 'Valider' and Env::has('url')) {
152 XDB::execute('UPDATE auth_user_quick
153 SET redirecturl = {?} WHERE user_id = {?}',
154 $url, S::v('uid'));
155 $log->log('carva_add', 'http://'.Env::v('url'));
156 $page->trigSuccess("Redirection activée vers <a href='http://$url'>$url</a>");
157 } elseif (Env::v('submit') == "Supprimer") {
158 XDB::execute("UPDATE auth_user_quick
159 SET redirecturl = ''
160 WHERE user_id = {?}",
161 S::v('uid'));
162 $log->log("carva_del", $url);
163 Post::kill('url');
164 $page->trigSuccess('Redirection supprimée');
165 }
166
167 $res = XDB::query('SELECT redirecturl
168 FROM auth_user_quick
169 WHERE user_id = {?}',
170 S::v('uid'));
171 $page->assign('carva', $res->fetchOneCell());
172 }
173
174 function handler_prefs_rss(&$page)
175 {
176 $page->changeTpl('platal/filrss.tpl');
177
178 $page->assign('goback', Env::v('referer', 'login'));
179
180 if (Env::v('act_rss') == 'Activer') {
181 $this->__set_rss_state(true);
182 $page->trigSuccess("Ton Fil RSS est activé.");
183 }
184 }
185
186 function handler_password(&$page)
187 {
188 global $globals;
189
190 if (Post::has('response2')) {
191 require_once 'secure_hash.inc.php';
192 S::assert_xsrf_token();
193
194 $_SESSION['password'] = $password = Post::v('response2');
195
196 XDB::execute('UPDATE auth_user_md5
197 SET password={?}
198 WHERE user_id={?}', $password,
199 S::v('uid'));
200
201 // If GoogleApps is enabled, and the user did choose to use synchronized passwords,
202 // updates the Google Apps password as well.
203 if ($globals->mailstorage->googleapps_domain) {
204 require_once 'googleapps.inc.php';
205 $account = new GoogleAppsAccount(S::v('uid'), S::v('forlife'));
206 if ($account->active() && $account->sync_password) {
207 $account->set_password($password);
208 }
209 }
210
211 $log =& S::v('log');
212 $log->log('passwd', '');
213
214 if (Cookie::v('ORGaccess')) {
215 setcookie('ORGaccess', hash_encrypt($password), (time()+25920000), '/', '' ,0);
216 }
217
218 $page->changeTpl('platal/motdepasse.success.tpl');
219 $page->run();
220 }
221
222 $page->changeTpl('platal/motdepasse.tpl');
223 $page->addJsLink('motdepasse.js');
224 $page->assign('xorg_title','Polytechnique.org - Mon mot de passe');
225 }
226
227 function handler_smtppass(&$page)
228 {
229 $page->changeTpl('platal/acces_smtp.tpl');
230 $page->assign('xorg_title','Polytechnique.org - Acces SMTP/NNTP');
231
232 require_once 'wiki.inc.php';
233 wiki_require_page('Xorg.SMTPSécurisé');
234 wiki_require_page('Xorg.NNTPSécurisé');
235
236 $uid = S::v('uid');
237 $pass = Env::v('smtppass1');
238 $log = S::v('log');
239
240 if (Env::v('op') == "Valider" && strlen($pass) >= 6
241 && Env::v('smtppass1') == Env::v('smtppass2'))
242 {
243 XDB::execute('UPDATE auth_user_md5 SET smtppass = {?}
244 WHERE user_id = {?}', $pass, $uid);
245 $page->trigSuccess('Mot de passe enregistré');
246 $log->log("passwd_ssl");
247 } elseif (Env::v('op') == "Supprimer") {
248 XDB::execute('UPDATE auth_user_md5 SET smtppass = ""
249 WHERE user_id = {?}', $uid);
250 $page->trigSuccess('Compte SMTP et NNTP supprimé');
251 $log->log("passwd_del");
252 }
253
254 $res = XDB::query("SELECT IF(smtppass != '', 'actif', '')
255 FROM auth_user_md5
256 WHERE user_id = {?}", $uid);
257 $page->assign('actif', $res->fetchOneCell());
258 }
259
260 function handler_recovery(&$page)
261 {
262 global $globals;
263
264 $page->changeTpl('platal/recovery.tpl');
265
266 if (!Env::has('login') || !Env::has('birth')) {
267 return;
268 }
269
270 if (!ereg('[0-3][0-9][0-1][0-9][1][9]([0-9]{2})', Env::v('birth'))) {
271 $page->trigError('Date de naissance incorrecte ou incohérente');
272 return;
273 }
274
275 $birth = sprintf('%s-%s-%s',
276 substr(Env::v('birth'), 4, 4),
277 substr(Env::v('birth'), 2, 2),
278 substr(Env::v('birth'), 0, 2));
279
280 $mailorg = strtok(Env::v('login'), '@');
281
282 // paragraphe rajouté : si la date de naissance dans la base n'existe pas, on l'update
283 // avec celle fournie ici en espérant que c'est la bonne
284
285 $res = XDB::query(
286 "SELECT user_id, naissance
287 FROM auth_user_md5 AS u
288 INNER JOIN aliases AS a ON (u.user_id=a.id AND type != 'homonyme')
289 WHERE a.alias={?} AND u.perms IN ('admin','user') AND u.deces=0", $mailorg);
290 list($uid, $naissance) = $res->fetchOneRow();
291
292 if ($naissance == $birth) {
293 $res = XDB::query("SELECT COUNT(*)
294 FROM emails
295 WHERE uid = {?} AND flags != 'panne' AND flags != 'filter'", $uid);
296 $count = intval($res->fetchOneCell());
297 if ($count == 0) {
298 $page->assign('no_addr', true);
299 return;
300 }
301
302 $page->assign('ok', true);
303
304 $url = rand_url_id();
305 XDB::execute('INSERT INTO perte_pass (certificat,uid,created)
306 VALUES ({?},{?},NOW())', $url, $uid);
307 $res = XDB::query('SELECT email
308 FROM emails
309 WHERE uid = {?} AND email = {?}',
310 $uid, Post::v('email'));
311 if ($res->numRows()) {
312 $mails = $res->fetchOneCell();
313 } else {
314 $res = XDB::query('SELECT email
315 FROM emails
316 WHERE uid = {?} AND NOT FIND_IN_SET("filter", flags)', $uid);
317 $mails = implode(', ', $res->fetchColumn());
318 }
319 $mymail = new PlMailer();
320 $mymail->setFrom('"Gestion des mots de passe" <support+password@' . $globals->mail->domain . '>');
321 $mymail->addTo($mails);
322 $mymail->setSubject('Ton certificat d\'authentification');
323 $mymail->setTxtBody("Visite la page suivante qui expire dans six heures :
324 {$globals->baseurl}/tmpPWD/$url
325
326 Si 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.
327
328 --
329 Polytechnique.org
330 \"Le portail des élèves & anciens élèves de l'Ecole polytechnique\"
331
332 Mail envoyé à ".Env::v('login') . (Post::has('email') ? "
333 Adresse de secours : " . Post::v('email') : ""));
334 $mymail->send();
335
336 // on cree un objet logger et on log l'evenement
337 $logger = $_SESSION['log'] = new CoreLogger($uid);
338 $logger->log('recovery', $mails);
339 } else {
340 $page->trigError('Les informations que tu as rentrées ne permettent pas de récupérer ton mot de passe.<br />'.
341 'Si tu as un homonyme, utilise prenom.nom.promo comme login');
342 }
343 }
344
345 function handler_tmpPWD(&$page, $certif = null)
346 {
347 global $globals;
348 XDB::execute('DELETE FROM perte_pass
349 WHERE DATE_SUB(NOW(), INTERVAL 380 MINUTE) > created');
350
351 $res = XDB::query('SELECT uid FROM perte_pass WHERE certificat={?}', $certif);
352 $ligne = $res->fetchOneAssoc();
353 if (!$ligne) {
354 $page->changeTpl('platal/index.tpl');
355 $page->kill("Cette adresse n'existe pas ou n'existe plus sur le serveur.");
356 }
357
358 $uid = $ligne["uid"];
359 if (Post::has('response2')) {
360 $password = Post::v('response2');
361 XDB::query('UPDATE auth_user_md5 SET password={?}
362 WHERE user_id={?} AND perms IN("admin","user")',
363 $password, $uid);
364 XDB::query('DELETE FROM perte_pass WHERE certificat={?}', $certif);
365
366 // If GoogleApps is enabled, and the user did choose to use synchronized passwords,
367 // updates the Google Apps password as well.
368 if ($globals->mailstorage->googleapps_domain) {
369 require_once 'googleapps.inc.php';
370 $account = new GoogleAppsAccount($uid);
371 if ($account->active() && $account->sync_password) {
372 $account->set_password($password);
373 }
374 }
375
376 $logger = new CoreLogger($uid);
377 $logger->log("passwd","");
378 $page->changeTpl('platal/tmpPWD.success.tpl');
379 } else {
380 $page->changeTpl('platal/motdepasse.tpl');
381 $page->addJsLink('motdepasse.js');
382 }
383 }
384
385 function handler_skin(&$page)
386 {
387 global $globals;
388
389 $page->changeTpl('platal/skins.tpl');
390 $page->assign('xorg_title','Polytechnique.org - Skins');
391
392 if (Env::has('newskin')) { // formulaire soumis, traitons les données envoyées
393 XDB::execute('UPDATE auth_user_quick
394 SET skin={?} WHERE user_id={?}',
395 Env::i('newskin'), S::v('uid'));
396 S::kill('skin');
397 set_skin();
398 }
399
400 $res = XDB::query('SELECT id FROM skins WHERE skin_tpl={?}', S::v('skin'));
401 $page->assign('skin_id', $res->fetchOneCell());
402
403 $sql = "SELECT s.*,auteur,count(*) AS nb
404 FROM skins AS s
405 LEFT JOIN auth_user_quick AS a ON s.id=a.skin
406 WHERE skin_tpl != '' AND ext != ''
407 GROUP BY id ORDER BY s.date DESC";
408 $page->assign('skins', XDB::iterator($sql));
409 }
410
411 function handler_exit(&$page, $level = null)
412 {
413 if (S::has('suid')) {
414 $a4l = S::v('forlife');
415 $suid = S::v('suid');
416 $log = S::v('log');
417 $log->log("suid_stop", S::v('forlife') . " by " . $suid['forlife']);
418 $_SESSION = $suid;
419 S::kill('suid');
420 pl_redirect('admin/user/' . $a4l);
421 }
422
423 if ($level == 'forget' || $level == 'forgetall') {
424 setcookie('ORGaccess', '', time() - 3600, '/', '', 0);
425 Cookie::kill('ORGaccess');
426 if (isset($_SESSION['log']))
427 $_SESSION['log']->log("cookie_off");
428 }
429
430 if ($level == 'forgetuid' || $level == 'forgetall') {
431 setcookie('ORGuid', '', time() - 3600, '/', '', 0);
432 Cookie::kill('ORGuid');
433 setcookie('ORGdomain', '', time() - 3600, '/', '', 0);
434 Cookie::kill('ORGdomain');
435 }
436
437 if (isset($_SESSION['log'])) {
438 $ref = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
439 $_SESSION['log']->log('deconnexion',$ref);
440 }
441
442 XorgSession::destroy();
443
444 if (Get::has('redirect')) {
445 http_redirect(rawurldecode(Get::v('redirect')));
446 } else {
447 $page->changeTpl('platal/exit.tpl');
448 }
449 }
450
451 function handler_review(&$page, $action = null, $mode = null)
452 {
453 require_once 'wiki.inc.php';
454 require_once dirname(__FILE__) . '/platal/review.inc.php';
455 $dir = wiki_work_dir();
456 $dom = 'Review';
457 if (@$GLOBALS['IS_XNET_SITE']) {
458 $dom .= 'Xnet';
459 }
460 if (!is_dir($dir)) {
461 $page->kill("Impossible de trouver le wiki");
462 }
463 if (!file_exists($dir . '/' . $dom . '.Admin')) {
464 $page->kill("Impossible de trouver la page d'administration");
465 }
466 $conf = preg_grep('/^text=/', explode("\n", file_get_contents($dir . '/' . $dom . '.Admin')));
467 $conf = preg_split('/(text\=|\%0a)/', array_shift($conf), -1, PREG_SPLIT_NO_EMPTY);
468 $wiz = new PlWizard('Tour d\'horizon', 'core/plwizard.tpl', true);
469 foreach ($conf as $line) {
470 $list = preg_split('/\s*[*|]\s*/', $line, -1, PREG_SPLIT_NO_EMPTY);
471 $wiz->addPage('ReviewPage', $list[0], $list[1]);
472 }
473 $wiz->apply($page, 'review', $action, $mode);
474 }
475 }
476
477 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
478 ?>