72. Projet - Ajax

L'objectif de ce projet est simple, il s'agit de concevoir un petit chat en Ajax entre un serveur PHP et MySQL et des clients HTML purs.

Voici mon travail réalisé.

72.1. Le code Serveur

<?php
	header("Access-Control-Allow-Origin: *");

	$link = mysql_connect("127.0.0.1", "root", "root")
		or die("mysql_connect error 0 : [" . mysql_error() . "]");
	mysql_select_db('ajax_projet', $link);
	
	switch ($_GET['action']) {
		case 'checkLogin' :
			$query = "SELECT COUNT(*) "
					."FROM users "
					."WHERE name like '".trim($_GET['login'])."';";
			$checkLogin = mysql_query($query)
				or die("mysql_query error 1 : [" . mysql_error() . "]");
				
			echo (mysql_result($checkLogin, 0) == 0) ? "true" : "false";
			break;

		case 'addLogin' :
			$query = "INSERT INTO users(name) VALUES ('".trim($_GET['login'])."');";
			mysql_query($query)	 
				or die("mysql_query error 2 : [" . mysql_error() . "]");
				
			$query = "INSERT INTO messages(name) VALUES ('".trim($_GET['login'])."');";
			mysql_query($query)	 
				or die("mysql_query error 3 : [" . mysql_error() . "]");
				
			echo "true";
			break;

		case 'loadMessages' :
			// Récupération dernier(s) message(s).
			$query = "SELECT last_messages "
					."FROM messages "
					."WHERE name like '".$_GET['login']."';";

			$loadMessages = mysql_query($query)
				or die("mysql_query error 4 : [" . mysql_error() . "]");
			
			// Réinitialisation du champ "last_messages".
			$query = "UPDATE messages "
					."SET last_messages = '' "
					."WHERE name like '".$_GET['login']."';";
			mysql_query($query)	 
				or die("mysql_query error 5 : [" . mysql_error() . "]");

			// Mise à jour champ "last_refresh".
			$query = "UPDATE users "
					."SET last_refresh = CURRENT_TIME() "
					."WHERE name like '".$_GET['login']."';";
			mysql_query($query)	 
				or die("mysql_query error 6 : [" . mysql_error() . "]");
			
			echo mysql_result($loadMessages, 0);
			break;
			
		case 'sendMessage' :
			// Ajout du message pour chaque utilisateur.
			$query = "UPDATE messages "
					."SET last_messages = CONCAT(last_messages, '\n".$_GET['login']." : ".trim(rawurldecode($_GET['message']))."');";
			mysql_query($query)	 
				or die("mysql_query error 7 : [" . mysql_error() . "]");
			break;
			
		case "refreshMessages" :
			// Récupération des derniers messages.
			$query = "SELECT last_messages "
					."FROM messages "
					."WHERE name like '".$_GET['login']."';";
			$refreshMessages = mysql_query($query)
				or die("mysql_query error 8 : [" . mysql_error() . "]");

			// Mise à jour champ "last_refresh".
			$query = "UPDATE users "
					."SET last_refresh = CURRENT_TIME() "
					."WHERE name like '".$_GET['login']."';";
			mysql_query($query)	 
				or die("mysql_query error 9 : [" . mysql_error() . "]");
				
			echo mysql_result($refreshMessages, 0);
			break;
			
		case "getOnlineGuys" :
			$query = "SELECT name "
					."FROM users "
					."WHERE TIME_TO_SEC(CURRENT_TIME()) - TIME_TO_SEC(last_refresh) < 10;";
			$getOnlineGuys = mysql_query($query)
				or die("mysql_query error 10 : [" . mysql_error() . "]");
				
			while ($row = mysql_fetch_row($getOnlineGuys)) {
				echo $row[0].";";
			}
			break;

		default:
			die("Unknown function : [" . $_GET['action'] . "]");
			break;
	}
	mysql_close($link);
?>

Le script sql d'initialisation :

DROP DATABASE IF EXISTS ajax_projet;
CREATE DATABASE ajax_projet;
CONNECT ajax_projet;

DROP TABLE IF EXISTS users;
CREATE TABLE users (
        name VARCHAR(15) NOT NULL,
        last_refresh TIME,
        CONSTRAINT uniq_users_name UNIQUE(name)
);

DROP TABLE IF EXISTS messages;
CREATE TABLE messages (
        name VARCHAR(15) NOT NULL,
        last_messages VARCHAR(100),
        CONSTRAINT uniq_messages_name UNIQUE(name)
);

72.2. Le codes Clients

72.2.1. La page de connection

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
    <head>
        <title>login.html</title>
        <style>
            #isAvailable.true {
                width: 15px;
                height: 15px;
                background-color: green;
            }
            #isAvailable.false {
                width: 15px;
                height: 15px;
                background-color: red;
            }
        </style>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <script type="text/javascript">
 
            function getXMLHttpRequest() {
                if (window.XMLHttpRequest)
                    return new XMLHttpRequest();
                else if (window.ActiveXObject)
                    new ActiveXObject("Microsoft.XMLHTTP");
                else
                    return null;
            }
            
			/*
			 * Vérifier l'existence du login dans la base de données
			 * @param login
			 */
            function checkLogin(login) {
                var url = "http://192.168.5.53/ajax_projet/functions.php?action=checkLogin&login=" + login;
                var xhr = getXMLHttpRequest();
 
                xhr.onreadystatechange = function() {
                    if(xhr.readyState  == 4) {
                        if(xhr.status  == 200) {
                            document.getElementById("isAvailable").className = xhr.responseText;
							if (xhr.responseText == "true")
								document.getElementsByName("connect")[0].disabled = false;
							else
								document.getElementsByName("connect")[0].disabled = true;
                        } else {
                            alert('Error code : ' + xhr.status); 
                        }
                    }
                }
                xhr.open("GET", url, true);
                xhr.send();
            }
			
			/*
			 * Ajouter le login dans la base de données.
			 * @param login
			 */
			function addLogin(login) {
				var url = "http://192.168.5.53/ajax_projet/functions.php?action=addLogin&login=" + login;
				var xhr = getXMLHttpRequest();
				
                xhr.onreadystatechange = function() {
                    if(xhr.readyState  == 4) {
                        if(xhr.status  == 200) {
							if (xhr.responseText == "true")
								// Redirection vers la page de chat en cas de succès.
								document.location.href = "chat.html?login=" + login;
							else
								alert("Chat connexion error !");
                        } else {
                            alert("Error code : " + xhr.status); 
                        }
                    }
                }
                xhr.open("GET", url, true);
                xhr.send();
			}
 
        </script>
    </head>
    <body>
       <form method="GET" name="form" action="javascript:checkLogin(this.form.login.value);" >
            <table>
				<tr>
					<td><label>Login : </label></td>
					<td><input type="text" name="login" onKeyUp="javascript:this.form.submit();" /></td>
				</tr>
				<tr>
					<td><label>Available ? </label></td>
					<td><div id="isAvailable"></div></td>
				</tr>
				<tr>
					<td><input type="button" name="connect" value="connect" disabled="disabled" onClick="javascript:addLogin(this.form.login.value);" /></td>
				</tr>
            </table>
		</form>
	</body>
</html>

72.2.2. La page de chat

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
    <head>
        <title>chat.html</title>
        <style>
        </style>
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <script type="text/javascript">
 
            function getXMLHttpRequest() {
                if (window.XMLHttpRequest)
                    return new XMLHttpRequest();
                else if (window.ActiveXObject)
                    new ActiveXObject("Microsoft.XMLHTTP");
                else
                    return null;
            }
			
			function getURLparam(param) {
				var vars = {};
				var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m, key, value) {
					vars[key] = value;
				});
				return vars[param];
			}
			
			function setLoginName() {
				document.getElementById('login').innerHTML = decodeURIComponent(getURLparam('login')) + " says : ";
			}
			
			function startTimer() {
				refreshMessages(getURLparam('login'));
				getOnlineGuys();
				setTimeout("startTimer()", 5000);
			}
			
			function loadMessages(login) {
				var url = "http://192.168.5.53/ajax_projet/functions.php?action=loadMessages&login=" + login;
				var xhr = getXMLHttpRequest();
				
                xhr.onreadystatechange = function() {
                    if(xhr.readyState  == 4) {
                        if(xhr.status  == 200) {
							document.getElementById("messages_pool").value = xhr.responseText;
                        } else {
                            alert('Error code : ' + xhr.status); 
                        }
                    }
                }
                xhr.open("GET", url, true);
                xhr.send();
			}
			
			function refreshMessages(login) {
				var url = "http://192.168.5.53/ajax_projet/functions.php?action=refreshMessages&login=" + login;
				var xhr = getXMLHttpRequest();
				
                xhr.onreadystatechange = function() {
                    if(xhr.readyState  == 4) {
                        if(xhr.status  == 200) {
							document.getElementById("messages_pool").value = xhr.responseText;
                        } else {
                            alert('Error code : ' + xhr.status); 
                        }
                    }
                }
                xhr.open("GET", url, true);
                xhr.send();
			}
			
			function getOnlineGuys() {
				var url = "http://192.168.5.53/ajax_projet/functions.php?action=getOnlineGuys";
				var xhr = getXMLHttpRequest();
				
                xhr.onreadystatechange = function() {
                    if(xhr.readyState  == 4) {
                        if(xhr.status  == 200) {
							document.getElementById("online").innerHTML = xhr.responseText.replace(/;/g, "<br />");
                        } else {
                            alert('Error code : ' + xhr.status); 
                        }
                    }
                }
                xhr.open("GET", url, true);
                xhr.send();
			}
			
			function sendMessage(message, login) {
				var url = "http://192.168.5.53/ajax_projet/functions.php?action=sendMessage&message=" + encodeURIComponent(message) + "&login=" + login;
				var xhr = getXMLHttpRequest();
				
                xhr.onreadystatechange = function() {
                    if(xhr.readyState  == 4) {
                        if(xhr.status  == 200) {
							// Réinitialisation champ.
							document.form.message.value = '';
							refreshMessages(login);
                        } else {
                            alert('Error code : ' + xhr.status); 
                        }
                    }
                }
                xhr.open("GET", url, true);
                xhr.send();
			}
 
        </script>
    </head>
    <body onLoad="javascript:loadMessages(getURLparam('login'));setLoginName();startTimer();">
		<form name="form">
			<table>
				<tr>
					<td colspan="2"><textarea readonly="readonly" id="messages_pool" rows="6" cols="60"></textarea></td>
				</tr>
				<tr>
					<td><label id="login"></label><input type="text" name="message" size="55" /></td>
					<td><input type="button" value="send" onClick="javascript:sendMessage(this.form.message.value, getURLparam('login'));" /></td>
				</tr>
			</table>

			<br />
			<br />

			<table>
				<tr><td>Who's online ?</td></tr>
				<tr>
					<td id="online"></td>
				</tr>
			</table>
		</form>
	</body>
</html>

72.3. Illustrations et sources

Voici quelques illustrations du chat en action (le côté esthétique a volontairement été ignoré). De plus, étant donné que les paramètres sont passés par la méthode GET, il est assez facile de corrompre l'application en modifiant soi-même les valeurs mais là encore, ce n'est pas le but principal de ce projet.

Figure 61. La page de connexion

Figure 62. La page de chat

Pour les sources de l'application, il suffit de cliquer sur ce lien.

Si jamais vous voulez tester, ne pas oublier de modifier les url dans les fonctions javascripts.