ACCES INTERZIS | blog de programare si securitate IT


UPDATED ARTICLE

Prin ce se caracterizeaza acest formular de contact?

  • toate datele sunt validate server-side
  • protectie antispam 100% datorita sistemului CAPTCHA integrat in formular
  • fiecare mesaj de eroare este personalizat pentru fiecare eroare in parte si apare deasupra campului unde a fost detectata eroarea
  • campul unde exista o eroare este evidentiat
  • datele completate raman in campurile formularului atunci cand se detecteaza o eroare
  • skin creat EXCLUSIV din CSS
  • formularul poate fi usor de integrat intr-un website
  • skinul emailului trimis poate fi formatat prin folosirea tagurilor HTML si a regulilor CSS aplicate inline
  • in subsolul emailului trimis exista cateva informatii despre expeditor

<?php
/*
Titlu: Cum fac un formular de contact?
Autor: Marian Barbu aka AccesInterzis
Website: http://www.accesinterzis.ro
2010 (c) Toate drepturile rezervate
*/

//-----creez o sesiune pe server pentru a salva in ea codul generat aleatoriu de sistemul CAPTCHA
#1
session_start();

//-----infasor in strip_tags() si htmlentities() URL-urile obtinute dinamic si http_user_agent-ul ca sa ma asigur ca nu contin cod malitios
#2
$php_self = htmlentities(strip_tags($_SERVER['PHP_SELF']), ENT_QUOTES, 'utf-8');
$referer = (isset($_SERVER['HTTP_REFERER'])) ? htmlentities(strip_tags($_SERVER['HTTP_REFERER']), ENT_QUOTES, 'utf-8') : NULL;
$browser_os = htmlentities(strip_tags($_SERVER['HTTP_USER_AGENT']), ENT_QUOTES, 'utf-8');

//-----specific EXACT cu ce campuri se va lucra
#3
$required_fields = array('name', 'phone_number', 'email', 'message', 'security_code', 'send');
$sent_fields = array_keys($_POST);

//------scriptul PHP se executa doar daca cererea a fost facuta de pe aceeasi pagina pe care se afla formularul si doar daca toate campurile formularului au fos trimise
#4
if ($referer == 'http://'.$_SERVER['HTTP_HOST'].$php_self && $required_fields == $sent_fields) {
	//-----initializez array-ul in care voi stoca mesajele de eroare si array-ul in care voi pasa datele din $_POST dupa ce le filtrez
	#4.1
	$errors = array();
	$post = array();

	#4.2
	//Starting data validation
	if (empty($_POST['name'])) {
		$errors['name'] = 'You forgot to enter the <strong>name</strong>.';
	} else {
		$post['name'] = trim($_POST['name']);

		if (ini_get('magic_quotes_gpc')) {
			$post['name'] = stripslashes($post['name']);
		}

		if (strlen($post['name']) < 3) {
			$errors['name'] = 'The <strong>name</strong> is too short.';
		} else {
			if (strlen($post['name']) > 30) {
				$errors['name'] = 'The <strong>name</strong> is too long.';
			} else {
				if (!preg_match('/^[a-z0-9][a-z0-9_ ]*[a-z0-9]$/i', $post['name'])) {
					$errors['name'] = 'The <strong>name</strong> isn\'t valid.';
				}
			}
		}
	}

	if (empty($_POST['phone_number'])) {
		$errors['phone_number'] = 'You forgot to enter the <strong>phone number</strong>.';
	} else {
		$post['phone_number'] = trim($_POST['phone_number']);

		if (ini_get('magic_quotes_gpc')) {
			$post['phone_number'] = stripslashes($post['phone_number']);
		}

		if (strlen($post['phone_number']) < 3) {
			$errors['phone_number'] = 'The <strong>phone number</strong> is too short.';
		} else {
			if (strlen($post['phone_number']) > 15) {
				$errors['phone_number'] = 'The <strong>phone number</strong> is too long.';
			} else {
				if (!preg_match('/^[0-9+][0-9.+ ]*[0-9]$/', $post['phone_number'])) {
					$errors['phone_number'] = 'The <strong>phone number</strong> isn\'t valid.';
				}
			}
		}
	}

	if (empty($_POST['email'])) {
		$errors['email'] = 'You forgot to enter the <strong>email address</strong>.';
	} else {
		$post['email'] = trim($_POST['email']);

		if (ini_get('magic_quotes_gpc')) {
			$post['email'] = stripslashes($post['email']);
		}

		if (strlen($post['email']) < 3) {
			$errors['email'] = 'The <strong>email address</strong> is too short.';
		} else {
			if (strlen($post['email']) > 30) {
				$errors['email'] = 'The <strong>email address</strong> is too long.';
			} else {
				if (!preg_match('/^[a-z0-9][a-z0-9_.]+@[a-z0-9-.]+\.[a-z]{2,4}$/i', $post['email'])) {
					$errors['email'] = 'The <strong>email address</strong> isn\'t valid.';
				}
			}
		}
	}

	if (empty($_POST['message'])) {
		$errors['message'] = 'You forgot to enter the <strong>message</strong>.';
	} else {
		$post['message'] = trim($_POST['message']);

		if (ini_get('magic_quotes_gpc')) {
			$post['message'] = stripslashes($post['message']);
		}

		if (strlen($post['message']) < 3) {
			$errors['message'] = 'The <strong>message</strong> is too short.';
		} else {
			if (strlen($post['message']) > 100000) {
				$errors['message'] = 'The <strong>message</strong> is too long.';
			}
		}
	}

	if (empty($_POST['security_code'])) {
		$errors['security_code'] = 'You forgot to enter the <strong>security code</strong>.';
	} else {
		$post['security_code'] = trim($_POST['security_code']);

		if (ini_get('magic_quotes_gpc')) {
			$post['security_code'] = stripslashes($post['security_code']);
		}

		if (strlen($post['security_code']) < 3) {
			$errors['security_code'] = 'The <strong>security code</strong> is too short.';
		} else {
			if (strlen($post['security_code']) > 10) {
				$errors['security_code'] = 'The <strong>security code</strong> is too long.';
			} else {
				if (!preg_match('/^[a-z0-9]*$/i', $post['security_code'])) {
					$errors['security_code'] = 'The <strong>security code</strong> isn\'t valid.';
				} else {
					if ($_SESSION['security_code'] != $_POST['security_code']) {
						$errors['security_code'] = 'The <strong>security code</strong> entered is wrong.';
					}
				}
			}
		}
	}
	//Ending data validation

    //------daca nu exista niciun fel de erori trimit emailul
	#4.3
	if(count($errors) == 0) {
		//-----infasor datele in htmlentities() si nl2br() deoarece urmeaza sa le trimit
		#4.3.1
		foreach ($post as $k => $v) {
			$post[$k] = nl2br(htmlentities($v, ENT_QUOTES, 'utf-8'));
		}

        #4.3.2
        $to      = 'whovisitedme@gmail.com';
        $subject = substr($post['message'], 0, 20).'...';
        $body    = 'This message is received from http://'.$_SERVER['HTTP_HOST'].$php_self.'<br /><br />
                    <strong>Name</strong>: '.$post['name'].'<br />
                    <strong>Phone number</strong>: '.$post['phone_number'].'<br />
                    <strong>Email address</strong>: '.$post['email'].'<br />
                    <strong>Mesagge</strong>: '.$post['message'].'<br /><br />
                    <strong style="color:#c00;">Infos about sender:</strong><br />
                    <strong>IP address</strong>: '.$_SERVER['REMOTE_ADDR'].'<br />
                    <strong>browser and operating system</strong>: '.$browser_os.'<br />
                    <strong>dispatch hour</strong>: '.date("l, F j, Y, H:i:s");
        $headers  = "From: ".$post['email']."\r\n";

		//-----ma asigur ca pot formata emailul cu taguri HTML si reguli CSS aplicate inline
        #4.3.3
        $headers .= 'MIME-Version: 1.0'."\r\n";
        $headers .= 'Content-type: text/html; charset=utf-8' . "\r\n";

		//------daca emailul a fost intr-adevar trimis se va afisa pe monitor un mesaj de confirmare
        #4.3.4
        if (mail($to, $subject, $body, $headers)) {
			$confirmation = 'Your message was succesfully sent. We will get in touch with you as soon as possible.';
        } else {
			$confirmation = 'Something is wrong with the server. Your message wasn\'t sent.';
        }

		$confirmation .= ' <a href="http://'.$_SERVER['HTTP_HOST'].$php_self.'" title="Back" id="back">Back to contact form</a>';

		#4.3.5
		$display = 'style="display:none;"';
    }

	//-----infasor datele in htmlentities() deoarece urmeaza sa le afisez in formular
	#4.4
	foreach ($post as $k => $v) {
		$post[$k] = htmlentities($v, ENT_QUOTES, 'utf-8');
	}
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>How do I make a contact form?</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="description" content="How do I make a contact form?" />
<meta name="keywords" content="contact,form,php,script,send,email" />
<meta name="abstract" content="How do I make a contact form?" />
<meta name="author" content="AccesInterzis" />
<meta name="copyright" content="AccesInterzis" />
<meta name="robots" content="index,follow" />
<meta name="revisit-after" content="7 days" />

<style type="text/css">
* {
	margin:0;
	padding:0;
	outline:none;
}

html {
	color:black;
	background-color:white;
	font: normal normal normal 12px  Verdana;
	/*font-style font-variant font-weight font-size font-family*/
}

/*INCEPUT - LINIILE CSS CARE CREEAZA SKINUL FORMULARULUI DE CONTACT*/

div#contactf {
	width:530px;
	margin:0px auto;
}

div#contactf h1 {
	color:black;
	font: normal normal normal 24px  Verdana;
	/*font-style font-variant font-weight font-size font-family*/
	padding-bottom:5px;
}

div#contactf div {
	margin:0 0 5px 0;
}

div#contactf label {
	width:115px;
	float:left;
}

div#contactf label span {
	color:#c00;
}

div#contactf input {
	width:200px;
}

div#contactf textarea {
	width:400px;
	height:150px;
}

div#contactf input, div#contactf textarea {
	border:1px #ccc solid;
}

div#contactf input:hover, div#contactf textarea:hover {
	border:1px #666 solid;
}

div#contactf input#send {
	width:auto;
	color:#FFF;
	background-color:#333;
	border:1px #000 solid !important;
	cursor:pointer;
}

div#contactf input#send:hover {
	color:#333;
	background-color:#fff;
	border:1px #333 solid;
}

/*Inceput - stilurile erorilor*/
div#contactf p {
	color:#c00;
	font-size:10px;
	padding:0 0 0 115px;
	text-align:left;
}

div#contactf div#name_field label,
div#contactf div#email_field label,
div#contactf div#phone_number_field label,
div#contactf div#message_field label,
div#contactf div#security_code_field label {
	color:#c00;
}

div#contactf div#name_field input,
div#contactf div#email_field input,
div#contactf div#phone_number_field input,
div#contactf div#message_field textarea,
div#contactf div#security_code_field input {
	border:1px #c00 solid;
	color:#c00;
}

div#contactf div#name_field input:hover,
div#contactf div#email_field input:hover,
div#contactf div#phone_number_field input:hover,
div#contactf div#message_field textarea:hover,
div#contactf div#security_code_field input:hover {
	border:1px #c00 solid;
}

div#contactf a#back {
	color:#900;
	font-weight:bold;
	text-decoration:underline;
}
/*Sfarsit - stilurile erorilor*/

/*SFARSIT - LINIILE CSS CARE CREEAZA SKINUL FORMULARULUI DE CONTACT*/
</style>
</head>

<body>
<div id="contactf">
	<h1>
        <label>&nbsp;</label>
        Contact us
    </h1>

    <?php if (isset($confirmation)) echo '<p>'.$confirmation.'</p>'; ?>

	<form action="<?php echo 'http://'.$_SERVER['HTTP_HOST'].$php_self; ?>" method="post" <?php if (isset($display)) echo $display; ?>>
		<?php echo (isset($errors['name'])) ? '<p>'.$errors['name'].'</p><div id="name_field">' : '<div>' ; ?>
			<label for="name">Name<span>*</span>:</label>
			<input name="name" type="text" id="name" value="<?php if (isset($post['name'])) echo $post['name']; ?>" />
		</div>

		<?php echo (isset($errors['phone_number'])) ? '<p>'.$errors['phone_number'].'</p><div id="phone_number_field">' : '<div>' ; ?>
			<label for="phone_number">Phone number<span>*</span>:</label>
			<input name="phone_number" type="text" id="phone_number" value="<?php if (isset($post['phone_number'])) echo $post['phone_number']; ?>" />
		</div>

		<?php echo (isset($errors['email'])) ? '<p>'.$errors['email'].'</p><div id="email_field">' : '<div>' ; ?>
			<label for="email">Email<span>*</span>:</label>
			<input name="email" type="text" id="email" value="<?php if (isset($post['email'])) echo $post['email']; ?>" />
		</div>

		<?php echo (isset($errors['message'])) ? '<p>'.$errors['message'].'</p><div id="message_field">' : '<div>' ; ?>
			<label for="message">Your message<span>*</span>:</label>
			<textarea name="message" rows="1" cols="1" id="message"><?php if (isset($post['message'])) echo $post['message']; ?></textarea>
		</div>

		<p>
			<img src="includes/captchaimage.inc.php?width=120&height=40&characters=5" />
		</p>

		<?php echo (isset($errors['security_code'])) ? '<p>'.$errors['security_code'].'</p><div id="security_code_field">' : '<div>' ; ?>
			<label for="security_code">Are you human?<span>*</span></label>
			<input id="security_code" name="security_code" type="text" />
		</div>

		<div>
			<label> &nbsp; </label>
			<input name="send" type="submit" id="send" value="send" />
		</div>
	</form>
</div>
</body>
</html>

Pe langa fisierul principal de mai sus mai avem nevoie de fisierul care genereaza imaginea cu codul de securitate si anume captchaimage.inc.php care se gaseste in folderul “includes” si de fontul folosit pentru generarea codului de securitate si anume monofont.ttf care trebuie sa se afle in acelasi folder cu captchaimage.inc.php.

<?php
/*
File: CaptchaSecurityImages.php
Author: Simon Jarvis
Copyright: 2006 Simon Jarvis
Date: 03/08/06
Updated: 07/02/07
Requirements: PHP 4/5 with GD and FreeType libraries
Link: http://www.white-hat-web-design.co.uk/articles/php-captcha.php
*/

session_start();

class CaptchaSecurityImages {

	var $font = 'monofont.ttf';

	function generateCode($characters) {
		/* list all possible characters, similar looking characters and vowels have been removed */
		$possible = '23456789bcdfghjkmnpqrstvwxyz';
		$code = '';
		$i = 0;
		while ($i < $characters) {
			$code .= substr($possible, mt_rand(0, strlen($possible)-1), 1);
			$i++;
		}
		return $code;
	}

	function CaptchaSecurityImages($width='120',$height='40',$characters='6') {
		$code = $this->generateCode($characters);
		/* font size will be 75% of the image height */
		$font_size = $height * 0.75;
		$image = @imagecreate($width, $height) or die('Cannot initialize new GD image stream');
		/* set the colours */
		$background_color = imagecolorallocate($image, 255, 255, 255);
		$text_color = imagecolorallocate($image, 51, 51, 51);
		$noise_color = imagecolorallocate($image, 110, 110, 110);
		/* generate random dots in background */
		for( $i=0; $i<($width*$height)/10; $i++ ) {
			imagefilledellipse($image, mt_rand(0,$width), mt_rand(0,$height), 1, 1, $noise_color);
		}
		/* generate random lines in background */
		for( $i=0; $i<($width*$height)/150; $i++ ) {
			imageline($image, mt_rand(0,$width), mt_rand(0,$height), mt_rand(0,$width), mt_rand(0,$height), $noise_color);
		}
		/* create textbox and add text */
		$textbox = imagettfbbox($font_size, 0, $this->font, $code) or die('Error in imagettfbbox function');
		$x = ($width - $textbox[4])/2;
		$y = ($height - $textbox[5])/2;
		imagettftext($image, $font_size, 0, $x, $y, $text_color, $this->font , $code) or die('Error in imagettftext function');
		/* output captcha image to browser */
		header('Content-Type: image/jpeg');
		imagejpeg($image);
		imagedestroy($image);
		$_SESSION['security_code'] = $code;
	}

}

$width = isset($_GET['width']) ? $_GET['width'] : '120';
$height = isset($_GET['height']) ? $_GET['height'] : '40';
$characters = isset($_GET['characters']) && $_GET['characters'] > 1 ? $_GET['characters'] : '6';

$captcha = new CaptchaSecurityImages($width,$height,$characters);

?>

Pentru un mai bun managment al codului este indicat ca scriptul PHP de deasupra DOCTYPE-ului, care valideaza datele introduse in formular si trimite emailul, sa se bage intr-un fisier include si sa fie apelat prin functia PHP include().

<?php @include('includes/send_email.inc.php'); ?>

De asemenea, este indicat ca liniile CSS, care creeaza skinul formularului de contact, din sectiunea <head> </head> sa fie bagate intr-un fisier CSS extern si apelate cu tagul HTML <link />.

<link href="css/contact_form_design.css" type="text/css" rel="stylesheet" media="all" />

Post to Twitter Publica acest articol pe Twitter

Articole asemanatoare:

Publicat de: admin
Ultima modificare: 17, 2010, 13:14

Etichete
Etichete: , ,
Categorii: programare


 

Comentarii lasate » (2 Total)

 
  1. x6IT32 says:

    Frumos tutorialul, mi-a fost de folos.

    Apropo, frumos blog, mult succes!

  2. admin says:

    O sa mai lucrez la acest tutorial. Vreau sa fac mai multe versiuni de formular de contact. Unele mai complexe, altele mai basic. Eventual niste js-uri implemetate ca sa fie mai user-friendly.

    Dar cel mai mult ma intereseaza partea de PHP. Vreau sa optimizez codul PHP cat mai mult.

Lasa un comentariu

XHTML: Poti folosi urmatoarele taguri HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>