begin process at 2010 03 22 06:56:35
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Class et Objet ( POO )

 > IMAGE BODY GUARD

IMAGE BODY GUARD


 Information sur la source

Note :
Aucune note
Catégorie :Class et Objet ( POO ) Classé sous :poo, protection, image Niveau :Initié Date de création :28/05/2007 Vu / téléchargé :4 042 / 97

Auteur : neigedhiver

Ecrire un message privé
Commentaire sur cette source (11)
Ajouter un commentaire et/ou une note

 Description

Salut,

J'avais envie de faire une petite fonction qui gère l'affichage d'une image.
L'idée était de ne pas pouvoir appeler l'image directement, mais de passer forcément par un script. La raison était simple : permettre de limiter l'affichage au site web auquel elle appartient, gérer des permissions en fonction de critères divers et variés (que je n'ai pas implémentés et qui peuvent l'être grâce à une fonction de callback.

Je sais bien qu'on peut obtenir la même chose avec un fichier .htaccess, mais... là, on peut gérer les droits en fonction d'une session php. Par ailleurs, cette source n'empêche évidemment pas l'utilisateur d'enregistrer l'image sur son disque dur, hein...

Au final, j'ai fait une classe en PHP5, ce qui permet :
- d'avoir une fonction de callback pour gérer les autorisations (adresse IP, ses
- d'étendre la classe pour lui apporter des fonctionnalités en plus (rajouter un copyright, par exemple)
- de récupérer le contenu de l'image sans pour autant l'afficher (sous forme d'une chaine, je sais, c'est crade)
- d'avoir un code propre (c'est peut-être idiot ce que je dis) avec des Exceptions
- d'éviter les doublons dans le code
- de se passer de .htaccess sur Windows...

Le code est documenté au standard phpDoc et je pense assez clair, mais je vous fait quand même un petit topo.

Les méthodes publiques sont :
Setters :
- set_auth_handler : définit la fonction qui gère les autorisations. Si elle n'est pas utilisée, la fonctionnalité est désactivée.
- set_directory : définit le répertoire par défaut où piocher les images (peut être spécifié explicitement pour chaque image, si besoin)
- set_referer_check : même principe que session_referer_check. Il s'agit d'une sous-chaine recherchée dans le referer HTTP. Si elle n'est pas utilisée, la fonctionnalité n'est pas utilisée.
- set_forbidden_image : image à afficher à la place de l'image demandée en cas d'interdiction

Affichage d'image :
- display : affiche l'image en paramètre, se trouvant éventuellement dans le répertoire en paramètre
- get_image : récupère dans une chaine le contenu de l'image et stocke dans la propriété header l'entête à renvoyer (avec header() ) pour un affichage ultérieur
- display_forbidden : affiche l'image d'interdiction

Les messages renvoyés avec les exceptions qui sont levées peuvent être :
- IBG_Error_occured : erreur lors de l'accès au fichier (qui existe pourtant) : n'est pas censée se produire...
- IBG_Not_an_image : le fichier demandé n'est pas une image
- IG_File_not_exists : le fichier demandé n'existe pas
- IG_Forbidden : affichage interdit pour cette image. Ne survient que si aucune image d'interdiction n'est définie.

Voici donc la source :

Source

  • <?php
  • /**
  • * Project : Image Body Guard
  • * File : ImageGuard.class.php
  • *
  • * @author Neige < neige at orphyx dot net >
  • * @copyright &copy; 2007 - Neige
  • * @package Image Body Guard
  • * @version 1.0.0
  • * @licence http://creativecommons.org/licenses/by-nc-sa/2.0/fr/
  • */
  • /**
  • * @package Image Body Guard
  • */
  • class ImageBodyGuard
  • {
  • /**
  • * Callback function to check authorization to display image
  • * @var string
  • */
  • protected $_auth_handler;
  • /**
  • * Substring to check presence in HTTP Referer
  • * @var string
  • */
  • protected $_referer_check;
  • /**
  • * Default directory to use
  • * @var string
  • */
  • protected $_directory;
  • /**
  • * Image to display when display not authorized
  • * Contents : header (mime type) and image contents
  • * @var array
  • */
  • protected $_forbidden_image = array();
  • /**
  • * Header to be sent for image to display
  • * @var string
  • */
  • public $_header;
  • /**
  • * Instance of the object
  • * @var object
  • */
  • protected static $_instance;
  • /**
  • * Returns the unique instance of the class
  • * @return object
  • */
  • public static function getInstance()
  • {
  • if (empty(self::$_instance))
  • {
  • self::$_instance = new ImageGuard();
  • }
  • return self::$_instance;
  • }
  • /**
  • * Setter for $_auth_handler
  • * @param string The function name
  • */
  • public function set_auth_handler($function_name)
  • {
  • if (is_callable($function_name))
  • {
  • $this -> _auth_handler = $function_name;
  • }
  • }
  • /**
  • * Setter for $_referer_check
  • * @param string Substring to search for in HTTP Referer
  • */
  • public function set_referer_check($referer_check)
  • {
  • $this -> _referer_check = (string) $referer_check;
  • }
  • /**
  • * Setter for $_forbidden_image
  • * @param string Path to image
  • */
  • public function set_forbidden_image($image)
  • {
  • $image_size = $this -> _get_image_size($image);
  • $this -> _forbidden_image = array(
  • 'header' => 'Content-Type: ' . $image_size['mime'],
  • 'contents' => file_get_contents($image));
  • }
  • /**
  • * Setter for $_directory
  • * @param string Default directory
  • */
  • /**
  • * Checks if referer is ok
  • * @todo Allow multiple referers to display image
  • */
  • protected function _check_referer()
  • {
  • $referer_ok = TRUE;
  • if (!empty($this -> _referer_check))
  • {
  • if (array_key_exists('HTTP_REFERER', $_SERVER))
  • {
  • $referer = $_SERVER['HTTP_REFERER'];
  • if (stristr($referer, $this -> _referer_check) === FALSE)
  • {
  • $referer_ok = FALSE;
  • }
  • }
  • }
  • return $referer_ok;
  • }
  • /**
  • * Check if display is authorized according
  • * to auth callback function
  • */
  • protected function _check_auth()
  • {
  • if (!empty($this -> _auth_handler) && function_exists($this -> _auth_handler))
  • {
  • if (call_user_func($this -> _auth_handler))
  • {
  • return TRUE;
  • }
  • else
  • {
  • return FALSE;
  • }
  • }
  • else
  • {
  • return TRUE;
  • }
  • }
  • /**
  • * Check general auth
  • */
  • protected function _is_auth()
  • {
  • return ($this -> _check_auth() && $this -> _check_referer());
  • }
  • /**
  • * Display forbidden image if not authorized
  • * @todo Display a message if no default image file
  • */
  • protected function display_forbidden()
  • {
  • if (!empty($this -> _forbidden_image))
  • {
  • header($this -> _forbidden_image['header']);
  • echo $this -> _forbidden_image['contents'];
  • }
  • else
  • {
  • throw new Exception('IBG_Forbidden');
  • }
  • }
  • /**
  • * Display the image
  • * @param string $filename Image filename
  • * @param string $directory Directory where image is located
  • */
  • public function display($file_name, $directory = '')
  • {
  • if ($this -> _is_auth())
  • {
  • $image_content = $this -> get_image($file_name, $directory);
  • header($this -> _header);
  • echo $image_content;
  • }
  • else
  • {
  • $this -> display_forbidden();
  • }
  • }
  • /**
  • * Returns image contents and sets $this -> header
  • * @param string $image_file
  • * @param string $directory
  • */
  • public function get_image($image_file, $directory = '')
  • {
  • $image_size = $this -> _get_image_size($image_file, $directory);
  • $this -> _header = 'Content-Type: ' . $image_size['mime'];
  • $image_content = @file_get_contents($image_file);
  • if ($image_content === FALSE)
  • {
  • throw new Exception('IBG_Error_occured');
  • }
  • else
  • {
  • return $image_content;
  • }
  • }
  • /**
  • * Returns image size, mime type and other data provided
  • * by php native function getimagesize()
  • * @param string $image_file
  • * @param string $directory
  • */
  • protected function _get_image_size($image_file, $directory = '')
  • {
  • if (!empty($this -> directory) && empty($directory))
  • {
  • $directory = $this -> _directory;
  • }
  • if (is_file($directory . $image_file))
  • {
  • if (!$image_size = getimagesize($image_file))
  • {
  • throw new Exception('IBG_Not_an_image');
  • }
  • else
  • {
  • return $image_size;
  • }
  • }
  • else
  • {
  • throw new Exception('IBG_File_not_exists');
  • }
  • }
  • }
  • ?>
  • <?php
  • /*
  • * EXEMPLE D'UTILISATION
  • */
  • $imageBG = ImageBodyGuard::getInstance();
  • $imageBG -> set_auth_handler('auth');
  • $imageBG -> set_referer_check('domaine.tld');
  • $image = $_GET['image'];
  • $imageBG -> display($image);
  • ?>
<?php
/**
 * Project : Image Body Guard
 * File    : ImageGuard.class.php
 *
 * @author Neige < neige at orphyx dot net >
 * @copyright &copy; 2007 - Neige
 * @package Image Body Guard
 * @version 1.0.0
 * @licence http://creativecommons.org/licenses/by-nc-sa/2.0/fr/
 */

/**
 * @package Image Body Guard
 */
class ImageBodyGuard
{
	/**
	 * Callback function to check authorization to display image
	 * @var string
	 */
	protected $_auth_handler;

	/**
	 * Substring to check presence in HTTP Referer
	 * @var string
	 */
	protected $_referer_check;

	/**
	 * Default directory to use
	 * @var string
	 */
	protected $_directory;

	/**
	 * Image to display when display not authorized
	 * Contents : header (mime type) and image contents
	 * @var array
	 */
	protected $_forbidden_image = array();

	/**
	 * Header to be sent for image to display
	 * @var string
	 */
	public $_header;

	/**
	 * Instance of the object
	 * @var object
	 */
	protected static $_instance;

	/**
	 * Returns the unique instance of the class
	 * @return object
	 */
	public static function getInstance()
	{
		if (empty(self::$_instance))
		{
			self::$_instance = new ImageGuard();
		}
		return self::$_instance;
	}

	/**
	 * Setter for $_auth_handler
	 * @param string The function name
	 */
	public function set_auth_handler($function_name)
	{
		if (is_callable($function_name))
		{
			$this -> _auth_handler = $function_name;
		}
	}

	/**
	 * Setter for $_referer_check
	 * @param string Substring to search for in HTTP Referer
	 */
	public function set_referer_check($referer_check)
	{
		$this -> _referer_check = (string) $referer_check;
	}

	/**
	 * Setter for $_forbidden_image
	 * @param string Path to image
	 */
	public function set_forbidden_image($image)
	{
		$image_size = $this -> _get_image_size($image);
		$this -> _forbidden_image = array(
			'header' => 'Content-Type: ' . $image_size['mime'],
			'contents' => file_get_contents($image));
	}

	/**
	 * Setter for $_directory
	 * @param string Default directory
	 */

	/**
	 * Checks if referer is ok
	 * @todo Allow multiple referers to display image
	 */
	protected function _check_referer()
	{
		$referer_ok = TRUE;
		if (!empty($this -> _referer_check))
		{
			if (array_key_exists('HTTP_REFERER', $_SERVER))
			{
				$referer = $_SERVER['HTTP_REFERER'];
				if (stristr($referer, $this -> _referer_check) === FALSE)
				{
					$referer_ok = FALSE;
				}
			}
		}
		return $referer_ok;
	}

	/**
	 * Check if display is authorized according
	 * to auth callback function
	 */
	protected function _check_auth()
	{
		if (!empty($this -> _auth_handler) && function_exists($this -> _auth_handler))
		{
			if (call_user_func($this -> _auth_handler))
			{
				return TRUE;
			}
			else
			{
				return FALSE;
			}
		}
		else
		{
			return TRUE;
		}
	}

	/**
	 * Check general auth
	 */
	protected function _is_auth()
	{
		return ($this -> _check_auth() && $this -> _check_referer());
	}

	/**
	 * Display forbidden image if not authorized
	 * @todo Display a message if no default image file
	 */
	protected function display_forbidden()
	{
		if (!empty($this -> _forbidden_image))
		{
			header($this -> _forbidden_image['header']);
			echo $this -> _forbidden_image['contents'];
		}
		else
		{
			throw new Exception('IBG_Forbidden');
		}
	}

	/**
	 * Display the image
	 * @param string $filename Image filename
	 * @param string $directory Directory where image is located
	 */
	public function display($file_name, $directory = '')
	{
		if ($this -> _is_auth())
		{
			$image_content = $this -> get_image($file_name, $directory);
			header($this -> _header);
			echo $image_content;
		}
		else
		{
			$this -> display_forbidden();
		}
	}

	/**
	 * Returns image contents and sets $this -> header
	 * @param string $image_file
	 * @param string $directory
	 */
	public function get_image($image_file, $directory = '')
	{
		$image_size = $this -> _get_image_size($image_file, $directory);
		$this -> _header = 'Content-Type: ' . $image_size['mime'];
		$image_content = @file_get_contents($image_file);
		if ($image_content === FALSE)
		{
			throw new Exception('IBG_Error_occured');
		}
		else
		{
			return $image_content;
		}
	}

	/**
	 * Returns image size, mime type and other data provided
	 * by php native function getimagesize()
	 * @param string $image_file
	 * @param string $directory
	 */
	protected function _get_image_size($image_file, $directory = '')
	{
		if (!empty($this -> directory) && empty($directory))
		{
			$directory = $this -> _directory;
		}
		if (is_file($directory . $image_file))
		{
			if (!$image_size = getimagesize($image_file))
			{
				throw new Exception('IBG_Not_an_image');
			}
			else
			{
				return $image_size;
			}
		}
		else
		{
			throw new Exception('IBG_File_not_exists');
		}
	}
}
?>

<?php

/*
 * EXEMPLE D'UTILISATION
 */

$imageBG = ImageBodyGuard::getInstance();
$imageBG -> set_auth_handler('auth');
$imageBG -> set_referer_check('domaine.tld');

$image = $_GET['image'];

$imageBG -> display($image);

?>

 Conclusion

J'ai fait ça sans trop me poser de question sur l'utilité ou les performances.
Question utilité, j'en ai déjà parlé un peu... J'attends vos avis éclairés et avisés sur la chose.
Concernant les performances, il est évident que traiter l'affichage d'une image consomme des ressources... J'ai essayé de ne pas trop abuser. J'attends aussi vos commentaires sur le sujet.

En ce qui concerne la sécurité, je ne sais pas trop ce que ça vaut non plus... Comme montré dans l'exemple, une utilisation typique est $image = $_GET['image'];
Faut-il faire ou non un traitement sur la variable GET malgré les tests effectués dans le code ? J'ai pas trop de recul à ce niveau là, donc là encore, tout commentaire est le bienvenu.

Evolution que j'envisage : possibilité d'autoriser plusieurs Referers

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Sources du même auteur

Source avec Zip [PHP5] LIGHTEMPLATE - MOTEUR DE TEMPLATES ULTRA-LÉGER
Source avec Zip [PHP5.1] LISTING D'UN RÉPERTOIRE AVEC FILTRES
[PHP5.1] STRING ITERATOR
Source avec Zip [PHP5] ORPHYX PLUGIN SYSTEM
Source avec Zip [PHP5] GESTIONNAIRE DE CONFIGURATIONS

 Sources de la même categorie

Source avec Zip CLASSE TABLE HTML DYNAMIQUE par LDDL
Source avec Zip GÉNÉRATEUR DE COUCHE DAO POUR SITE WEB À PARTIR D'UNE BASE D... par alexfool
Source avec Zip [PHP5.2] CLASSE PDO par hornetbzz
Source avec Zip POO - LOGGING PACKAGE par Waredan
POO - OBJECT CLASS par Waredan

 Sources en rapport avec celle ci

Source avec Zip [PHP5.2] CLASSE PDO par hornetbzz
Source avec Zip FUNCTION IMAGE SIMPLE ET ARRAY par astro53
Source avec Zip CLASSE DE MINIATURISATION D'IMAGE par Palleas_44
FILIGRANE D'UNE IMAGE par f0x
Source avec Zip CLASS IMAGE FLOODÉ ENTIÈREMENT PARAMÈTRABLE par babid

Commentaires et avis

Commentaire de coucou747 le 29/05/2007 02:38:22

en fait, je ne vois pas vraiment l'interret de passer par une classe pour ca... tu fais une verif d'auth par un pointeur sur fonction, ca reviendrait au meme que de le faire directement avec un truc genre

if (auth() && refer()){
header(...);
echo file_get_contents(..);
}

sinon, tu pourrais proposer un header sans appeller getimagesize et autre car c'est pas toujours obligatoire

Commentaire de neigedhiver le 29/05/2007 08:26:46

Ben ouais, y'a peut-être pas d'intérêt...
Faut encore que j'y réfléchisse...

"sinon, tu pourrais proposer un header sans appeller getimagesize et autre car c'est pas toujours obligatoire"
=> Pas compris...

Commentaire de coucou747 le 29/05/2007 15:47:25

display affiche le header que lui donne getimage, or si moi j'ai que des .jpg, bah j'ai pas besoin de ca...

Commentaire de neigedhiver le 29/05/2007 17:03:58

Certes... Je n'avais pas vu les choses comme ça... Ben dans ce cas, j'utilise une autre méthode pour récupérer le header.

Sinon, j'ai pas réussi à déterminer si la classe était vraiment utile... Ah bravo...

Commentaire de malalam le 29/05/2007 18:33:49 administrateur CS

Hello,

c'est pas mal codé, mais j'ai, moi aussi, du mal à me décider sur l'intérêt réel de ton code, lol.
Je n'arrive pas à trouver dans quel cas je pourrais avoir besoin d'une telle "protection". Et si, dans un tel cas, je ne passerais en effet pas par un simple if ().
Mais ça reste intéressant quand même...sur le fond. Ca peut amener a des réflexions pour approfondir ça, je pense. Bon, y a des bémols hein : le HTTP_REFERER...par exemple...si il n'y est pas, par défaut, c'est ok. Donc, suffit de de le désactiver ou de le masquer (c'est faisable). IE par exemple, bien souvent, par défaut, le masque...

Commentaire de coucou747 le 29/05/2007 18:46:59

tu fais un site pour adultes, et seuls ceux qui ont payes accedent aux images, ca peut etre utile.... mais c'est clair que cette classe est disproportionee comparee a ce qu'elle fait...

Commentaire de neigedhiver le 29/05/2007 22:56:22

@malalam
"c'est pas mal codé,"
=> Merci. Venant de ta part, ça fait plaisir.

"Bon, y a des bémols hein : le HTTP_REFERER...par exemple...si il n'y est pas, par défaut, c'est ok."
=> Tiens oui, c'est idiot... Si le referer est nécessaire, ça ne devrait pas se comporter comme ça...

@coucou747
"mais c'est clair que cette classe est disproportionee comparee a ce qu'elle fait..."
Ben ouais, plus j'y pense, et plus c'est ce que je me dis.

En même temps, faut replacer les choses dans mon contexte actuel... J'ai récemment fait l'acquisition d'un bouquin sur PHP5 (PHP5 - Best practices chez Eyrolles) et du coup, je suis un peu à fond dans la POO, je vois des classes partout...
Quand j'ai pensé à cette fonctionnalité, j'ai commencé par une fonction et, assez naturellement, j'en suis venu à faire une classe, pour regrouper des fonctions au même endroit, sans me poser la question : "est-ce nécessaire ou bien est-ce démesuré" ?

Manifestement, ce n'était pas nécessaire.

Ca m'aura au moins permis de vérifier que je code pas trop dégueulasse, si j'en crois malalam...

On va dire que c'était de l'entrainement...

En tout cas merci pour vos commentaires, je vais peut-être réécrire tout ça avec de simples fonctions toutes bêtes...

Commentaire de coucou747 le 29/05/2007 23:17:31

eh, j'ai pas dit que c'etait crade... seulement voila, tu mets 150 lignes pour faire un truc reutilisable dans un seul cas... celui ou 5 lignes suffisent... c'est bien code, mais selon moi, pas utile

Commentaire de neigedhiver le 29/05/2007 23:29:49

Ah mais j'ai pas dit que t'avais dit que... C'était plutôt une réflexion à voix haute, pour moi... mais à voix haute...

Non mais de faire des trucs qui servent à rien, c'est au moins utile pour moi : je m'entraine, j'apprends à me poser les bonnes questions (est-ce que c'est vraiment la peine, etc).

Donc merci pour les commentaires, encore une fois, ça me permet d'y voir plus clair.

Commentaire de bugs74 le 04/06/2007 11:05:19

il me semble que qu'une protection par htaccess fait ca très bien.
google : hotlinking htaccess

Commentaire de neigedhiver le 04/06/2007 11:07:01

Ca fait plaisir de voir qu'on lit mes commentaires :

"Je sais bien qu'on peut obtenir la même chose avec un fichier .htaccess, mais... là, on peut gérer les droits en fonction d'une session php."

Donc merci de la précision inutile...

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Protection d' image original [ par overbrave ] Salut Dieu du code,Je sais qu'il existe toute sorte de script ou fonction permettant de bloquer le clique droit, etc ...Ces fonction sont senc&#233; n réécriture d'un script en POO, comment faire? [ par craso ] Bonjour,j'ai développé cette petite application http://pipcorp.free.fr/Il s'agit d'une image clicable, le personnage centrale se positionne a l'endroi protection données envoi mail [ par eva4 ] hello vous tous. J'ai un petit problème. lors d'envoie de messages (avec photo dans le corp de texte) lorsqu'on fait un clic droit sur l'image, il ap Comment ca marche cette petite bete? [ par craso ] bonjour,en surfant, je suis tombé sur le site http://www.phpied.com/image-fun/ .Je souhaite qu'on m'explique comment trnsformer une image comme sur le Aide sur image anti-spam... [ par Tanaka56 ] Bonjour. J'ai intégré sur une page l'image anti-spam du lien :http://www.phpcs.com/codes/IMAGE-ANTI-SPAM_38969.aspxCependant, je rencontre un problème balise select [ par pyb54 ] Bonjour, j'ai une balise select qui retourne une liste de ville, le select en lui même est une image crée via photoshop, mais si je clique dessus j'o Texte ou image aléatoire [ par ndmsp ] Bonsoir à tous. Je cherche un script (php ?), qui me permettrais d'afficher aléatoirement une image ou un texte... Connaissez vous une méthode ??? Bie Problème avec la fonction preg_replace [ par Sub_Mat ] Bonjour à tous, [b]Voici mon problème :[/b] Je récupère de ma base de donnée une donnée commentaire. Dans ce commentaire, il y a des images qui sont Affichage d'image après choix dans liste déroulante [ par kentinn07 ] Bonsoir je suis en train de tenter d'afficher les images contenues dans un dossier dans une liste déroulante puis ensuite d'afficher l'image choisie.


Nos sponsors


Sondage...

CalendriCode

Mars 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728
293031    

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,655 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales