Where people come together to learn, code, and play. Custom-built HTTP server, site generator, and website from scratch using no external libraries. Goal is to be as minimalistic and fun as possible.
http://projectdivar.com
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
537 lines
40 KiB
537 lines
40 KiB
import java.io.BufferedReader;
|
|
import java.io.File;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStreamReader;
|
|
import java.io.OutputStream;
|
|
import java.net.ServerSocket;
|
|
import java.net.Socket;
|
|
import java.net.SocketException;
|
|
import java.net.URLDecoder;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.Paths;
|
|
import java.nio.file.StandardOpenOption;
|
|
import java.nio.file.attribute.FileTime;
|
|
import java.time.Instant;
|
|
import java.time.ZoneId;
|
|
import java.time.ZonedDateTime;
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.time.temporal.ChronoUnit;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.regex.Pattern;
|
|
|
|
public class sigServer {
|
|
ServerSocket socket;
|
|
|
|
/**
|
|
* Writes a span tag with the included class.
|
|
* **/
|
|
private static String SPAN(String className) {
|
|
return "<span class=\""+className+"\">";
|
|
}
|
|
private static boolean validNumericalConstantCharacters(String storedCodeBlock,int lengthOfConstant, int j) {
|
|
return storedCodeBlock.charAt(j)>='0'&&storedCodeBlock.charAt(j)<='9'||lengthOfConstant>0&&storedCodeBlock.charAt(j)=='.'||lengthOfConstant>0&&storedCodeBlock.charAt(j)>='A'&&lengthOfConstant>0&&storedCodeBlock.charAt(j)<='F'||lengthOfConstant>0&&storedCodeBlock.charAt(j)>='a'&&lengthOfConstant>0&&storedCodeBlock.charAt(j)<='f'||lengthOfConstant>0&&storedCodeBlock.charAt(j)=='x'||lengthOfConstant>0&&storedCodeBlock.charAt(j)=='X';
|
|
}
|
|
private static boolean isAlphanumeric(String storedCodeBlock,int j) {
|
|
return storedCodeBlock.charAt(j)>='0'&&storedCodeBlock.charAt(j)<='9'||storedCodeBlock.charAt(j)>='A'&&storedCodeBlock.charAt(j)<='Z'||storedCodeBlock.charAt(j)>='a'&&storedCodeBlock.charAt(j)<='z';
|
|
}
|
|
|
|
sigServer() {
|
|
try {
|
|
socket = new ServerSocket(sigPlace.PORT);
|
|
System.out.println("Listening on port "+sigPlace.PORT+".");
|
|
while (true) {
|
|
try (Socket client = socket.accept()) {
|
|
System.out.println("New client connection detected: "+client.toString());
|
|
InputStreamReader reader = new InputStreamReader(client.getInputStream(),"ISO-8859-1");
|
|
BufferedReader in = new BufferedReader(reader);
|
|
String requestLine,line;
|
|
ZonedDateTime modifiedDate = null;
|
|
String boundary=null;
|
|
boolean truncateUntilBoundary=false;
|
|
String filename=null;
|
|
OutputStream stream = null;
|
|
int expectedDataLength=0;
|
|
requestLine=in.readLine(); //Read the first line, this should be our request.
|
|
//System.out.println(requestLine);
|
|
if (requestLine!=null) {
|
|
String[] splitter = requestLine.split(Pattern.quote(" "));
|
|
boolean ISPOST = splitter[0].equals("POST");
|
|
boolean isApplication=false;
|
|
if (splitter.length==3) {
|
|
while (in.ready()) {
|
|
line=in.readLine();
|
|
//System.out.println(line);
|
|
if (ISPOST) {
|
|
if (isApplication) {
|
|
if (line.length()==0) { //Now expecting the body since the header is done.
|
|
for (int i=0;i<expectedDataLength;i++) {
|
|
System.out.print((char)in.read());
|
|
}
|
|
break;
|
|
}
|
|
} else //File transfer?
|
|
if (boundary!=null) {
|
|
if (!truncateUntilBoundary) {
|
|
System.out.println(line);
|
|
|
|
if (boundary.length()>0) {
|
|
if (line.equals(boundary)) {
|
|
truncateUntilBoundary=true;
|
|
}
|
|
}
|
|
} else
|
|
if (line.contains("Content-Disposition: ")||line.contains("Content-Type: ")) {
|
|
if (line.contains("filename=")) {
|
|
filename=line.substring(line.indexOf("filename=")+"filename=".length()+1);
|
|
filename = filename.substring(0,filename.length()-1);
|
|
} else {
|
|
System.out.println(line);
|
|
}
|
|
} else {
|
|
File myFile = new File(new File(sigPlace.OUTDIR,sigPlace.UPLOADSDIR),filename);
|
|
// check if file exist, otherwise create the file before writing
|
|
myFile.mkdirs();
|
|
if (!myFile.exists()) {
|
|
myFile.createNewFile();
|
|
} else {
|
|
myFile.delete();
|
|
myFile.createNewFile();
|
|
}
|
|
stream = new FileOutputStream(myFile);
|
|
char[] buffer = new char[1024];
|
|
int count;
|
|
while ((count = in.read(buffer))>0) {
|
|
//stream.write(in.read(buffer));
|
|
//stream.write(buffer.,0,count);
|
|
String buf = new String(buffer);
|
|
byte[] data = buf.getBytes("ISO-8859-1");
|
|
stream.write(data,0,count);
|
|
if (buf.contains(boundary)) {
|
|
System.out.println("");
|
|
System.out.println("<...>");
|
|
System.out.println("");
|
|
System.out.println(new String(data,StandardCharsets.UTF_8));
|
|
break;
|
|
}
|
|
}
|
|
stream.close();
|
|
|
|
filename=null;
|
|
System.out.println("Saving upload to "+sigPlace.UPLOADSDIR+" directory.");
|
|
}
|
|
}
|
|
if (line.contains("Content-Length: ")) {
|
|
expectedDataLength=Integer.parseInt(line.substring("Content-Length: ".length()));
|
|
System.out.println("Expecting a length of "+expectedDataLength);
|
|
}
|
|
if (line.contains("Content-Type:")) {
|
|
if (line.contains("Content-Type: multipart/form-data; boundary=")) {
|
|
boundary="--"+line.substring("Content-Type: multipart/form-data; boundary=".length());
|
|
} else
|
|
if (line.contains("application/json")){
|
|
isApplication=true;
|
|
System.out.println("Application request detected.");
|
|
//Keep going for now.
|
|
} else {
|
|
break; //Incompatible type.
|
|
}
|
|
}
|
|
} else
|
|
if (modifiedDate==null&&line.startsWith("If-Modified-Since: ")) {
|
|
String modifiedSince=line.replace("If-Modified-Since: ","");
|
|
modifiedDate = ZonedDateTime.parse(modifiedSince,DateTimeFormatter.RFC_1123_DATE_TIME);
|
|
//System.out.println("Found a modified date of: "+modifiedDate);
|
|
}
|
|
}
|
|
//This is valid.
|
|
if (splitter[0].equals("GET")) { //This is a GET request.
|
|
if (splitter[2].equals("HTTP/1.1")||splitter[2].equals("HTTP/2.0")) {
|
|
String[] requestSplit = splitter[1].split(Pattern.quote("?"));
|
|
String requestloc = requestSplit[0];
|
|
HashMap<String,String> requestParams = new HashMap<>();
|
|
if (requestSplit.length>1) {
|
|
String[] params = requestSplit[1].split(Pattern.quote("&"));
|
|
for (String s : params) {
|
|
String key = s.substring(0,s.indexOf('='));
|
|
String value = s.substring(s.indexOf('=')+1);
|
|
requestParams.put(key,value);
|
|
}
|
|
System.out.println(" ==Params for this request are: "+requestParams);
|
|
}
|
|
if (requestloc.equals("/")) {
|
|
//Send default directory.
|
|
if (modifiedDate==null||modifiedDate.isBefore(GetLastModifiedDate(sigPlace.OUTDIR,"testfile.html"))) {
|
|
System.out.println(GetLastModifiedDate(sigPlace.OUTDIR,"testfile.html")+"//"+modifiedDate);
|
|
CreateRequest(client,"200","OK",Paths.get(sigPlace.OUTDIR,"testfile.html"));
|
|
} else {
|
|
//System.out.println(" testfile.html is cached! No sending required.");
|
|
CreateRequest(client,"304","Not Modified",Paths.get(sigPlace.OUTDIR,"testfile.html"));
|
|
}
|
|
} else {
|
|
String location = URLDecoder.decode(requestloc.replaceFirst("/",""),StandardCharsets.UTF_8);
|
|
|
|
Path file = null;
|
|
if (location.equals("COMMENTS")) {
|
|
file = Paths.get(sigPlace.COMMENTSDIR,requestParams.get("article"));
|
|
} else {
|
|
file = Paths.get(sigPlace.OUTDIR,location);
|
|
}
|
|
if (location.equals("COMMENTS")&&requestParams.containsKey("message")&&requestParams.containsKey("name")&&requestParams.containsKey("color")) {
|
|
//System.out.println(requestParams);
|
|
String finalMsg = requestParams.get("message").replaceAll(Pattern.quote("%3C"),"<");
|
|
if (finalMsg.length()>0&&URLDecoder.decode(requestParams.get("message"),StandardCharsets.UTF_8).replaceAll(Pattern.quote(" "),"").length()<=1000&&
|
|
(requestParams.get("color").equals("BLUE")||
|
|
requestParams.get("color").equals("RED")||
|
|
requestParams.get("color").equals("GREEN")||
|
|
requestParams.get("color").equals("YELLOW")||
|
|
requestParams.get("color").equals("MAGENTA")||
|
|
requestParams.get("color").equals("CYAN")||
|
|
requestParams.get("color").equals("WHITE"))) {
|
|
boolean boldBlock=false;
|
|
boolean italicBlock=false;
|
|
boolean underlineBlock=false;
|
|
boolean codeBlock=false;
|
|
boolean linkBlock=false;
|
|
StringBuilder storedLink=new StringBuilder();
|
|
StringBuilder codeBlockMsg = new StringBuilder();
|
|
StringBuilder buildMsg = new StringBuilder();
|
|
for (int i=0;i<finalMsg.length();i++) {
|
|
if (i<finalMsg.length()-1&&finalMsg.charAt(i)=='~'&&finalMsg.charAt(i+1)=='~') {
|
|
if (codeBlock) {
|
|
codeBlockMsg.append("~~");
|
|
String storedCodeBlock="";
|
|
String s = URLDecoder.decode(codeBlockMsg.toString().replaceAll(Pattern.quote("%0A"),"\\\\\\\\NEWLINE\\\\\\\\"),StandardCharsets.UTF_8.toString());
|
|
boolean keyword=false;
|
|
boolean inString=false;
|
|
boolean inComment=false;
|
|
boolean inMultiLineComment=false;
|
|
char stringChar=' ';
|
|
boolean canBeNumericalConstant=false;
|
|
int lengthOfConstant=0;
|
|
storedCodeBlock+=s.substring(0,s.indexOf("~~"));
|
|
storedCodeBlock=storedCodeBlock.replaceAll(Pattern.quote("<"),"\2");
|
|
int startPos=0;
|
|
String endText=s.substring(s.indexOf("~~")+"~~".length(),s.length());
|
|
s="";
|
|
for (int j=0;j<storedCodeBlock.length()-1;j++) {
|
|
if (storedCodeBlock.charAt(j)=='\n'&&inString) {
|
|
inString=false;
|
|
s+="</span>";
|
|
} else
|
|
if (storedCodeBlock.charAt(j)=='\n'&&inComment) {
|
|
inComment=false;
|
|
s+=SPAN("comment")+storedCodeBlock.substring(startPos,j)+"</span>";
|
|
startPos=j+1;
|
|
}
|
|
if (!inComment&&!inMultiLineComment&&(j>0&&storedCodeBlock.charAt(j-1)!='\\'&&(!inString&&(storedCodeBlock.charAt(j)=='"'||storedCodeBlock.charAt(j)=='\'')||inString&&(storedCodeBlock.charAt(j)==stringChar)))) {
|
|
inString=!inString;
|
|
if (inString) {
|
|
stringChar=storedCodeBlock.charAt(j);
|
|
s+=SPAN("string")+stringChar;
|
|
} else {
|
|
s+=stringChar;
|
|
s+="</span>";
|
|
startPos=j+1;
|
|
}
|
|
} else
|
|
if (!inString) {
|
|
if (canBeNumericalConstant&&validNumericalConstantCharacters(storedCodeBlock,lengthOfConstant, j)) {
|
|
lengthOfConstant++;
|
|
//System.out.println("Length of Constant now "+lengthOfConstant);
|
|
}
|
|
if (j>0&&storedCodeBlock.charAt(j)=='/'&&storedCodeBlock.charAt(j+1)=='*'||inMultiLineComment) {
|
|
if (!inMultiLineComment) {
|
|
inMultiLineComment=true;
|
|
} else {
|
|
if (storedCodeBlock.charAt(j-1)=='*'&&storedCodeBlock.charAt(j)=='/') {
|
|
inMultiLineComment=false;
|
|
s+=SPAN("comment")+storedCodeBlock.substring(startPos,j)+storedCodeBlock.charAt(j)+"</span>";
|
|
startPos=j+1;
|
|
}
|
|
}
|
|
//Stops further execution since we're in a comment.
|
|
} else
|
|
if (j>0&&storedCodeBlock.charAt(j)=='/'&&storedCodeBlock.charAt(j+1)=='/'||inComment) {
|
|
if (!inComment) {
|
|
inComment=true;
|
|
}
|
|
//Stops further execution since we're in a comment.
|
|
} else
|
|
if (canBeNumericalConstant&&lengthOfConstant>0&&!(validNumericalConstantCharacters(storedCodeBlock,lengthOfConstant, j))) {
|
|
s+=SPAN("number")+storedCodeBlock.substring(startPos,j)+"</span>"+storedCodeBlock.charAt(j);
|
|
//System.out.println("Setting "+storedCodeBlock.substring(startPos,j)+storedCodeBlock.charAt(j));
|
|
lengthOfConstant=0;
|
|
canBeNumericalConstant=false;
|
|
startPos=j+1;
|
|
} else
|
|
if (!canBeNumericalConstant&&storedCodeBlock.charAt(j)=='.') {
|
|
//Previous section was a member.
|
|
s+=SPAN("class")+storedCodeBlock.substring(startPos,j)+"</span>"+storedCodeBlock.charAt(j);
|
|
startPos=j+1;
|
|
} else
|
|
if (j>3&&storedCodeBlock.substring(j-3,j+1).equals("true")&&!isAlphanumeric(storedCodeBlock,j-4)&&!isAlphanumeric(storedCodeBlock,j+1)) {
|
|
s+=SPAN("number")+storedCodeBlock.substring(startPos,j)+storedCodeBlock.charAt(j)+"</span>";
|
|
startPos=j+1;
|
|
} else
|
|
if (j>4&&storedCodeBlock.substring(j-4,j+1).equals("false")&&!isAlphanumeric(storedCodeBlock,j-5)&&!isAlphanumeric(storedCodeBlock,j+1)) {
|
|
s+=SPAN("number")+storedCodeBlock.substring(startPos,j)+storedCodeBlock.charAt(j)+"</span>";
|
|
startPos=j+1;
|
|
} else
|
|
if (storedCodeBlock.charAt(j)=='(') {
|
|
s+=SPAN("function")+storedCodeBlock.substring(startPos,j)+"</span>"+storedCodeBlock.charAt(j);
|
|
startPos=j+1;
|
|
} else
|
|
if (j>0&&isAlphanumeric(storedCodeBlock,j-1) && storedCodeBlock.charAt(j)==' '&&storedCodeBlock.charAt(j-1)!=' ') {
|
|
//Previous section was a keyword.
|
|
keyword=true;
|
|
s+=SPAN("keyword")+storedCodeBlock.substring(startPos,j)+"</span>"+storedCodeBlock.charAt(j);
|
|
startPos=j+1;
|
|
} else
|
|
if (j>0&&isAlphanumeric(storedCodeBlock,j-1) && (storedCodeBlock.charAt(j)==';'||storedCodeBlock.charAt(j)==':')) {
|
|
//Previous section was a keyword.
|
|
//keyword=true;
|
|
s+=SPAN("keyword")+storedCodeBlock.substring(startPos,j)+"</span>"+storedCodeBlock.charAt(j);
|
|
startPos=j+1;
|
|
} else
|
|
if (keyword&&!(storedCodeBlock.charAt(j)=='_'||storedCodeBlock.charAt(j)>='0'&&storedCodeBlock.charAt(j)<='9'||storedCodeBlock.charAt(j)>='A'&&storedCodeBlock.charAt(j)<='Z'||storedCodeBlock.charAt(j)>='a'&&storedCodeBlock.charAt(j)<='z'||storedCodeBlock.charAt(j)==' ')) {
|
|
keyword=false;
|
|
s+=SPAN("variable")+storedCodeBlock.substring(startPos,j)+"</span>"+storedCodeBlock.charAt(j);
|
|
startPos=j+1;
|
|
} else
|
|
if (!isAlphanumeric(storedCodeBlock,j)){
|
|
if (startPos<j) {
|
|
s+=storedCodeBlock.substring(startPos,j)+storedCodeBlock.charAt(j);
|
|
} else {
|
|
s+=storedCodeBlock.charAt(j);
|
|
}
|
|
startPos=j+1;
|
|
}
|
|
} else {
|
|
s+=storedCodeBlock.charAt(j);
|
|
startPos=j+1;
|
|
}
|
|
if (canBeNumericalConstant&&lengthOfConstant==0&&!(storedCodeBlock.charAt(j)>='0'&&storedCodeBlock.charAt(j)<='9')) {
|
|
canBeNumericalConstant=false;
|
|
}
|
|
if (!canBeNumericalConstant&&!isAlphanumeric(storedCodeBlock,j)) {
|
|
canBeNumericalConstant=true;
|
|
lengthOfConstant=0;
|
|
//System.out.println("Found "+storedCodeBlock.charAt(j)+", can be numeric...");
|
|
}
|
|
}
|
|
for (int j=0;j<s.length();j++) {
|
|
if (s.charAt(j)=='\2') {
|
|
s=s.substring(0,j)+"<"+s.substring(j+1,s.length());
|
|
}
|
|
}
|
|
s="<pre>"+s+"</pre>";
|
|
s+=endText;
|
|
buildMsg.append(s);
|
|
} else {
|
|
codeBlockMsg=codeBlockMsg.delete(0, codeBlockMsg.length());
|
|
}
|
|
i+=1;
|
|
codeBlock=!codeBlock;
|
|
continue;
|
|
} else
|
|
if (codeBlock) {
|
|
codeBlockMsg.append(finalMsg.charAt(i));continue;
|
|
}
|
|
if (foundSub("%5E%5E",finalMsg,i)) {
|
|
if (boldBlock) {
|
|
buildMsg.append("</b>");
|
|
} else {
|
|
buildMsg.append("<b>");
|
|
}
|
|
boldBlock=!boldBlock;
|
|
i+=5;
|
|
continue;
|
|
}
|
|
if (i<finalMsg.length()-1&&finalMsg.charAt(i)=='*'&&finalMsg.charAt(i+1)=='*') {
|
|
if (italicBlock) {
|
|
buildMsg.append("</i>");
|
|
} else {
|
|
buildMsg.append("<i>");
|
|
}
|
|
italicBlock=!italicBlock;
|
|
i+=1;
|
|
continue;
|
|
}
|
|
if (i<finalMsg.length()-1&&finalMsg.charAt(i)=='_'&&finalMsg.charAt(i +1)=='_') {
|
|
if (underlineBlock) {
|
|
buildMsg.append("</u>");
|
|
} else {
|
|
buildMsg.append("<u>");
|
|
}
|
|
underlineBlock=!underlineBlock;
|
|
i+=1;
|
|
continue;
|
|
}
|
|
if (foundSub("%5B%5B",finalMsg,i)||foundSub("%5D%5D",finalMsg,i)) {
|
|
if (linkBlock) {
|
|
buildMsg.append("\">").append(storedLink).append("</a>");
|
|
} else {
|
|
storedLink.delete(0,storedLink.length());
|
|
buildMsg.append("<a href=\"");
|
|
}
|
|
linkBlock=!linkBlock;
|
|
i+=5;
|
|
continue;
|
|
}
|
|
if (linkBlock) {
|
|
storedLink.append(finalMsg.charAt(i));
|
|
}
|
|
if (i<finalMsg.length()-1&&finalMsg.charAt(i)=='_'&&finalMsg.charAt(i+1)=='_') {
|
|
if (underlineBlock) {
|
|
buildMsg.append("</u>");
|
|
} else {
|
|
buildMsg.append("<u>");
|
|
}
|
|
underlineBlock=!underlineBlock;
|
|
i+=1;
|
|
continue;
|
|
}
|
|
if (finalMsg.charAt(i)=='<') {
|
|
buildMsg.append("<");
|
|
continue;
|
|
}
|
|
buildMsg.append(finalMsg.charAt(i));
|
|
}
|
|
if (Files.exists(Paths.get(sigPlace.COMMENTSDIR,requestParams.get("article")))) {
|
|
List<String> data = Files.readAllLines(Paths.get(sigPlace.COMMENTSDIR,requestParams.get("article")));
|
|
data.set(0,Integer.toString(Integer.parseInt(data.get(0))+1));
|
|
data.add(buildMsg.toString()+"\n"+requestParams.get("name")+ZonedDateTime.now()+";"+requestParams.get("color"));
|
|
Files.write(Paths.get(sigPlace.COMMENTSDIR,requestParams.get("article")), data, StandardOpenOption.TRUNCATE_EXISTING,StandardOpenOption.WRITE);
|
|
} else {
|
|
List<String> data = new ArrayList<String>();
|
|
data.add("1");
|
|
data.add(buildMsg.toString()+"\n"+requestParams.get("name")+ZonedDateTime.now()+";"+requestParams.get("color"));
|
|
Files.write(Paths.get(sigPlace.COMMENTSDIR,requestParams.get("article")), data, StandardOpenOption.TRUNCATE_EXISTING,StandardOpenOption.WRITE,StandardOpenOption.CREATE_NEW);
|
|
}
|
|
CreateRequest(client,"200","OK",Paths.get(sigPlace.OUTDIR,"testfile.html"));
|
|
} else {
|
|
CreateRequest(client,"304","Not Modified",Paths.get(sigPlace.OUTDIR,"testfile.html"));
|
|
}
|
|
} else {
|
|
if (modifiedDate==null||Files.exists(file)&&modifiedDate.isBefore(GetLastModifiedDate(file)))
|
|
{
|
|
CreateRequest(client,"200","OK",file);
|
|
} else {
|
|
//System.out.println(" "+location+" is cached! No sending required.");
|
|
CreateRequest(client,"304","Not Modified",file);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else
|
|
if (splitter[0].equals("POST")) { //This is a POST request.
|
|
if (boundary!=null) {
|
|
CreateRequest(client,"200","OK",Paths.get(sigPlace.OUTDIR,"testfile.html"));
|
|
} else {
|
|
CreateRequest(client,"400","Bad Request",Paths.get(sigPlace.OUTDIR,"testfile.html"));
|
|
}
|
|
} else {
|
|
CreateRequest(client,"501","Not Implemented",Paths.get(sigPlace.OUTDIR,"testfile.html"));
|
|
}
|
|
} else {
|
|
in.close();
|
|
CreateRequest(client,"400","Bad Request",Paths.get(sigPlace.OUTDIR,"testfile.html"));
|
|
}
|
|
}
|
|
} catch(SocketException|NullPointerException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
private boolean foundSub(String string, String finalMsg, int i) {
|
|
if (i+string.length()<=finalMsg.length()) {
|
|
for (int j=0;j<string.length();j++) {
|
|
if (string.charAt(j)!=finalMsg.charAt(i+j)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
private ZonedDateTime GetLastModifiedDate(Path p) throws IOException {
|
|
Instant newTime = Files.getLastModifiedTime(p).toInstant();
|
|
newTime = newTime.truncatedTo(ChronoUnit.SECONDS);
|
|
return newTime.atZone(ZoneId.of("GMT"));
|
|
}
|
|
|
|
private ZonedDateTime GetLastModifiedDate(String first,String...more) throws IOException {
|
|
return GetLastModifiedDate(Paths.get(first,more));
|
|
}
|
|
|
|
private void CreateRawRequest(OutputStream stream, String statusCode, String statusMsg, String contentType, byte[] content) {
|
|
CreateRawRequest(stream, statusCode, statusMsg, contentType, content,null);
|
|
}
|
|
|
|
private void CreateRawRequest(OutputStream stream, String statusCode, String statusMsg, String contentType, byte[] content, FileTime lastModified) {
|
|
try {
|
|
stream.write(("HTTP/1.1 "+statusCode+" "+statusMsg+"\r\n").getBytes());
|
|
stream.write(("ContentType: "+contentType+"\r\n").getBytes());
|
|
if (lastModified!=null) {
|
|
ZonedDateTime date = lastModified.toInstant().truncatedTo(ChronoUnit.SECONDS).atZone(ZoneId.of("GMT"));
|
|
stream.write(("Last-Modified: "+date.format(DateTimeFormatter.RFC_1123_DATE_TIME)+"\r\n").getBytes());
|
|
}
|
|
stream.write("\r\n".getBytes());
|
|
stream.write(content);
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
private void CreateRequest(Socket client, String statusCode, String statusMsg, Path file) {
|
|
long startTime = System.currentTimeMillis();
|
|
try {
|
|
OutputStream clientOutput = client.getOutputStream();
|
|
if (statusCode.equals("200")) {
|
|
if (Files.exists(file)) {
|
|
if (Files.isDirectory(file)) {
|
|
CreateRawRequest(clientOutput,statusCode,statusMsg,"text/html",Files.readAllBytes(Paths.get(file.toAbsolutePath().toString(),sigPlace.DIRECTORYLISTING_FILENAME)),Files.getLastModifiedTime(file));
|
|
clientOutput.write(("<div class=\"generateTime\">Webpage generated in "+(System.currentTimeMillis()-startTime)+"ms</div>\r\n").getBytes());
|
|
} else {
|
|
CreateRawRequest(clientOutput,statusCode,statusMsg,Files.probeContentType(file),Files.readAllBytes(file),Files.getLastModifiedTime(file));
|
|
String contentType = Files.probeContentType(file);
|
|
if (contentType!=null&&contentType.equals("text/html")) {
|
|
clientOutput.write(("<div class=\"generateTime\">Webpage generated in "+(System.currentTimeMillis()-startTime)+"ms</div>\r\n").getBytes());
|
|
}
|
|
//System.out.println(contentType);
|
|
}
|
|
System.out.println("Sent "+file+" to client "+client+".");
|
|
} else {
|
|
System.out.println("Did not find "+file+". Sending an error instead.");
|
|
file=Paths.get(sigPlace.OUTDIR,"error.html");
|
|
CreateRawRequest(clientOutput,"404",statusMsg,Files.probeContentType(file),Files.readAllBytes(file),Files.getLastModifiedTime(file));
|
|
String contentType = Files.probeContentType(file);
|
|
if (contentType!=null&&contentType.equals("text/html")) {
|
|
clientOutput.write(("<div class=\"generateTime\">Webpage generated in "+(System.currentTimeMillis()-startTime)+"ms</div>\r\n").getBytes());
|
|
}
|
|
}
|
|
} else {
|
|
CreateRawRequest(clientOutput,statusCode,statusMsg,Files.probeContentType(file),Files.readAllBytes(file),Files.getLastModifiedTime(file));
|
|
String contentType = Files.probeContentType(file);
|
|
if (contentType!=null&&contentType.equals("text/html")) {
|
|
clientOutput.write(("<div class=\"generateTime\">Webpage generated in "+(System.currentTimeMillis()-startTime)+"ms</div>\r\n").getBytes());
|
|
}
|
|
System.out.println("Sent "+file+" with status ["+statusCode+"] "+statusMsg);
|
|
}
|
|
clientOutput.write("\r\n\r\n".getBytes());
|
|
clientOutput.flush();
|
|
client.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
|