$valeur) { $methode="set_$attribut"; if(method_exists(__CLASS__,$methode)) { if(!$this->$methode($valeur)) $erreur_ok=true; } else $this->$attribut=$valeur; } if(($erreur_ok)&&(empty($this->erreurs))) $this->erreurs=(array) ERREUR_IMPREVUE; } } /** * Méthode testant la validité du fuseau horaire et l'attribuant à l'objet si ok * * @return booléen suivant succès * @author Fabrice PENHOËT **/ public function set_fuseau_horaire($fuseau=null) { $fuseau_defaut=date_default_timezone_get(); if(empty($fuseau)) $fuseau=$fuseau_defaut; else { $tz=new DateTimeZone($fuseau_defaut); $zones=$tz->listIdentifiers(); if(!in_array($fuseau,$zones)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_FORMAT." >> ".htmlentities($fuseau,ENT_QUOTES))); return false; } } $this->fuseau_horaire=$fuseau; return true; } /** * Test si une valeur donnée pour un champ est déjà utilisée par un autre utilisateur * id_utilisateur doit être connu si il s'agit d'un utilisateur existant * * @param le champ recherché, l'attribut devant avoir le même nom * @return true si valeur non trouvée * @author Fabrice PENHOËT **/ public function est_libre($champ="pseudo") { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; if(empty($this->$champ))//à ajouter aussi dans les autres classes { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_MANQUANT)); return false; } if(empty($this->id_utilisateur))//nouvel utilisateur non encore enregistré { $prepare=$Bd->prepare("SELECT id_utilisateur FROM utilisateurs WHERE $champ=:valeur"); $recherche=$prepare->execute(array(":valeur"=>$this->$champ)); } else { $prepare=$Bd->prepare("SELECT id_utilisateur FROM utilisateurs WHERE ($champ=:valeur and id_utilisateur!=:id)"); $recherche=$prepare->execute(array(":valeur"=>$this->$champ,":id"=>$this->id_utilisateur)); } if((test_requete(__FILE__,__LINE__,$recherche,$prepare)===false)) return false; $resultat=$prepare->fetch(); $prepare=null; if(empty($resultat))//pas de doublon return true; else return false; } /** * Méthode cherchant un utilisateur dans le bd via une valeur l'identifiant de manière unique * champs acceptés : id_utilisateur,pseudo,email * * @param la valeur recherchée, le champ de recherche et les champs souhaités en sortie * @return les données de la table dans un tableau si trouvé. false si pas trouvé ou en cas d'erreur * @author Fabrice PENHOËT **/ static function recherche($valeur,$champ_recherche="id_utilisateur",$champ_sortie="*") { global $Bd; if(strpos("id_utilisateur,pseudo,email",$champ_recherche)===false) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_CHAMP_RECHERCHE." >> ".htmlentities($champ_recherche,ENT_QUOTES))); return false; } if((isset_connexion(__FILE__,__LINE__)===false)) return false; $prepare=$Bd->prepare("SELECT $champ_sortie FROM utilisateurs WHERE $champ_recherche=:valeur"); $recherche=$prepare->execute(array(":valeur"=>$valeur)); if((test_requete(__FILE__,__LINE__,$recherche,$prepare)===false)) return false; $resultat=$prepare->fetch(PDO::FETCH_ASSOC); $prepare=null; if(empty($resultat)) return false; else return $resultat; } /** * Méthode de recherche parmi les comptes utilisateur. * * @param l'expression recherchée + les champs souhaités en sortie * @return les données de la table dans un tableau php si trouvé. false si pas trouvé ou en cas d'erreur. * @author Fabrice PENHOËT **/ static function recherche_globale($recherche,$champ_sortie="*") { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; $recherche=strip_tags(strval(trim($recherche))); $recherche_like="%".str_replace(" ","%",$recherche)."%"; $prepare=$Bd->prepare("SELECT $champ_sortie FROM utilisateurs WHERE (pseudo LIKE :recherche_l OR email LIKE :recherche_l OR presentation LIKE :recherche_l OR id_utilisateur=:recherche) ORDER BY pseudo ASC;"); $recherche=$prepare->execute(array(":recherche_l"=>$recherche_like,":recherche"=>$recherche)); if((test_requete(__FILE__,__LINE__,$recherche,$prepare)===false)) return false; $resultat=$prepare->fetchAll(PDO::FETCH_ASSOC); $prepare=null; if(empty($resultat)) return false; else return $resultat; } /** * Méthode vérifiant que l'utilisateur est un administrateur * * @return booléen * @author Fabrice PENHOËT **/ public function est_admin() { global $Bd; if(empty($this->id_utilisateur)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_MANQUANT)); return false; } $infos=self::recherche($this->id_utilisateur,"id_utilisateur","statut"); if(empty($infos)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_ENREG_ABSENT." >> ".intval($this->id_utilisateur))); return false; } if($infos["statut"]=="administrateur") return true; else return false; } /** * Méthode créant le fichier cache contenant les infos d'un utilisateur * id_utilisateur doit être connu * * @return booléen suivant succès * @author Fabrice PENHOËT **/ public function crea_cache() { if(empty($this->id_utilisateur)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_MANQUANT)); return false; } $info=self::recherche($this->id_utilisateur,"id_utilisateur","pseudo,email,statut,presentation,illustration,time_validation"); if($info===false) return false; /*if(empty($info["time_validation"]))-> à revoir, bug lors création compte { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_ACTION_NON_AUTORISEE." >> ".intval($this->id_utilisateur))); return false; }*/ $id=strval($this->id_utilisateur); return crea_cache(CACHE_REP_UTILISATEURS."/".$id[0]."/$id.txt",$info); } /** * Méthode de suppression du fichier cache contenant les infos utiles d'un utilisateur * id_utilisateur doit être connu * * @return booléen suivant succès * @author Fabrice PENHOËT **/ public function suppr_cache() { if(empty($this->id_utilisateur)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_MANQUANT)); return false; } $fichier=$this->id_utilisateur.".txt"; $chemin=CACHE_REP."/".CACHE_REP_UTILISATEURS."/".$fichier[0]."/".$fichier; if((file_exists($chemin))&&(!unlink($chemin))) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FICHIER_SUPPR." >> ".htmlentities($chemin,ENT_QUOTES))); return false; } //ses marque-pages $chemin=CACHE_REP."/".CACHE_REP_UTILISATEURS."/".$fichier[0]."/MP-$fichier"; if((file_exists($chemin))&&(!unlink($chemin))) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FICHIER_SUPPR." >> ".htmlentities($chemin,ENT_QUOTES))); return false; } //ses abonnements $chemin=CACHE_REP."/".CACHE_REP_UTILISATEURS."/".$fichier[0]."/abo-$fichier"; if((file_exists($chemin))&&(!unlink($chemin))) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FICHIER_SUPPR." >> ".htmlentities($chemin,ENT_QUOTES))); return false; } return true; } /** * Méthode enregistrant un nouvel utilisateur lors de la création de son compte * pseudo, email et origine doivent être fournis * * @param $crea_session à true si il faut créer une session à l'utilisateur en cas de succès, * $validation=false si compte créé sans devoir valider l'email (compte créé par un administrateur) * $validation=true si processus de validation classique * $validation=ext si la suite est traitée par une méthode externe (ex.: publication d'une annonce) * @return booléen suivant succès * @author Fabrice PENHOËT **/ public function ajout($crea_session=false,$validation=true) { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; if(empty($this->pseudo)||(empty($this->email))||(empty($this->origine))) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_CHAMPS_ABSENTS); return false; } $pseudo_depart=$this->pseudo; $i=2;$trouve=false; while((strlen($this->pseudo)<=UTILISATEUR_MAX_PSEUDO)&&(!$trouve)) { if(!($this->est_libre("pseudo"))) {//pour ne pas bloquer, on cherche un pseudo libre en incrémentant $this->pseudo=$pseudo_depart.$i; $i++; } else $trouve=true; } if(!$trouve)//je suis sorti parce que trop de caractères... { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_PSEUDO_LIBRE); return false; } if(!($this->est_libre("email"))) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_EMAIL_LIBRE); return false; } $ip=getIp(); if($ip===false) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_AUTORISES)); return false; } if(empty($this->fuseau_horaire)) $this->fuseau_horaire=date_default_timezone_get(); $this->ip_crea=$ip; $this->time_crea=time(); $this->statut="utilisateur";//toujours le cas lors d'une création de compte. Attribut nécessaire pour créer session + loin. $prepare=$Bd->prepare("INSERT INTO utilisateurs (pseudo,email,ip_crea,time_crea,origine,fuseau_horaire) VALUES (:pseudo,:email,:ip_crea,:time_crea,:origine,:fuseau)"); $ajout=$prepare->execute(array(':pseudo'=>$this->pseudo,':email'=>$this->email,':ip_crea'=>$this->ip_crea,':time_crea'=>$this->time_crea,':origine'=>$this->origine,':fuseau'=>$this->fuseau_horaire)); if((test_requete(__FILE__,__LINE__,$ajout,$prepare)===false)) return false; $this->id_utilisateur=$Bd->lastInsertId(); $prepare=null; if(empty($this->id_utilisateur)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_AJOUT." >> ".htmlentities($this->email,ENT_QUOTES))); return false; } // + sauvegardes $prepare_svg=$Bd->prepare("INSERT INTO utilisateurs_svg (id_utilisateur,time_maj,pseudo,email,ip_crea,time_crea,origine,fuseau_horaire) VALUES (:id,:time_maj,:pseudo,:email,:ip_crea,:time_crea,:origine,:fuseau)"); $svg=$prepare_svg->execute(array(':id'=>$this->id_utilisateur,':time_maj'=>$this->time_crea,':pseudo'=>$this->pseudo,':email'=>$this->email,':ip_crea'=>$this->ip_crea,':time_crea'=>$this->time_crea,':origine'=>$this->origine,':fuseau'=>$this->fuseau_horaire)); if((test_requete(__FILE__,__LINE__,$svg,$prepare_svg)===false)) return false; $prepare_svg=null; $ticket=crea_ticket($this->id_utilisateur,TICKET_VALID_REP,"valid"); if($ticket===false) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FICHIER_CREA)); $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_VALIDATION_MESSAGE); } else { $id=substr($ticket,(strrpos($ticket,"/"))+1); if($validation===true) {//l'utilisatdeur doit valider son compte // + envoi du message avec PHPMailer $Mail_expediteur_email=EMAIL_TRANSACTIONNEL_DE; $Mail_expediteur_nom=SITE_NOM; $Mail_destinataire_email=$this->email; $Mail_destinataire_nom=$this->pseudo; $Mail_sujet=COMPTE_VALIDATION_OBJET; // message alternatif lorsque le html n'est pas lu : $Mail_boby_txt=str_replace(array("__NOM_UTILISATEUR__","__ID__"),array($this->pseudo,$id),COMPTE_VALIDATION_CORPS); //-- version html : //texte invisible (sauf certains webmail ?) : $Mail_html_sujet="Valider sans tarder votre inscription sur ".SITE_NOM."."; //entête avant logo : $Mail_html_header="

Valider sans tarder votre inscription sur ".SITE_NOM.".

"; //texte du message, hors liste de liens : $Mail_html_intro=str_replace("__NOM_UTILISATEUR__",htmlentities($this->pseudo),COMPTE_VALIDATION_CORPS_HTML); //liens sous forme de grands boutons. L'ancre ne doit donc pas être trop longue : $Mail_html_liens_action[0]="Valider."; //footer du mail html : $Mail_html_footer="

".SITE_NOM.", ".SITE_SLOGAN."

"; $Mail_boby_html=""; ob_start(); include(BASE_REP."../www/".TEMPLATE_REP."/mail/defaut.php"); $Mail_boby_html=ob_get_contents(); ob_end_clean(); $SMTP_CustomHeader["X-Mailin-Tag"]="inscription"; // connexion au serveur smtp si il y a lieu : require(BASE_REP."../divers/phpmailer-initialise.php"); require(BASE_REP."../divers/phpmailer-envoi.php"); if(!$mail->Send()) { sleep(2);// blocage temporaire smtp ??? if(!$mail->Send()) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_EMAIL_ENVOI.$mail->ErrorInfo)); $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_VALIDATION_MESSAGE); return false; } } } else if($validation=="ext") $this->ticket=$id; else//compte automatiquement validé $this->valide($id,false); } if((empty($this->erreurs))&&($crea_session)) $this->crea_session(false,true); return true; } /** * Méthode appelée lors de la validation de son compte par un utilisateur * On va notamment générer son mot de passe et l'enregister * * @param l'adresse du ticket contenant l'identifiant de l'utilisateur, $crea_session=true si on souhaite créer une session temporaire * @return booléen suivant succès * @author Fabrice PENHOËT **/ public function valide($ticket,$crea_session=false) { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; if(strpos($ticket,"/")!==false) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_AUTORISES)); return false; } if(!file_exists(TICKET_VALID_REP."/$ticket")) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_VALIDATION_LIEN); return false; } $id_utilisateur=file_get_contents(TICKET_VALID_REP."/$ticket"); if(empty($id_utilisateur)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FICHIER_EXISTE." >> ".htmlentities($ticket,ENT_QUOTES))); return false; } unlink(TICKET_VALID_REP."/$ticket"); $info=self::recherche((int) $id_utilisateur); if($info===false) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_VALIDATION_EXPIRE); return false; } if(!empty($info["time_validation"])) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_VALIDATION_DOUBLE); return false; } $passe=crea_passe(); if($passe===false) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_UTILISA_PASSE_CREA." >> ".intval($id_utilisateur))); return false; } $this->set_passe($passe); if(empty($this->erreurs)) { $this->id_utilisateur=(int) $id_utilisateur; $this->time_validation=time()+1;//+1 pour éviter bug clé primaire quand la validation suit l'enregistrement du compte $prepare=$Bd->prepare("UPDATE utilisateurs SET passe=:passe,time_validation=:time where id_utilisateur=:id"); $maj=$prepare->execute(array(':passe'=>$this->chiffre,':time'=>$this->time_validation,':id'=>$this->id_utilisateur)); if((test_requete(__FILE__,__LINE__,$maj,$prepare)===false)) return false; $nb_enreg=$prepare->rowCount(); $prepare=null; if($nb_enreg==0) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_MAJ." >> ".intval($this->id_utilisateur))); return false; } $prepare_svg=$Bd->prepare("INSERT INTO utilisateurs_svg (id_utilisateur,time_maj,passe,time_validation) VALUES (:id,:time_maj,:passe,:time)"); $svg=$prepare_svg->execute(array(':id'=>$this->id_utilisateur,':time_maj'=>$this->time_validation,':passe'=>$this->chiffre,':time'=>$this->time_validation)); if((test_requete(__FILE__,__LINE__,$svg,$prepare_svg)===false)) return false; $prepare_svg=null; $this->pseudo=$info["pseudo"]; $this->email=$info["email"]; // + envoi du message avec PHPMailer $Mail_expediteur_email=EMAIL_TRANSACTIONNEL_DE; $Mail_expediteur_nom=SITE_NOM; $Mail_destinataire_email=$this->email; $Mail_destinataire_nom=$this->pseudo; $Mail_sujet=ENVOI_MOT_PASSE_OBJET; // message alternatif lorsque le html n'est pas lu : $Mail_boby_txt=str_replace(array("__NOM_UTILISATEUR__","__PASSE__"),array($this->pseudo,$this->passe),ENVOI_MOT_PASSE_CORPS); //-- version html : //texte invisible (sauf certains webmail ?) : $Mail_html_sujet="Bienvenue sur ".SITE_NOM.". Voici votre mot de passe."; //entête avant logo : $Mail_html_header="

Bienvenue sur ".SITE_NOM.". Voici votre mot de passe.

"; //texte du message, hors liste de liens : $Mail_html_intro=str_replace(array("__NOM_UTILISATEUR__","__PASSE__"),array($this->pseudo,$this->passe),ENVOI_MOT_PASSE_CORPS_HTML); $Mail_html_items[0]="

Pour vous connecter, cliquez-ici.

"; $Mail_html_items[1]="

Pour modifier votre mot de passe ou votre email, cliquez-ici.

"; $Mail_html_items[2]="

Pour modifier vos autres informations (pseudo, ...), cliquez-ici.

"; $Mail_html_items[3]="

Pour gérer vos abonnements (sites, jours d'envoi...), cliquez-ici.

"; $Mail_html_items[4]="

Pour stopper temporairement l'envoi de vos abonnements (vacances...), cliquez-ici.

"; $Mail_html_items[5]="

Pour proposer une actualité locale (spectacle, conférence, promo ...), cliquez-ici.

"; $Mail_html_complement="

Dernier conseil : pour éviter que les messages de ".SITE_NOM." arrivent dans votre dossier \"spam\", ajoutez ".EMAIL_MAILINGS." à votre carnet d'adresses.

"; //footer du mail html : $Mail_html_footer="

".SITE_NOM.", ".SITE_SLOGAN."

"; $Mail_boby_html=""; ob_start(); include(BASE_REP."../www/".TEMPLATE_REP."/mail/defaut.php"); $Mail_boby_html=ob_get_contents(); ob_end_clean(); $SMTP_CustomHeader["X-Mailin-Tag"]="bienvenue"; // connexion au serveur smtp si il y a lieu : require(BASE_REP."../divers/phpmailer-initialise.php"); require(BASE_REP."../divers/phpmailer-envoi.php"); if(!$mail->Send()) { sleep(2);// blocage temporaire smtp ??? if(!$mail->Send()) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_EMAIL_ENVOI.$mail->ErrorInfo)); $this->erreurs=array_merge($this->erreurs,(array) ERREUR_EMAIL_ENVOI); } } $this->crea_cache(); $this->statut=$info["statut"]; if((empty($this->erreurs))&&($crea_session)) $this->crea_session(false); return true; } else return false; } /** * Méthode enregistrant une mise à jour des informations de l'utilisateur * l'email et le mot de passe nécessitent une procédure spéciale * @param @suppr_illustration pour les demandes de suppression de l'image, * $identifiants_ok si on peut changer l'email et le mot de passe sans passer par la procédure normale (doit être demandé par un administrateur) * * @return booléen suivant succès * @author Fabrice PENHOËT **/ public function actualise($suppr_illustration=false,$identifiants_ok=false) { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; if(!isset($this->id_utilisateur)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_MANQUANT)); return false; } if(!($this->est_libre("pseudo"))) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_PSEUDO_LIBRE); $this->suppr_illustration(); return false; } if($suppr_illustration) $this->illustration="";//pour suppression réelle ci-dessous if(isset($this->illustration)) {//je viens de télécharger une nouvelle illustration ou souhaite enregistrer une suppression $ancien=self::recherche($this->id_utilisateur,"id_utilisateur","illustration"); if($ancien===false) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_RECHERCHE." >> ".$this->id_utilisateur)); return false; } $ancien_illustration=$ancien["illustration"]; if(!empty($ancien_illustration)) unlink(UTILISATEUR_ILLUS_REP."/".$ancien_illustration[0]."/".$ancien_illustration); $prepare=$Bd->prepare("UPDATE utilisateurs SET illustration=:illustration WHERE id_utilisateur=:id_utilisateur;"); $maj=$prepare->execute(array(':illustration'=>$this->illustration,':id_utilisateur'=>$this->id_utilisateur)); // + sauvegardes $prepare_svg=$Bd->prepare("INSERT INTO utilisateurs_svg (id_utilisateur,time_maj,illustration) VALUES (:id,:time_maj,:illustration)"); $svg=$prepare_svg->execute(array(':id'=>$this->id_utilisateur,':time_maj'=>time()+1,':illustration'=>$this->illustration));//à revoir, +1 pour éviter doublon sql } elseif(($identifiants_ok)&&(!empty($this->email))&&($_SESSION["statut"]=="administrateur")) { if(!($this->est_libre("email")))//doit tout de même être unique... { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_EMAIL_LIBRE); return false; } if(empty($this->passe)) { $prepare=$Bd->prepare("UPDATE utilisateurs SET pseudo=:pseudo,presentation=:presentation,email=:email,fuseau_horaire=:fuseau WHERE id_utilisateur=:id_utilisateur;"); $maj=$prepare->execute(array(':pseudo'=>$this->pseudo,':presentation'=>$this->presentation,':id_utilisateur'=>$this->id_utilisateur,':email'=>$this->email,':fuseau'=>$this->fuseau_horaire)); // + sauvegardes $prepare_svg=$Bd->prepare("INSERT INTO utilisateurs_svg (id_utilisateur,time_maj,pseudo,presentation,email,fuseau_horaire) VALUES (:id,:time_maj,:pseudo,:presentation,:email,:fuseau)"); $svg=$prepare_svg->execute(array(':id'=>$this->id_utilisateur,':time_maj'=>time(),':pseudo'=>$this->pseudo,':presentation'=>$this->presentation,':email'=>$this->email,':fuseau'=>$this->fuseau_horaire)); } else { $prepare=$Bd->prepare("UPDATE utilisateurs SET pseudo=:pseudo,presentation=:presentation,email=:email,passe=:passe,fuseau_horaire=:fuseau WHERE id_utilisateur=:id_utilisateur;"); $maj=$prepare->execute(array(':pseudo'=>$this->pseudo,':presentation'=>$this->presentation,':id_utilisateur'=>$this->id_utilisateur,':email'=>$this->email,':passe'=>$this->chiffre,':fuseau'=>$this->fuseau_horaire)); // + sauvegardes $prepare_svg=$Bd->prepare("INSERT INTO utilisateurs_svg (id_utilisateur,time_maj,pseudo,presentation,email,passe,fuseau_horaire) VALUES (:id,:time_maj,:pseudo,:presentation,:email,:passe,:fuseau)"); $svg=$prepare_svg->execute(array(':id'=>$this->id_utilisateur,':time_maj'=>time(),':pseudo'=>$this->pseudo,':presentation'=>$this->presentation,':email'=>$this->email,':passe'=>$this->chiffre,':fuseau'=>$this->fuseau_horaire)); } } else { $prepare=$Bd->prepare("UPDATE utilisateurs SET pseudo=:pseudo,presentation=:presentation,fuseau_horaire=:fuseau WHERE id_utilisateur=:id_utilisateur;"); $maj=$prepare->execute(array(':pseudo'=>$this->pseudo,':presentation'=>$this->presentation,':id_utilisateur'=>$this->id_utilisateur,':fuseau'=>$this->fuseau_horaire)); // + sauvegardes $prepare_svg=$Bd->prepare("INSERT INTO utilisateurs_svg (id_utilisateur,time_maj,pseudo,presentation,fuseau_horaire) VALUES (:id,:time_maj,:pseudo,:presentation,:fuseau)"); $svg=$prepare_svg->execute(array(':id'=>$this->id_utilisateur,':time_maj'=>time(),':pseudo'=>$this->pseudo,':presentation'=>$this->presentation,':fuseau'=>$this->fuseau_horaire)); } if((test_requete(__FILE__,__LINE__,$maj,$prepare)===false)) { $this->suppr_illustration(); return false; } $prepare=null; if((test_requete(__FILE__,__LINE__,$svg,$prepare_svg)===false)) return false; $prepare_svg=null; $this->crea_cache(); } /** * Méthode enregistrant une mise à jour des informations de connexion (email / mot de passe) * l'ancien mot de passe doit nécessairement être fourni et contrôlé * dans le cas d'un chgt d'email, un lien de vérification sera envoyé sur la nouvelle adresse * * @param le nouveau mot de passe si chgt * @return false en cas d'erreur, null sinon. * @author Fabrice PENHOËT **/ public function actualise_infos_connexion($nouveau_passe="") { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; if((empty($this->id_utilisateur))||(empty($this->email))||(empty($this->passe))) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_MANQUANT)); return false; } $resultat=self::recherche($this->id_utilisateur,"id_utilisateur","passe,email,pseudo"); if($resultat===false) return false; if(!(password_verify($this->passe,$resultat["passe"]))) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_PASSE_CORRECT); return false; } if($this->email!=$resultat["email"]) { if(!($this->est_libre("email"))) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_EMAIL_LIBRE); return false; } $ticket=crea_ticket($this->email."|".$this->id_utilisateur,TICKET_VALID_REP,"email"); if($ticket===false) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FICHIER_CREA)); return false; } else { // + envoi du message avec PHPMailer $Mail_expediteur_email=EMAIL_TRANSACTIONNEL_DE; $Mail_expediteur_nom=SITE_NOM; $Mail_destinataire_email=$this->email; $Mail_destinataire_nom=$this->pseudo; $Mail_sujet=NOUVEL_EMAIL_VALIDATION_OBJET; // message alternatif lorsque le html n'est pas lu : $id=substr($ticket,(strrpos($ticket,"/"))+1); $Mail_boby_txt=str_replace(array("__NOM_UTILISATEUR__","__ID__"),array($resultat["pseudo"],$id),NOUVEL_EMAIL_VALIDATION_CORPS); //-- version html : //texte invisible (sauf certains webmail ?) : $Mail_html_sujet="Valider sans tarder votre nouvelle adresse email sur ".SITE_NOM."."; //entête avant logo : $Mail_html_sujet="Valider sans tarder votre nouvelle adresse email sur ".SITE_NOM."."; //texte du message, hors liste de liens : $Mail_html_intro=str_replace("__NOM_UTILISATEUR__",htmlentities($resultat["pseudo"]),NOUVEL_EMAIL_VALIDATION_CORPS_HTML); //liens sous forme de grands boutons. L'ancre ne doit donc pas être trop longue : $Mail_html_liens_action[0]="Valider."; //footer du mail html : $Mail_html_footer="

".SITE_NOM.", ".SITE_SLOGAN."

"; $Mail_boby_html=""; ob_start(); include(BASE_REP."../www/".TEMPLATE_REP."/mail/defaut.php"); $Mail_boby_html=ob_get_contents(); ob_end_clean(); $SMTP_CustomHeader["X-Mailin-Tag"]="nouvel_email"; // connexion au serveur smtp si il y a lieu : require(BASE_REP."../divers/phpmailer-initialise.php"); require(BASE_REP."../divers/phpmailer-envoi.php"); if(!$mail->Send()) { sleep(2);// blocage temporaire smtp ??? if(!$mail->Send()) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_EMAIL_ENVOI.$mail->ErrorInfo)); return false; } } } } if(!empty($nouveau_passe)) { if($this->set_passe($nouveau_passe)===true) { $prepare=$Bd->prepare("UPDATE utilisateurs SET passe=:passe WHERE id_utilisateur=:id_utilisateur;"); $maj=$prepare->execute(array(':passe'=>$this->chiffre,':id_utilisateur'=>$this->id_utilisateur)); if((test_requete(__FILE__,__LINE__,$maj,$prepare)===false)) return false; $nb_enreg=$prepare->rowCount(); if($nb_enreg==0) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_MAJ." >> ".intval($this->id_utilisateur))); return false; } $prepare=null; // + sauvegardes $prepare_svg=$Bd->prepare("INSERT INTO utilisateurs_svg (id_utilisateur,time_maj,passe) VALUES (:id,:time_maj,:passe)"); $svg=$prepare_svg->execute(array(':id'=>$this->id_utilisateur,':time_maj'=>time(),':passe'=>$this->chiffre)); if((test_requete(__FILE__,__LINE__,$svg,$prepare_svg)===false)) return false; $prepare_svg=null; } else return false; } return true; } /** * Méthode enregistrant une mise à jour du fuseau horaire uniquement. * * @param * @return booléen suivant succès. * @author Fabrice PENHOËT **/ public function actualise_fuseau_horaire() { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; if((empty($this->id_utilisateur))||(empty($this->fuseau_horaire))) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_MANQUANT)); return false; } $prepare=$Bd->prepare("UPDATE utilisateurs SET fuseau_horaire=:fuseau WHERE id_utilisateur=:id_utilisateur;"); $maj=$prepare->execute(array(':fuseau'=>$this->fuseau_horaire,':id_utilisateur'=>$this->id_utilisateur)); if((test_requete(__FILE__,__LINE__,$maj,$prepare)===false)) return false; $prepare=null; // + sauvegardes $timeS=time()+2;//time_maj doit être différent $prepare_svg=$Bd->prepare("INSERT INTO utilisateurs_svg (id_utilisateur,time_maj,fuseau_horaire) VALUES (:id,:time_maj,:fuseau)"); $svg=$prepare_svg->execute(array(':id'=>$this->id_utilisateur,':time_maj'=>$timeS,':fuseau'=>$this->fuseau_horaire)); if((test_requete(__FILE__,__LINE__,$svg,$prepare_svg)===false)) return false; $prepare_svg=null; return true; } /** * Méthode appelée lors de la validation de chgt d'adresse email * * @param $ticket l'adresse du ticket contenant l'identifiant de l'utilisateur + sa nouvelle adresse * @return booléen suivant succès * @author Fabrice PENHOËT **/ public function valide_email($ticket) { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; if(strpos($ticket,"/")!==false) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_AUTORISES)); return false; } if(!file_exists(TICKET_VALID_REP."/$ticket")) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_VALIDATION_EMAIL_LIEN); return false; } $donnees_fichier=file_get_contents(TICKET_VALID_REP."/$ticket"); if(empty($donnees_fichier)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FICHIER_EXISTE." >> ".htmlentities($ticket,ENT_QUOTES))); return false; } unlink(TICKET_VALID_REP."/$ticket"); $donnees_fichier=explode("|",$donnees_fichier); $info=self::recherche((int) $donnees_fichier[1],"id_utilisateur","id_utilisateur"); if($info===false) return false; if($this->id_utilisateur!=(int) $donnees_fichier[1])//comparaison à l'id de l'utilisateur connecté return false; if($this->set_email($donnees_fichier[0])!==false) { $prepare=$Bd->prepare("UPDATE utilisateurs SET email=:email where id_utilisateur=:id"); $maj=$prepare->execute(array(':email'=>$this->email,':id'=>$this->id_utilisateur)); if((test_requete(__FILE__,__LINE__,$maj,$prepare)===false)) return false; $nb_enreg=$prepare->rowCount(); if($nb_enreg==0) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_MAJ." >> ".intval($this->id_utilisateur))); return false; } $prepare=null; // + sauvegardes $prepare_svg=$Bd->prepare("INSERT INTO utilisateurs_svg (id_utilisateur,time_maj,email) VALUES (:id,:time_maj,:email)"); $svg=$prepare_svg->execute(array(':id'=>$this->id_utilisateur,':time_maj'=>time(),':email'=>$this->email)); if((test_requete(__FILE__,__LINE__,$svg,$prepare_svg)===false)) return false; $prepare_svg=null; //+ le cache $this->crea_cache(); return true; } else return false; } /** * Méthode envoyant un nouveau mot de passe à l'utilisateur bloqué * * @param null mais attribut doit être fourni * @return booléen suivant réussite * @author Fabrice PENHOËT **/ public function get_nouveau_passe() { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; $resultat=self::recherche($this->email,"email","id_utilisateur,pseudo"); if($resultat===false) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_PASSE_ENVOI); return false; } $passe=crea_passe(); if($this->set_passe($passe)===false) return false; $prepare=$Bd->prepare("UPDATE utilisateurs SET passe=:passe where email=:email"); $maj=$prepare->execute(array(':email'=>$this->email,':passe'=>$this->chiffre)); if((test_requete(__FILE__,__LINE__,$maj,$prepare)===false)) return false; $nb_enreg=$prepare->rowCount(); if($nb_enreg==0) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_MAJ." >> ".intval($resultat["id_utilisateur"]))); return false; } $prepare=null; // + sauvegardes $prepare_svg=$Bd->prepare("INSERT INTO utilisateurs_svg (id_utilisateur,time_maj,passe) VALUES (:id,:time_maj,:passe)"); $svg=$prepare_svg->execute(array(':id'=>$resultat["id_utilisateur"],':time_maj'=>time(),':passe'=>$this->chiffre)); if((test_requete(__FILE__,__LINE__,$svg,$prepare_svg)===false)) return false; $prepare_svg=null; // + envoi du message avec PHPMailer $Mail_expediteur_email=EMAIL_TRANSACTIONNEL_DE; $Mail_expediteur_nom=SITE_NOM; $Mail_destinataire_email=$this->email; $Mail_destinataire_nom=$resultat["pseudo"]; $Mail_reponse_email=EMAIL_TRANSACTIONNEL_DE; $Mail_sujet=ENVOI_NOUVEAU_MOT_PASSE_OBJET; // message alternatif lorsque le html n'est pas lu : $Mail_boby_txt=str_replace(array("__NOM_UTILISATEUR__","__PASSE__"),array($resultat["pseudo"],$this->passe),ENVOI_NOUVEAU_MOT_PASSE_CORPS); //-- version html : //texte invisible (sauf certains webmail ?) : $Mail_html_sujet="Votre nouveau mot de passe ".SITE_NOM."."; //entête avant logo : $Mail_html_sujet="Votre nouveau mot de passe ".SITE_NOM."."; //texte du message, hors liste de liens : $Mail_html_intro=str_replace(array("__NOM_UTILISATEUR__","__PASSE__"),array($resultat["pseudo"],$this->passe),ENVOI_NOUVEAU_MOT_PASSE_CORPS_HTML); //liens sous forme de grands boutons. L'ancre ne doit donc pas être trop longue : $Mail_html_items[0]="

Pour vous connecter, cliquez-ici.

"; $Mail_html_items[1]="

Pour modifier votre mot de passe ou votre email, cliquez-ici.

"; $Mail_html_items[2]="

Pour modifier vos autres informations (pseudo,...), cliquez-ici.

"; $Mail_html_items[3]="

Pour gérer vos abonnements (sites, jours d'envoi...), cliquez-ici.

"; //footer du mail html : $Mail_html_footer="

".SITE_NOM.", ".SITE_SLOGAN."

"; $Mail_boby_html=""; ob_start(); include(BASE_REP."../www/".TEMPLATE_REP."/mail/defaut.php"); $Mail_boby_html=ob_get_contents(); ob_end_clean(); $SMTP_CustomHeader["X-Mailin-Tag"]="nouveau_passe"; // connexion au serveur smtp si il y a lieu : require_once(BASE_REP."../divers/phpmailer-initialise.php"); require_once(BASE_REP."../divers/phpmailer-envoi.php"); if(!$mail->Send()) { sleep(2);// blocage temporaire smtp ??? if(!$mail->Send()) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,$mail->ErrorInfo)); return false; } } return true; } /** * Méthode envoyant un lien par email permettant à un utilisateur de supprimer son compte * * @return booléen suivant succès * @author Fabrice PENHOËT **/ public function get_lien_suppression() { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; if(empty($this->email)) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_CHAMPS_ABSENTS); return false; } // est-ce qu'un compte existe pour cette email ? $infos=FclFlux_utilisateur::recherche($this->email,"email","id_utilisateur,pseudo,statut"); if(empty($infos)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_RECHERCHE)); return false; } if($infos["statut"]=="administrateur") { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_ACTION_NON_AUTORISEE)); return false; } //tout semble ok et on peut créé le ticket qui va bien $txt=$infos["id_utilisateur"]."|".time(); $ticket=crea_ticket($txt,TICKET_SUPPR_REP,"suppr"); if($ticket===false) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FICHIER_CREA)); $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_CREA_LIEN_SUPPRESSION); return false; } else { $id=substr($ticket,(strrpos($ticket,"/"))+1); // envoi du message avec PHPMailer $Mail_expediteur_email=EMAIL_TRANSACTIONNEL_DE; $Mail_expediteur_nom=SITE_NOM; $Mail_destinataire_email=$this->email; $Mail_destinataire_nom=$infos["pseudo"]; $Mail_sujet=COMPTE_LIEN_SUPPRESSION_OBJET; // message alternatif lorsque le html n'est pas lu : $Mail_boby_txt=str_replace(array("__NOM_UTILISATEUR__","__ID__"),array($Mail_destinataire_nom,$id),COMPTE_LIEN_SUPPRESSION_CORPS); //-- version html : //texte invisible (sauf certains webmail ?) : $Mail_html_sujet="Supprimez votre compte sur ".SITE_NOM." ?"; //entête avant logo : $Mail_html_header="

Procédure de suppression de compte.

"; //texte du message, hors liste de liens : $Mail_html_intro=str_replace("__NOM_UTILISATEUR__",htmlentities($Mail_destinataire_nom),COMPTE_LIEN_SUPPRESSION_CORPS_HTML); //liens sous forme de grands boutons. L'ancre ne doit donc pas être trop longue : $Mail_html_liens_action[0]="Confirmer la suppression."; //footer du mail html : $Mail_html_footer="

".SITE_NOM.", ".SITE_SLOGAN."

"; $Mail_boby_html=""; ob_start(); include(BASE_REP."../www/".TEMPLATE_REP."/mail/defaut.php"); $Mail_boby_html=ob_get_contents(); ob_end_clean(); $SMTP_CustomHeader["X-Mailin-Tag"]="supprime_compte"; // connexion au serveur smtp si il y a lieu : require(BASE_REP."../divers/phpmailer-initialise.php"); require(BASE_REP."../divers/phpmailer-envoi.php"); if(!$mail->Send()) { sleep(2);// blocage temporaire smtp ??? if(!$mail->Send()) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_EMAIL_ENVOI.$mail->ErrorInfo)); $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_CREA_LIEN_SUPPRESSION); return false; } } } return true; } /** * Méthode appelée lorsqu'un utilisateur clique sur le lien lui permettant de supprimer son compte * * @param l'adresse du ticket à contrôler * @return booléen suivant succès * @author Fabrice PENHOËT **/ public function test_lien_suppression($ticket) { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; if(strpos($ticket,"/")!==false) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_AUTORISES)); return false; } if(!file_exists(TICKET_SUPPR_REP."/$ticket")) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_LIEN_SUPPRESSION); return false; } $donnees_fichier=explode("|",file_get_contents(TICKET_SUPPR_REP."/$ticket")); unlink(TICKET_SUPPR_REP."/$ticket"); if(count($donnees_fichier)!=2) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_AUTORISES." >> ".htmlentities(implode("|",$donnees_fichier),ENT_QUOTES))); return false; } if($donnees_fichier[1]<(time()-3600*COMPTE_LIEN_SUPPRESSION_MAX_DUREE)) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_LIEN_SUPPRESSION); return false; } $info=self::recherche((int) $donnees_fichier[0]); if($info===false) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_LIEN_SUPPRESSION); return false; } if(empty($this->erreurs)) { $this->id_utilisateur=(int) $donnees_fichier[0]; $this->supprime(); if(empty($this->erreurs)) return true; else return false; } else return false; } /** * Méthode supprimant les infos d'un utilisateur * ne concerne pas la table des sauvegardes, ni celles des sessions ayant une durée de vie + longue * je garde tout de même dans table sauvegardes la date de suppression du compte (pour stats) * si tout se passe bien il faudra supprimer la session de l'utilisateur connecté (sauf si admin) * * @param $valide booléen pour savoir si il s'agit d'un utilisateur ayant validé son compte ou non * @return booléen suivant succès * @author Fabrice PENHOËT **/ public function supprime($valide=true) { global $Bd; if(!isset($this->id_utilisateur)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_MANQUANT)); return false; } if((isset_connexion(__FILE__,__LINE__)===false)) return false; $resultat=$this->recherche($this->id_utilisateur,"id_utilisateur","illustration"); if(empty($resultat)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_ENREG_ABSENT)); return false; } // je commence par supprimer tous les enregistrements dépendants (pour suppression des fichiers associés). // -- les abonnements require_once("FclFlux_abonnement.php"); $abos=FclFlux_abonnement::get_liste_abo_cache($this,true);//force la création du cache if(!empty($abos)) { $infos["proprietaire"]=$this; foreach($abos as $abo_infos) { $infos["id_abonnement"]=$abo_infos["id_abonnement"]; $abo=new FclFlux_abonnement($infos); $abo->supprime(); unset($abo); } } $prepare=$Bd->prepare("DELETE FROM utilisateurs WHERE id_utilisateur=:id_utilisateur;"); $suppr=$prepare->execute(array(':id_utilisateur'=>$this->id_utilisateur)); if((test_requete(__FILE__,__LINE__,$suppr,$prepare)===false)); $nb_enreg=$prepare->rowCount(); if(empty($nb_enreg)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_SUPPR." >> ".intval($this->id_utilisateur))); return false; } $prepare=null; if($valide) { // + sauvegardes $prepare_svg=$Bd->prepare("INSERT INTO utilisateurs_svg (id_utilisateur,time_maj,time_suppr) VALUES (:id,:time,:time)"); $svg=$prepare_svg->execute(array(':id'=>$this->id_utilisateur,':time'=>time())); if((test_requete(__FILE__,__LINE__,$svg,$prepare_svg)===false)) return false; $prepare_svg=null; } $this->illustration=$resultat["illustration"]; $this->suppr_illustration(); $this->suppr_cache(); if(($valide)&&((empty($_SESSION)||($_SESSION["statut"]!="administrateur"))))//c'est un admin qui supprime un compte $this->supprime_session(); } /** * Méthode ouvrant le fichier cache contenant les infos d'un utilisateur * * @param crea_cache : un booléen pour savoir si il faut tester la création du fichier en cas d'absence * @return tableau contenant les infos de l'utilisateur fournies par le fichier (si trouvé), false en cas d'erreur * @author Fabrice PENHOËT **/ public function get_infos_cache($crea_cache=false) { global $Bd; if(empty($this->id_utilisateur)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_MANQUANT)); return false; } $id=strval($this->id_utilisateur); $fichier=CACHE_REP."/".CACHE_REP_UTILISATEURS."/".$id[0]."/$id.txt"; $infos=array(); if(!file_exists($fichier)) { if($crea_cache) { require("connexion-bd.php"); if(empty($GLOBALS['Bd'])) return false; if(!$this->crea_cache()) return false; } else return false; } include($fichier); if(empty($t)) return false; else { foreach($t as $key => $value) { if(!is_array($value)) $infos[$key]=stripslashes($value); } } if(empty($infos)) return false; else return $infos; } /** * Méthode contrôlant les données saisies lors d'une tentative de connexion * * @param persistence : booléen indiquant si souhait de créer une session persistante via cookies * @return booléen suivant réussite * @author Fabrice PENHOËT **/ public function test_connexion($persistence=false) { global $Bd; if((empty($this->email))||(empty($this->passe))) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_CHAMPS_ABSENTS); return false; } if((isset_connexion(__FILE__,__LINE__)===false)) return false; $resultat=$this->recherche($this->email,"email","passe,id_utilisateur,pseudo,statut,time_validation"); if(($resultat===false)||(!(password_verify($this->passe,$resultat["passe"])))) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_CONNEXION); return false; } //données utiles pour création session & co $this->id_utilisateur=$resultat["id_utilisateur"]; $this->pseudo=$resultat["pseudo"]; $this->statut=$resultat["statut"]; //première connexion ok d'un utilisateur n'ayant pas validé son compte lors de l'inscription //mais ayant demandé et reçu un nouveau mot de passe : if($resultat["time_validation"]==0) { $prepare=$Bd->prepare("UPDATE utilisateurs SET time_validation=:time where id_utilisateur=:id"); $maj=$prepare->execute(array(':time'=>time(),':id'=>$this->id_utilisateur)); test_requete(__FILE__,__LINE__,$maj,$prepare);//on ne bloque pas même si c'est gênant... } if($this->crea_session($persistence,true)!==false) return true; else return false; } /** * Méthode contrôlant les données passées par l'url * et créant une session à l'utilisateur si elles sont ok * * @param objet utilisateur pour le propriétaire de l'abonnement, le timestamp d'envoi du message + la clé générée lors du même envoi * @return booléen suivant si les données sont ok et la session de l'utilisateur créé * @author Fabrice PENHOËT **/ public function crea_session_lien_abo($time_lien,$cle_lien) { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; if((empty($time_lien))||(empty($cle_lien))) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_MANQUANT)); return false; } $prepare=$Bd->prepare("SELECT U.id_utilisateur,U.pseudo,U.statut FROM utilisateurs as U,abonnements_mail as A WHERE (U.id_utilisateur=A.utilisateur_id AND A.time_envoi=:time AND A.cle=:cle);"); $recherche=$prepare->execute(array(":time"=>$time_lien,":cle"=>$cle_lien)); if((test_requete(__FILE__,__LINE__,$recherche,$prepare)===false)) return false; $abo_infos=$prepare->fetch(PDO::FETCH_ASSOC); $prepare=null; if(empty($abo_infos)) return false; else { if($abo_infos["statut"]=="administrateur") { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,"Tentative de connexion non autorisée en tant qu'administrateur.")); return false; } $this->id_utilisateur=$abo_infos["id_utilisateur"]; $this->pseudo=$abo_infos["pseudo"]; $this->statut=$abo_infos["statut"]; $this->crea_session(false,false); return $this->connexion_ok; } } /** * Méthode envoyant un lien par email permettant de se connecter sans mot de passe * * @param l'utilisateur a-t'il demandé une connexion persistente ? * @return booléen suivant succès * @author Fabrice PENHOËT **/ public function get_lien_connexion($persistence=false) { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; if(empty($this->email)) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_CHAMPS_ABSENTS); return false; } // est-ce qu'un compte existe pour cette email ? $infos=FclFlux_utilisateur::recherche($this->email,"email","id_utilisateur,pseudo,statut"); if(empty($infos)) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_EMAIL_CONNEXION); return false; } if($infos["statut"]=="administrateur") { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_ACTION_NON_AUTORISEE)); return false; } //tout semble ok et on peut créé le ticket qui va bien $txt=$infos["id_utilisateur"]."|".time()."|".$persistence; $ticket=crea_ticket($txt,TICKET_CONNECT_REP,"cnx"); if($ticket===false) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FICHIER_CREA)); $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_CREA_LIEN_CONNEXION); return false; } else { $id=substr($ticket,(strrpos($ticket,"/"))+1); // envoi du message avec PHPMailer // connexion au serveur smtp si il y a lieu : $Mail_expediteur_email=EMAIL_TRANSACTIONNEL_DE; $Mail_expediteur_nom=SITE_NOM; $Mail_destinataire_email=$this->email; $Mail_destinataire_nom=$infos["pseudo"]; $Mail_sujet=COMPTE_LIEN_CONNEXION_OBJET; // message alternatif lorsque le html n'est pas lu : $Mail_boby_txt=str_replace(array("__NOM_UTILISATEUR__","__ID__"),array($Mail_destinataire_nom,$id),COMPTE_LIEN_CONNEXION_CORPS); //-- version html : //texte invisible (sauf certains webmail ?) : $Mail_html_sujet="Lien de connexion à ".SITE_NOM."."; //entête avant logo : $Mail_html_header="

Vous connecter à ".SITE_NOM.".

"; //texte du message, hors liste de liens : $Mail_html_intro=str_replace("__NOM_UTILISATEUR__",htmlentities($Mail_destinataire_nom),COMPTE_LIEN_CONNEXION_CORPS_HTML); //liens sous forme de grands boutons. L'ancre ne doit donc pas être trop longue : $Mail_html_liens_action[0]="Connexion."; //footer du mail html : $Mail_html_footer="

".SITE_NOM.", ".SITE_SLOGAN."

"; $Mail_boby_html=""; ob_start(); include(BASE_REP."../www/".TEMPLATE_REP."/mail/defaut.php"); $Mail_boby_html=ob_get_contents(); ob_end_clean(); $SMTP_CustomHeader["X-Mailin-Tag"]="lien_connexion_sans_passe"; require(BASE_REP."../divers/phpmailer-initialise.php"); require(BASE_REP."../divers/phpmailer-envoi.php"); //echo var_dump($mail); if(!$mail->Send()) { sleep(2);// blocage temporaire smtp ??? if(!$mail->Send()) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_EMAIL_ENVOI.$mail->ErrorInfo)); $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_CREA_LIEN_CONNEXION); return false; } } } return true; } /** * Méthode appelée lorsqu'un utilisateur clique sur un lien de connexion envoyé sur son email * * @param l'adresse du ticket à contrôler * @return booléen suivant succès * @author Fabrice PENHOËT **/ public function crea_session_lien_connexion($ticket) { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; if(strpos($ticket,"/")!==false) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_AUTORISES)); return false; } if(!file_exists(TICKET_CONNECT_REP."/$ticket")) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_LIEN_CONNEXION); return false; } $donnees_fichier=explode("|",file_get_contents(TICKET_CONNECT_REP."/$ticket")); unlink(TICKET_CONNECT_REP."/$ticket"); if(count($donnees_fichier)!=3) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_AUTORISES." >> ".htmlentities(implode("|",$donnees_fichier),ENT_QUOTES))); return false; } if($donnees_fichier[1]<(time()-60*COMPTE_LIEN_CONNEXION_MAX_DUREE)) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_LIEN_CONNEXION); return false; } $info=self::recherche((int) $donnees_fichier[0]); if($info===false) { $this->erreurs=array_merge($this->erreurs,(array) ERREUR_UTILISA_LIEN_CONNEXION); return false; } if(empty($this->erreurs)) { $this->id_utilisateur=(int) $donnees_fichier[0]; $this->pseudo=$info["pseudo"]; $this->statut=$info["statut"]; if(empty($this->erreurs)) $this->crea_session($donnees_fichier[2]); return true; } else return false; } /** * Méthode enregistrant une nouvelle session * un fichier temporaire contiendra l'id de l'utilisateur + le timestamp et différentes infos pour les stats * si connexion persistente demandée, on créé un cookie + un ticket pour les futurs contrôles du cookie * mais connexion persistente interdite pour les administrateurs. * * @param persistence (booléen) souhait ou non d'une connexion persistente (cookies), * initialise_session (booléen) : session déjà initialisée au préalable ? * @return booléen suivant réussite * @author Fabrice PENHOËT **/ public function crea_session($persistence,$initialise_session=false) { if((empty($this->id_utilisateur))||(empty($this->pseudo))||(empty($this->statut))) return false; if(!$initialise_session) { session_save_path(SESSIONS_REP); ini_set("session.use_only_cookies",1); session_regenerate_id(true); session_start(); } $ip_connexion=getIp(); $user_agent=$_SERVER["HTTP_USER_AGENT"]; if((empty($ip_connexion))||(empty($user_agent))) return false; $_SESSION["id_utilisateur"]=$this->id_utilisateur; $_SESSION["pseudo"]=htmlspecialchars($this->pseudo);//donnée que j'affiche $_SESSION["statut"]=$this->statut; $_SESSION["controle"]=$user_agent; $_SESSION["controle_ip"]=$ip_connexion; $referer=""; if(!empty($_SERVER["HTTP_REFERER"])) $referer=$_SERVER["HTTP_REFERER"]; if(!empty($_SESSION)) { $this->connexion_ok=true; $code=htmlentities($this->id_utilisateur)."##".time()."##".$ip_connexion."##".htmlentities($user_agent)."##".htmlentities($referer); $ticket=crea_ticket($code,SESSIONS_TEMP_REP,"ses"); if($ticket===false) $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FICHIER_CREA)); } else return false; if(($persistence===true)&&($this->statut!="administrateur")) { $str_mois=strval(date("Y/m")); $code=$this->id_utilisateur.",".$_SESSION["controle"].",".$_SESSION["controle_ip"]; $ticket=crea_ticket($code,COOKIES_REP."/".$str_mois,"cook"); if($ticket===false) $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FICHIER_CREA)); else { $date_expire_cookie=time()+3600*24*180;//6 mois, durée max autorisée par la cnil... setcookie("ctrl",str_replace("cook","",substr($ticket,(strrpos($ticket,"/"))+1)),$date_expire_cookie,"/",SITE_COOKIES_DOMAINE); setcookie("mois",strval(date("Y-m")),$date_expire_cookie,"/",SITE_COOKIES_DOMAINE); } } } /** * Méthode enregistrant un cookie éphémère * dans le but de stocker une adresse vers laquelle rediriger l'utilisateur une fois qu'il sera connecté * * @param l'url vers laquelle rediriger le gus + la durée de vie en jours du cookie * @return booléen suivant réussite * @author Fabrice PENHOËT **/ static function crea_cookie_redirection($url=SITE_URL,$duree=1) { if(strpos($url,SITE_COOKIES_DOMAINE)===false) return false; $date_expire_cookie=time()+(3600*24)*$duree; setcookie("rdg",$url,$date_expire_cookie,"/",SITE_COOKIES_DOMAINE); } /** * Méthode testant les cookies de connexion * si tout est ok, on créé des variables de session * sinon on supprime les éventuels cookies * * @return booléen suivant réussite * @author Fabrice PENHOËT **/ public function test_cookies() { if((empty($_COOKIE["ctrl"]))||(empty($_COOKIE["mois"]))) return false; if((strpos("/",$_COOKIE["ctrl"])!==false)||(strpos("/",$_COOKIE["mois"])!==false)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_AUTORISES)); setcookie("ctrl","",time()-42000,"/",SITE_COOKIES_DOMAINE); setcookie("mois","",time()-42000,"/",SITE_COOKIES_DOMAINE); return false; } $tab_mois=explode("-",$_COOKIE["mois"]); $mois_ok=array("01","02","03","04","05","06","07","08","09","10","11","12"); if(!in_array($tab_mois[1],$mois_ok)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_AUTORISES)); setcookie("ctrl","",time()-42000,"/",SITE_COOKIES_DOMAINE); setcookie("mois","",time()-42000,"/",SITE_COOKIES_DOMAINE); return false; } $chemin_ticket=COOKIES_REP."/".intval($tab_mois[0])."/".$tab_mois[1]."/cook".$_COOKIE["ctrl"]; if(!file_exists($chemin_ticket)) { $this->supprime_session(); return false; } $code=explode(",",file_get_contents($chemin_ticket)); /* bloque certains utilisateurs et ne protège pas de grand chose... * $ip_connexion=getIp(); $user_agent=$_SERVER["HTTP_USER_AGENT"]; if((empty($ip_connexion))||(empty($user_agent))) return false; if(($code[1]!=$user_agent)&&($code[2]!=$ip_connexion))//il semble que le user-agent change parfois aussi en cours de route, les 2 c'est louche ! { $this->supprime_session(); return false; }*/ $this->id_utilisateur=intval($code[0]); $infos=$this->get_infos_cache(true);//force la création du cache si nécessaire if(empty($infos)) { $this->id_utilisateur=null; $this->supprime_session(); return false; } else { $this->pseudo=stripslashes($infos["pseudo"]); $this->statut=stripslashes($infos["statut"]); $this->crea_session(false,true); } return true; } /** * Méthode testant si l'utilisateur est connecté ou non * si oui l'objet courant se voit attribuer les données de la session * * @param $destroy, booléen suivant si je veux détruire ou non la variable de session, $admin à true si page uniquement pour les administrateurs * @return booléen suivant si connexion active ou non * @author Fabrice PENHOËT **/ public function test_session($destroy=true,$admin=false) { if(MSG_MAINTENANCE!="") return false; session_save_path(SESSIONS_REP); ini_set("session.use_only_cookies",1); session_start(); if(empty($_SESSION)) $this->test_cookies(); /* // bloque certains utilisateurs et ne sécurise pas grand chose.. // données servant à contrôler la session : $ip_connexion=getIp(); $user_agent=$_SERVER["HTTP_USER_AGENT"]; if((empty($ip_connexion))||(empty($user_agent))) return false; if((!empty($_SESSION["id_utilisateur"]))&&(!empty($_SESSION["pseudo"]))&&(!empty($_SESSION["statut"]))&&(($_SESSION["controle"]==$user_agent)||($_SESSION["controle_ip"]==$ip_connexion)))//il semble que le user-agent change parfois aussi en cours de route mais les 2 c'est louche !*/ if((!empty($_SESSION["id_utilisateur"]))&&(!empty($_SESSION["pseudo"]))&&(!empty($_SESSION["statut"]))) { $this->id_utilisateur=$_SESSION["id_utilisateur"]; $this->pseudo=strval($_SESSION["pseudo"]);//atttibut privé ne pouvant être utilisé en dehors de la classe. Du coup, voir si vraiment utile ? $this->statut=strval($_SESSION["statut"]);//idem $this->connexion_ok=true; if(($admin)&&($_SESSION["statut"]!="administrateur")) return false; else return true; } else { if(($destroy)&&(!empty($_SESSION))) { $_SESSION=array(); session_destroy(); } } } /** * Méthode supprimant tout ce qui est rapport avec une session * cookies, fichiers de contrôle et variables de session * * @param null * @return booléen suivant réussite * @author Fabrice PENHOËT **/ public function supprime_session() { if(!isset($_SESSION)) { session_save_path(SESSIONS_REP); session_start(); } if((!empty($_COOKIE["ctrl"]))&&(!empty($_COOKIE["mois"]))) { if((strpos("/",$_COOKIE["ctrl"])!==false)||(strpos("/",$_COOKIE["mois"])!==false)) $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_AUTORISES)); else { $tab_mois=explode("-",$_COOKIE["mois"]); $mois_ok=array("01","02","03","04","05","06","07","08","09","10","11","12"); if(!in_array($tab_mois[1],$mois_ok)) $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_AUTORISES)); else { $chemin_ticket=COOKIES_REP."/".intval($tab_mois[0])."/".$tab_mois[1]."/cook".$_COOKIE["ctrl"]; unlink($chemin_ticket); } } setcookie("ctrl","",time()-42000,"/",SITE_COOKIES_DOMAINE); setcookie("mois","",time()-42000,"/",SITE_COOKIES_DOMAINE); } setcookie("rdg","",time()-42000,"/",SITE_COOKIES_DOMAINE);//peut exister si l'utilisateur a été redirigé lors de la connexion $_SESSION=array(); if (ini_get("session.use_cookies")) { $params=session_get_cookie_params(); setcookie(session_name(),"",time()- 42000,$params["path"],$params["domain"],$params["secure"], $params["httponly"]); } session_destroy(); if(empty($_SESSION)) return true; else return false; } /** * Méthode important dans la bd le contenu des fichiers temporaires de session * puis supprimant les fichiers en question * * @param null * @return booléen suivant réussite * @author Fabrice PENHOËT **/ static function sauve_sessions() { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; if(!is_dir(SESSIONS_TEMP_REP)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_REP_EXISTE." >> ".htmlentities(SESSIONS_REP,ENT_QUOTES))); return false; } $rep=opendir(SESSIONS_TEMP_REP); $tab=array(); while($fichier=readdir($rep)) { if(!(is_dir(SESSIONS_TEMP_REP."/$fichier"))&&($fichier!=".")&&($fichier!="..")) $tab[$fichier]=file_get_contents(SESSIONS_TEMP_REP."/$fichier"); } closedir($rep); $nb_import=0; if(!empty($tab)) { $prepare=$Bd->prepare("INSERT INTO utilisateurs_sessions (utilisateur_id,time_session,ip_session,config,referer) VALUES (:id,:time,:ip,:config,:referer)"); foreach ($tab as $fichier=>$contenu) { $tab2=explode("##",$contenu); if(count($tab2)==5) { $ajout=$prepare->execute(array(':id'=>$tab2[0],':time'=>$tab2[1],':ip'=>$tab2[2],':config'=>$tab2[3],':referer'=>$tab2[4])); test_requete(__FILE__,__LINE__,$ajout,$prepare);//pour infos mais je ne bloque pas sinon fichier non supprimé $nb_import++; } unlink(SESSIONS_TEMP_REP."/$fichier");//contenu ok ou pas, le fichier est supprimé... } $prepare=null; } return $nb_import; } /** * Méthode actualisant un journal comptabilisant les pages visitées par un abonné connecté * * @param $page affichée et $contexte de l'affichage (pour distinguer les mails) * @return booléen suivant succès * @author Fabrice PENHOËT **/ public function ajout_journal_affichage($page=null,$contexte="site") { if(empty($this->id_utilisateur)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_FORMAT)); return false; } if(empty($page) || (strpos($page,SITE_URL) === false && strpos($page,str_replace("https", "http", SITE_URL)) === false)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_FORMAT)); return false; } else $page=str_replace(SITE_URL,"",$page); if(empty($page)) $page="accueil"; $contextes_ok=explode("|",ABO_AFFICHAGES_CONTEXTE); if (!in_array($contexte,$contextes_ok)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_AUTORISES." >> ".htmlentities($contexte,ENT_QUOTES))); return false; } $repertoire_fichier=CACHE_REP."/".CACHE_REP_UTILISATEURS."/affichages/"; $nom_fichier=strval(date('Y-m-d-H-i')); $now=time(); if($contexte=="email") $config=$_SERVER['HTTP_USER_AGENT']; else $config=null;//info déjà récupérée lors de la connexion au site $code="\$a[$now]['c']='".$contexte."';\$a[$now]['u_id']='".$this->id_utilisateur."';\$a[$now]['page']=\"".htmlentities($page,ENT_QUOTES)."\";\$a[$now]['conf']=\"".htmlentities($config,ENT_QUOTES)."\";"; if(file_exists($repertoire_fichier.$nom_fichier)) { if(!file_put_contents($repertoire_fichier.$nom_fichier,$code,FILE_APPEND | LOCK_EX)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FICHIER_ECRITURE)); return false; } else return true; } else { if(!file_exists($repertoire_fichier)) { if(!mkdir($repertoire_fichier,CACHE_REP_CHMOD,true)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_REP_CREA)); return false; } } if(!file_put_contents($repertoire_fichier.$nom_fichier,"query("SELECT id_utilisateur,pseudo,email FROM utilisateurs WHERE statut='administrateur';"); if((test_requete(__FILE__,__LINE__,$get_admins)===false)) return false; $resultat=$get_admins->fetchAll(PDO::FETCH_ASSOC); if(empty($resultat)) return false; else return $resultat; } /** * Méthode enregistrant le contenu du journal des affichages * * @param null * @return booléen suivant succès * @author Fabrice PENHOËT **/ static function sauve_journal_affichages() { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; $time_limite=time()-60;//un fichier est créé / minute, donc si fichier a + de 60 secondes, on peut l'importer $repertoire_fichier=CACHE_REP."/".CACHE_REP_UTILISATEURS."/affichages/"; $rep=opendir($repertoire_fichier); $affichages=array(); while($fichier=readdir($rep)) { if(!(is_dir($repertoire_fichier.$fichier))&&($fichier!=".")&&($fichier!="..")) { $dates_fichier=explode("-",$fichier); if(!checkdate($dates_fichier[1],$dates_fichier[2],$dates_fichier[0])) $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_DATE_VALIDE)); else { $time_fichier=filemtime($repertoire_fichier.$fichier); if($time_fichier<$time_limite) { include($repertoire_fichier.$fichier); if(is_array($a)) $affichages=$affichages+$a; unlink($repertoire_fichier.$fichier);//dans tous les cas, le fichier est supprimé unset($a); } } } } closedir($rep);$nb_import=0; if(count($affichages)!=0) { $prepare=$Bd->prepare("INSERT INTO utilisateurs_affichages (utilisateur_id,page,config,time_affichage,contexte) VALUES (:id,:page,:config,:time,:contexte)"); foreach ($affichages as $time_a=>$infos) { $test_utilisateur=FclFlux_utilisateur::recherche($infos["u_id"],"id_utilisateur","id_utilisateur"); if(!empty($test_utilisateur)) { $ajout=$prepare->execute(array(':id'=>$infos["u_id"],':page'=>$infos["page"],':config'=>$infos["conf"],':time'=>$time_a,':contexte'=>$infos["c"])); if((test_requete(__FILE__,__LINE__,$ajout,$prepare)===false)) return false; $nb_import++; } } $prepare=null; } return $nb_import; } /** * Méthode vidant les valeurs anciennes de la table comptant les affichages * tout en archivant certaines statistiques de configuration * * @param mois à archiver format YYYY-N, vide si c'est le mois précédent * @return booléen suivant succès * @author Fabrice PENHOËT **/ static function nettoye_logs_affichages($mois=null) { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; //d'abord les affichages des utilisateurs connectés sur le site $time_limite=time()-NB_JOURS_LOGS_AFFICHAGES*3600*24; $suppr_log=$Bd->query("DELETE FROM utilisateurs_affichages WHERE contexte='site' AND time_affichage<$time_limite;"); if((test_requete(__FILE__,__LINE__,$suppr_log)===false)) return false; unset($suppr_log); //pour les logs d'email, soit le mois à traiter est fourni, //soit je traite le mois précédent mais seulement si nous sommes le 1er du mois. if(empty($mois)&&(date("j")==1)) { $m=date("n"); if($m!=1) { $m=$m-1; $mois=date("Y")."-$m"; } else { $a=date("Y")-1; $mois="$a-12";//décembre de l'année précédente } } if(!empty($mois)) { $Date_debut=explode("-",$mois); $time_premier_jour=mktime(0,0,0,intval($Date_debut[1]),1,intval($Date_debut[0])); if($time_premier_jour===false) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_FORMAT.$mois)); return false; } if($Date_debut[1]=="12")//chgt d'année { $Date_fin[1]=1; $Date_fin[0]=$Date_debut[0]+1; } else { $Date_fin[1]=$Date_debut[1]+1; $Date_fin[0]=$Date_debut[0]; } $time_dernier_jour=mktime(0,0,0,$Date_fin[1],1,$Date_fin[0]); if($time_dernier_jour===false) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_FORMAT.$Date_fin[0]."-".$Date_fin[1])); return false; } $recherche_config=$Bd->query("SELECT config,count(DISTINCT utilisateur_id) AS nb FROM utilisateurs_affichages WHERE contexte='email' AND time_affichage>=$time_premier_jour AND time_affichage<$time_dernier_jour GROUP BY config;"); if((test_requete(__FILE__,__LINE__,$recherche_config)===false)) return false; $resultats=$recherche_config->fetchAll(PDO::FETCH_ASSOC); unset($recherche_config); $prepare=$Bd->prepare("INSERT INTO utilisateurs_config_svg (config,mois,nb_utilisateurs) VALUES (:config,:mois,:nb)"); foreach($resultats as $config) { $ajout=$prepare->execute(array(':config'=>$config["config"],':mois'=>$mois,':nb'=>$config["nb"])); if((test_requete(__FILE__,__LINE__,$ajout,$prepare)===false)) return false; } //pas de bug arrivé là, je peux supprimer les enregistrements du mois. $suppr_log=$Bd->query("DELETE FROM utilisateurs_affichages WHERE contexte='email' AND time_affichage>=$time_premier_jour AND time_affichage<$time_dernier_jour;"); if((test_requete(__FILE__,__LINE__,$suppr_log)===false)) return false; } return true; } /** * Méthode parcourant les répertoires contenant des fichiers temporaires pour supprimer ceux obsolètes * concernés : tickets validation compte/nouvelle email, fichiers/session, fichiers ctrl des cookies, tickets de connexion * * @param null * @return booléen suivant réussite * @author Fabrice PENHOËT **/ static function supprime_fichiers_temp() { if(is_dir(SESSIONS_REP)) { $rep=opendir(SESSIONS_REP); while($fichier=readdir($rep)) { if(!(is_dir(SESSIONS_REP."/".$fichier))&&($fichier!=".")&&($fichier!="..")) { if(filemtime(SESSIONS_REP."/".$fichier)<(time()-3600*3)) { if(!unlink(SESSIONS_REP."/".$fichier)) $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FICHIER_SUPPR." >> ".SESSIONS_REP."/".htmlentities($fichier,ENT_QUOTES))); } } } closedir($rep); } if(is_dir(COOKIES_REP)) { $time_limite_cookies=time()-(180*24*3600);//durée max cnil $date_limite=date("Y-m",$time_limite_cookies); $dates_limite=explode("-",$date_limite); $rep=opendir(COOKIES_REP); while($fichier=readdir($rep)) { if((is_dir(COOKIES_REP."/".$fichier))&&($fichier!=".")&&($fichier!="..")) { if(intval($fichier)> ".TICKET_VALID_REP."/".htmlentities($fichier,ENT_QUOTES))); } } else if(strpos($fichier,"email")!==false) { if(filemtime(TICKET_VALID_REP."/$fichier")<(time()-3600*24*NOUVEL_EMAIL_MAX_DUREE_VALIDATION)) { if(!unlink(TICKET_VALID_REP."/".$fichier)) $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FICHIER_SUPPR." >> ".TICKET_VALID_REP."/".htmlentities($fichier,ENT_QUOTES))); } } } } closedir($rep); } if(is_dir(TICKET_CONNECT_REP)) { $rep=opendir(TICKET_CONNECT_REP); while($fichier=readdir($rep)) { if(!(is_dir(TICKET_CONNECT_REP."/".$fichier))&&($fichier!=".")&&($fichier!="..")) { if(filemtime(TICKET_CONNECT_REP."/".$fichier)<(time()-60*COMPTE_LIEN_CONNEXION_MAX_DUREE)) { if(!unlink(TICKET_CONNECT_REP."/".$fichier)) $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_FICHIER_SUPPR." >> ".TICKET_CONNECT_REP."/".htmlentities($fichier,ENT_QUOTES))); } } } closedir($rep); } return true; } /** * Méthode supprimant les données sauvegardées / anciens utilisateurs * ceci inclus les données de leurs sessions * on garde néanmoins une version anonymisée des enregistrements de création / suppresion de compte (pour stats) !!! * supprime aussi les utilisateurs qui n'ont pas validé leur compte au-delà la date limite ou encore étant inactif depuis + d'un an * * @return booléen suivant succès * @author Fabrice PENHOËT **/ static function supprime_anciens_utilisateurs() { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; $time_limite=time()-DUREE_SVG_DONNEES*24*3600; $cherche_anciens=$Bd->query("SELECT id_utilisateur,time_maj,time_crea,time_suppr FROM utilisateurs_svg WHERE (id_utilisateur NOT IN (SELECT id_utilisateur FROM utilisateurs)) and (id_utilisateur in (SELECT id_utilisateur FROM utilisateurs_svg GROUP BY id_utilisateur HAVING MAX(time_maj)<$time_limite));"); if((test_requete(__FILE__,__LINE__,$cherche_anciens)===false)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_RECHERCHE." >> ".$time_limite)); return false; } $resultats=$cherche_anciens->fetchAll(PDO::FETCH_ASSOC); $cherche_anciens=null; $prepare_suppr=$Bd->prepare("DELETE FROM utilisateurs_svg WHERE id_utilisateur=:id AND time_maj=:time;"); $prepare_anonyme=$Bd->prepare("UPDATE utilisateurs_svg SET pseudo=NULL,passe=NULL,email=NULL,presentation=NULL,illustration=NULL,ip_crea=NULL,fuseau_horaire=NULL WHERE id_utilisateur=:id AND time_maj=:time;"); $i=0; while(isset($resultats[$i])) { if(($resultats[$i]["time_crea"]!=$resultats[$i]["time_maj"])&&(empty($resultats[$i]["time_suppr"]))) { $suppr=$prepare_suppr->execute(array(':id'=>$resultats[$i]["id_utilisateur"],':time'=>$resultats[$i]["time_maj"])); if((test_requete(__FILE__,__LINE__,$suppr,$prepare_suppr)===false)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_SUPPR." >> ".$resultats[$i]["id_utilisateur"])); return false; } } else {// je garde les dates de création et suppression du compte mais sans données perso $maj=$prepare_anonyme->execute(array(':id'=>$resultats[$i]["id_utilisateur"],':time'=>$resultats[$i]["time_maj"])); if((test_requete(__FILE__,__LINE__,$maj,$prepare_anonyme)===false)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_MAJ." >> ".$resultats[$i]["id_utilisateur"])); return false; } } $i++; } $prepare_suppr=null;$prepare_anonyme=null; $suppr_sessions=$Bd->query("DELETE FROM utilisateurs_sessions WHERE utilisateur_id IN (select id_utilisateur FROM utilisateurs_svg WHERE time_suppr< $time_limite);"); if((test_requete(__FILE__,__LINE__,$suppr_sessions)===false)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_SUPPR)); return false; } $suppr_sessions=null; //les utilisateurs qui n'ont pas validé leur compte dans les temps sont supprimés des 2 tables $suppr_sans_validation=$Bd->query("DELETE FROM utilisateurs_svg WHERE id_utilisateur IN (SELECT id_utilisateur FROM utilisateurs WHERE time_validation=0 and time_crea<".(time()-(3600*24*COMPTE_VALIDATION_MAX_DUREE)).");"); if((test_requete(__FILE__,__LINE__,$suppr_sans_validation)===false)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_SUPPR." >> ".$time_limite)); return false; } //l'utilisateur ayant pu s'abonner et modifier ses infos lors de la création de son compte, il faut lancer une suppression "normale" (fichiers cache, etc.) //!!! peut-être garder des stats quelque part ??? $suppr_sans_validation=$Bd->query("SELECT id_utilisateur FROM utilisateurs WHERE time_validation=0 and time_crea<".(time()-(3600*24*COMPTE_VALIDATION_MAX_DUREE)).";"); if((test_requete(__FILE__,__LINE__,$suppr_sans_validation)===false)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_SQL_RECHERCHE)); return false; } $resultat_suppr=$suppr_sans_validation->fetchAll(PDO::FETCH_ASSOC); $suppr_sans_validation=null; foreach($resultat_suppr as $suppr) { $ancien=new FclFlux_utilisateur(); $ancien->id_utilisateur=$suppr["id_utilisateur"]; $ancien->supprime(false); unset($ancien); } } /** * Méthode retournant les principales stats concernant les utilisateurs du site durant une période donnée : * création comptes, email envoyés, clics, etc. * * @param timestamp de début et de fin de la période visée * @return un tableau contenant les chiffres * @author Fabrice PENHOËT **/ static function get_stats_utilisateurs($time_debut=0,$time_fin=0) { global $Bd;global $hub_site; if((isset_connexion(__FILE__,__LINE__)===false)) return false; if(empty($time_fin)) $time_fin=time(); if((empty($time_debut))&&($time_debut!=0)) $time_debut=$time_fin-3600*24; $statistiques=array(); // les comptes créés : $get_stats=$Bd->query("SELECT id_utilisateur FROM utilisateurs WHERE time_crea>$time_debut AND time_crea<$time_fin;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_comptes"]=$get_stats->rowCount(); // les comptes validés : $get_stats=$Bd->query("SELECT id_utilisateur FROM utilisateurs WHERE time_validation>$time_debut AND time_validation<$time_fin;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_comptes_valide"]=$get_stats->rowCount(); // tous les comptes de + de 6 mois : $time_limite_6mois=time()-3600*24*180; $get_stats=$Bd->query("SELECT DISTINCT id_utilisateur FROM utilisateurs_svg WHERE time_crea<$time_limite_6mois;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_comptes_6mois"]=$get_stats->rowCount(); // tous les comptes de + de 1 an : $time_limite_1an=time()-3600*24*365; $get_stats=$Bd->query("SELECT DISTINCT id_utilisateur FROM utilisateurs_svg WHERE time_crea<$time_limite_1an;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_comptes_1an"]=$get_stats->rowCount(); // les comptes supprimés : $get_stats=$Bd->query("SELECT id_utilisateur FROM utilisateurs_svg WHERE time_suppr>$time_debut AND time_suppr<$time_fin;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_comptes_suppr"]=$get_stats->rowCount(); // pour toutes les stats sur les abonnements, on ne compte pas l'abonnement par défaut aux news du site : $sup_sql=""; if(!empty($hub_site["id"])) $sup_sql="AND id_abonnement NOT IN (SELECT DISTINCT id_abonnement FROM abonnements_hub WHERE id_hub=".$hub_site["id"].")"; // tous les abonnements : $get_stats=$Bd->query("SELECT id_abonnement FROM abonnements WHERE time_crea>$time_debut AND time_crea<$time_fin $sup_sql;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_abo"]=$get_stats->rowCount(); // les abonnements avec envoi / mail : $get_stats=$Bd->query("SELECT id_abonnement FROM abonnements WHERE time_crea>$time_debut AND time_crea<$time_fin AND jours_alerte!='' $sup_sql;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_abo_email"]=$get_stats->rowCount(); // tous les abonnés : $get_stats=$Bd->query("SELECT distinct auteur_id FROM abonnements WHERE time_crea>$time_debut AND time_crea<$time_fin $sup_sql;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_abonnes"]=$get_stats->rowCount(); // tous les abonnés de + de 6 mois : $get_stats=$Bd->query("SELECT distinct auteur_id FROM abonnements WHERE time_crea<$time_limite_6mois $sup_sql;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_abonnes_6mois"]=$get_stats->rowCount(); // tous les abonnés de + de 1an : $get_stats=$Bd->query("SELECT distinct auteur_id FROM abonnements WHERE time_crea<$time_limite_1an $sup_sql;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_abonnes_1an"]=$get_stats->rowCount(); // les abonnés avec au moins un abonnement actif : $get_stats=$Bd->query("SELECT distinct auteur_id FROM abonnements WHERE time_crea>$time_debut AND time_crea<$time_fin AND jours_alerte!='' $sup_sql;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_abonnes_email"]=$get_stats->rowCount(); // les abonnés toujours actifs au-delà de 6 mois : $get_stats=$Bd->query("SELECT distinct auteur_id FROM abonnements WHERE time_crea<$time_limite_6mois AND jours_alerte!='' $sup_sql;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_abonnes_email_6mois"]=$get_stats->rowCount(); // les abonnés toujours actifs au-delà de 1 an : $get_stats=$Bd->query("SELECT distinct auteur_id FROM abonnements WHERE time_crea<$time_limite_1an AND jours_alerte!='' $sup_sql;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_abonnes_email_1an"]=$get_stats->rowCount(); // tous les comptes sans abonnements : $statistiques["nb_fantomes"]=$statistiques["nb_comptes_valide"]-$statistiques["nb_abonnes"]; // les comptes ayant au moins un abonnement mais aucun actif : $statistiques["nb_abonnes_desactives"]=$statistiques["nb_abonnes"]-$statistiques["nb_abonnes_email"]; // tous les emails envoyés : $get_stats=$Bd->query("SELECT abonnement_id FROM abonnements_mail WHERE time_envoi>$time_debut AND time_envoi<$time_fin;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_mail_envoyes"]=$get_stats->rowCount(); // les emails envoyés uniques : $get_stats=$Bd->query("SELECT distinct utilisateur_id FROM abonnements_mail WHERE time_envoi>$time_debut AND time_envoi<$time_fin;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_mail_uniques_envoyes"]=$get_stats->rowCount(); // tous les clics dans les emails : $get_stats=$Bd->query("SELECT id_clic FROM stat_clics_posts WHERE time_clic>$time_debut AND time_clic<$time_fin AND contexte='email';"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_clics_email"]=$get_stats->rowCount(); // les clics uniques dans les emails : $get_stats=$Bd->query("SELECT distinct utilisateur_id FROM stat_clics_posts WHERE time_clic>$time_debut AND time_clic<$time_fin AND contexte='email';"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_clics_uniques_email"]=$get_stats->rowCount(); // tous les clics web sur le site : $get_stats=$Bd->query("SELECT id_clic FROM stat_clics_posts WHERE time_clic>$time_debut AND time_clic<$time_fin AND contexte='site';"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_clics_site"]=$get_stats->rowCount(); // les clics uniques sur le site : $get_stats=$Bd->query("SELECT distinct utilisateur_id FROM stat_clics_posts WHERE time_clic>$time_debut AND time_clic<$time_fin AND contexte='site';"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_clics_uniques_site"]=$get_stats->rowCount(); // tous les clics sur la période : $statistiques["nb_clics"]=$statistiques["nb_clics_email"]+$statistiques["nb_clics_site"]; // tous les clics uniques : $get_stats=$Bd->query("SELECT distinct utilisateur_id FROM stat_clics_posts WHERE time_clic>$time_debut AND time_clic<$time_fin;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["nb_clics_uniques"]=$get_stats->rowCount(); unset($get_stats); unset($stats); if(empty($statistiques)) return false; else return $statistiques; } /** * Méthode retournant les principales stats concernant les adresses emails des utilisateurs du site durant une période donnée. * Pour chaque domaine : nombre de comptes actifs, inactifs, cliqueurs... * * @param timestamp de début et de fin de la période visée, $nb_min nombre minimum d'utilisateur ayant une adresse de ce fournisseur. * @return un tableau contenant les chiffres * @author Fabrice PENHOËT **/ static function get_stats_email($time_debut=0,$time_fin=0,$nb_min=2) { global $Bd;global $hub_site; if((isset_connexion(__FILE__,__LINE__)===false)) return false; if(empty($time_fin)) $time_fin=time(); if((empty($time_debut))&&($time_debut!=0)) $time_debut=$time_fin-3600*24; $statistiques=array(); // les fournisseurs d'adresses email des comptes actifs ou non : $get_stats=$Bd->query("SELECT SUBSTRING(email,(LOCATE(\"@\",email))+1) AS ndd,count(*) AS cpt FROM utilisateurs GROUP BY ndd HAVING cpt>$nb_min ORDER BY count(*) DESC;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["liste_emails_total"]=$get_stats->fetchAll(); // pour toutes les stats sur les abonnements, on ne compte pas l'abonnement par défaut aux news du site : $sup_sql=""; if(!empty($hub_site["id"])) $sup_sql="AND id_abonnement NOT IN (SELECT DISTINCT id_abonnement FROM abonnements_hub WHERE id_hub=".$hub_site["id"].")"; // les fournisseurs d'adresses email des comptes ayant encore au moins un abonnement actif : $get_stats=$Bd->query("SELECT SUBSTRING(email,(LOCATE(\"@\",email))+1) AS ndd,count(*) AS cpt FROM utilisateurs WHERE (id_utilisateur in (SELECT distinct auteur_id FROM abonnements WHERE jours_alerte!='' $sup_sql)) GROUP BY ndd HAVING Cpt>$nb_min ORDER BY cpt DESC;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["liste_emails_actifs"]=$get_stats->fetchAll(); // les fournisseurs d'adresses email des cliqueurs sur la période demandée : $get_stats=$Bd->query("SELECT SUBSTRING(email,(LOCATE(\"@\",email))+1) AS ndd,count(*) AS cpt FROM utilisateurs WHERE (id_utilisateur in (SELECT distinct utilisateur_id FROM stat_clics_posts WHERE time_clic>$time_debut AND time_clic<$time_fin)) GROUP BY ndd HAVING Cpt>$nb_min ORDER BY cpt DESC;"); if((test_requete(__FILE__,__LINE__,$get_stats)!==false)) $statistiques["liste_emails_cliqueur"]=$get_stats->fetchAll(); unset($get_stats); if(empty($statistiques)) return false; else return $statistiques; } /** * Méthode fournissant à un administrateur, certaines infos concernant l'utilisateur. * * @param * @return tableaux avec les différentes données * @author Fabrice PENHOËT **/ public function get_infos_admin() { global $Bd; if((isset_connexion(__FILE__,__LINE__)===false)) return false; if(empty($this->id_utilisateur)) { $ajout_journal=new journal_erreurs(array(__FILE__,__LINE__,ERREUR_PARAM_FORMAT)); return false; } $id_utilisateur=$this->id_utilisateur; $infos=array(); //ses abonnements. $get_abos=$Bd->query("SELECT * FROM abonnements WHERE auteur_id=$id_utilisateur;"); if((test_requete(__FILE__,__LINE__,$get_abos)===false)) return false; $abos=$get_abos->fetchAll(PDO::FETCH_ASSOC); if(count($abos)!=0) { $i=0; foreach ($abos as $abo) { $infos["abos"][$i]=$abo; //dernier envoi réussi ? $get_dernier_envoi=$Bd->query("SELECT time_envoi FROM abonnements_mail WHERE abonnement_id=".$abo["id_abonnement"]." ORDER BY time_envoi DESC LIMIT 0,1;"); if((test_requete(__FILE__,__LINE__,$get_dernier_envoi)===false)) return false; $envoi=$get_dernier_envoi->fetchAll(PDO::FETCH_ASSOC); if(!empty($envoi[0]["time_envoi"])) $infos["abos"][$i]["time_dernier_envoi"]=$envoi[0]["time_envoi"]; //liste des hubs concernés par cet abonnement $get_hubs=$Bd->query("SELECT H.nom,H.id_hub FROM hub AS H,abonnements_hub AS A WHERE ((H.id_hub=A.id_hub) AND (A.id_abonnement=".$abo["id_abonnement"]."));"); if((test_requete(__FILE__,__LINE__,$get_hubs)===false)) return false; $hubs=$get_hubs->fetchAll(PDO::FETCH_ASSOC); if(count($hubs)!=0) $infos["abos"][$i]["hubs"]=$hubs; $i++; } } $get_dernier_envoi=null;$get_hubs=null;$get_abos=null; // dernières activités du compte $hier=time()-3600*24; $semaine=time()-3600*24*7; //les 10 dernières sessions enregistrées $get_sessions=$Bd->query("SELECT * FROM utilisateurs_sessions WHERE utilisateur_id=$id_utilisateur AND time_session>$semaine ORDER BY time_session DESC LIMIT 0,10;"); $sessions=$get_sessions->fetchAll(PDO::FETCH_ASSOC); if(count($sessions)!=0) $infos["sessions"]=$sessions; $get_sessions=null; //les pages où il est passé $get_pages=$Bd->query("SELECT page,time_affichage,contexte FROM utilisateurs_affichages WHERE utilisateur_id=$id_utilisateur AND time_affichage>$semaine ORDER BY time_affichage DESC;"); $pages=$get_pages->fetchAll(PDO::FETCH_ASSOC); $nb_pages=count($pages); if(count($pages)!=0) $infos["pages"]=$pages; return $infos; } }