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.Charset; 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 ""; } 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;i0) { 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 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("%0A"),"
").replaceAll(Pattern.quote("%3C"),"<"); if (finalMsg.length()>0) { 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"; 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+="
"; 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)+""; 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)+""+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)+""+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)+""; 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)+""; startPos=j+1; } else if (storedCodeBlock.charAt(j)=='(') { s+=SPAN("function")+storedCodeBlock.substring(startPos,j)+""+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)+""+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)+""+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)+""+storedCodeBlock.charAt(j); startPos=j+1; } else if (!isAlphanumeric(storedCodeBlock,j)){ if (startPos='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"); } else { buildMsg.append(""); } boldBlock=!boldBlock; i+=5; continue; } if (i"); } else { buildMsg.append(""); } italicBlock=!italicBlock; i+=1; continue; } if (i"); } else { buildMsg.append(""); } underlineBlock=!underlineBlock; i+=1; continue; } if (foundSub("%5B%5B",finalMsg,i)||foundSub("%5D%5D",finalMsg,i)) { if (linkBlock) { buildMsg.append("\">").append(storedLink).append(""); } else { storedLink.delete(0,storedLink.length()); buildMsg.append(" 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 data = new ArrayList(); 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;jWebpage generated in "+(System.currentTimeMillis()-startTime)+"ms\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(("
Webpage generated in "+(System.currentTimeMillis()-startTime)+"ms
\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(("
Webpage generated in "+(System.currentTimeMillis()-startTime)+"ms
\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(("
Webpage generated in "+(System.currentTimeMillis()-startTime)+"ms
\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(); } } }