source: alternc/trunk/bureau/class/m_mem.php @ 3135

Revision 3135, 20.1 KB checked in by fufroma, 14 months ago (diff)

Commit "bourrin", beaucoup de choses.

  • Nouvelle interface de mail, elle n'est pas terminée mais est bien avancée
  • Beaucoup de correction php (notice)
  • Premier jet de la gestion de tache planifiées (cron)
  • Ajout d'un mode de debug pour l'admin

Reste en ToDo :

  • pas mal de fixme dans le code
  • corriger le schema de base pour les mails (Squidly a tout ce qu'il faut, il faut qu'il le commit)
  • configuration Dovecot et Postfix a commiter (pareil, Squidly à tout, plukacommiter)
  • suppression de mail
  • et beaucoup de debug...

Maintenant que le gros est commité, attendez-vous à beaucoup de petit commit.

Line 
1<?php
2/*
3 $Id: m_mem.php,v 1.19 2006/01/12 08:04:43 anarcat Exp $
4 ----------------------------------------------------------------------
5 LICENSE
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License (GPL)
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 To read the license please visit http://www.gnu.org/copyleft/gpl.html
18 ----------------------------------------------------------------------
19 Original Author of file: Benjamin Sonntag
20 Purpose of file: Manage Login session on the virtual desktop and
21        member parameters
22 ----------------------------------------------------------------------
23*/
24/**
25* This class manage user sessions in the web desktop.
26*
27* This class manage user sessions and administration in AlternC.
28* @copyright    AlternC-Team 2002-2005 http://alternc.org/
29*
30*/
31class m_mem {
32
33  /** Original uid for the temporary uid swapping (for administrators) */
34  var $olduid=0;
35 
36  /** This array contains the Tableau contenant les champs de la table "membres" du membre courant
37   * Ce tableau est utilisable globalement par toutes les classes filles.
38   */
39  var $user;
40  /** Tableau contenant les champs de la table "local" du membre courant
41   * Ce tableau est utilisable globalement par toutes les classes filles.
42   * Note : les champs de "local" sont spécifiques à l'hébergeur.
43   */
44  var $local;
45
46  /* ----------------------------------------------------------------- */
47  /**
48   * Constructeur
49   */
50  function m_mem() {
51  }
52
53  /* ----------------------------------------------------------------- */
54  /**
55   * Password kind used in this class (hook for admin class)
56   */
57  function alternc_password_policy() {
58    return array("mem"=>"AlternC's account password");
59  }
60
61
62  /* ----------------------------------------------------------------- */
63  /** Check that the current user is an admnistrator.
64   * @return boolean TRUE if we are super user, or FALSE if we are not.
65   */
66  function checkright() {
67    return ($this->user["su"]=="1");
68  }
69
70  /* ----------------------------------------------------------------- */
71  /** Start a session in the web desktop. Check username and password.
72   * <b>Note : </b>If the user entered a bas password, the failure will be logged
73   * and told to the corresponding user on next successfull login.
74   * @param $username string Username that want to get connected.
75   * @param $password string User Password.
76   * @return boolean TRUE if the user has been successfully connected, or FALSE if an error occured.
77   */
78  function login($username,$password,$restrictip=0,$authip_token=false) {
79    global $db,$err,$cuid, $authip;
80    $err->log("mem","login",$username);
81    //    $username=addslashes($username);
82    //    $password=addslashes($password);
83    $db->query("select * from membres where login='$username';");
84    if ($db->num_rows()==0) {
85      $err->raise("mem",1);
86      return false;
87    }
88    $db->next_record();
89    if (_md5cr($password,$db->f("pass"))!=$db->f("pass")) {
90      $db->query("UPDATE membres SET lastfail=lastfail+1 WHERE uid='".$db->f("uid")."';");
91      $err->raise("mem",1);
92      return false;
93    } 
94    if (!$db->f("enabled")) {
95      $err->raise("mem",2);
96      return false;
97    }
98    $this->user=$db->Record;
99    $cuid=$db->f("uid");
100
101    // AuthIP
102    $allowed_ip=false;
103    if ( $authip_token ) $allowed_ip = $this->authip_tokencheck($authip_token);
104
105    $aga = $authip->get_allowed('panel');
106    foreach ($aga as $k=>$v ) {
107      if ( $authip->is_in_subnet(getenv("REMOTE_ADDR"), $v['ip'], $v['subnet']) ) $allowed=true ;
108    }
109
110    // Error if there is rules, the IP is not allowed and it's not in the whitelisted IP
111    if ( sizeof($aga)>1 && !$allowed_ip && !$authip->is_wl(getenv("REMOTE_ADDR")) ) {
112      $err->raise("mem",42); // FIXME have a real error code -- Votre ip est pas authorisée
113      return false;
114    }
115    // End AuthIP
116
117    if ($restrictip) {
118      $ip="'".getenv("REMOTE_ADDR")."'";
119    } else $ip="''";
120    /* Close sessions that are more than 2 days old. */
121    $db->query("DELETE FROM sessions WHERE DATE_ADD(ts,INTERVAL 2 DAY)<NOW();");
122    /* Open the session : */
123    $_REQUEST["session"]=md5(uniqid(mt_rand()));
124    $db->query("insert into sessions (sid,ip,uid) values ('".$_REQUEST["session"]."',$ip,'$cuid');");
125    setcookie("session",$_REQUEST["session"],0,"/");
126    $err->error=0;
127    /* Fill in $local */
128    $db->query("SELECT * FROM local WHERE uid='$cuid';");
129    if ($db->num_rows()) {
130      $db->next_record();
131      $this->local=$db->Record;
132    }
133    return true;
134  }
135
136  /* ----------------------------------------------------------------- */
137  /** Start a session as another user from an administrator account.
138   * This function is not the same as su. setid connect the current user in the destination
139   * account (for good), and su allow any user to become another account for some commands only.
140   * (del_user, add_user ...) and allow to bring back admin rights with unsu
141   *
142   * @param $id integer User id where we will connect to.
143   * @return boolean TRUE if the user has been successfully connected, FALSE else.
144   */
145  function setid($id) {
146    global $db,$err,$cuid;
147    $err->log("mem","setid",$id);
148    $db->query("select * from membres where uid='$id';");
149    if ($db->num_rows()==0) {
150      $err->raise("mem",1);
151      return false;
152    }
153    $db->next_record();
154    $this->user=$db->Record;
155    $cuid=$db->f("uid");
156    $ip=getenv("REMOTE_ADDR");
157    $_REQUEST["session"]=md5(uniqid(mt_rand()));
158    $db->query("insert into sessions (sid,ip,uid) values ('".$_REQUEST["session"]."','$ip','$cuid');");
159    setcookie("session",$_REQUEST["session"],0,"/");
160    $err->error=0;
161    /* Fill in $local */
162    $db->query("SELECT * FROM local WHERE uid='$cuid';");
163    if ($db->num_rows()) {
164      $db->next_record();
165      $this->local=$db->Record;
166    }
167    return true;
168  }
169
170  /* ----------------------------------------------------------------- */
171  /** Suite à la connexion de l'utilisateur, réinitialise ses paramètres de dernière connexion
172   */
173  function resetlast() {
174    global $db,$cuid;
175    $ip=addslashes(getenv("REMOTE_HOST"));
176    if (!$ip) $ip=addslashes(getenv("REMOTE_ADDR"));
177    $db->query("UPDATE membres SET lastlogin=NOW(), lastfail=0, lastip='$ip' WHERE uid='$cuid';");
178  }
179
180  function authip_token($bis=false) {
181    global $db,$cuid;
182    $db->query("select pass from membres where uid='$cuid';");
183    $db->next_record();
184    $i=intval(time()/3600);
185    if ($bis) ++$i;
186    return md5("$i--".$db->f('pass'));
187  }
188
189  function authip_tokencheck($t) {
190    if ($t==$this->authip_token() || $t==$this->authip_token(true) ) return true;
191    return false;
192  }
193
194/* Faut finir de l'implémenter :)
195  function authip_class() {
196    global $cuid;
197    $c = Array();
198    $c['name']="Panel access";
199    $c['protocol']="panel";
200    $c['values']=Array($cuid=>'');
201
202    return $c;
203  }
204*/
205
206  /* ----------------------------------------------------------------- */
207  /** Vérifie que la session courante est correcte (cookie ok et ip valide).
208   * Si besoin, et si réception des champs username & password, crée une nouvelle
209   * session pour l'utilisateur annoncé.
210   * Cette fonction doit être appellée à chaque page devant être authentifiée.
211   * et AVANT d'émettre des données. (un cookie peut être envoyé)
212   * @global string $session Le cookie de session eventuel
213   * @global string $username/password le login/pass de l'utilisateur
214   * @return TRUE si la session est correcte, FALSE sinon.
215   */
216  function checkid() {
217    global $db,$err,$cuid,$restrictip,$authip;
218    if (isset($_REQUEST["username"])) {
219      if ($_REQUEST["username"] && $_REQUEST["password"]) {
220        return $this->login($_REQUEST["username"],$_REQUEST["password"],$_REQUEST["restrictip"]);
221      }
222    } // end isset
223    $_COOKIE["session"]=isset($_COOKIE["session"])?addslashes($_COOKIE["session"]):"";
224    if (strlen($_COOKIE["session"])!=32) {
225      $err->raise("mem",3);
226      return false;
227    }
228    $ip=getenv("REMOTE_ADDR");
229    $db->query("select uid,'$ip' as me,ip from sessions where sid='".$_COOKIE["session"]."'");
230    if ($db->num_rows()==0) {
231      $err->raise("mem",4);
232      return false;
233    }
234    $db->next_record();
235    if ($db->f("ip")) {
236      if ($db->f("me")!=$db->f("ip")) {
237              $err->raise("mem",5);
238              return false;
239      }
240    }
241    $cuid=$db->f("uid");
242    $db->query("select * from membres where uid='$cuid';");
243    $db->next_record();
244    $this->user=$db->Record;
245    $err->error=0;
246    /* Remplissage de $local */
247    $db->query("SELECT * FROM local WHERE uid='$cuid';");
248    if ($db->num_rows()) {
249      $db->next_record();
250      $this->local=$db->Record;
251    }
252    return true;
253  }
254
255  /* ----------------------------------------------------------------- */
256  /** Change l'identité d'un utilisateur temporairement.
257   * @global string $uid Utilisateur dont on prends l'identité
258   * @return TRUE si la session est correcte, FALSE sinon.
259   */
260  function su($uid) {
261    global $cuid,$db,$err;
262    if (!$this->olduid)
263            $this->olduid=$cuid;
264    $db->query("select * from membres where uid='$uid';");
265    if ($db->num_rows()==0) {
266      $err->raise("mem",1);
267      return false;
268    }
269    $db->next_record();
270    $this->user=$db->Record;
271    $cuid=$db->f("uid");
272    return true;
273  }
274
275  /* ----------------------------------------------------------------- */
276  /** Retourne a l'identite d'origine de l'utilisateur apres su.
277   * @return TRUE si la session est correcte, FALSE sinon.
278   */
279  function unsu() {
280    global $cuid;
281    if (!$this->olduid)
282        return false;
283    $this->su($this->olduid);
284    $this->olduid=0;
285    return true;
286  }
287
288
289  /* ----------------------------------------------------------------- */
290  /** Termine une session du bureau virtuel (logout)
291   * @return boolean TRUE si la session a bien été détruite, FALSE sinon.
292   */
293  function del_session() {
294    global $db,$user,$err,$cuid,$classes;
295    $err->log("mem","del_session");
296    $_COOKIE["session"]=addslashes(isset($_COOKIE["session"])?$_COOKIE["session"]:'');
297    setcookie("session","",0,"/");
298    setcookie("oldid","",0,"/admin/");
299    if ($_COOKIE["session"]=="") {
300      $err->error=0;
301      return true;
302    }
303    if (strlen($_COOKIE["session"])!=32) {
304      $err->raise("mem",3);
305      return false;
306    }
307    $ip=getenv("REMOTE_ADDR");
308    $db->query("select uid,'$ip' as me,ip from sessions where sid='".$_COOKIE["session"]."'");
309    if ($db->num_rows()==0) {
310      $err->raise("mem",4);
311      return false;
312    }
313    $db->next_record();
314    if ($db->f("me")!=$db->f("ip")) {
315      $err->raise("mem",5);
316      return false;
317    }
318    $cuid=$db->f("uid");
319    $db->query("delete from sessions where sid='".$_COOKIE["session"]."';");
320    $err->error=0;
321   
322    # Invoker le logout dans toutes les autres classes
323    foreach($classes as $c) {
324      if (method_exists($GLOBALS[$c],"alternc_del_session")) {
325            $GLOBALS[$c]->alternc_del_session();
326      }
327    }
328    return true;
329  }
330
331  /* ----------------------------------------------------------------- */
332  /** Change le mot de passe de l'utilisateur courant.
333   * @param string $oldpass Ancien mot de passe.
334   * @param string $newpass Nouveau mot de passe
335   * @param string $newpass2 Nouveau mot de passe (à nouveau)
336   * @return boolean TRUE si le mot de passe a été changé, FALSE sinon.
337   */
338  function passwd($oldpass,$newpass,$newpass2) {
339    global $db,$err,$cuid,$admin;
340    $err->log("mem","passwd");
341    $oldpass=stripslashes($oldpass);
342    $newpass=stripslashes($newpass);
343    $newpass2=stripslashes($newpass2);
344    if (!$this->user["canpass"]) {
345      $err->raise("mem",11);
346      return false;
347    }
348    if ($this->user["pass"]!=_md5cr($oldpass,$this->user["pass"])) {
349      $err->raise("mem",6);
350      return false;
351    }
352    if ($newpass!=$newpass2) {
353      $err->raise("mem",7);
354      return false;
355    }
356    if (strlen($newpass)<3) {
357      $err->raise("mem",8);
358      return false;
359    }
360    $db->query("SELECT login FROM membres WHERE uid='$cuid';");   
361    $db->next_record();
362    $login=$db->Record["login"];
363    if (!$admin->checkPolicy("mem",$login,$newpass)) {
364      return false; // The error has been raised by checkPolicy()
365    }
366    $newpass=_md5cr($newpass);
367    $db->query("UPDATE membres SET pass='$newpass' WHERE uid='$cuid';");
368    $err->error=0;
369    return true;
370  }
371
372  /* ----------------------------------------------------------------- */
373  /** Change les préférences administrateur d'un compte
374   * @param integer $admlist Mode de visualisation des membres (0=large 1=courte)
375   * @return boolean TRUE si les préférences ont été changées, FALSE sinon.
376   */
377  function adminpref($admlist) {
378    global $db,$err,$cuid;
379    $err->log("mem","admlist");
380    if (!$this->user["su"]) {
381      $err->raise("mem",12);
382      return false;
383    }
384    $db->query("UPDATE membres SET admlist='$admlist' WHERE uid='$cuid';");
385    $err->error=0;
386    return true;
387  }
388
389  /* ----------------------------------------------------------------- */
390  /** Envoie en mail le mot de passe d'un compte.
391   * <b>Note : </b>On ne peut demander le mot de passe qu'une seule fois par jour.
392   * TODO : Translate this mail into the localization program.
393   * TODO : Check this function's !
394   * @return boolean TRUE si le mot de passe a été envoyé avec succès, FALSE sinon.
395   */
396  function send_pass($login) {
397    global $err,$db,$L_HOSTING,$L_FQDN;
398    $err->log("mem","send_pass");
399    $db->query("SELECT * FROM membres WHERE login='$login';");
400    if (!$db->num_rows()) {
401      $err->raise("mem",2);
402      return false;
403    }
404    $db->next_record();
405    if (time()-$db->f("lastaskpass")<86400) {
406      $err->raise("mem",7);
407      return false;
408    }
409    $txt="Bonjour,
410Il semblerait que vous ayez demandé à recevoir le mot de passe du
411compte ".$login." sur $L_HOSTING
412Voici donc le nom d'utilisateur et le mot de passe qui vous
413permettront de rentrer sur le bureau virtuel :
414
415--------------------------------------
416
417Nom d'utilisateur : ".$db->f("login")."
418
419Mot de passe : ".$db->f("pass")."
420
421--------------------------------------
422
423Note : si vous n'avez pas fait cette demande, cela signifie que
424quelqu'un l'a faite pour vous. Vous pouvez donc ignorer ce message.
425Si cela se reproduit, n'hésitez pas à contacter l'administrateur
426de votre serveur.
427
428Cordialement.
429";
430    mail($db->f("mail"),"Votre mot de passe sur $L_HOSTING",$txt,"From: postmaster@$L_FQDN\nReply-to: postmaster@$L_FQDN");
431    $db->query("UPDATE membres SET lastaskpass=".time()." WHERE login='$login';");
432    return true;
433  }
434
435  /* ----------------------------------------------------------------- */
436  /** Change le mail d'un membre (première etape, envoi du CookiE)
437   * TODO : insert this mail string into the localization system
438   * @param string $newmail Nouveau mail souhaité pour le membre.
439   * @return string le cookie si le mail a bien été envoyé, FALSE sinon
440   */
441  function ChangeMail1($newmail) {
442    global $err,$db,$L_HOSTING,$L_FQDN,$cuid;
443    $err->log("mem","changemail1",$newmail);
444    $db->query("SELECT * FROM membres WHERE uid='$cuid';");
445    if (!$db->num_rows()) {
446      $err->raise("mem",2);
447      return false;
448    }
449    $db->next_record();
450
451    // un cookie de 20 caractères pour le mail
452    $COOKIE=substr(md5(uniqid(rand(),1)),0,20);
453    // et de 6 pour la clé à entrer. ca me semble suffisant...
454    $KEY=substr(md5(uniqid(rand(),1)),0,6);
455    // TODO : Translate this and insert this in alternc.po
456    $txt="Bonjour,
457Quelqu'un (peut-etre vous) a demandé le changement de l'email du compte
458".$db->f("login")." sur $L_HOSTING
459Afin de confirmer que cet email est valide, merci de vous rendre à l'adresse
460ci-dessous :
461
462https://$L_FQDN/admin/mem_cm.php?usr=$cuid&cookie=$COOKIE
463
464(attention : si cette adresse est coupée sur 2 lignes, ne pas oublier de
465reconstituer sur une seule ligne). Le bureau vous demandera la clé qui vous
466a été donnée lors de la demande de changement d'email.
467
468Note : si vous n'avez pas fait cette demande, cela signifie que quelqu'un
469l'a faite pour vous. Vous pouvez donc ignorer ce message. Si cela se
470reproduit, n'hésitez pas à contacter l'administrateur de votre serveur.
471
472Cordialement.
473";
474    mail($newmail,"Changement d'email sur $L_HOSTING",$txt,"From: postmaster@$L_FQDN\nReply-to: postmaster@$L_FQDN");
475    // Supprime les demandes précédentes de ce compte !
476    $db->query("DELETE FROM chgmail WHERE uid='$cuid';");
477    $db->query("INSERT INTO chgmail (cookie,ckey,uid,mail,ts) VALUES ('$COOKIE','$KEY','$cuid','$newmail',".time().");");
478    // Supprime les cookies de la veille :)
479    $lts=time()-86400;
480    $db->query("DELETE FROM chgmail WHERE ts<'$lts';");
481    return $KEY;
482  }
483
484  /* ----------------------------------------------------------------- */
485    /** Change le mail d'un membre (seconde etape, CookiE+clé = application)
486     * @param string $COOKIE Cookie envoyé par mail
487     * @param string $KEY clé affichée à l'écran
488     * @param integer $uid Utilisateur concerné (on est hors session)
489     * @return TRUE si le mail a bien été modifié, FALSE sinon
490     */
491    function ChangeMail2($COOKIE,$KEY,$uid) {
492      global $err,$db,$L_HOSTING,$L_FQDN;
493      $err->log("mem","changemail2",$uid);
494      $db->query("SELECT * FROM chgmail WHERE cookie='$COOKIE' and ckey='$KEY' and uid='$uid';");
495      if (!$db->num_rows()) {
496        $err->raise("mem",9);
497        return false;
498      }
499      $db->next_record();
500
501      // met à jour le compte :
502      $db->query("UPDATE membres SET mail='".$db->f("mail")."' WHERE uid='$uid';");
503
504      $db->query("DELETE FROM chgmail WHERE uid='$uid';");
505      // Supprime les cookies de la veille :)
506      $lts=time()-86400;
507      $db->query("DELETE FROM chgmail WHERE ts<'$lts';");
508      return true;
509    }
510
511    /* ----------------------------------------------------------------- */
512    /** Modifie le paramètre d'aide en ligne (1/0)
513     * @param integer $show Faut-il (1) ou non (0) afficher l'aide en ligne
514     */
515    function set_help_param($show) {
516      global $db,$err,$cuid;
517      $err->log("mem","set_help_param",$show);
518      $db->query("UPDATE membres SET show_help='$show' WHERE uid='$cuid';");
519    }
520
521    /* ----------------------------------------------------------------- */
522    /** Dit si l'aide en ligne est demandée
523     * @return boolean TRUE si l'aide en ligne est demandée, FALSE sinon.
524     */
525    function get_help_param() {
526      return $this->user["show_help"];
527    }
528
529    /* ----------------------------------------------------------------- */
530    /** Affiche (echo) l'aide contextuelle
531     * @param integer $file Numéro de fichier d'aide à afficher.
532     * @return TRUE si l'aide contextuelle a été trouvée, FALSE sinon
533     */
534  function show_help($file,$force=false) {
535    global $err;
536    $err->log("mem","show_help");
537    if ($this->user["show_help"] || $force) {
538      $hlp=_("hlp_$file");
539      if ($hlp!="hlp_$file") {
540              $hlp=preg_replace(
541                          "#HELPID_([0-9]*)#",
542                          "<a href=\"javascript:help(\\1);\"><img src=\"/admin/aide/help.png\" width=\"17\" height=\"17\" style=\"vertical-align: middle;\" alt=\""._("Help")."\" /></a>",$hlp);
543        echo "<p class=\"hlp\">".$hlp."</p>";
544        return true;
545      }
546      return false;
547    } else {
548      return true;
549    }
550  }
551
552
553  /* ----------------------------------------------------------------- */
554  /**
555   * Exports all the personnal user related information for an account.
556   * @access private
557   */
558  function alternc_export_conf() {
559    global $db,$err;
560    $err->log("mem","export");
561    $str="<table border=\"1\"><caption > Member </caption>\n";
562    $users=$this->user;
563      $str.="  <tr> <td>".$users["uid"]."</td></tr>\n";
564      $str.="  <tr> <td>".$users["login"]."</td></tr>\n";
565      $str.="  <tr> <td>".$users["enabled"]."</td></tr>\n";
566      $str.="  <tr> <td>".$users["su"]."</td></tr>\n";
567      $str.="  <tr> <td>".$users["pass"]."</td></tr>\n";
568      $str.="  <tr> <td>".$users["mail"]."</td></tr>\n";
569      $str.="  <tr> <td>".$users["created"]."</td></tr>\n";
570      $str.="  <tr> <td>".$users["lastip"]."</td></tr>\n";
571      $str.="  <tr> <td>".$users["lastlogin"]."</td></tr>\n";
572      $str.="  <tr> <td>".$users["lastfail"]."</td></tr>\n";
573    $str.="</table>\n";
574    return $str;
575  }
576
577
578
579
580} /* Classe Membre */
581
582?>
Note: See TracBrowser for help on using the repository browser.