-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathexample.php
More file actions
172 lines (142 loc) · 6.31 KB
/
Copy pathexample.php
File metadata and controls
172 lines (142 loc) · 6.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
<?php
/**
* Simple chat example by Stephan Soller
* See http://arkanis.de/projects/simple-chat/
*/
// Name of the message buffer file. You have to create it manually with read and write permissions for the webserver.
$messages_buffer_file = 'messages.json';
// Number of most recent messages kept in the buffer
$messages_buffer_size = 10;
if ( isset($_POST['content']) and isset($_POST['name']) )
{
// Open, lock and read the message buffer file
$buffer = fopen($messages_buffer_file, 'r+b');
flock($buffer, LOCK_EX);
$buffer_data = stream_get_contents($buffer);
// Append new message to the buffer data or start with a message id of 0 if the buffer is empty
$messages = $buffer_data ? json_decode($buffer_data, true) : array();
$next_id = (count($messages) > 0) ? $messages[count($messages) - 1]['id'] + 1 : 0;
$messages[] = array('id' => $next_id, 'time' => time(), 'name' => $_POST['name'], 'content' => $_POST['content']);
// Remove old messages if necessary to keep the buffer size
if (count($messages) > $messages_buffer_size)
$messages = array_slice($messages, count($messages) - $messages_buffer_size);
// Rewrite and unlock the message file
ftruncate($buffer, 0);
rewind($buffer);
fwrite($buffer, json_encode($messages));
flock($buffer, LOCK_UN);
fclose($buffer);
// Optional: Append message to log file (file appends are atomic)
//file_put_contents('chatlog.txt', strftime('%F %T') . "\t" . strtr($_POST['name'], "\t", ' ') . "\t" . strtr($_POST['content'], "\t", ' ') . "\n", FILE_APPEND);
exit();
}
?>
<!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" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Simple Chat</title>
<script type="text/javascript" src="jquery-1.4.2.min.js"></script>
<script type="text/javascript">
// <![CDATA[
$(document).ready(function(){
// Remove the "loading…" list entry
$('ul#messages > li').remove();
$('form').submit(function(){
var form = $(this);
var name = form.find("input[name='name']").val();
var content = form.find("input[name='content']").val();
// Only send a new message if it's not empty (also it's ok for the server we don't need to send senseless messages)
if (name == '' || content == '')
return false;
// Append a "pending" message (not yet confirmed from the server) as soon as the POST request is finished. The
// text() method automatically escapes HTML so no one can harm the client.
$.post(form.attr('action'), {'name': name, 'content': content}, function(data, status){
$('<li class="pending" />').text(content).prepend($('<small />').text(name)).appendTo('ul#messages');
$('ul#messages').scrollTop( $('ul#messages').get(0).scrollHeight );
form.find("input[name='content']").val('').focus();
});
return false;
});
// Poll-function that looks for new messages
var poll_for_new_messages = function(){
$.ajax({url: 'messages.json', dataType: 'json', ifModified: true, timeout: 2000, success: function(messages, status){
// Skip all responses with unmodified data
if (!messages)
return;
// Remove the pending messages from the list (they are replaced by the ones from the server later)
$('ul#messages > li.pending').remove();
// Get the ID of the last inserted message or start with -1 (so the first message from the server with 0 will
// automatically be shown).
var last_message_id = $('ul#messages').data('last_message_id');
if (last_message_id == null)
last_message_id = -1;
// Add a list entry for every incomming message, but only if we not already inserted it (hence the check for
// the newer ID than the last inserted message).
for(var i = 0; i < messages.length; i++)
{
var msg = messages[i];
if (msg.id > last_message_id)
{
var date = new Date(msg.time * 1000);
$('<li/>').text(msg.content).
prepend( $('<small />').text(date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds() + ' ' + msg.name) ).
appendTo('ul#messages');
$('ul#messages').data('last_message_id', msg.id);
}
}
// Remove all but the last 50 messages in the list to prevent browser slowdown with extremely large lists
// and finally scroll down to the newes message.
$('ul#messages > li').slice(0, -50).remove();
$('ul#messages').scrollTop( $('ul#messages').get(0).scrollHeight );
}});
};
// Kick of the poll function and repeat it every two seconds
poll_for_new_messages();
setInterval(poll_for_new_messages, 2000);
});
// ]]>
</script>
<style type="text/css">
html { margin: 0em; padding: 0; }
body { margin: 2em; padding: 0; font-family: sans-serif; font-size: medium; color: #333; }
h1 { margin: 0; padding: 0; font-size: 2em; }
p.subtitle { margin: 0; padding: 0 0 0 0.125em; font-size: 0.77em; color: gray; }
ul#messages { overflow: auto; height: 15em; margin: 1em 0; padding: 0 3px; list-style: none; border: 1px solid gray; }
ul#messages li { margin: 0.35em 0; padding: 0; }
ul#messages li small { display: block; font-size: 0.59em; color: gray; }
ul#messages li.pending { color: #aaa; }
form { font-size: 1em; margin: 1em 0; padding: 0; }
form p { position: relative; margin: 0.5em 0; padding: 0; }
form p input { font-size: 1em; }
form p input#name { width: 10em; }
form p button { position: absolute; top: 0; right: -0.5em; }
ul#messages, form p, input#content { width: 40em; }
pre { font-size: 0.77em; }
</style>
<meta name="author" content="Stephan Soller" />
</head>
<body>
<h1>Simple Chat</h1>
<p class="subtitle">With about 20 lines of PHP and about 40 lines of JavaScript</p>
<ul id="messages">
<li>loading…</li>
</ul>
<form action="<?= htmlentities($_SERVER['PHP_SELF'], ENT_COMPAT, 'UTF-8'); ?>" method="post">
<p>
<input type="text" name="content" id="content" />
</p>
<p>
<label>
Name:
<input type="text" name="name" id="name" value="Anonymous" />
</label>
<button type="submit">Send</button>
</p>
</form>
<p>Back to the <a href="./">project page</a>.</p>
<h2 id="source">Source</h2>
<p>This is the source code if this file, including the PHP code:</p>
<pre><? show_source(__FILE__); ?></pre>
</body>
</html>