├── README for Whispering.txt
├── README.markdown
├── Setup.sql
├── chatrooms.php
├── check.js
├── dbcon.php
├── images
├── bg.jpg
└── logo.jpg
├── index.php
├── jumpin.php
├── main.css
└── room
├── chat.js
├── chatroom-css.txt
├── chatroom-html.txt
├── chatroom-javascript.txt
├── index.php
├── process.php
├── settings.js
├── smiles
├── bigsmile.png
├── sad.png
├── smile.gif
└── tongue.png
├── update.php
└── userlist.php
/README for Whispering.txt:
--------------------------------------------------------------------------------
1 | -----------
2 | Add Whispering in Chat v2, by Christian Mehler
3 | --------------
4 |
5 |
6 | Changes to chat.js:
7 |
8 | function Chat (filetxt, user) {
9 | file = filetxt;
10 | usernameid = user;
11 | this.init = chatInit;
12 | this.update = updateChat;
13 | this.send = sendChat;
14 | this.getState = getStateOfChat;
15 | this.trim = trimstr;
16 | this.getUsers = getuserlist;
17 | }
18 |
19 | function updateChat(){
20 |
21 | $.ajax({
22 |
23 | type: "GET",
24 | url: "update.php",
25 | data: {
26 | 'state': state,
27 | 'file' : file,
28 | 'nickname': usernameid
29 | },
30 | dataType: "json",
31 | ...
32 |
33 | function getuserlist(room, username) {
34 |
35 | roomid = room;
36 | usernameid = username;
37 |
38 | $.ajax({
39 | type: "GET",
40 | url: "userlist.php",
41 | data: {
42 | 'room' : room,
43 | 'username': username,
44 | 'current' : numOfUsers
45 |
46 | },
47 | dataType: "json",
48 | cache: false,
49 | success: function(data) {
50 |
51 | if (numOfUsers != data.numOfUsers) {
52 | numOfUsers = data.numOfUsers;
53 | var list = "
54 |
55 | Current Chatters
56 | ";
57 | for (var i = 0; i < data.userlist.length; i++) {
58 | list += '
59 | '+ data.userlist[i] +"
60 | ";
61 | }
62 | $('#userlist').html($("
63 | "+ list +"
64 | "));
65 | }
66 |
67 | setTimeout('getuserlist(roomid, usernameid)', 1);
68 |
69 | },
70 | });
71 |
72 | }
73 |
74 | function wisper(to)
75 | {
76 | $('#sendie').val('@'+to+' '+$('#sendie').val());
77 | }
78 |
79 |
80 |
81 |
82 |
83 | ---------
84 | Changes to process.php (other saving):
85 | ---------
86 |
87 | fwrite(fopen($file, 'a'), $nickname . "~\t~" . $message = str_replace("\n", " ", $message) . "\n");
88 |
89 |
90 | ---------
91 | Changes to update.php
92 | ---------
93 |
94 | - at the beginning add
95 | $nickname = htmlentities(strip_tags($_GET['nickname']), ENT_QUOTES);
96 |
97 |
98 | -later
99 | ...
100 | if ($state == $count) {
101 |
102 | $log['state'] = $state;
103 | $log['t'] = "continue";
104 |
105 | } else {
106 |
107 | $text= array();
108 | $log['state'] = $state + getlines(getfile($file)) - $state;
109 |
110 | foreach (getfile($file) as $line_num => $line) {
111 | if ($line_num >= $state) {
112 | $line = explode("~\t~", $line);
113 | if(substr($line[1], 0, 1)!='@')
114 | $text[] = ''.$line[0].''.$line[1];
115 | elseif($line[0]==$nickname || substr($line[1], 0, strlen('@'.$nickname))=='@'.$nickname)
116 | $text[] = ''.$line[0].' '.$line[1].'';
117 | }
118 |
119 | $log['text'] = $text;
120 | }
121 | }
122 |
123 | echo json_encode($log);
124 |
125 | ?>
--------------------------------------------------------------------------------
/README.markdown:
--------------------------------------------------------------------------------
1 | A group chat room with PHP, jQuery, and Text Files.
2 |
3 | [Tutorial article for Chat v1](http://css-tricks.com/jquery-php-chat/)
4 | [Tutorial article for Chat v2](http://css-tricks.com/chat2/)
5 |
6 | **WARNING**: Please check out the file at /room/update.php which contained some commented code on only allowing that file to be called
7 | via AJAX and from a certain referrer. Without that precaution, a crafty hacker could gain access to any file on the server.
--------------------------------------------------------------------------------
/Setup.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE IF NOT EXISTS `chat_rooms` (
2 | `id` tinyint(4) NOT NULL AUTO_INCREMENT,
3 | `name` varchar(20) NOT NULL,
4 | `numofuser` int(10) NOT NULL,
5 | `file` varchar(30) NOT NULL,
6 | PRIMARY KEY (`id`)
7 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
8 |
9 | CREATE TABLE IF NOT EXISTS `chat_users` (
10 | `id` tinyint(10) NOT NULL AUTO_INCREMENT,
11 | `username` varchar(100) NOT NULL,
12 | `status` tinyint(1) NOT NULL,
13 | `time_mod` int(100) NOT NULL,
14 | PRIMARY KEY (`id`),
15 | UNIQUE KEY `username` (`username`)
16 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=23 ;
17 |
18 | CREATE TABLE IF NOT EXISTS `chat_users_rooms` (
19 | `id` int(100) NOT NULL AUTO_INCREMENT,
20 | `username` varchar(100) NOT NULL,
21 | `room` varchar(100) NOT NULL,
22 | `mod_time` int(40) NOT NULL,
23 | PRIMARY KEY (`id`)
24 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1472 ;
25 |
--------------------------------------------------------------------------------
/chatrooms.php:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | Chat Rooms
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
37 |
38 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/check.js:
--------------------------------------------------------------------------------
1 | $(function() {
2 |
3 | $("#userid").keyup(function(event) {
4 |
5 | var username = $(this).val();
6 |
7 | $.ajax({
8 | type: "POST",
9 | url: "jumpin.php",
10 | data: { userid : username },
11 | dataType: "json",
12 | success: function(data){
13 | $("#status").html(data.result);
14 |
15 | if (data.inuse == "inuse") {
16 | $("#jumpin").val("Check");
17 | } else {
18 | $("#jumpin").val("Go in!");
19 | }
20 |
21 | }
22 | });
23 |
24 | });
25 |
26 | });
--------------------------------------------------------------------------------
/dbcon.php:
--------------------------------------------------------------------------------
1 | |
66 | // +----------------------------------------------------------------------+
67 | //
68 | // Kohana Modifications:
69 | // * Changed double quotes to single quotes, changed indenting and spacing
70 | // * Removed magic_quotes stuff
71 | // * Increased regex readability:
72 | // * Used delimeters that aren't found in the pattern
73 | // * Removed all unneeded escapes
74 | // * Deleted U modifiers and swapped greediness where needed
75 | // * Increased regex speed:
76 | // * Made capturing parentheses non-capturing where possible
77 | // * Removed parentheses where possible
78 | // * Split up alternation alternatives
79 | // * Made some quantifiers possessive
80 |
81 | // Fix &entity\n;
82 | $data = str_replace(array('&','<','>'), array('&','<','>'), $data);
83 | $data = preg_replace('/(*\w+)[\x00-\x20]+;/u', '$1;', $data);
84 | $data = preg_replace('/(*[0-9A-F]+);*/iu', '$1;', $data);
85 | $data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');
86 |
87 | // Remove any attribute starting with "on" or xmlns
88 | $data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data);
89 |
90 | // Remove javascript: and vbscript: protocols
91 | $data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
92 | $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
93 | $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);
94 |
95 | // Only works in IE:
96 | $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
97 | $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
98 | $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);
99 |
100 | // Remove namespaced elements (we do not need them)
101 | $data = preg_replace('#*\w+:\w[^>]*+>#i', '', $data);
102 |
103 | do
104 | {
105 | // Remove really unwanted tags
106 | $old_data = $data;
107 | $data = preg_replace('#*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
108 | }
109 | while ($old_data !== $data);
110 |
111 | return $data;
112 | }
113 | ?>
--------------------------------------------------------------------------------
/images/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSS-Tricks/Chat2/01fbad700e70c594fcfabfd08eb2ebefae7057b1/images/bg.jpg
--------------------------------------------------------------------------------
/images/logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSS-Tricks/Chat2/01fbad700e70c594fcfabfd08eb2ebefae7057b1/images/logo.jpg
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | Chat2
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
28 |
29 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/jumpin.php:
--------------------------------------------------------------------------------
1 | Great! You found a username not in use";
20 | $data['inuse'] = "notinuse";
21 | } else {
22 | $data['result'] = "That username is already in use. (Usernames take 2 minutes without use to expire)
";
23 | $data['inuse'] = "inuse";
24 | }
25 |
26 | echo json_encode($data);
27 |
28 | }
29 |
30 | } else {
31 |
32 | $username = cleanInput($_POST['userid']);
33 |
34 | if (checkVar($username)) {
35 |
36 | $getUsers = "SELECT *
37 | FROM chat_users
38 | WHERE username = '$username'";
39 |
40 | if (!hasData($getUsers)) {
41 |
42 | $now = time();
43 |
44 | $postUsers = "INSERT INTO `chat_users` (
45 | `id` ,
46 | `username` ,
47 | `status` ,
48 | `time_mod`
49 | )
50 | VALUES (
51 | NULL , '$username', '1', '$now'
52 | )";
53 |
54 | mysql_query($postUsers);
55 |
56 | $_SESSION['userid'] = $username;
57 |
58 | header('Location: ./chatrooms.php');
59 |
60 | } else {
61 |
62 | header('Location: ./?error=1');
63 |
64 | }
65 |
66 | }
67 |
68 | }
69 |
70 | ?>
--------------------------------------------------------------------------------
/main.css:
--------------------------------------------------------------------------------
1 | * { margin: 0; padding: 0; }
2 | body { font: 14px/1.4 Georgia, Serif; background: url(images/bg.jpg); color: white; }
3 |
4 | #page-wrap { margin: 0 auto; width: 600px; position: relative; }
5 |
6 | #header h1 a { display: block; width: 173px; height: 79px; background: url(images/logo.jpg) no-repeat; text-indent: -9999px; }
7 |
8 | h1,h2,h3 { margin: 0 0 20px 0; font-weight: normal; }
9 | h1 { font-size: 36px; }
10 | h2 { font-size: 30px }
11 | h3 { font-size: 24px }
12 | a:focus { outline: 0; }
13 |
14 | .message { margin: 15px 0; padding: 10px; -moz-border-radius: 20px; -webkit-border-radius: 20px; font-size: 15px; }
15 | .warning { background: #ffd5d5; border: 3px solid #ff3939; color: #ff3939; }
16 | .success { background: #e5ffdb; border: 3px solid #0dba32; color: #0dba32; }
17 |
18 | label { font-size: 20px; }
19 |
20 | #section { background: rgba(0,0,0,0.2); padding: 20px; }
21 | #userid { font-size: 20px; padding:8px 10px; width: 330px; }
22 |
23 | #you { position: absolute; top: 45px; right: 0; font-size: 20px; background: rgba(0,0,0,0.2); padding: 5px 10px; }
24 | #you span { font: italic 12px Georgia, Serif; }
25 |
26 | #rooms { }
27 | #rooms ul { list-style: none; }
28 | #rooms ul li { margin: 0 0 5px 0; }
29 | #rooms li a { background: rgba(0,0,0,0.2); padding: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px; display: block; position: relative; }
30 | #rooms li a:hover { background: none; -moz-box-shadow: 0 0 5px black; -webkit-box-shadow: 0 0 5px black; }
31 | #rooms li a span { position: absolute; top: 3px; right: 10px; }
32 | #rooms li a span strong { color: white; font-size: 20px; }
33 | #rooms a { text-decoration: none; color: #4fb90f; font: 18px;}
34 |
35 | #chat-wrap { border: 1px solid #eee; width: 380px; float:left; }
36 | #chat-area { height: 300px; overflow: auto; padding: 20px; background: white; }
37 | #chat-area span { color: white; background: #333; padding: 4px 8px; -moz-border-radius: 5px; -webkit-border-radius: 8px; margin: 0 5px 0 0; }
38 | #chat-area p { padding: 8px 0; border-bottom: 1px solid #ccc; color: #333; }
39 |
40 | #name-area { top: 12px; right: 0; color: white; font: bold 12px "Lucida Grande", Sans-Serif; text-align: right; }
41 | #name-area span { color: #fa9f00; }
42 |
43 | #send-message-area p { float: left; color: white; padding-top: 27px; font-size: 14px; }
44 |
45 | #sendie { width: 360px; padding: 10px; margin: 5px 0 0 0; font: 12px "Lucida Grande", Sans-Serif; }
46 |
47 | #userlist { float: right; width: 160px; height: 410px; overflow-y: scroll; }
48 | #userlist ul { color: #fff; font-size: 18px; list-style: none; }
49 | #userlist ul li { }
50 | #userlist ul li.head { border-bottom: 1px solid #eee; }
51 |
52 |
--------------------------------------------------------------------------------
/room/chat.js:
--------------------------------------------------------------------------------
1 | var state;
2 | var mes;
3 | var file;
4 | var numOfUsers = 0;
5 | var roomid;
6 | var usernameid;
7 |
8 | function Chat (filetxt) {
9 | file = filetxt;
10 | this.init = chatInit;
11 | this.update = updateChat;
12 | this.send = sendChat;
13 | this.getState = getStateOfChat;
14 | this.trim = trimstr;
15 | this.getUsers = getuserlist;
16 | }
17 |
18 | function chatInit(){
19 | getStateOfChat();
20 | }
21 |
22 | function wait(){
23 | updateChat();
24 | }
25 |
26 | $.ajaxSetup({
27 | cache: false // for ie
28 | });
29 |
30 | //gets the state of the chat
31 | function getStateOfChat(){
32 | $.ajax({
33 | type: "POST",
34 | url: "process.php",
35 | data: {
36 | 'function': 'getState',
37 | 'file': file
38 | },
39 | dataType: "json",
40 |
41 | success: function(data){
42 | state = data.state-5;
43 | updateChat();
44 | },
45 | });
46 | }
47 |
48 | //Updates the chat
49 | function updateChat(){
50 |
51 | $.ajax({
52 |
53 | type: "GET",
54 | url: "update.php",
55 | data: {
56 | 'state': state,
57 | 'file' : file
58 | },
59 | dataType: "json",
60 | cache: false,
61 | success: function(data) {
62 |
63 | if (data.text != null) {
64 | for (var i = 0; i < data.text.length; i++) {
65 | $('#chat-area').append($(""+ data.text[i] +"
"));
66 | }
67 |
68 | document.getElementById('chat-area').scrollTop = document.getElementById('chat-area').scrollHeight;
69 |
70 | }
71 |
72 | instanse = false;
73 | state = data.state;
74 | setTimeout('updateChat()', 1);
75 |
76 | },
77 | });
78 | }
79 |
80 | //send the message
81 | function sendChat(message, nickname) {
82 |
83 | $.ajax({
84 | type: "POST",
85 | url: "process.php",
86 | data: {
87 | 'function': 'send',
88 | 'message': message,
89 | 'nickname': nickname,
90 | 'file': file
91 | },
92 | dataType: "json",
93 | success: function(data){
94 |
95 | },
96 | });
97 |
98 | }
99 |
100 | function trimstr(s, limit) {
101 | return s.substring(0, limit);
102 | }
103 |
104 | function getuserlist(room, username) {
105 |
106 | roomid = room;
107 | usernameid = username;
108 |
109 | $.ajax({
110 | type: "GET",
111 | url: "userlist.php",
112 | data: {
113 | 'room' : room,
114 | 'username': username,
115 | 'current' : numOfUsers
116 |
117 | },
118 | dataType: "json",
119 | cache: false,
120 | success: function(data) {
121 |
122 | if (numOfUsers != data.numOfUsers) {
123 | numOfUsers = data.numOfUsers;
124 | var list = "Current Chatters";
125 | for (var i = 0; i < data.userlist.length; i++) {
126 | list += ""+ data.userlist[i] +"";
127 | }
128 | $('#userlist').html($(""));
129 | }
130 |
131 | setTimeout('getuserlist(roomid, usernameid)', 1);
132 |
133 | },
134 | });
135 |
136 | }
--------------------------------------------------------------------------------
/room/chatroom-css.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSS-Tricks/Chat2/01fbad700e70c594fcfabfd08eb2ebefae7057b1/room/chatroom-css.txt
--------------------------------------------------------------------------------
/room/chatroom-html.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSS-Tricks/Chat2/01fbad700e70c594fcfabfd08eb2ebefae7057b1/room/chatroom-html.txt
--------------------------------------------------------------------------------
/room/chatroom-javascript.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSS-Tricks/Chat2/01fbad700e70c594fcfabfd08eb2ebefae7057b1/room/chatroom-javascript.txt
--------------------------------------------------------------------------------
/room/index.php:
--------------------------------------------------------------------------------
1 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | Welcome to:
36 |
37 |
38 |
39 |
40 |
41 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
62 |
63 |
64 |
65 |
66 |
67 |
70 |
71 |
72 |
73 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
90 |
--------------------------------------------------------------------------------
/room/process.php:
--------------------------------------------------------------------------------
1 | ", "
", "
", "
", "
");
24 | $reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
25 | $blankexp = "/^\n/";
26 | $message = htmlentities(strip_tags($_POST['message']), ENT_QUOTES);
27 |
28 | if (!preg_match($blankexp, $message)) {
29 |
30 | if (preg_match($reg_exUrl, $message, $url)) {
31 | $message = preg_replace($reg_exUrl, ''.$url[0].'', $message);
32 | }
33 | $message = preg_replace($patterns, $replacements, $message);
34 |
35 | fwrite(fopen($file, 'a'), "". $nickname . "" . $message = str_replace("\n", " ", $message) . "\n");
36 | }
37 |
38 | break;
39 |
40 | }
41 |
42 | echo json_encode($log);
43 |
44 | ?>
--------------------------------------------------------------------------------
/room/settings.js:
--------------------------------------------------------------------------------
1 | $(function() {
2 |
3 | $("#sendie").keydown(function(event) {
4 |
5 | var key = event.which;
6 |
7 | // all keys including return
8 | if (key >= 33) {
9 |
10 | var maxLength = $(this).attr("maxlength");
11 | var length = this.value.length;
12 |
13 | if (length >= maxLength) {
14 | event.preventDefault();
15 | }
16 | }
17 | });
18 |
19 | $('#sendie').keyup(function(e) {
20 |
21 | if (e.keyCode == 13) {
22 |
23 | var text = $(this).val();
24 | var maxLength = $(this).attr("maxlength");
25 | var length = text.length;
26 |
27 | if (length <= maxLength + 1) {
28 | chat.send(text, name);
29 | $(this).val("");
30 | } else {
31 | $(this).val(text.substring(0, maxLength));
32 | }
33 |
34 | }
35 |
36 | });
37 |
38 | });
--------------------------------------------------------------------------------
/room/smiles/bigsmile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSS-Tricks/Chat2/01fbad700e70c594fcfabfd08eb2ebefae7057b1/room/smiles/bigsmile.png
--------------------------------------------------------------------------------
/room/smiles/sad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSS-Tricks/Chat2/01fbad700e70c594fcfabfd08eb2ebefae7057b1/room/smiles/sad.png
--------------------------------------------------------------------------------
/room/smiles/smile.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSS-Tricks/Chat2/01fbad700e70c594fcfabfd08eb2ebefae7057b1/room/smiles/smile.gif
--------------------------------------------------------------------------------
/room/smiles/tongue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSS-Tricks/Chat2/01fbad700e70c594fcfabfd08eb2ebefae7057b1/room/smiles/tongue.png
--------------------------------------------------------------------------------
/room/update.php:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 | $line) {
59 | if ($line_num >= $state) {
60 | $text[] = $line = str_replace("\n", "", $line);
61 | }
62 |
63 | $log['text'] = $text;
64 | }
65 | }
66 |
67 | echo json_encode($log);
68 |
69 | ?>
--------------------------------------------------------------------------------
/room/userlist.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------