package web;
import io.ADXInput;
import java.util.ArrayList;
import java.util.HashMap;
import net.ADXNetServer;
import net.ADXNetServer.Client;
import render.ADXGraphics;
import frame.ADXGame;
import frame.ADXInstance;
public class ADXWebServer extends ADXInstance {
private int maxClients = 16;
private int port;
private HashMap<String, ADXWebPage> mapPage = new HashMap<String, ADXWebPage>();
private HashMap<String, ADXWebFile> mapFile = new HashMap<String, ADXWebFile>();
private long userID = 0;
private ArrayList<WebOnline> lOnline = new ArrayList<WebOnline>();
public ADXWebServer(int port) {
this.port = port;
}
public class WebOnline {
public String ip;
public long userID;
public int timeLeft;
public WebOnline(String ip, long userID, int timeLeft) {
this.ip = ip;
this.userID = userID;
this.timeLeft = timeLeft;
}
}
public ArrayList<WebOnline> getOnline() {
return lOnline;
}
@Override
public void init(ADXGame game) {
ADXGame.postString("Opening Web Server...");
ADXNetServer.createSocket(port, maxClients);
}
@Override
public void update(ADXGame game, ADXInput input) {
Client c;
for (int i = 0; i < maxClients; i++) {
c = ADXNetServer.getClient(i);
if (c != null) {
String request = c.readRawString();
if (request.length() == 0) {
if (c.getBytesIn() > 0) {
ADXNetServer.closeClient(i);
}
} else {
String[] requests = request.split("\\r?\\n\\r?\\n(GET|POST)");
for (String r : requests) {
analyseRequest(i, r);
}
}
}
}
for (WebOnline o : lOnline) {
if (o.timeLeft == 0) {
lOnline.remove(o);
} else {
o.timeLeft -= 1;
}
}
}
@Override
public void render(ADXGame game, ADXGraphics g) {
}
@Override
public void delete(ADXGame game) {
ADXGame.postString("Closing Web Server...");
ADXNetServer.closeSocket();
}
private void analyseRequest(int i, String request) {
HashMap<String, String> map = new HashMap<String, String>();
HashMap<String, String> post = new HashMap<String, String>();
HashMap<String, String> cookies = new HashMap<String, String>();
boolean inPost = false;
boolean sent = false;
// Split the request into lines
String[] split = request.split("\\r?\\n");
String page = "";
for (String str : split) {
if (str.startsWith("GET")) {
// Split GET to get all variables in url and good page string
String url = str.split(" ")[1];
String[] urlSplit = url.split("(\\?|&)");
page = urlSplit[0];
if (urlSplit.length > 1) {
for (int j = 1; j < urlSplit.length; j++) {
String[] kv = urlSplit[j].split("=");
post.put(kv[0], kv[1]);
}
}
} else if (str.startsWith("POST")) {
page = str.split(" ")[1];
} else if (str.startsWith("Cookie:")) {
String[] c = str.split(" ");
for (int j = 1; j < c.length; j++) {
String[] kv = c[j].split("=");
cookies.put(kv[0], kv[1]);
}
} else if (str.length() == 0) {
inPost = true;
} else {
if (!inPost) {
map.put(str.substring(0, str.indexOf(": ")), str.substring(str.indexOf(": ") + 2, str.length()));
} else {
post.put(str.substring(0, str.indexOf("=")), str.substring(str.indexOf("=") + 1, str.length()));
}
}
}
// Find a page that correspond to the resquest
if (mapPage.containsKey(page)) {
ADXWebPage wp = mapPage.get(page);
writePage(wp, i, post, cookies);
sent = true;
}
// If no page has been found, try to find a file
if (!sent) {
if (mapFile.containsKey(page)) {
ADXWebFile wf = mapFile.get(page);
boolean send = true;
if (map.containsKey("If-Modified-Since")) {
long timeStamp = Long.parseLong(map.get("If-Modified-Since"));
if (timeStamp >= wf.getLastModified()) {
ADXNetServer.clearBuffer();
writeHTTPHeaderNotModified();
ADXNetServer.sendTo(i);
send = false;
}
}
if (send) {
ADXNetServer.clearBuffer();
writeHTTPHeader(wf.getLastModified());
wf.write();
ADXNetServer.sendTo(i);
}
sent = true;
}
}
// If nothing has been sent, error
if (!sent) {
// Error 404 - Resource not found
}
}
private void writePage(ADXWebPage page, int i, HashMap<String, String> post, HashMap<String, String> cookies) {
ADXNetServer.clearBuffer();
//writeHTTPHeader();
ADXNetServer.writeRawString("HTTP/1.1 200 OK\r\n");
ADXNetServer.writeRawString("Content-Type: text/html\r\n");
WebOnline on = null;
if (!cookies.containsKey("userID")) {
ADXNetServer.writeRawString("Set-Cookie: userID=" + userID + "\r\n");
on = new WebOnline(ADXNetServer.getClient(i).getIP(), userID, 60 * 60 * 10);
lOnline.add(on);
userID += 1;
} else {
boolean found = false;
long user = Long.parseLong(cookies.get("userID"));
for (WebOnline o : lOnline) {
if (o.userID == user) {
o.timeLeft = 60 * 60 * 10;
on = o;
found = true;
}
}
if (!found) {
ADXNetServer.writeRawString("Set-Cookie: userID=" + userID + "\r\n");
on = new WebOnline(ADXNetServer.getClient(i).getIP(), userID, 60 * 60 * 10);
lOnline.add(on);
userID += 1;
}
}
ADXNetServer.writeRawString("Connection: close\r\n\r\n");
page.write(i, post, on);
ADXNetServer.sendTo(i);
}
public void addPage(String path, ADXWebPage page) {
mapPage.put(path, page);
}
public void addFile(String path, ADXWebFile file) {
mapFile.put(path, file);
}
/*private void writeHTTPHeader() {
ADXNetServer.writeRawString("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n");
}*/
private void writeHTTPHeader(long lastModified) {
ADXNetServer.writeRawString("HTTP/1.1 200 OK\r\nLast-Modified: " + lastModified + "\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n");
}
private void writeHTTPHeaderNotModified() {
ADXNetServer.writeRawString("HTTP/1.1 304 Not Modified\r\n\r\n");
}
}