2 /***************************************************************************
3 * Copyright (C) 2003-2010 Polytechnique.org *
4 * http://opensource.polytechnique.org/ *
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. *
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. *
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 *
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
20 ***************************************************************************/
22 function bugize($list)
24 $list = split(',', $list);
27 foreach ($list as $bug) {
28 $clean = str_replace('#', '', $bug);
29 $ans[] = "<a href='http://trackers.polytechnique.org/task/$clean'>$bug</a>";
32 return join(',', $ans);
36 class PlatalModule
extends PLModule
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
),
45 // Preferences thingies
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
, 'mail'),
49 'prefs/skin' => $this->make_hook('skin', AUTH_COOKIE
),
51 // password related thingies
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
, 'mail'),
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
),
62 function handler_index(&$page)
64 // Include X-XRDS-Location response-header for Yadis discovery
66 header('X-XRDS-Location: ' . $globals->baseurl
. '/openid/xrds');
68 // Redirect to the suitable page
70 pl_redirect('events');
71 } else if (!@$GLOBALS['IS_XNET_SITE']) {
72 $this->handler_review($page);
76 function handler_cacert(&$page)
78 pl_cached_content_headers("application/x-x509-ca-cert");
79 readfile("/etc/ssl/xorgCA/cacert.pem");
83 function handler_changelog(&$page, $core = null
)
85 $page->changeTpl('platal/changeLog.tpl');
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'),
96 '<a href="\\0">\\0</a>',
97 '\\1<a href="http://www.\\2">www.\\2</a>',
98 '<a href="mailto:\\0">\\0</a>'),
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>");
104 if ($core != 'core') {
105 $page->assign('core', false
);
106 $page->assign('ChangeLog', formatChangeLog(dirname(__FILE__
).'/../ChangeLog'));
108 $page->assign('core', true
);
109 $page->assign('ChangeLog', formatChangeLog(dirname(__FILE__
).'/../core/ChangeLog'));
113 function __set_rss_state($state)
116 S
::user()->token
= rand_url_id(16);
117 XDB
::execute('UPDATE accounts
119 WHERE uid = {?}', S
::user()->token
, S
::i('uid'));
122 XDB
::execute('UPDATE accounts
124 WHERE uid = {?}', S
::i('uid'));
128 function handler_prefs(&$page)
130 $page->changeTpl('platal/preferences.tpl');
131 $page->setTitle('Mes préférences');
133 if (Post
::has('email_format')) {
134 $fmt = Post
::s('email_format');
135 S
::user()->setEmailFormat($fmt);
138 if (Post
::has('rss')) {
139 $this->__set_rss_state(Post
::b('rss'));
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
146 WHERE uid = {?} AND FIND_IN_SET('bestalias', flags)",
148 $page->assign('bestalias', $res->fetchOneCell());
151 function handler_webredir(&$page)
153 $page->changeTpl('platal/webredirect.tpl');
154 $page->setTitle('Redirection de page WEB');
156 if (Env
::v('submit') == 'Valider' && !Env
::blank('url')) {
157 if (Env
::blank('url')) {
158 $page->trigError('URL invalide');
160 $url = Env
::t('url');
161 XDB
::execute('REPLACE INTO carvas (uid, url)
164 S
::logger()->log('carva_add', 'http://' . $url);
165 $page->trigSuccess("Redirection activée vers <a href='http://$url'>$url</a>");
167 } elseif (Env
::v('submit') == 'Supprimer') {
168 XDB
::execute('DELETE FROM carvas
169 WHERE uid = {?}', S
::i('uid'));
171 S
::logger()->log('carva_del');
172 $page->trigSuccess('Redirection supprimée');
175 $url = XDB
::fetchOneCell('SELECT url
177 WHERE uid = {?}', S
::i('uid'));
178 $page->assign('carva', $url);
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
184 WHERE uid = {?} AND FIND_IN_SET('bestalias', flags)",
186 $page->assign('bestalias', $res->fetchOneCell());
189 function handler_prefs_rss(&$page)
191 $page->changeTpl('platal/filrss.tpl');
193 $page->assign('goback', Env
::v('referer', 'login'));
195 if (Env
::v('act_rss') == 'Activer') {
196 $this->__set_rss_state(true
);
197 $page->trigSuccess("Ton Fil RSS est activé.");
201 function handler_password(&$page)
205 if (Post
::has('pwhash') && Post
::t('pwhash')) {
206 S
::assert_xsrf_token();
208 S
::set('password', $password = Post
::t('pwhash'));
209 XDB
::execute('UPDATE accounts
211 WHERE uid={?}', $password,
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';
218 $account = new GoogleAppsAccount(S
::user());
219 if ($account->active() && $account->sync_password
) {
220 $account->set_password($password);
224 S
::logger()->log('passwd');
225 Platal
::session()->setAccessCookie(true
);
227 $page->changeTpl('platal/password.success.tpl');
231 $page->changeTpl('platal/password.tpl');
232 $page->addJsLink('password.js');
233 $page->setTitle('Mon mot de passe');
236 function handler_smtppass(&$page)
238 $page->changeTpl('platal/acces_smtp.tpl');
239 $page->setTitle('Acces SMTP/NNTP');
241 $wp = new PlWikiPage('Xorg.SMTPSécurisé');
243 $wp = new PlWikiPage('Xorg.NNTPSécurisé');
247 $pass = Env
::v('smtppass1');
249 if (Env
::v('op') == "Valider" && strlen($pass) >= 6
250 && Env
::v('smtppass1') == Env
::v('smtppass2')) {
251 XDB
::execute('UPDATE accounts
252 SET weak_password = {?}
253 WHERE uid = {?}', $pass, $uid);
254 $page->trigSuccess('Mot de passe enregistré');
255 S
::logger()->log("passwd_ssl");
256 } elseif (Env
::v('op') == "Supprimer") {
257 XDB
::execute('UPDATE accounts
258 SET weak_password = NULL
259 WHERE uid = {?}', $uid);
260 $page->trigSuccess('Compte SMTP et NNTP supprimé');
261 S
::logger()->log("passwd_del");
264 $res = XDB
::query("SELECT weak_password IS NOT NULL
266 WHERE uid = {?}", $uid);
267 $page->assign('actif', $res->fetchOneCell());
270 function handler_recovery(&$page)
274 $page->changeTpl('platal/recovery.tpl');
276 if (!Env
::has('login') ||
!Env
::has('birth')) {
280 if (!ereg('[0-3][0-9][0-1][0-9][1][9]([0-9]{2})', Env
::v('birth'))) {
281 $page->trigError('Date de naissance incorrecte ou incohérente');
285 $birth = sprintf('%s-%s-%s',
286 substr(Env
::v('birth'), 4, 4),
287 substr(Env
::v('birth'), 2, 2),
288 substr(Env
::v('birth'), 0, 2));
290 $mailorg = strtok(Env
::v('login'), '@');
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');
299 $user = $profile->owner();
300 if ($user->state
!= 'active') {
301 $page->trigError('Ton compte n\'est pas activé.');
305 $res = XDB
::query("SELECT COUNT(*)
307 WHERE uid = {?} AND flags != 'panne' AND flags != 'filter'", $user->id());
308 $count = intval($res->fetchOneCell());
310 $page->assign('no_addr', true
);
314 $page->assign('ok', true
);
316 $url = rand_url_id();
317 XDB
::execute('INSERT INTO account_lost_passwords (certificat,uid,created)
318 VALUES ({?},{?},NOW())', $url, $user->id());
319 $res = XDB
::query('SELECT email
321 WHERE uid = {?} AND email = {?}',
322 $user->id(), Post
::v('email'));
323 if ($res->numRows()) {
324 $mails = $res->fetchOneCell();
326 $res = XDB
::query("SELECT email
328 WHERE uid = {?} AND NOT FIND_IN_SET('filter', flags)", $user->id());
329 $mails = implode(', ', $res->fetchColumn());
331 $mymail = new PlMailer();
332 $mymail->setFrom('"Gestion des mots de passe" <support+password@' . $globals->mail
->domain
. '>');
333 $mymail->addTo($mails);
334 $mymail->setSubject("Ton certificat d'authentification");
335 $mymail->setTxtBody("Visite la page suivante qui expire dans six heures :
336 {$globals->baseurl}/tmpPWD/$url
338 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.
342 \"Le portail des élèves & anciens élèves de l'École polytechnique\"
344 Email envoyé à ".Env
::v('login') . (Post
::has('email') ?
"
345 Adresse de secours : " . Post
::v('email') : ""));
348 // on cree un objet logger et on log l'evenement
349 S
::logger($user->id())->log('recovery', $mails);
352 function handler_tmpPWD(&$page, $certif = null
)
355 // XXX: recovery requires data from the profile
356 XDB
::execute('DELETE FROM account_lost_passwords
357 WHERE DATE_SUB(NOW(), INTERVAL 380 MINUTE) > created');
359 $res = XDB
::query('SELECT uid
360 FROM account_lost_passwords WHERE certificat={?}', $certif);
361 $ligne = $res->fetchOneAssoc();
363 $page->changeTpl('platal/index.tpl');
364 $page->kill("Cette adresse n'existe pas ou n'existe plus sur le serveur.");
367 $uid = $ligne["uid"];
368 if (Post
::has('pwhash') && Post
::t('pwhash')) {
369 $password = Post
::t('pwhash');
370 XDB
::query('UPDATE accounts
372 WHERE uid = {?} AND state = \'active\'',
374 XDB
::query('DELETE FROM account_lost_passwords
375 WHERE certificat={?}', $certif);
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';
381 $account = new GoogleAppsAccount(User
::getSilent($uid));
382 if ($account->active() && $account->sync_password
) {
383 $account->set_password($password);
387 S
::logger($uid)->log("passwd", "");
388 $page->changeTpl('platal/tmpPWD.success.tpl');
390 $page->changeTpl('platal/password.tpl');
391 $page->addJsLink('password.js');
395 function handler_skin(&$page)
399 $page->changeTpl('platal/skins.tpl');
400 $page->setTitle('Skins');
402 if (Env
::has('newskin')) { // formulaire soumis, traitons les données envoyées
403 XDB
::execute('UPDATE accounts
406 Env
::i('newskin'), S
::i('uid'));
408 Platal
::session()->setSkin();
411 $res = XDB
::query('SELECT id
413 WHERE skin_tpl = {?}', S
::v('skin'));
414 $page->assign('skin_id', $res->fetchOneCell());
416 $sql = 'SELECT s.*, auteur, COUNT(*) AS nb
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';
421 $page->assign('skins', XDB
::iterator($sql));
424 function handler_exit(&$page, $level = null
)
427 S
::logger()->log('suid_stop', S
::user()->login() . " by " . S
::suid('hruid'));
428 Platal
::session()->stopSUID();
429 pl_redirect('admin/user/' . S
::user()->login());
432 if ($level == 'forget' ||
$level == 'forgetall') {
433 Platal
::session()->killAccessCookie();
436 if ($level == 'forgetuid' ||
$level == 'forgetall') {
437 Platal
::session()->killLoginFormCookies();
441 S
::logger()->log('deconnexion', @$_SERVER['HTTP_REFERER']);
442 Platal
::session()->destroy();
445 if (Get
::has('redirect')) {
446 http_redirect(rawurldecode(Get
::v('redirect')));
448 $page->changeTpl('platal/exit.tpl');
452 function handler_review(&$page, $action = null
, $mode = null
)
454 // Include X-XRDS-Location response-header for Yadis discovery
456 header('X-XRDS-Location: ' . $globals->baseurl
. '/openid/xrds');
458 $this->load('review.inc.php');
460 if (@$GLOBALS['IS_XNET_SITE']) {
463 $wp = new PlWikiPage($dom . '.Admin');
464 $conf = explode('%0a', $wp->getField('text'));
465 $wiz = new PlWizard('Tour d\'horizon', PlPage
::getCoreTpl('plwizard.tpl'), true
);
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]);
470 $wiz->apply($page, 'review', $action, $mode);
474 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: