From Chaos Communication Camp 2007
package ccc.camp.chat;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Eliza extends HttpServlet {
public static final String webcamUrl = "http://81.163.48.165/~fh/images/dbadatccc.jpg";
/**
*
*/
private static final long serialVersionUID = 1L;
static List<Message> messages = new ArrayList<Message>();
static Map<String,Date> online = new HashMap<String, Date>();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String pathInfo = req.getPathInfo();
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
if (pathInfo.startsWith("/messages")) {
printProtocol(req, resp);
System.err.print("request: " + pathInfo);
System.err.print("\n");
return;
}
if (pathInfo.startsWith("/lastmessages")) {
trackOnlineUsers(req);
printLastMessagesTable(req, resp.getWriter());
return;
}
PrintWriter writer = resp.getWriter();
if (pathInfo.startsWith("/users")) {
writer.println(online.size());
return;
}
writer.print("<html><body onload=\"document.getElementById('msg').focus()\">\n");
writer.print("<h1>SimpleCCCCChatServer</h1>");
writer.print("<div style=\"float:left\">");
writer.print("<form>");
writer.print("enter your message: ");
writer.print("<input type=\"text\" size=\"80\" id=\"msg\" name=\"msg\"/>");
writer.print("");
writer.print("");
writer.print("");
writer.print("");
Map<String, String[]> params = req.getParameterMap();
for (String param : params.keySet()) {
StringBuilder msg = new StringBuilder(param);
msg.append(": ");
String msgbody = params.get(param)[0];
msg.append(msgbody);
addMsgToHistory(req, msgbody);
System.err.print("\tmsg: " + msgbody + "\n");
}
writer.println("</form>");
writer.print("<div style=\"width:500px; text-align:right\"><span id=\"online\">");
writer.print(online.size());
writer.print("</span> user(s) online.</div>");
writer.print("<div id=\"lastmsgs\">");
printLastMessagesTable(req, writer);
writer.print("</div>");
writer.print("<a href=\"/messages\">see all messages...</a></div><div style=\"float:left\"><br><br>see where this server is located:<br><br><img id=\"campcam\" src=\"");
writer.print(webcamUrl);
writer.print("\"><div>");
printImgUpdateScript(writer);
writer.print("</body></html>\n");
writeProtocol();
}
private void trackOnlineUsers(HttpServletRequest req) {
Date now = new Date();
boolean newIp = true;
String remoteHost = req.getRemoteHost();
for(String ip : online.keySet()) {
Date d = online.get(ip);
if (now.getTime() - d.getTime() > 5 * 60 * 1000){ // 5 minutes
online.remove(ip);
System.err.print("offline: " + ip);
System.err.print("\n");
}
if(ip.equals(remoteHost)){
online.put(ip, now);
newIp = false;
System.err.print("updated: " + remoteHost);
System.err.print("\n");
}
}
if(newIp) {
System.err.print("new: " + remoteHost);
System.err.print("\n");
online.put(remoteHost, now);
}
}
private synchronized void writeProtocol() throws IOException, FileNotFoundException {
File saveProtocolFile = new File("/tmp/chatprotocol.serialized");
ObjectOutputStream ostream = new ObjectOutputStream(new FileOutputStream(saveProtocolFile));
ostream.writeObject(messages);
ostream.close();
}
private synchronized void addMsgToHistory(HttpServletRequest req, String msgbody) {
int msize = messages.size();
if(msize>0){
Message last = messages.get(msize-1);
if(msgbody.equals(last.msg)){
// avoid double msg on reload
return;
}
}
messages.add(new Message(req.getRemoteHost(), new Date(), msgbody));
}
private void printLastMessagesTable(HttpServletRequest req,
PrintWriter writer) {
if (messages.size() > 0) {
writer.print("<table>");
for(int i=messages.size() - 1; i>=0 && i>messages.size()-8; i--) {
writer.println("<tr><td>");
Message msg = messages.get(i);
writer.print(msg.ip(req));
writer.print("</td><td>answered at</td><td>");
writer.print(msg.date());
writer.print(":</td><td><b>");
writer.write(msg.msgFiltered());
writer.print("</b></td></tr>");
}
writer.print("</table>");
}
}
private void printProtocol(HttpServletRequest req, HttpServletResponse resp) throws IOException {
PrintWriter writer = resp.getWriter();
writer.print("<html><body><h1>SimpleCCCCChatServer - The whole story</h1>");
writer.print("<div style=\"float:left\">\n");
for (int i=messages.size()-1; i>=0; i--) {
Message msg = messages.get(i);
writer.print(msg.out(req));
writer.print("<br/>\n");
}
writer.print("</div><div style=\"margin:10px; float:left\">see where this server is located:<br><br><img id=\"webcam\" src=\"");
writer.print(webcamUrl);
writer.print("\"><div>");
printImgUpdateScript(writer);
writer.print("</body></html>\n");
}
private void printImgUpdateScript(PrintWriter writer) {
writer.println("<script>");
writer.println("var http_request_msgs = false;");
writer.println("var http_request_users = false;");
writer.println("function loadMessages(){");
writer.println("http_request_msgs=null");
// code for Mozilla, etc.
writer.println("if (window.XMLHttpRequest){");
writer.println(" http_request_msgs=new XMLHttpRequest()");
writer.println(" } else if(window.ActiveXObject){");
// code for IE
writer.println(" http_request_msgs=new ActiveXObject(\"Microsoft.XMLHTTP\")");
writer.println(" }");
writer.println("if (http_request_msgs!=null){");
writer.println(" http_request_msgs.onreadystatechange=state_Change1");
writer.println(" var jetzt = new Date();\n var delay=3000;\n");
writer.println(" http_request_msgs.open(\"GET\",'/lastmessages?' + jetzt.getTime(),true)");
writer.println(" http_request_msgs.send(null)");
writer.println("}");
writer.println("}");
writer.println("function state_Change1(){");
writer.println(" if (http_request_msgs.readyState == 4) {");
writer.println(" var table=document.getElementById(\"lastmsgs\")");
writer.println(" table.innerHTML = http_request_msgs.responseText");
writer.println(" }");
writer.println("}");
writer.println("function loadUsers(){");
writer.println("http_request_users=null");
// code for Mozilla, etc.
writer.println("if (window.XMLHttpRequest){");
writer.println(" http_request_users=new XMLHttpRequest()");
writer.println(" } else if(window.ActiveXObject){");
// code for IE
writer.println(" http_request_users=new ActiveXObject(\"Microsoft.XMLHTTP\")");
writer.println(" }");
writer.println("if (http_request_users!=null){");
writer.println(" http_request_users.onreadystatechange=state_Change2");
writer.println(" var jetzt = new Date();\n var delay=3000;\n");
writer.println(" http_request_users.open(\"GET\",'/users?' + jetzt.getTime(),true)");
writer.println(" http_request_users.send(null)");
writer.println("}");
writer.println("}");
writer.println("function state_Change2(){");
writer.println(" if (http_request_msgs.readyState == 4) {");
writer.println(" var users=document.getElementById(\"online\")");
writer.println(" users.innerHTML = http_request_users.responseText");
writer.println(" }");
writer.println("}");
writer.println("function update(){");
writer.println("var jetzt = new Date();\n var delay=3000;\n");
writer.println("loadMessages();loadUsers();document.getElementById(\"campcam\").src =\"http://81.163.48.165/~fh/images/dbadatccc.jpg?\" + jetzt.getTime();");
writer.println("setTimeout(\"update()\",delay)};");
writer.println("update()");
writer.println("</script>");
}
private class Message implements Serializable {
/**
*
*/
private static final long serialVersionUID = 7916883126928225837L;
private String ip;
private Date date;
private String msg;
public Message(String ip, Date date, String msg) {
super();
this.ip = ip;
this.date = date;
this.msg = msg;
}
public String out(HttpServletRequest req) {
StringBuilder s = new StringBuilder(date());
s.append(" (");
s.append(ip(req));
s.append("): ");
s.append(msgFiltered());
return s.toString();
}
public String date() {
DateFormat tf = new SimpleDateFormat("hh:mm");
return tf.format(date);
}
public String ip(HttpServletRequest req) {
return req.getRemoteHost().equals(ip) ? "You" : ip;
}
public String msgFiltered(){
String out = msg.replaceAll("<", "<");
out = out.replaceAll("\"", """);
out = out.replaceAll("fuck", "f**k");
return out;
}
}
@Override
public void init() throws ServletException {
super.init();
File chatProtFile = new File("/tmp/chatprotocol.serialized");
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(chatProtFile));
messages = (List<Message>)ois.readObject();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}