package net.cubespace.dynmap.multiserver.HTTP.Handler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.DefaultFileRegion; import io.netty.handler.codec.http.*; import net.cubespace.dynmap.multiserver.HTTP.HandlerUtil; import java.io.File; import java.io.FileNotFoundException; import java.io.RandomAccessFile; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Locale; import static io.netty.handler.codec.http.HttpHeaders.Names.*; import static io.netty.handler.codec.http.HttpResponseStatus.*; import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; /** * @author geNAZt (fabian.fassbender42@googlemail.com) */ public class StaticFileHandler implements IHandler { private ArrayList<String> indexFiles = new ArrayList<>(); private String webDir = System.getProperty("user.dir"); @Override public void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { //Check for index final String path = webDir + File.separator + request.getUri(); final String uri = request.getUri(); if (uri.endsWith("/")) { for (String index : indexFiles) { File checkFile = new File(path, index); if (checkFile.exists()) { HandlerUtil.sendRedirect(ctx, uri + index); return; } } } File file = new File(path.replace("/", File.separator)); if (file.isHidden() || !file.exists()) { HandlerUtil.sendError(ctx, NOT_FOUND); return; } if (file.isDirectory()) { if (uri.endsWith("/")) { HandlerUtil.sendError(ctx, FORBIDDEN); } else { HandlerUtil.sendRedirect(ctx, uri + '/'); } return; } if (!file.isFile()) { HandlerUtil.sendError(ctx, FORBIDDEN); return; } // Cache Validation String ifModifiedSince = request.headers().get(IF_MODIFIED_SINCE); if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) { SimpleDateFormat dateFormatter = new SimpleDateFormat(HandlerUtil.HTTP_DATE_FORMAT, Locale.US); Date ifModifiedSinceDate = dateFormatter.parse(ifModifiedSince); // Only compare up to the second because the datetime format we send to the client // does not have milliseconds long ifModifiedSinceDateSeconds = ifModifiedSinceDate.getTime() / 1000; long fileLastModifiedSeconds = file.lastModified() / 1000; if (ifModifiedSinceDateSeconds == fileLastModifiedSeconds) { HandlerUtil.sendNotModified(ctx); return; } } RandomAccessFile raf; try { raf = new RandomAccessFile(file, "r"); } catch (FileNotFoundException fnfe) { HandlerUtil.sendError(ctx, NOT_FOUND); return; } long fileLength = raf.length(); HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK); HandlerUtil.setContentTypeHeader(response, file.getName()); HandlerUtil.setDateAndCacheHeaders(response, file.lastModified()); response.headers().set(CONTENT_LENGTH, fileLength); response.headers().set(CONNECTION, HttpHeaders.Values.CLOSE); response.headers().set(VARY, ACCEPT_ENCODING); // Write the initial line and the header. ctx.write(response); // Write the content. ctx.write(new DefaultFileRegion(raf.getChannel(), 0, fileLength)); ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); } public void addIndex(String file) { indexFiles.add(file); } public void setWebDir(String path) { webDir = path; } }