Try to define an exhaustive list of tables to copy.
[platal.git] / modules / register.php
CommitLineData
f59bc2fb 1<?php
2/***************************************************************************
9f5bd98e 3 * Copyright (C) 2003-2010 Polytechnique.org *
f59bc2fb 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
22class RegisterModule extends PLModule
23{
24 function handlers()
25 {
26 return array(
20d90835 27 'register' => $this->make_hook('register', AUTH_PUBLIC),
28 'register/end' => $this->make_hook('end', AUTH_PUBLIC),
f59bc2fb 29 );
30 }
31
20d90835 32 function handler_register(&$page, $hash = null)
f59bc2fb 33 {
5480a216 34 $alert = null;
cab08090 35 $sub_state = S::v('sub_state', Array());
f59bc2fb 36 if (!isset($sub_state['step'])) {
37 $sub_state['step'] = 0;
38 }
2efe5355 39 if (!isset($sub_state['backs'])) {
40 $sub_state['backs'] = array();
41 }
5e2307dc 42 if (Get::has('back') && Get::i('back') < $sub_state['step']) {
43 $sub_state['step'] = max(0,Get::i('back'));
2efe5355 44 $state = $sub_state;
45 unset($state['backs']);
46 $sub_state['backs'][] = $state;
47 if (count($sub_state['backs']) == 3) {
97a82cd2 48 $alert .= "Tentative d'inscription très hésitante - ";
eaf30d86 49 }
f59bc2fb 50 }
51
20d90835 52 if ($hash) {
08cce2ff 53 $res = XDB::query(
ecc734a5 54 "SELECT m.uid, u.promo, u.nom, u.prenom, u.matricule, u.naissance_ini, FIND_IN_SET('watch', u.flags)
f59bc2fb 55 FROM register_marketing AS m
56 INNER JOIN auth_user_md5 AS u ON u.user_id = m.uid
20d90835 57 WHERE m.hash={?}", $hash);
ecc734a5 58 if (list($uid, $promo, $nom, $prenom, $ourmat, $naiss, $watch) = $res->fetchOneRow()) {
f59bc2fb 59 $sub_state['uid'] = $uid;
20d90835 60 $sub_state['hash'] = $hash;
f59bc2fb 61 $sub_state['promo'] = $promo;
62 $sub_state['nom'] = $nom;
63 $sub_state['prenom'] = $prenom;
64 $sub_state['ourmat'] = $ourmat;
eaf30d86 65 $sub_state['watch'] = $watch;
ecc734a5 66 $sub_state['naissance_ini'] = $naiss;
f59bc2fb 67
08cce2ff 68 XDB::execute(
f59bc2fb 69 "REPLACE INTO register_mstats (uid,sender,success)
70 SELECT m.uid, m.sender, 0
71 FROM register_marketing AS m
72 WHERE m.hash", $sub_state['hash']);
73 }
74 }
75
76 switch ($sub_state['step']) {
77 case 0:
8f201b69
FB
78 $wp = new PlWikiPage('Reference.Charte');
79 $wp->buildCache();
f59bc2fb 80 if (Post::has('step1')) {
81 $sub_state['step'] = 1;
82 if (isset($sub_state['hash'])) {
83 $sub_state['step'] = 3;
460d8f55 84 $this->load('register.inc.php');
f59bc2fb 85 create_aliases($sub_state);
86 }
87 }
88 break;
89
90 case 1:
91 if (Post::has('promo')) {
5e2307dc 92 $promo = Post::i('promo');
a41bf2f8 93 $res = XDB::query("SELECT COUNT(*)
94 FROM auth_user_md5
95 WHERE perms='pending' AND deces = '0000-00-00'
96 AND promo = {?}",
97 $promo);
98 if (!$res->fetchOneCell()) {
97a82cd2 99 $err = "La promotion saisie est incorrecte ou tous les camarades de cette promotion sont inscrits !";
f59bc2fb 100 } else {
101 $sub_state['step'] = 2;
102 $sub_state['promo'] = $promo;
103 if ($promo >= 1996 && $promo<2000) {
104 $sub_state['mat'] = ($promo % 100)*10 . '???';
105 } elseif($promo >= 2000) {
106 $sub_state['mat'] = 100 + ($promo % 100) . '???';
107 }
108 }
109 }
110 break;
111
112 case 2:
113 if (count($_POST)) {
460d8f55 114 $this->load('register.inc.php');
5e2307dc 115 $sub_state['prenom'] = Post::v('prenom');
116 $sub_state['nom'] = Post::v('nom');
117 $sub_state['mat'] = Post::v('mat');
f59bc2fb 118 $err = check_new_user($sub_state);
119
120 if ($err !== true) { break; }
121 $err = create_aliases($sub_state);
122 if ($err === true) {
123 unset($err);
124 $sub_state['step'] = 3;
125 }
126 }
127 break;
128
129 case 3:
130 if (count($_POST)) {
460d8f55 131 $this->load('register.inc.php');
97a82cd2
VZ
132
133 // Validate the email address format and domain.
c6310567 134 require_once 'emails.inc.php';
5e2307dc 135 if (!isvalid_email(Post::v('email'))) {
97a82cd2 136 $err[] = "Le champ 'Email' n'est pas valide.";
5e2307dc 137 } elseif (!isvalid_email_redirection(Post::v('email'))) {
f59bc2fb 138 $err[] = $sub_state['forlife']." doit renvoyer vers un email existant ".
a7de4ef7 139 "valide, en particulier, il ne peut pas être renvoyé vers lui-même.";
f59bc2fb 140 }
97a82cd2
VZ
141
142 // Validate the birthday format and range.
1970c12b 143 $birth = trim(Env::v('naissance'));
12e5d7a6 144 if (!preg_match('@^[0-3]?\d/[01]?\d/(19|20)?\d{2}$@', $birth)) {
f59bc2fb 145 $err[] = "La 'Date de naissance' n'est pas correcte.";
35cd1be1 146 } else {
12e5d7a6 147 $birth = explode('/', $birth, 3);
7caaaf6d
AA
148 for ($i = 0; $i < 3; $i++)
149 $birth[$i] = intval($birth[$i]);
150 if ($birth[2] < 100) $birth[2] += 1900;
151 $year = $birth[2];
35cd1be1 152 $promo = (int)$sub_state['promo'];
153 if ($year > $promo - 15 || $year < $promo - 30) {
154 $err[] = "La 'Date de naissance' n'est pas correcte.";
97a82cd2 155 $alert = "Date de naissance incorrecte à l'inscription - ";
fb5d164e 156 $sub_state['wrong_naissance'] = $birth;
35cd1be1 157 }
f59bc2fb 158 }
159
3546b253
VZ
160 // Register the optional services requested by the user.
161 $services = array();
162 foreach (array('ax_letter', 'imap', 'ml_promo', 'nl') as $service) {
163 if (Post::b($service)) {
164 $services[] = $service;
165 }
166 }
167 $sub_state['services'] = $services;
168
97a82cd2
VZ
169 // Validate the password.
170 if (!Post::v('response2', false)) {
171 $err[] = "Le mot de passe n'est pas valide.";
172 }
173
174 // Check if the given email is known as dangerous.
15836cdd 175 $res = XDB::query("SELECT w.state, w.description
06f4daf9 176 FROM email_watch AS w
15836cdd
FB
177 WHERE w.email = {?} AND w.state != 'safe'",
178 Post::v('email'));
706ed3ef 179 $email_banned = false;
15836cdd
FB
180 if ($res->numRows()) {
181 list($state, $description) = $res->fetchOneRow();
97a82cd2 182 $alert .= "Email surveillé proposé à l'inscription - ";
15836cdd 183 $sub_state['email_desc'] = $description;
706ed3ef
FB
184 if ($state == 'dangerous') {
185 $email_banned = true;
186 }
5480a216 187 }
0be07aa6 188 if ($sub_state['watch']) {
4653799f 189 $alert .= "Inscription d'un utilisateur surveillé - ";
0be07aa6 190 }
5480a216 191
97a82cd2 192 if (($ip_banned = check_ip('unsafe'))) {
5480a216 193 unset($err);
bf273d6a 194 }
195
f59bc2fb 196 if (isset($err)) {
197 $err = join('<br />', $err);
198 } else {
12e5d7a6
FB
199 $sub_state['naissance'] = sprintf("%04d-%02d-%02d",
200 intval($birth[2]), intval($birth[1]), intval($birth[0]));
97a82cd2
VZ
201 $sub_state['email'] = Post::v('email');
202 $sub_state['password'] = Post::v('response2');
203
204 // Update the current alert if the birthdate is incorrect,
205 // or if the IP address of the user has been banned.
ecc734a5 206 if ($sub_state['naissance_ini'] != '0000-00-00' && $sub_state['naissance'] != $sub_state['naissance_ini']) {
207 $alert .= "Date de naissance incorrecte à l'inscription - ";
208 }
706ed3ef 209 if ($ip_banned) {
97a82cd2 210 $alert .= "Tentative d'inscription depuis une IP surveillée";
706ed3ef 211 }
97a82cd2
VZ
212
213 // Prevent banned user from actually registering; save the current state for others.
706ed3ef 214 if ($email_banned || $ip_banned) {
115c90db 215 global $globals;
5480a216 216 $err = "Une erreur s'est produite lors de l'inscription."
1d55fe45 217 . " Merci de contacter <a href='mailto:register@{$globals->mail->domain}>"
218 . " register@{$globals->mail->domain}</a>"
5480a216 219 . " pour nous faire part de cette erreur";
5480a216 220 } else {
221 $sub_state['step'] = 4;
9fc2d0d2 222 if (count($sub_state['backs']) >= 3) {
a7de4ef7 223 $alert .= "Fin d'une inscription hésitante";
2efe5355 224 }
5480a216 225 finish_ins($sub_state);
226 }
bf273d6a 227 }
f59bc2fb 228 }
229 break;
230 }
231
232 $_SESSION['sub_state'] = $sub_state;
4653799f 233 if (!empty($alert)) {
5480a216 234 send_warning_mail($alert);
235 }
97a82cd2 236
a41bf2f8 237 $page->changeTpl('register/step'.intval($sub_state['step']).'.tpl');
97a82cd2 238 $page->addJsLink('motdepasse.js');
f59bc2fb 239 if (isset($err)) {
a7d35093 240 $page->trigError($err);
f59bc2fb 241 }
f59bc2fb 242 }
243
244 function handler_end(&$page, $hash = null)
245 {
246 global $globals;
a41bf2f8 247 $_SESSION['sub_state'] = array('step' => 5);
ecc734a5 248
97a82cd2
VZ
249 // Reject registration requests from unsafe IP addresses (and remove the
250 // registration information from the database, to prevent IP changes).
ecc734a5 251 if (check_ip('unsafe')) {
252 send_warning_mail('Une IP surveillée a tenté de finaliser son inscription');
97a82cd2
VZ
253 XDB::execute("DELETE FROM register_pending
254 WHERE hash = {?} AND hash != 'INSCRIT'", $hash);
ecc734a5 255 return PL_FORBIDDEN;
256 }
257
97a82cd2
VZ
258 // Retrieve the pre-registration information using the url-provided
259 // authentication token.
f59bc2fb 260 if ($hash) {
08cce2ff 261 $res = XDB::query(
f59bc2fb 262 "SELECT r.uid, r.forlife, r.bestalias, r.mailorg2,
3546b253 263 r.password, r.email, r.services, r.naissance, u.nom, u.prenom,
ecc734a5 264 u.promo, FIND_IN_SET('femme', u.flags), u.naissance_ini
f59bc2fb 265 FROM register_pending AS r
266 INNER JOIN auth_user_md5 AS u ON r.uid = u.user_id
97a82cd2 267 WHERE hash = {?} AND hash != 'INSCRIT'", $hash);
f59bc2fb 268 }
97a82cd2 269 if (!$hash || $res->numRows() == 0) {
f59bc2fb 270 $page->kill("<p>Cette adresse n'existe pas, ou plus, sur le serveur.</p>
97a82cd2 271 <p>Causes probables&nbsp;:</p>
f59bc2fb 272 <ol>
a7de4ef7 273 <li>Vérifie que tu visites l'adresse du dernier
97a82cd2 274 email reçu s'il y en a eu plusieurs.</li>
a7de4ef7 275 <li>Tu as peut-être mal copié l'adresse reçue par
97a82cd2 276 email, vérifie-la à la main.</li>
a7de4ef7 277 <li>Tu as peut-être attendu trop longtemps pour
278 confirmer. Les pré-inscriptions sont annulées
f59bc2fb 279 tous les 30 jours.</li>
a7de4ef7 280 <li>Tu es en fait déjà inscrit.</li>
f59bc2fb 281 </ol>");
282 }
283
3546b253 284 list($uid, $forlife, $bestalias, $mailorg2, $password, $email, $services,
97a82cd2 285 $naissance, $nom, $prenom, $promo, $femme, $naiss_ini) = $res->fetchOneRow();
f59bc2fb 286
97a82cd2
VZ
287 // Prepare the template for display.
288 $page->changeTpl('register/end.tpl');
289 $page->addJsLink('do_challenge_response_logged.js');
290 $page->assign('forlife', $forlife);
291 $page->assign('prenom', $prenom);
292 $page->assign('femme', $femme);
293
294 // Check if the user did enter a valid password; if not (or if none is found),
295 // get her an information page.
296 if (Env::has('response')) {
297 require_once 'secure_hash.inc.php';
298 $expected_response = hash_encrypt("$forlife:$password:" . S::v('challenge'));
299 if (Env::v('response') != $expected_response) {
300 $page->trigError("Mot de passe invalide.");
301 S::logger($uid)->log('auth_fail', 'bad password (register/end)');
302 return;
303 }
304 } else {
305 return;
306 }
f59bc2fb 307
97a82cd2
VZ
308 //
309 // Create the user account.
310 //
311 XDB::execute("UPDATE auth_user_md5
312 SET password = {?}, perms = 'user',
313 date = NOW(), naissance = {?}, date_ins = NOW()
314 WHERE user_id = {?}", $password, $naissance, $uid);
315 XDB::execute("REPLACE INTO auth_user_quick (user_id) VALUES ({?})", $uid);
316 XDB::execute("INSERT INTO aliases (id, alias, type)
317 VALUES ({?}, {?}, 'a_vie')", $uid, $forlife);
318 XDB::execute("INSERT INTO aliases (id, alias, type, flags)
319 VALUES ({?}, {?}, 'alias', 'bestalias')", $uid, $bestalias);
f59bc2fb 320 if ($mailorg2) {
97a82cd2
VZ
321 XDB::execute("INSERT INTO aliases (id, alias, type)
322 VALUES ({?}, {?}, 'alias')", $uid, $mailorg2);
f59bc2fb 323 }
324
97a82cd2 325 // Add the registration email address as first and only redirection.
726eaf7a 326 require_once 'emails.inc.php';
12a587df
VZ
327 $user = User::getSilent($uid);
328 $redirect = new Redirect($user);
f59bc2fb 329 $redirect->add_email($email);
330
3546b253
VZ
331 // Try to start a session (so the user don't have to log in); we will use
332 // the password available in Post:: to authenticate the user.
333 Platal::session()->start(AUTH_MDP);
334
335 // Subscribe the user to the services she did request at registration time.
336 foreach (explode(',', $services) as $service) {
337 switch ($service) {
338 case 'ax_letter':
339 Platal::load('axletter', 'axletter.inc.php');
bf1525f7 340 AXLetter::subscribe(S::user()->id());
3546b253
VZ
341 break;
342 case 'imap':
3546b253
VZ
343 $user = S::user();
344 $storage = new EmailStorage($user, 'imap');
345 $storage->activate();
346 break;
347 case 'ml_promo':
eb41eda9 348 $r = XDB::query('SELECT id FROM groups WHERE diminutif = {?}', S::user()->promo());
3546b253
VZ
349 if ($r->numRows()) {
350 $asso_id = $r->fetchOneCell();
eb41eda9 351 XDB::execute('REPLACE INTO group_members (uid, asso_id)
3546b253
VZ
352 VALUES ({?}, {?})',
353 S::user()->id(), $asso_id);
354 $mmlist = new MMList(S::user()->id(), S::v('password'));
355 $mmlist->subscribe("promo" . S::v('promo'));
356 }
357 break;
358 case 'nl':
359 require_once 'newsletter.inc.php';
360 NewsLetter::subscribe();
361 break;
362 }
363 }
364
97a82cd2 365 // Log the registration in the user session.
03c0a3a7 366 S::logger($uid)->log('inscription', $email);
97a82cd2
VZ
367 XDB::execute("UPDATE register_pending
368 SET hash = 'INSCRIT'
369 WHERE uid = {?}", $uid);
f59bc2fb 370
97a82cd2 371 // Congratulate our newly registered user by email.
1e33266a 372 $mymail = new PlMailer('register/inscription.reussie.tpl');
f59bc2fb 373 $mymail->assign('forlife', $forlife);
374 $mymail->assign('prenom', $prenom);
375 $mymail->send();
376
97a82cd2 377 // Index the user, to allow her to appear in searches.
726eaf7a 378 Profile::rebuildSearchTokens($uid);
2a54eb4d 379
97a82cd2 380 // Notify other users which were watching for her arrival.
03c0a3a7
FB
381 require_once 'notifs.inc.php';
382 register_watch_op($uid, WATCH_INSCR);
383 inscription_notifs_base($uid);
384
97a82cd2
VZ
385 // Forcibly register the new user on default forums.
386 $promo_forum = 'xorg.promo.x' . $promo;
387 $registered_forums = array('xorg.general', 'xorg.pa.divers', 'xorg.pa.logements', $promo_forum);
388 foreach ($registered_forums as $forum) {
00112b2e 389 XDB::execute("INSERT INTO #forums#.abos (fid,uid)
97a82cd2 390 SELECT fid, {?}
00112b2e 391 FROM #forums#.list
97a82cd2
VZ
392 WHERE nom = {?}",
393 $uid, $val);
394
395 // Notify the newsgroup admin of the promotion forum needs be created.
396 if (XDB::affectedRows() == 0 && $forum == $promo_forum) {
03c0a3a7
FB
397 $res = XDB::query("SELECT SUM(perms IN ('admin','user') AND deces = 0), COUNT(*)
398 FROM auth_user_md5
399 WHERE promo = {?}", $promo);
97a82cd2
VZ
400 list($promo_registered_count, $promo_count) = $res->fetchOneRow();
401 if ($promo_registered_count > 0.2 * $promo_count) {
03c0a3a7
FB
402 $mymail = new PlMailer('admin/forums-promo.mail.tpl');
403 $mymail->assign('promo', $promo);
404 $mymail->send();
405 }
406 }
407 }
408
97a82cd2 409 // Update the global registration count stats.
ebfdf077 410 $globals->updateNbIns();
b5dd6f2f 411
97a82cd2
VZ
412 //
413 // Update collateral data sources, and inform watchers by email.
414 //
f59bc2fb 415
97a82cd2 416 // Email the referrer(s) of this new user.
08cce2ff 417 $res = XDB::iterRow(
ebb129a4
FB
418 "SELECT sa.alias, IF(s.nom_usage,s.nom_usage,s.nom) AS nom,
419 s.prenom, FIND_IN_SET('femme', s.flags) AS femme,
e4705641 420 GROUP_CONCAT(m.email SEPARATOR ', ') AS mails, MAX(m.last) AS dateDernier
f59bc2fb 421 FROM register_marketing AS m
97a82cd2
VZ
422 INNER JOIN auth_user_md5 AS s ON (m.sender = s.user_id)
423 INNER JOIN aliases AS sa ON (sa.id = m.sender
424 AND FIND_IN_SET('bestalias', sa.flags))
ebb129a4 425 WHERE m.uid = {?}
38acbdf3
BFPC
426 GROUP BY m.sender
427 ORDER BY dateDernier DESC", $uid);
97a82cd2
VZ
428 XDB::execute("UPDATE register_mstats
429 SET success = NOW()
430 WHERE uid = {?}", $uid);
f59bc2fb 431
ebb129a4 432 $market = array();
381a3df0
OLF
433 while (list($salias, $snom, $sprenom, $sfemme, $mails, $dateDernier) = $res->next()) {
434 $market[] = " - par $snom $sprenom sur $mails (le plus récemment le $dateDernier)";
1e33266a 435 $mymail = new PlMailer();
a7de4ef7 436 $mymail->setSubject("$prenom $nom s'est inscrit à Polytechnique.org !");
1d55fe45 437 $mymail->setFrom('"Marketing Polytechnique.org" <register@' . $globals->mail->domain . '>');
f59bc2fb 438 $mymail->addTo("\"$sprenom $snom\" <$salias@{$globals->mail->domain}>");
a7de4ef7 439 $msg = ($sfemme?'Chère':'Cher')." $sprenom,\n\n"
ecc734a5 440 . "Nous t'écrivons pour t'informer que $prenom $nom (X$promo), "
a7de4ef7 441 . "que tu avais incité".($femme?'e':'')." à s'inscrire à Polytechnique.org, "
442 . "vient à l'instant de terminer son inscription.\n\n"
443 . "Merci de ta participation active à la reconnaissance de ce site !!!\n\n"
f59bc2fb 444 . "Bien cordialement,\n"
97a82cd2 445 . "-- \n"
a7de4ef7 446 . "L'équipe Polytechnique.org";
f59bc2fb 447 $mymail->setTxtBody(wordwrap($msg, 72));
448 $mymail->send();
449 }
5f5f0eb5 450
97a82cd2 451 // Email the plat/al administrators about the registration.
9812efa0 452 if ($globals->register->notif) {
453 $mymail = new PlMailer();
454 $mymail->setSubject("Inscription de $prenom $nom (X$promo)");
1d55fe45 455 $mymail->setFrom('"Webmaster Polytechnique.org" <web@' . $globals->mail->domain . '>');
9812efa0 456 $mymail->addTo($globals->register->notif);
280c6e4d 457 $mymail->addHeader('Reply-To', $globals->register->notif);
a7de4ef7 458 $msg = "$prenom $nom (X$promo) a terminé son inscription avec les données suivantes :\n"
9812efa0 459 . " - nom : $nom\n"
460 . " - prenom : $prenom\n"
461 . " - promo : $promo\n"
ecc734a5 462 . " - naissance : $naissance (date connue : $naiss_ini)\n"
9812efa0 463 . " - forlife : $forlife\n"
464 . " - email : $email\n"
5f5f0eb5 465 . " - sexe : $femme\n"
edc55095
FB
466 . " - ip : " . S::logger()->ip . " (" . S::logger()->host . ")\n"
467 . (S::logger()->proxy_ip ? " - proxy : " . S::logger()->proxy_ip . " (" . S::logger()->proxy_host . ")\n" : "")
defff1aa
SJ
468 . "\n\n";
469 if (count($market) > 0) {
470 $msg .= "Les marketings suivants avaient été effectués :\n"
471 . implode("\n", $market);
472 } else {
8f794f88 473 $msg .= "$prenom $nom n'a jamais reçu d'email de marketing.";
defff1aa 474 }
9812efa0 475 $mymail->setTxtBody($msg);
eaf30d86 476 $mymail->send();
9812efa0 477 }
f59bc2fb 478
97a82cd2 479 // Remove old pending marketing requests for the new user.
e654517d 480 Marketing::clear($uid);
f59bc2fb 481
97a0a459
FB
482 pl_redirect('profile/edit');
483 }
f59bc2fb 484}
485
a7de4ef7 486// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
f59bc2fb 487?>