From 18e3175db995f50933c8ae27bf158d1a205138f3 Mon Sep 17 00:00:00 2001 From: Ziver Koc Date: Mon, 30 Mar 2015 01:25:36 +0000 Subject: [PATCH] Added HttpFilePage to hosts static content --- src/zutil/io/file/FileUtil.java | 2 +- src/zutil/log/LogUtil.java | 2 +- src/zutil/net/http/HttpPrintStream.java | 46 ++++-- src/zutil/net/http/HttpServer.java | 32 ++--- src/zutil/net/http/pages/HttpFilePage.java | 155 +++++++++++++++++++++ src/zutil/plugin/PluginData.java | 8 +- src/zutil/plugin/PluginManager.java | 14 +- 7 files changed, 220 insertions(+), 39 deletions(-) create mode 100644 src/zutil/net/http/pages/HttpFilePage.java diff --git a/src/zutil/io/file/FileUtil.java b/src/zutil/io/file/FileUtil.java index 9373957..2df1595 100644 --- a/src/zutil/io/file/FileUtil.java +++ b/src/zutil/io/file/FileUtil.java @@ -278,7 +278,7 @@ public class FileUtil { } /** - * Returns the extension of the file + * Returns the extension(without the dot) of the file. e.g. "png" "avi" * * @param file is the file * @return The extension diff --git a/src/zutil/log/LogUtil.java b/src/zutil/log/LogUtil.java index 79e187b..05f8686 100644 --- a/src/zutil/log/LogUtil.java +++ b/src/zutil/log/LogUtil.java @@ -53,7 +53,7 @@ public class LogUtil { for(int i=1; i pages; private HttpPage defaultPage; private Map> sessions; @@ -79,7 +77,6 @@ public class HttpServer extends ThreadedTCPNetworkServer{ */ public HttpServer(int port, File keyStore, String keyStorePass){ super( port, keyStore, keyStorePass ); - this.server_port = port; pages = new ConcurrentHashMap(); sessions = new ConcurrentHashMap>(); @@ -158,7 +155,7 @@ public class HttpServer extends ThreadedTCPNetworkServer{ out = new HttpPrintStream(socket.getOutputStream()); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); this.socket = socket; - logger.fine("New Connection!!! "+socket.getInetAddress().getHostName()); + logger.fine("New Connection: " + socket.getInetAddress().getHostName()); } public void run(){ @@ -169,10 +166,10 @@ public class HttpServer extends ThreadedTCPNetworkServer{ //**************************** REQUEST ********************************* try { - logger.finer("Reciving Http Request!!!"); + logger.finer("Receiving Http Request"); HttpHeaderParser parser = new HttpHeaderParser(in); - logger.finest(parser.toString()); + //logger.finest(parser.toString()); request = parser.getURLAttributes(); cookie = parser.getCookies(); @@ -202,7 +199,7 @@ public class HttpServer extends ThreadedTCPNetworkServer{ } else if( tmp.contains("multipart/form-data") ){ // TODO: File upload - throw new Exception( "\"multipart-form-data\" Not implemented!!!" ); + throw new Exception( "\"multipart-form-data\" Not implemented." ); } } @@ -227,17 +224,17 @@ public class HttpServer extends ThreadedTCPNetworkServer{ client_session.put( "session_id", nextSessionId ); client_session.put( "ttl", ttl_time ); sessions.put( ""+nextSessionId, client_session ); - nextSessionId++; + ++nextSessionId; } // Debug - if(logger.isLoggable(Level.FINE)){ - logger.finest( "# page_url: "+parser.getRequestURL() ); - logger.finest( "# client_session: "+client_session ); - logger.finest( "# cookie: "+cookie ); - logger.finest( "# request: "+request ); + if(logger.isLoggable(Level.FINEST)){ + logger.finest( "page_url: "+parser.getRequestURL() ); + logger.finest( "client_session: "+client_session ); + logger.finest( "cookie: "+cookie ); + logger.finest( "request: "+request ); } //**************************** RESPONSE ************************************ - logger.finer("Sending Http Response!!!"); + logger.finer("Sending Http Response"); out.setStatusCode(200); out.setHeader( "Server", SERVER_VERSION ); out.setHeader( "Content-Type", "text/html" ); @@ -252,15 +249,14 @@ public class HttpServer extends ThreadedTCPNetworkServer{ else{ out.setStatusCode( 404 ); out.println( "404 Page Not Found: "+parser.getRequestURL() ); - logger.fine( "404 Page Not Found: "+parser.getRequestURL() ); + logger.warning("Page not defined: " + parser.getRequestURL()); } //******************************************************************************** } catch (Exception e) { logger.log(Level.WARNING, "500 Internal Server Error", e); - try { + if(!out.isHeaderSent()) out.setStatusCode( 500 ); - } catch (Exception e1) {} if(e.getMessage() != null) out.println( "500 Internal Server Error: "+e.getMessage() ); else if(e.getCause() != null){ @@ -272,7 +268,7 @@ public class HttpServer extends ThreadedTCPNetworkServer{ } try{ - logger.fine("Connection Closed!!!"); + logger.fine("Connection Closed."); out.close(); in.close(); socket.close(); diff --git a/src/zutil/net/http/pages/HttpFilePage.java b/src/zutil/net/http/pages/HttpFilePage.java new file mode 100644 index 0000000..2263ce6 --- /dev/null +++ b/src/zutil/net/http/pages/HttpFilePage.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2015 Ziver + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package zutil.net.http.pages; + +import zutil.io.IOUtil; +import zutil.io.file.FileUtil; +import zutil.log.LogUtil; +import zutil.net.http.HttpHeaderParser; +import zutil.net.http.HttpPage; +import zutil.net.http.HttpPrintStream; + +import java.io.*; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This Http Page will host static content from the server. + * + * Created by Ziver on 2015-03-30. + */ +public class HttpFilePage implements HttpPage{ + private static final Logger log = LogUtil.getLogger(); + + private File resource_root; + private boolean showFolders; + private boolean redirectToIndex; + + /** + * @param file a reference to a root directory or a file. + */ + public HttpFilePage(File file){ + this.resource_root = file; + this.showFolders = true; + this.redirectToIndex = true; + } + + + @Override + public void respond(HttpPrintStream out, + HttpHeaderParser client_info, + Map session, + Map cookie, + Map request) { + + try { + // Is the root only one file or a folder + if (resource_root.isFile()) { + deliverFile(resource_root, out); + } + else { // Resource root is a folder + File file = new File(resource_root, + client_info.getRequestURL()); + if(file.getAbsolutePath().startsWith(resource_root.getAbsolutePath())){ + if(file.isDirectory() && showFolders){ + File indexFile = new File(file, "index.html"); + // Redirect to index.html + if(redirectToIndex && indexFile.isFile()) { + deliverFile(indexFile, out); + } + // Show folder contents + else if(showFolders){ + out.println("

Directory: " + client_info.getRequestURL() + "

"); + out.println("
    "); + for (String f : file.list()) { + out.println("
  • " + f + "
  • "); + } + out.println("

"); + } + } + else { + deliverFile(file, out); + } + } + else { + throw new SecurityException("File is outside of root directory: root=" + resource_root.getAbsolutePath() + " file=" + file.getAbsolutePath()); + } + } + + }catch (FileNotFoundException e){ + if(!out.isHeaderSent()) + out.setStatusCode(404); + log.log(Level.WARNING, null, e); + out.println("404 Page Not Found: " + client_info.getRequestURL()); + }catch (SecurityException e){ + if(!out.isHeaderSent()) + out.setStatusCode(404); + log.log(Level.WARNING, null, e); + out.println("404 Page Not Found: " + client_info.getRequestURL() ); + }catch (IOException e){ + if(!out.isHeaderSent()) + out.setStatusCode(500); + log.log(Level.WARNING, null, e); + out.println("500 Internal Server Error: "+e.getMessage() ); + } + } + + private void deliverFile(File file, HttpPrintStream out) throws IOException { + out.setHeader("Content-Type", getMIMEType(file)); + out.flush(); + + BufferedInputStream in = new BufferedInputStream(new FileInputStream(file)); + IOUtil.copyStream(in, out); + in.close(); + } + + private String getMIMEType(File file){ + switch(FileUtil.getFileExtension(file)){ + case "css": return "text/css"; + case "cvs": return "text/csv"; + case "jpg": return "image/jpeg"; + case "js": return "application/javascript"; + case "png": return "image/png"; + case "htm": + case "html": return "text/html"; + case "xml": return "text/xml"; + default: return "text/plain"; + } + } + + + /** + * Enable or disable showing of folder contents + */ + public void showFolders(boolean enabled){ + this.showFolders = enabled; + } + + /** + * If directory links should be redirected to index files + */ + public void redirectToIndexFile(boolean enabled){ + this.redirectToIndex = enabled; + } +} diff --git a/src/zutil/plugin/PluginData.java b/src/zutil/plugin/PluginData.java index 6bb9fd8..e10f0d6 100644 --- a/src/zutil/plugin/PluginData.java +++ b/src/zutil/plugin/PluginData.java @@ -56,13 +56,13 @@ public class PluginData { pluginVersion = data.getDouble("version"); pluginName = data.getString("name"); - log.fine("Found plugin: "+pluginName); + log.fine("Plugin: "+this); DataNode node = data.get("interfaces"); Iterator intfIt = node.keyIterator(); while (intfIt.hasNext()) { String intf = intfIt.next(); - log.finer("Plugin interface: "+ intf+"-->"+node.get(intf).getString()); + log.finer("Plugin interface: "+ intf+" --> "+node.get(intf).getString()); classMap.put( getClassByName(intf), getClassByName(node.get(intf).getString())); @@ -98,4 +98,8 @@ public class PluginData { public boolean contains(Class intf){ return classMap.containsKey(intf); } + + public String toString(){ + return getName()+"(ver: "+getVersion()+")"; + } } diff --git a/src/zutil/plugin/PluginManager.java b/src/zutil/plugin/PluginManager.java index 38cbdcc..6af839a 100644 --- a/src/zutil/plugin/PluginManager.java +++ b/src/zutil/plugin/PluginManager.java @@ -71,12 +71,22 @@ public class PluginManager implements Iterable{ for(FileSearch.FileSearchItem file : search){ try { DataNode node = JSONParser.read(IOUtil.getContentString(file.getInputStream())); + log.fine("Found plugin: "+file.getPath()); PluginData plugin = new PluginData(node); - if (!plugins.containsKey(plugin.getName()) || - plugins.get(plugin.getName()).getVersion() < plugin.getVersion()){ + if (!plugins.containsKey(plugin.getName())){ plugins.put(plugin.getName(), plugin); } + else { + double version = plugins.get(plugin.getName()).getVersion(); + if(version < plugin.getVersion()) + plugins.put(plugin.getName(), plugin); + else if(version == plugin.getVersion()) + log.fine("Ignoring duplicate plugin: " + plugin); + else + log.fine("Ignoring outdated plugin: "+plugin); + + } } catch (Exception e) { e.printStackTrace(); }