Dépôt officiel du core SPIP * Copie possible par svn sur svn://trac.rezo.net/spip * Les svn:externals sont présent dans https://git.spip.net/SPIP/[nom du plugin dist] https://www.spip.net
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

377 lines
10 KiB

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