[SPIP] v3.2.1-->v3.2.2
[lhc/web/www.git] / www / ecrire / action / inscrire_auteur.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2019 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
8 * *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
12
13 /**
14 * Gestion de l'inscription d'un auteur
15 *
16 * @package SPIP\Core\Inscription
17 **/
18 if (!defined('_ECRIRE_INC_VERSION')) {
19 return;
20 }
21
22
23 /**
24 * Inscrire un nouvel auteur sur la base de son nom et son email
25 *
26 * L'email est utilisé pour repérer si il existe déjà ou non
27 * => identifiant par défaut
28 *
29 * @param string $statut
30 * @param string $mail_complet
31 * @param string $nom
32 * @param array $options
33 * - login : login precalcule
34 * - id : id_rubrique fournit en second arg de #FORMULAIRE_INSCRIPTION
35 * - from : email de l'envoyeur pour l'envoi du mail d'inscription
36 * - force_nouveau : forcer le statut nouveau sur l'auteur inscrit, meme si il existait deja en base
37 * - modele_mail : squelette de mail a utiliser
38 * @return array|string
39 */
40 function action_inscrire_auteur_dist($statut, $mail_complet, $nom, $options = array()) {
41 if (!is_array($options)) {
42 $options = array('id' => $options);
43 }
44
45 if (function_exists('test_inscription')) {
46 $f = 'test_inscription';
47 } else {
48 $f = 'test_inscription_dist';
49 }
50 $desc = $f($statut, $mail_complet, $nom, $options);
51
52 // erreur ?
53 if (!is_array($desc)) {
54 return _T($desc);
55 }
56
57 include_spip('base/abstract_sql');
58 $res = sql_select("statut, id_auteur, login, email", "spip_auteurs", "email=" . sql_quote($desc['email']));
59 // erreur ?
60 if (!$res) {
61 return _T('titre_probleme_technique');
62 }
63
64 $row = sql_fetch($res);
65 sql_free($res);
66 if ($row) {
67 if (isset($options['force_nouveau']) and $options['force_nouveau'] == true) {
68 $desc['id_auteur'] = $row['id_auteur'];
69 $desc = inscription_nouveau($desc);
70 } else {
71 $desc = $row;
72 }
73 } else // s'il n'existe pas deja, creer les identifiants
74 {
75 $desc = inscription_nouveau($desc);
76 }
77
78 // erreur ?
79 if (!is_array($desc)) {
80 return $desc;
81 }
82
83
84 // generer le mot de passe (ou le refaire si compte inutilise)
85 $desc['pass'] = creer_pass_pour_auteur($desc['id_auteur']);
86
87 // attribuer un jeton pour confirmation par clic sur un lien
88 $desc['jeton'] = auteur_attribuer_jeton($desc['id_auteur']);
89
90 // charger de suite cette fonction, pour ses utilitaires
91 $envoyer_inscription = charger_fonction("envoyer_inscription", "");
92 list($sujet, $msg, $from, $head) = $envoyer_inscription($desc, $nom, $statut, $options);
93
94 $notifications = charger_fonction('notifications', 'inc');
95 notifications_envoyer_mails($mail_complet, $msg, $sujet, $from, $head);
96
97 // Notifications
98 $notifications('inscription', $desc['id_auteur'],
99 array('nom' => $desc['nom'], 'email' => $desc['email'])
100 );
101
102 return $desc;
103 }
104
105
106 /**
107 * Contrôler que le nom (qui sert à calculer le login) est plausible
108 * et que l'adresse courriel est valide.
109 *
110 * On les normalise au passage (trim etc).
111 *
112 * On peut redéfinir cette fonction pour filtrer les adresses mail et les noms,
113 * et donner des infos supplémentaires
114 *
115 * @param string $statut
116 * @param string $mail
117 * @param string $nom
118 * @param array $options
119 * @return array|string
120 * - array : si ok, tableau avec au minimum email, nom, mode (redac / forum)
121 * - string : si ko, chaîne de langue servant d'argument au filtre `_T` expliquant le refus
122 *
123 */
124 function test_inscription_dist($statut, $mail, $nom, $options) {
125 include_spip('inc/filtres');
126 if (!$r = email_valide($mail)) {
127 return 'info_email_invalide';
128 }
129 $nom = trim(corriger_caracteres($nom));
130 $res = array('email' => $r, 'nom' => $nom, 'prefs' => $statut);
131 if (isset($options['login'])) {
132 $login = trim(corriger_caracteres($options['login']));
133 if ((strlen($login) >= _LOGIN_TROP_COURT) and (strlen($nom) <= 64)) {
134 $res['login'] = $login;
135 }
136 }
137 if (!isset($res['login']) and ((strlen($nom) < _LOGIN_TROP_COURT) or (strlen($nom) > 64))) {
138 return 'ecrire:info_login_trop_court';
139 }
140
141 return $res;
142 }
143
144
145 /**
146 * On enregistre le demandeur comme 'nouveau', en memorisant le statut final
147 * provisoirement dans le champ prefs, afin de ne pas visualiser les inactifs
148 * A sa premiere connexion il obtiendra son statut final.
149 *
150 * @param array $desc
151 * @return mixed|string
152 */
153 function inscription_nouveau($desc) {
154 if (!isset($desc['login']) or !strlen($desc['login'])) {
155 $desc['login'] = test_login($desc['nom'], $desc['email']);
156 }
157
158 $desc['statut'] = 'nouveau';
159 include_spip('action/editer_auteur');
160 if (isset($desc['id_auteur'])) {
161 $id_auteur = $desc['id_auteur'];
162 } else {
163 $id_auteur = auteur_inserer();
164 }
165
166 if (!$id_auteur) {
167 return _T('titre_probleme_technique');
168 }
169
170 $desc['lang'] = $GLOBALS['spip_lang'];
171
172 include_spip('inc/autoriser');
173 // lever l'autorisation pour pouvoir modifier le statut
174 autoriser_exception('modifier', 'auteur', $id_auteur);
175 auteur_modifier($id_auteur, $desc);
176 autoriser_exception('modifier', 'auteur', $id_auteur, false);
177
178 $desc['id_auteur'] = $id_auteur;
179
180 return $desc;
181 }
182
183
184 /**
185 * http://code.spip.net/@test_login
186 *
187 * @param string $nom
188 * @param string $mail
189 * @return string
190 */
191 function test_login($nom, $mail) {
192 include_spip('inc/charsets');
193 $nom = strtolower(translitteration($nom));
194 $login_base = preg_replace("/[^\w\d_]/", "_", $nom);
195
196 // il faut eviter que le login soit vraiment trop court
197 if (strlen($login_base) < 3) {
198 $mail = strtolower(translitteration(preg_replace('/@.*/', '', $mail)));
199 $login_base = preg_replace("/[^\w\d]/", "_", $mail);
200 }
201 if (strlen($login_base) < 3) {
202 $login_base = 'user';
203 }
204
205 $login = $login_base;
206
207 for ($i = 1; ; $i++) {
208 if (!sql_countsel('spip_auteurs', "login='$login'")) {
209 return $login;
210 }
211 $login = $login_base . $i;
212 }
213
214 return $login;
215 }
216
217
218 /**
219 * Construction du mail envoyant les identifiants
220 *
221 * Fonction redefinissable qui doit retourner un tableau
222 * dont les elements seront les arguments de inc_envoyer_mail
223 *
224 * @param array $desc
225 * @param string $nom
226 * @param string $mode
227 * @param array $options
228 * @return array
229 */
230 function envoyer_inscription_dist($desc, $nom, $mode, $options = array()) {
231
232 $contexte = array_merge($desc, $options);
233 $contexte['nom'] = $nom;
234 $contexte['mode'] = $mode;
235 $contexte['url_confirm'] = generer_url_action('confirmer_inscription', '', true, true);
236 $contexte['url_confirm'] = parametre_url($contexte['url_confirm'], 'email', $desc['email']);
237 $contexte['url_confirm'] = parametre_url($contexte['url_confirm'], 'jeton', $desc['jeton']);
238
239 $modele_mail = 'modeles/mail_inscription';
240 if (isset($options['modele_mail']) and $options['modele_mail']){
241 $modele_mail = $options['modele_mail'];
242 }
243 $message = recuperer_fond($modele_mail, $contexte);
244 $from = (isset($options['from']) ? $options['from'] : null);
245 $head = null;
246
247 return array("", $message, $from, $head);
248 }
249
250
251 /**
252 * Creer un mot de passe initial aleatoire
253 *
254 * @param int $id_auteur
255 * @return string
256 */
257 function creer_pass_pour_auteur($id_auteur) {
258 include_spip('inc/acces');
259 $pass = creer_pass_aleatoire(8, $id_auteur);
260 include_spip('action/editer_auteur');
261 auteur_instituer($id_auteur, array('pass' => $pass));
262
263 return $pass;
264 }
265
266 /**
267 * Determine le statut d'inscription :
268 * si $statut_tmp fourni, verifie qu'il est autorise
269 * sinon determine le meilleur statut possible et le renvoie
270 *
271 * @param string $statut_tmp
272 * @param int $id
273 * @return string
274 */
275 function tester_statut_inscription($statut_tmp, $id) {
276 include_spip('inc/autoriser');
277 if ($statut_tmp) {
278 return autoriser('inscrireauteur', $statut_tmp, $id) ? $statut_tmp : '';
279 } elseif (
280 autoriser('inscrireauteur', $statut_tmp = "1comite", $id)
281 or autoriser('inscrireauteur', $statut_tmp = "6forum", $id)
282 ) {
283 return $statut_tmp;
284 }
285
286 return '';
287 }
288
289
290 /**
291 * Un nouvel inscrit prend son statut definitif a la 1ere connexion.
292 * Le statut a ete memorise dans prefs (cf test_inscription_dist).
293 * On le verifie, car la config a peut-etre change depuis,
294 * et pour compatibilite avec les anciennes versions qui n'utilisaient pas "prefs".
295 *
296 * @param array $auteur
297 * @return array
298 */
299 function confirmer_statut_inscription($auteur) {
300 // securite
301 if ($auteur['statut'] != 'nouveau') {
302 return $auteur;
303 }
304
305 $s = $auteur['prefs'];
306 // securite, au cas ou prefs aurait ete corrompu (ou deja ecrase par un tableau serialize)
307 if (!preg_match(',^\w+$,', $s)) {
308 $s = '6forum';
309 }
310 include_spip('inc/autoriser');
311 if (!autoriser('inscrireauteur', $s)) {
312 return $auteur;
313 }
314
315 include_spip('inc/autoriser');
316 // accorder l'autorisation de modif du statut auteur
317 autoriser_exception('modifier', 'auteur', $auteur['id_auteur']);
318 include_spip('action/editer_auteur');
319 // changer le statut
320 auteur_modifier($auteur['id_auteur'], array('statut' => $s));
321 unset($_COOKIE['spip_session']); // forcer la maj de la session
322 // lever l'autorisation de modif du statut auteur
323 autoriser_exception('modifier', 'auteur', $auteur['id_auteur'], false);
324
325 // mettre a jour le statut
326 $auteur['statut'] = $s;
327
328 return $auteur;
329 }
330
331
332 /**
333 * Attribuer un jeton temporaire pour un auteur
334 * en assurant l'unicite du jeton
335 *
336 * @param int $id_auteur
337 * @return string
338 */
339 function auteur_attribuer_jeton($id_auteur) {
340 include_spip('inc/acces');
341 // s'assurer de l'unicite du jeton pour le couple (email,cookie)
342 do {
343 $jeton = creer_uniqid();
344 sql_updateq("spip_auteurs", array("cookie_oubli" => $jeton), "id_auteur=" . intval($id_auteur));
345 } while (sql_countsel("spip_auteurs", "cookie_oubli=" . sql_quote($jeton)) > 1);
346
347 return $jeton;
348 }
349
350 /**
351 * Retrouver l'auteur par son jeton
352 *
353 * @param string $jeton
354 * @return array|bool
355 */
356 function auteur_verifier_jeton($jeton) {
357 // refuser un jeton corrompu
358 if (preg_match(',[^0-9a-f.],i', $jeton)) {
359 return false;
360 }
361
362 // on peut tomber sur un jeton compose uniquement de chiffres, il faut forcer le $type pour sql_quote pour eviter de planter
363 $desc = sql_fetsel('*', 'spip_auteurs', "cookie_oubli=" . sql_quote($jeton, '', 'string'));
364
365 return $desc;
366 }
367
368 /**
369 * Effacer le jeton d'un auteur apres utilisation
370 *
371 * @param int $id_auteur
372 * @return bool
373 */
374 function auteur_effacer_jeton($id_auteur) {
375 return sql_updateq("spip_auteurs", array("cookie_oubli" => ''), "id_auteur=" . intval($id_auteur));
376 }