Database set-up:
Members Table:
id - int primary key auto_increment.
username - varchar 15.
password - varchar 32. will be a md5 and sha1 hash of the password then the username.
e-mail - varchar 35.
admin - tinyint. will either be a value of 1 (admin) or the default, 0 (regular member)
last_ip - varchar 15. will store the last ip address person logged in with.
Buddy List:
uid - User ID from members table. int.
buddy - Buddies username or id. either varchar 15 or int.
blocked - Blocked users username or id. either varchar 15 or int.
Messages:
id - message id. int primary key auto_increment.
from - users name. varchar 15 characters.
to - buddies name. varchar 15 characters.
message - blob
time - timestamp CURRENT_TIMESTAMP.
The smartest way to work this is have a cron job or windows task set up to remove all messages 10 minutes or older from the database to save space. After you have the database set-up its simply a matter of having ajax set-up to run a php script to check for new messages every second.
Also, you would be able to make this look any way you wanted it to and you can pretty much make it do anything you wanted it to, right down to playing a sound when you receive a message. People would possibly even be able to play their own sounds when they received a message.
config.php
CODE
<?php
$_dbUsr = "username"; // database username.
$_dbPass = "password"; // database password.
$_db = "database"; // database you're using.
$_dbHost = "localhost"; // most likely using localhost.
$_conn = @mysql_connect($_dbHost, $_dbUsr, $_dbPass);
if(!$_conn) { // This executes the connect code and checks it for errors.
print "Error: Problem connecting to database server. Please check your config files.";
}
$_select = @mysql_select_db($_db, $_conn);
if(!$_select) { // Executes the select database code and checks it for errors.
print "Error: Problem selecting database. Please check that database exists and is linked properly in config files.";
}
?>
$_dbUsr = "username"; // database username.
$_dbPass = "password"; // database password.
$_db = "database"; // database you're using.
$_dbHost = "localhost"; // most likely using localhost.
$_conn = @mysql_connect($_dbHost, $_dbUsr, $_dbPass);
if(!$_conn) { // This executes the connect code and checks it for errors.
print "Error: Problem connecting to database server. Please check your config files.";
}
$_select = @mysql_select_db($_db, $_conn);
if(!$_select) { // Executes the select database code and checks it for errors.
print "Error: Problem selecting database. Please check that database exists and is linked properly in config files.";
}
?>
register.php
CODE
<?php
require("config.php");
$_user = mysql_real_escape_string($_POST['user']);
$_pass = md5(sha1($_POST['pass'].$_POST['user']));
$_email = mysql_real_escape_string($_POST['email']);
$memtab = "name of your members table";
$_ip = $_SERVER['REMOTE_ADDR'];
if ((!$_user) || (!$_pass) || (!$_email)) {
print "You must fill in all fields before clicking the register button. Please go back and try again.";
} else {
$sel = @mysql_query("SELECT * FROM $memtab WHERE username = '$_user'");
if($sel) {
print "A user with that username exists. Please go back and choose a new username.";
} else {
$ins = @mysql_query("INSERT INTO $memtab (username, password, email, last_ip) VALUES(\"$_user\", \"$_pass\", \"$_email\", \"$_ip\")");
if ($ins) {
print "Registration complete. You may now begin using 'title of instant messenger'.";
} else {
print "Error: Could not create user. Please go back and try again.";
}
}
}
?>
require("config.php");
$_user = mysql_real_escape_string($_POST['user']);
$_pass = md5(sha1($_POST['pass'].$_POST['user']));
$_email = mysql_real_escape_string($_POST['email']);
$memtab = "name of your members table";
$_ip = $_SERVER['REMOTE_ADDR'];
if ((!$_user) || (!$_pass) || (!$_email)) {
print "You must fill in all fields before clicking the register button. Please go back and try again.";
} else {
$sel = @mysql_query("SELECT * FROM $memtab WHERE username = '$_user'");
if($sel) {
print "A user with that username exists. Please go back and choose a new username.";
} else {
$ins = @mysql_query("INSERT INTO $memtab (username, password, email, last_ip) VALUES(\"$_user\", \"$_pass\", \"$_email\", \"$_ip\")");
if ($ins) {
print "Registration complete. You may now begin using 'title of instant messenger'.";
} else {
print "Error: Could not create user. Please go back and try again.";
}
}
}
?>
login.php
CODE
<?php
require("config.php");
$memtab = "name of your members table";
$_user = mysql_real_escape_string($_GET['user']);
$_pass = md5(sha1($_GET['pass'].$_GET['user']));
$_sel = @mysql_query("SELECT * FROM $memtab WHERE username=$_user AND password=$_pass");
while($r = @mysql_fetch_array($_sel)) {
$_SESSION['user'] = $r["username"]; // There is going to be a session_start() function on top of index.php which will be the main page.
$admin = $r["admin"];
}
if($admin) { // If the admin column has a value of 1
print "<script language='text/javascript' src='ajax.js'>buddyLoad($_SESSION['user'],1);</script>";
} else {
print "<script language='text/javascript' src='ajax.js'>buddyLoad($_SESSION['user'],0);</script>";
}
?>
require("config.php");
$memtab = "name of your members table";
$_user = mysql_real_escape_string($_GET['user']);
$_pass = md5(sha1($_GET['pass'].$_GET['user']));
$_sel = @mysql_query("SELECT * FROM $memtab WHERE username=$_user AND password=$_pass");
while($r = @mysql_fetch_array($_sel)) {
$_SESSION['user'] = $r["username"]; // There is going to be a session_start() function on top of index.php which will be the main page.
$admin = $r["admin"];
}
if($admin) { // If the admin column has a value of 1
print "<script language='text/javascript' src='ajax.js'>buddyLoad($_SESSION['user'],1);</script>";
} else {
print "<script language='text/javascript' src='ajax.js'>buddyLoad($_SESSION['user'],0);</script>";
}
?>
sendim.php
CODE
<?php
if(!$_GET['m'] || !$_GET['from'] || !$_GET['to']) {
print "No message was sent.";
} else {
$user = mysql_real_escape_string($_GET['from']);
$buddy = mysql_real_escape_string($_GET['to']);
$msg = mysql_real_escape_string($_GET['m']);
$ins = @mysql_query("INSERT INTO messages ('from', 'to', 'message') VALUES(\"$user\", \"$buddy\", \"$msg\")"); /* The reason for only inserting the from, to, and message fields is because the message id should be set to auto_increment and the time should default to CURRENT_TIMESTAMP. */
if(!$ins) {
print "Message could not be sent. The server may be down.";
}
}
?>
if(!$_GET['m'] || !$_GET['from'] || !$_GET['to']) {
print "No message was sent.";
} else {
$user = mysql_real_escape_string($_GET['from']);
$buddy = mysql_real_escape_string($_GET['to']);
$msg = mysql_real_escape_string($_GET['m']);
$ins = @mysql_query("INSERT INTO messages ('from', 'to', 'message') VALUES(\"$user\", \"$buddy\", \"$msg\")"); /* The reason for only inserting the from, to, and message fields is because the message id should be set to auto_increment and the time should default to CURRENT_TIMESTAMP. */
if(!$ins) {
print "Message could not be sent. The server may be down.";
}
}
?>
checkims.php
CODE
<?php
require("config.php");
require("style.php"); // This will be the script that styles the way an instant message looks.
$user = mysql_real_escape_string($_GET['user']);
$buddy = mysql_real_escape_string($_GET['buddy']);
$time = $_GET['time'];
$sel = @mysql_query("SELECT * FROM messages WHERE to='$user' AND from='$buddy' ORDER BY time DESC LIMIT 1");
while($r = @mysql_fetch_array($sel)) {
$id = $r["id"];
$message = $r["message"];
$dbtime = $r["time"];
}
if ($time == $dbtime) {
return
} else {
style($user,$buddy,$dbtime,$message); // Style the instant message and display it.
}
?>
require("config.php");
require("style.php"); // This will be the script that styles the way an instant message looks.
$user = mysql_real_escape_string($_GET['user']);
$buddy = mysql_real_escape_string($_GET['buddy']);
$time = $_GET['time'];
$sel = @mysql_query("SELECT * FROM messages WHERE to='$user' AND from='$buddy' ORDER BY time DESC LIMIT 1");
while($r = @mysql_fetch_array($sel)) {
$id = $r["id"];
$message = $r["message"];
$dbtime = $r["time"];
}
if ($time == $dbtime) {
return
} else {
style($user,$buddy,$dbtime,$message); // Style the instant message and display it.
}
?>
ajax.js
CODE
/* This should be the same for all AJAX scripts. You find out if the person's browser supports AJAX and set the AJAX object to a variable. */
var xmlhttp;
try {
xmlhttp=new XMLHttpRequest();
} catch (e) {
try {
xmlhttp=new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
alert("Your browser does not support AJAX!");
return false;
}
}
}
/* Since we're going to be using the GET method, we're going to check to see how long the url is with the message included. Since the max allowed length of a url is 2083 characters, we're going to make sure our url length is less than 2083 characters before we send the message to the intended buddy. */
function checkIM() {
var msg=document.getElementById('msg').value;
var f=document.getElementById('user').value;
var t=document.getElementById('buddy').value;
var url='sendim.php?from='+f+'&to='+t+'&m='+msg;
if(url.length > 2083) {
document.getElementById('ims').innerHTML='Message too long.';
} else {
sendIM(url);
}
}
// After we've made sure the url is the right length, we can send it to our buddy.
function sendIM(url) {
xmlhttp.onreadystatechange=function() {
if(xmlhttp.readyState==4) {
document.getElementById('ims').innerHTML+=xmlhttp.responseText;
}
}
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
function cTime(time) {
document.getElementById('time').value = time;
}
// This function is what we will be calling during the login process.
function doLogin() {
var user=document.getElementById('username').value;
var pass=document.getElementById('pass').value;
var url='login.php?user='+user+'&pass='+pass;
xmlhttp.onreadystatechange=function() {
if(xmlhttp.readyState!=4) { // If the request is still loading, show loading image.
document.getElementById('main').innerHTML='<p><img src=images/loading.gif></p>';
} else {
document.getElementById('main').innerHTML=xhmlhttp.responseText;
}
}
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
// The function we will be calling to show the users their buddylists.
function buddyLoad(usr,admin) {
var url='buddylist.php?user='+usr+'&power='+admin;
xmlhttp.onreadystatechange=function() {
if(xmlhttp.readyState!=4) {
document.getElementById('main').innerHTML='<p><img src=images/loading.gif></p>';
} else {
document.getElementById('main').innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
// This will be what updates the users instant message window.
function checkIMs() {
var usr=document.getElementById('user').value; // Hidden field with the persons username.
var f=document.getElementById('buddy').value; // Hidden field with the buddy's username.
var time=document.getElementById('time').value;
var url='checkims.php?user='+usr+'&buddy='+f+'&time='+time;
xmlhttp.onreadystatechange=function() {
if(xmlhttp.readyState==4) {
document.getElementById('ims').innerHTML+=xmlhttp.responseText;
}
}
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
/* This is the instant message window timer that will run every second then call itself again to check for new im's. You can change the timer to run how ever often you would like it to, but keep in mind that if you have 20 users online, each with 5 im windows open, thats already 100 different timers running all calling the same php script from the checkIMs() function. This is where this idea may have problems. */
function Timer() {
setInterval("checkIMs()", 1000);
}
var xmlhttp;
try {
xmlhttp=new XMLHttpRequest();
} catch (e) {
try {
xmlhttp=new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
alert("Your browser does not support AJAX!");
return false;
}
}
}
/* Since we're going to be using the GET method, we're going to check to see how long the url is with the message included. Since the max allowed length of a url is 2083 characters, we're going to make sure our url length is less than 2083 characters before we send the message to the intended buddy. */
function checkIM() {
var msg=document.getElementById('msg').value;
var f=document.getElementById('user').value;
var t=document.getElementById('buddy').value;
var url='sendim.php?from='+f+'&to='+t+'&m='+msg;
if(url.length > 2083) {
document.getElementById('ims').innerHTML='Message too long.';
} else {
sendIM(url);
}
}
// After we've made sure the url is the right length, we can send it to our buddy.
function sendIM(url) {
xmlhttp.onreadystatechange=function() {
if(xmlhttp.readyState==4) {
document.getElementById('ims').innerHTML+=xmlhttp.responseText;
}
}
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
function cTime(time) {
document.getElementById('time').value = time;
}
// This function is what we will be calling during the login process.
function doLogin() {
var user=document.getElementById('username').value;
var pass=document.getElementById('pass').value;
var url='login.php?user='+user+'&pass='+pass;
xmlhttp.onreadystatechange=function() {
if(xmlhttp.readyState!=4) { // If the request is still loading, show loading image.
document.getElementById('main').innerHTML='<p><img src=images/loading.gif></p>';
} else {
document.getElementById('main').innerHTML=xhmlhttp.responseText;
}
}
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
// The function we will be calling to show the users their buddylists.
function buddyLoad(usr,admin) {
var url='buddylist.php?user='+usr+'&power='+admin;
xmlhttp.onreadystatechange=function() {
if(xmlhttp.readyState!=4) {
document.getElementById('main').innerHTML='<p><img src=images/loading.gif></p>';
} else {
document.getElementById('main').innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
// This will be what updates the users instant message window.
function checkIMs() {
var usr=document.getElementById('user').value; // Hidden field with the persons username.
var f=document.getElementById('buddy').value; // Hidden field with the buddy's username.
var time=document.getElementById('time').value;
var url='checkims.php?user='+usr+'&buddy='+f+'&time='+time;
xmlhttp.onreadystatechange=function() {
if(xmlhttp.readyState==4) {
document.getElementById('ims').innerHTML+=xmlhttp.responseText;
}
}
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
/* This is the instant message window timer that will run every second then call itself again to check for new im's. You can change the timer to run how ever often you would like it to, but keep in mind that if you have 20 users online, each with 5 im windows open, thats already 100 different timers running all calling the same php script from the checkIMs() function. This is where this idea may have problems. */
function Timer() {
setInterval("checkIMs()", 1000);
}
More stuff to come... Be sure to add your own input.
WHAT'S NEW
v.0.5.3 - Javascript update. Corrected some errors in the ajax.js file.
v.0.5.2 - PHP update. Completed checkims.php.
v.0.5.1 - Security and PHP update. Changed all htmlspecialchars and stripslashes to just mysql_real_escape_string. Cleaned up a lot of the code in the php files.
v.0.5 - PHP update. Added register.php.
v.0.4.1 - Security, PHP, and Database update. Added last_ip column to members table. Updated the SQL statement used in checkims.php. Now there is a htmlspecialchars() function added to all variables which call upon $_GET strings.
v.0.4 - PHP update. Added checkims.php.
v.0.3.1 - Database and Security update. Added time column to messages table. Changed password to md5 and sha1 hash of password + username.
v.0.3 - PHP update. Added config.php, login.php, and sendim.php files.
v.0.2.1 - Javascript update. Added checkIMs() and Timer() functions to ajax.js file.
v.0.2 - Javascript update. Created ajax.js file.
v.0.1 - Project started. Databases created.