diff --git a/connectors/jsp/auth.jsp b/connectors/jsp/auth.jsp index 3a313ef5..c83dd020 100644 --- a/connectors/jsp/auth.jsp +++ b/connectors/jsp/auth.jsp @@ -1,10 +1,12 @@ <%! /** * Check if user is authorized - * + * CHANGES + * - added Param request + * * @return boolean true is access granted, false if no access */ - public boolean auth() { + public boolean auth(HttpServletRequest request) { // You can insert your own code over here to check if the user is authorized. return true; } diff --git a/connectors/jsp/filemanager.jsp b/connectors/jsp/filemanager.jsp index 91afc8a1..78393499 100644 --- a/connectors/jsp/filemanager.jsp +++ b/connectors/jsp/filemanager.jsp @@ -1,91 +1,122 @@ +<%@ page pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%> <%@ page language="java" import="java.util.*"%> <%@ page import="com.nartex.*"%> <%@ page import="org.json.JSONObject"%> <%@ page import="java.io.*"%> -<%@ page import="org.apache.commons.fileupload.*"%> -<%@ page import="org.apache.commons.fileupload.disk.*"%> -<%@ page import="org.apache.commons.fileupload.servlet.*"%> <%@include file="auth.jsp"%> <% /* - * connector filemanager.jsp + * connector filemanager.jsp * - * @license MIT License - * @author Dick Toussaint - * @copyright Authors - */ - - FileManager fm = new FileManager(getServletContext(), request); + * @license MIT License + * @author Dick Toussaint + * @copyright Authors + * + * CHANGES: + * - check strictServletCompliance + */ + + FileManagerI fm = new FileManager(getServletContext(), request); + + boolean strictServletCompliance = false; // default value is ISO-8859-1. - JSONObject responseData = null; + JSONObject responseData = null; - String mode = ""; + String mode = ""; boolean putTextarea = false; - if(!auth()) { - fm.error(fm.lang("AUTHORIZATION_REQUIRED")); - } - else { - if(request.getMethod().equals("GET")) { - if(request.getParameter("mode") != null && request.getParameter("mode") != "") { - mode = request.getParameter("mode"); - if (mode.equals("getinfo")){ - if(fm.setGetVar("path", request.getParameter("path"))) { - responseData = fm.getInfo(); - } - } - else if (mode.equals("getfolder")){ - if(fm.setGetVar("path", request.getParameter("path"))) { - responseData = fm.getFolder(); - } - } - else if (mode.equals("rename")){ - if(fm.setGetVar("old", request.getParameter("old")) && - fm.setGetVar("new", request.getParameter("new"))) { - responseData = fm.rename(); - } - } - else if (mode.equals("delete")){ - if(fm.setGetVar("path", request.getParameter("path"))) { - responseData = fm.delete(); - } - } - else if (mode.equals("addfolder")){ - if(fm.setGetVar("path", request.getParameter("path")) && - fm.setGetVar("name", request.getParameter("name"))) { - responseData = fm.addFolder(); - } - } - else if (mode.equals("download")){ - if(fm.setGetVar("path", request.getParameter("path"))) { - fm.download(response); - } - } - else if (mode.equals("preview")){ - if(fm.setGetVar("path", request.getParameter("path"))) { - fm.preview(response); - } - } - else { - fm.error(fm.lang("MODE_ERROR")); - } + if(!auth(request)) { + fm.error(fm.lang("AUTHORIZATION_REQUIRED")); + } + else { + if(request.getMethod().equals("GET")) { + if(request.getParameter("mode") != null && request.getParameter("mode") != "") { + mode = request.getParameter("mode"); + // cft. http://wiki.apache.org/tomcat/FAQ/CharacterEncoding#Q2 + String [] queryParams = null; + Map qpm = new HashMap(); + if (strictServletCompliance) { + queryParams = java.net.URLDecoder.decode(request.getQueryString(), "UTF-8").split("&"); + for (int i = 0; i < queryParams.length; i++) { + String[] qp = queryParams[i].split("="); + if (qp.length >1) { + qpm.put(qp[0], qp[1]); + } else { + qpm.put(qp[0], ""); + } + } + } + if (mode.equals("getinfo")){ + if(fm.setGetVar("path", (strictServletCompliance)? qpm.get("path"): request.getParameter("path"))) { + responseData = fm.getInfo(); + } + } + else if (mode.equals("getfolder")){ + if(fm.setGetVar("path", (strictServletCompliance)? qpm.get("path"):request.getParameter("path"))) { + responseData = fm.getFolder(); + } + } + else if (mode.equals("rename")){ + if(fm.setGetVar("old", (strictServletCompliance)? qpm.get("old"):request.getParameter("old")) && + fm.setGetVar("new", (strictServletCompliance)? qpm.get("new"):request.getParameter("new"))) { + responseData = fm.rename(); + } + } + else if (mode.equals("delete")){ + if(fm.setGetVar("path", (strictServletCompliance)? qpm.get("path"):request.getParameter("path"))) { + responseData = fm.delete(); + } + } + else if (mode.equals("addfolder")){ + if(fm.setGetVar("path", (strictServletCompliance)? qpm.get("path"):request.getParameter("path")) && + fm.setGetVar("name", (strictServletCompliance)? qpm.get("name"):request.getParameter("name"))) { + responseData = fm.addFolder(); + } + } + else if (mode.equals("download")){ + if(fm.setGetVar("path", (strictServletCompliance)? qpm.get("path"):request.getParameter("path"))) { + responseData = fm.download(request, response); + } + } + else if (mode.equals("preview")){ + if(fm.setGetVar("path", (strictServletCompliance)? qpm.get("path"):request.getParameter("path"))) { + fm.preview(response); + } + } else if (mode.equals("move")){ + if(fm.setGetVar("old", (strictServletCompliance)? qpm.get("old"):request.getParameter("old")) && + fm.setGetVar("new", (strictServletCompliance)? qpm.get("new"):request.getParameter("new")) && + fm.setGetVar("root", (strictServletCompliance)? qpm.get("root"):request.getParameter("root")) + ) { + responseData = fm.moveItem(); + } + } + else { + fm.error(fm.lang("MODE_ERROR")); + } + } + } + else if(request.getMethod().equals("POST")){ + mode = "upload"; + responseData = fm.add(); + putTextarea = true; + } + } + if (responseData == null){ + responseData = fm.getError(); + } + if (responseData != null){ + //request.setCharacterEncoding("UTF-8"); + // only if set + if (putTextarea) { + response.setContentType("text/html; charset=UTF-8"); + } else { + response.setContentType("application/json; charset=UTF-8"); } - } - else if(request.getMethod().equals("POST")){ - mode = "upload"; - responseData = fm.add(); - putTextarea = true; - } - } - if (responseData == null){ - responseData = fm.getError(); - } - if (responseData != null){ - PrintWriter pw = response.getWriter(); - String responseStr = responseData.toString(); - if (putTextarea) - responseStr = ""; - //fm.log("c:\\logfilej.txt", "mode:" + mode + ",response:" + responseStr); - pw.print(responseStr); - pw.close(); - } - %> + PrintWriter pw = response.getWriter(); + String responseStr = responseData.toString(); + if (putTextarea) + responseStr = ""; + //fm.log("mode:" + mode + ",response:" + responseStr); + pw.print(responseStr); + pw.close(); + } + %> \ No newline at end of file diff --git a/connectors/jsp/libraries/java/bin/com/nartex/AbstractFM.class b/connectors/jsp/libraries/java/bin/com/nartex/AbstractFM.class new file mode 100644 index 00000000..b30d46e1 Binary files /dev/null and b/connectors/jsp/libraries/java/bin/com/nartex/AbstractFM.class differ diff --git a/connectors/jsp/libraries/java/bin/com/nartex/FileManager.class b/connectors/jsp/libraries/java/bin/com/nartex/FileManager.class index 256123d3..575c288d 100644 Binary files a/connectors/jsp/libraries/java/bin/com/nartex/FileManager.class and b/connectors/jsp/libraries/java/bin/com/nartex/FileManager.class differ diff --git a/connectors/jsp/libraries/java/bin/com/nartex/FileManagerI.class b/connectors/jsp/libraries/java/bin/com/nartex/FileManagerI.class new file mode 100644 index 00000000..44c4d9b4 Binary files /dev/null and b/connectors/jsp/libraries/java/bin/com/nartex/FileManagerI.class differ diff --git a/connectors/jsp/libraries/java/src/com/nartex/AbstractFM.java b/connectors/jsp/libraries/java/src/com/nartex/AbstractFM.java new file mode 100644 index 00000000..6946ff2c --- /dev/null +++ b/connectors/jsp/libraries/java/src/com/nartex/AbstractFM.java @@ -0,0 +1,622 @@ +package com.nartex; + +import java.awt.Dimension; +import java.awt.Image; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.swing.ImageIcon; + +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileItemFactory; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class AbstractFM implements FileManagerI { + + protected static Properties config = null; + protected static JSONObject language = null; + protected Map get = new HashMap(); + protected Map properties = new HashMap(); + protected Map item = new HashMap(); + protected Map params = new HashMap(); + protected Path documentRoot; + protected Path fileManagerRoot = null; + protected String referer = ""; + protected Logger log = LoggerFactory.getLogger("filemanager"); + protected JSONObject error = null; + protected SimpleDateFormat dateFormat; + protected List files = null; + + public AbstractFM(ServletContext servletContext, HttpServletRequest request) throws IOException { + String contextPath = request.getContextPath(); + + Path localPath = Paths.get(servletContext.getRealPath("/")); + Path docRoot4FileManager = localPath.toRealPath(LinkOption.NOFOLLOW_LINKS); + + this.referer = request.getHeader("referer"); + if (referer != null) { + this.fileManagerRoot = docRoot4FileManager. + resolve(referer.substring(referer.indexOf(contextPath) + 1 + contextPath.length(), referer.indexOf("index.html"))); + + } else if (request.getServletPath().indexOf("connectors") > 0) { + this.fileManagerRoot = docRoot4FileManager. + resolve(request.getServletPath().substring(1, request.getServletPath().indexOf("connectors"))); + // no pathInfo + } + log.debug("fileManagerRoot:"+ fileManagerRoot.toRealPath(LinkOption.NOFOLLOW_LINKS)); + + + // get uploaded file list + FileItemFactory factory = new DiskFileItemFactory(); + ServletFileUpload upload = new ServletFileUpload(factory); + if (ServletFileUpload.isMultipartContent(request)) + try { + files = upload.parseRequest(request); + } catch (Exception e) { // no error handling} + } + + this.properties.put("Date Created", null); + this.properties.put("Date Modified", null); + this.properties.put("Height", null); + this.properties.put("Width", null); + this.properties.put("Size", null); + + // load config file + loadConfig(); + + if (config.getProperty("doc_root") != null) { + // contextpath starts with slash + this.documentRoot = Paths.get(config.getProperty("doc_root") + request.getContextPath()); + } else { + if (this.documentRoot == null ) { + this.documentRoot = docRoot4FileManager.toRealPath(LinkOption.NOFOLLOW_LINKS); + } + } + + log.info("final documentRoot:"+ this.documentRoot); + dateFormat = new SimpleDateFormat(config.getProperty("date")); + + this.setParams(); + + loadLanguageFile(); + + } + + @Override + public JSONObject error(String msg, Throwable ex) { + JSONObject errorInfo = new JSONObject(); + try { + errorInfo.put("Error", msg); + errorInfo.put("Code", "-1"); + errorInfo.put("Properties", this.properties); + } catch (Exception e) { + this.error("JSONObject error"); + } + if (ex != null) { + log.error( msg, ex ); + } else { + log.error( msg); + } + this.error = errorInfo; + return error; + } + + + @Override + public JSONObject error(String msg) { + return error(msg, null); + } + + @Override + public JSONObject getError() { + return error; + } + + @Override + public String lang(String key) { + String text = ""; + try { + text = language.getString(key); + } catch (Exception e) { + } + if (text == null || text.equals("") ) + text = "Language string error on " + key; + return text; + } + + @Override + public boolean setGetVar(String var, String value) { + boolean retval = false; + if (value == null || value == "") { + this.error(sprintf(lang("INVALID_VAR"), var)); + } else { + // clean first slash, as Path does not resolve it relative otherwise + if (var.equals("path") && value.startsWith("/")) { + value = value.replaceFirst("/", ""); + } + this.get.put(var, sanitize(value)); + retval = true; + } + return retval; + } + + + protected boolean checkImageType() { + return this.params + .get("type").equals("Image") + && contains(config.getProperty("images"), (String) this.item.get("filetype")); + } + + protected boolean checkFlashType() { + return this.params + .get("type").equals("Flash") + && contains(config.getProperty("flash"), (String) this.item.get("filetype")); + } + + @Override + public JSONObject rename() { + if ((this.get.get("old")).endsWith("/")) { + this.get.put("old", (this.get.get("old")).substring(0, ((this.get.get("old")).length() - 1))); + } + boolean error = false; + JSONObject array = null; + String tmp[] = (this.get.get("old")).split("/"); + String filename = tmp[tmp.length - 1]; + int pos = this.get.get("old").lastIndexOf("/"); + String path = (this.get.get("old")).substring(0, pos + 1); + Path fileFrom = null; + Path fileTo = null; + try { + fileFrom = this.documentRoot.resolve(path).resolve(filename); + fileTo = this.documentRoot.resolve(path).resolve( this.get.get("new")); + if (fileTo.toFile().exists()) { + if (fileTo.toFile().isDirectory()) { + this.error(sprintf(lang("DIRECTORY_ALREADY_EXISTS"), this.get.get("new"))); + error = true; + } else { // fileTo.isFile + // Files.isSameFile(fileFrom, fileTo); + this.error(sprintf(lang("FILE_ALREADY_EXISTS"), this.get.get("new"))); + error = true; + } + } else { + //if (fileFrom.equals(fileTo)); + Files.move(fileFrom, fileTo, StandardCopyOption.REPLACE_EXISTING); + } + } catch (Exception e) { + if (fileFrom.toFile().isDirectory()) { + this.error(sprintf(lang("ERROR_RENAMING_DIRECTORY"), filename + "#" + this.get.get("new")),e); + } else { + this.error(sprintf(lang("ERROR_RENAMING_FILE"), filename + "#" + this.get.get("new")),e); + } + error = true; + } + if (!error) { + array = new JSONObject(); + try { + array.put("Error", ""); + array.put("Code", 0); + array.put("Old Path", this.get.get("old")); + array.put("Old Name", filename); + array.put("New Path", path + this.get.get("new")); + array.put("New Name", this.get.get("new")); + } catch (Exception e) { + this.error("JSONObject error"); + } + } + return array; + } + + @Override + public JSONObject delete() { + JSONObject array = null; + File file = this.documentRoot .resolve( this.get.get("path")).toFile(); + //new File(this.documentRoot + this.get.get("path")); + if (file.isDirectory()) { + array = new JSONObject(); + this.unlinkRecursive(this.documentRoot.resolve( this.get.get("path")).toFile(), true); + try { + array.put("Error", ""); + array.put("Code", 0); + array.put("Path", this.get.get("path")); + } catch (Exception e) { + this.error("JSONObject error"); + } + } else if (file.exists()) { + array = new JSONObject(); + if (file.delete()) { + try { + array.put("Error", ""); + array.put("Code", 0); + array.put("Path", this.get.get("path")); + } catch (Exception e) { + this.error("JSONObject error"); + } + } else + this.error(sprintf(lang("ERROR_DELETING FILE"), this.get.get("path"))); + return array; + } else { + this.error(lang("INVALID_DIRECTORY_OR_FILE")); + } + return array; + } + + + @Override + public JSONObject addFolder() { + JSONObject array = null; + String allowed[] = { "-", " " }; + LinkedHashMap strList = new LinkedHashMap(); + strList.put("fileName", this.get.get("name")); + String filename = cleanString(strList, allowed).get("fileName"); + if (filename.length() == 0) // the name existed of only special + // characters + this.error(sprintf(lang("UNABLE_TO_CREATE_DIRECTORY"), this.get.get("name"))); + else { + File file = this.documentRoot.resolve(this.get.get("path")).resolve(filename).toFile(); + if (file.isDirectory()) { + this.error(sprintf(lang("DIRECTORY_ALREADY_EXISTS"), filename)); + } else if (!file.mkdir()) { + this.error(sprintf(lang("UNABLE_TO_CREATE_DIRECTORY"), filename)); + } else { + try { + array = new JSONObject(); + array.put("Parent", this.get.get("path")); + array.put("Name", filename); + array.put("Error", ""); + array.put("Code", 0); + } catch (Exception e) { + this.error("JSONObject error"); + } + } + } + return array; + } + + @Override + public JSONObject moveItem() { + if ((this.get.get("old")).endsWith("/")) { + this.get.put("old", (this.get.get("old")).substring(0, ((this.get.get("old")).length() - 1))); + } + boolean error = false; + JSONObject array = null; + String tmp[] = (this.get.get("old")).split("/"); + String filename = tmp[tmp.length - 1]; + int pos = this.get.get("old").lastIndexOf("/"); + String path = (this.get.get("old")).substring(0, pos + 1); + String root = this.get.get("root"); // slash at beginning and end + String folder = this.get.get("new"); + if (folder.trim().startsWith( "/")) { + folder = folder.trim().replaceFirst( "/", "" ); + } + if (!folder.equals( "" )) { + folder = (folder.endsWith( "/" ))? folder:folder+"/"; + } + File fileFrom = null; + File fileTo = null; + log.info( "moving file from "+ this.documentRoot.resolve(this.get.get("old")) + +" to " + this.documentRoot.resolve(root).resolve(folder).resolve(filename)); + try { + fileFrom = this.documentRoot.resolve(this.get.get("old")).toFile(); + fileTo = this.documentRoot.resolve(root).resolve(folder).resolve(filename).toFile(); + if (fileTo.exists()) { + if (fileTo.isDirectory()) { + this.error(sprintf(lang("DIRECTORY_ALREADY_EXISTS"),this.documentRoot.resolve(root).resolve(folder).resolve(filename).toString())); + error = true; + } else { // fileTo.isFile + this.error(sprintf(lang("FILE_ALREADY_EXISTS"), folder + filename )); + error = true; + } + } else if (!fileFrom.renameTo(fileTo)) { + this.error(sprintf(lang("ERROR_RENAMING_DIRECTORY"), filename + "#" + this.get.get("new"))); + error = true; + } + } catch (Exception e) { + if (fileFrom.isDirectory()) { + this.error(sprintf(lang("ERROR_RENAMING_DIRECTORY"), filename + "#" + this.get.get("new"))); + } else { + this.error(sprintf(lang("ERROR_RENAMING_FILE"), filename + "#" + this.get.get("new"))); + } + error = true; + } + if (!error) { + array = new JSONObject(); + try { + array.put("Error", ""); + array.put("Code", 0); + array.put("Old Path", path); + array.put("Old Name", filename); + array.put("New Path", root + folder); + array.put("New Name", filename); + } catch (Exception e) { + this.error("JSONObject error"); + } + } + return array; + } + + protected void readFile(HttpServletResponse resp, File file) { + OutputStream os = null; + FileInputStream fis = null; + try { + os = resp.getOutputStream(); + fis = new FileInputStream(file); + byte fileContent[] = new byte[(int) file.length()]; + fis.read(fileContent); + os.write(fileContent); + } catch (Exception e) { + this.error(sprintf(lang("INVALID_DIRECTORY_OR_FILE"), file.getName())); + } finally { + try { + if (os != null) + os.close(); + } catch (Exception e2) { + } + try { + if (fis != null) + fis.close(); + } catch (Exception e2) { + } + } + } + + @Override + public void preview(HttpServletResponse resp) { + File file =this.documentRoot.resolve(this.get.get("path")).toFile(); + if (this.get.get("path") != null && file.exists()) { + resp.setHeader("Content-type", "image/" + getFileExtension(file.getName())); + resp.setHeader("Content-Transfer-Encoding", "Binary"); + resp.setHeader("Content-length", "" + file.length()); + resp.setHeader("Content-Disposition", "inline; filename=\"" + getFileBaseName(file.getName()) + "\""); + readFile(resp, file); + } else { + error(sprintf(lang("FILE_DOES_NOT_EXIST"), this.get.get("path"))); + } + } + + protected String getFileBaseName(String filename) { + String retval = filename; + int pos = filename.lastIndexOf("."); + if (pos > 0) + retval = filename.substring(0, pos); + return retval; + } + + protected String getFileExtension(String filename) { + String retval = filename; + int pos = filename.lastIndexOf("."); + if (pos > 0) + retval = filename.substring(pos + 1); + return retval; + } + + protected void setParams() { + if (this.referer != null) { + String[] tmp = this.referer.split("\\?"); + String[] params_tmp = null; + LinkedHashMap params = new LinkedHashMap(); + if (tmp.length > 1 && tmp[1] != "") { + params_tmp = tmp[1].split("&"); + for (int i = 0; i < params_tmp.length; i++) { + tmp = params_tmp[i].split("="); + if (tmp.length > 1 && tmp[1] != "") { + params.put(tmp[0], tmp[1]); + } + } + } + this.params = params; + } + } + + @Override + public String getConfigString(String key) { + return config.getProperty(key); + } + + public Path getDocumentRoot() { + return this.documentRoot; + } + + protected void getFileInfo(String path) throws JSONException { + String pathTmp = path; + if ("".equals(pathTmp)) { + pathTmp = this.get.get("path"); + } + String[] tmp = pathTmp.split("/"); + File file = this.documentRoot.resolve(pathTmp).toFile(); + this.item = new HashMap(); + String fileName = tmp[tmp.length - 1]; + this.item.put("filename", fileName); + if (file.isFile()) { + this.item.put("filetype", fileName.substring(fileName.lastIndexOf(".") + 1)); + } + else { + this.item.put("filetype", "dir"); + } + this.item.put("filemtime", "" + file.lastModified()); + this.item.put("filectime", "" + file.lastModified()); + + this.item.put("preview", config.getProperty("icons-path") + "/" + config.getProperty("icons-default")); // @simo + + JSONObject props = new JSONObject(); + if (file.isDirectory()) { + + this.item.put("preview", config.getProperty("icons-path") + config.getProperty("icons-directory")); + + } else if (isImage(pathTmp)) { + this.item.put("preview", "connectors/jsp/filemanager.jsp?mode=preview&path=" + pathTmp); + Dimension imgData = getImageSize(documentRoot.resolve(pathTmp).toString()); + props.put("Height", "" + imgData.height); + props.put("Width", "" + imgData.width); + props.put("Size", "" + file.length()); + } else { + File icon = fileManagerRoot.resolve(config.getProperty("icons-path")).resolve( + ((String) this.item.get("filetype")).toLowerCase() + ".png").toFile(); + if (icon.exists()) { + this.item.put("preview", + config.getProperty("icons-path") + ((String) this.item.get("filetype")).toLowerCase() + ".png"); + props.put("Size", "" + file.length()); + } + } + + props.put("Date Modified", dateFormat.format(new Date(new Long((String) this.item.get("filemtime"))))); + this.item.put("properties", props); + } + + protected boolean isImage(String fileName) { + boolean isImage = false; + String ext = ""; + int pos = fileName.lastIndexOf("."); + if (pos > 1 && pos != fileName.length()) { + ext = fileName.substring(pos + 1); + isImage = contains(config.getProperty("images"), ext); + } + return isImage; + } + + protected boolean contains(String where, String what) { + boolean retval = false; + + String[] tmp = where.split(","); + for (int i = 0; i < tmp.length; i++) { + if (what.equalsIgnoreCase(tmp[i])) { + retval = true; + break; + } + } + return retval; + } + + protected Dimension getImageSize(String path) { + Dimension imgData = new Dimension(); + Image img = new ImageIcon(path).getImage(); + imgData.height = img.getHeight(null); + imgData.width = img.getWidth(null); + return imgData; + } + + protected void unlinkRecursive(File dir, boolean deleteRootToo) { + //File dh = new File(dir); + File fileOrDir = null; + + if (dir.exists()) { + String[] objects = dir.list(); + for (int i = 0; i < objects.length; i++) { + fileOrDir = new File(dir + "/" + objects[i]); + if (fileOrDir.isDirectory()) { + if (!objects[i].equals(".") && !objects[i].equals("..")) { + unlinkRecursive(new File(dir + "/" + objects[i]), true); + } + } + fileOrDir.delete(); + + } + if (deleteRootToo) { + dir.delete(); + } + } + } + + protected HashMap cleanString(HashMap strList, String[] allowed) { + String allow = ""; + HashMap cleaned = null; + Iterator it = null; + String cleanStr = null; + String key = null; + for (int i = 0; i < allowed.length; i++) { + allow += "\\" + allowed[i]; + } + + if (strList != null) { + cleaned = new HashMap(); + it = strList.keySet().iterator(); + while (it.hasNext()) { + key = it.next(); + cleanStr = strList.get(key).replaceAll("[^{" + allow + "}_a-zA-Z0-9]", ""); + cleaned.put(key, cleanStr); + } + } + return cleaned; + } + + protected String sanitize(String var) { + String sanitized = var.replaceAll("\\<.*?>", ""); + sanitized = sanitized.replaceAll("http://", ""); + sanitized = sanitized.replaceAll("https://", ""); + sanitized = sanitized.replaceAll("\\.\\./", ""); + return sanitized; + } + + protected String checkFilename(String path, String filename, int i) { + File file = new File(path + filename); + String i2 = ""; + String[] tmp = null; + if (!file.exists()) { + return filename; + } else { + if (i != 0) + i2 = "" + i; + tmp = filename.split(i2 + "\\."); + i++; + filename = filename.replace(i2 + "." + tmp[tmp.length - 1], i + "." + tmp[tmp.length - 1]); + return this.checkFilename(path, filename, i); + } + } + + protected void loadConfig() { + InputStream is; + if (config == null) { + try { + //log.info("reading from " + this.fileManagerRoot.resolve("connectors/jsp/config.properties").toString()); + is = new FileInputStream( this.fileManagerRoot.resolve("connectors/jsp/config.properties").toString()); + config = new Properties(); + config.load(is); + } catch (Exception e) { + error("Error loading config file "+ this.fileManagerRoot.resolve("connectors/jsp/config.properties")); + } + } + } + + protected String sprintf(String text, String params) { + String retText = text; + String[] repl = params.split("#"); + for (int i = 0; i < repl.length; i++) { + retText = retText.replaceFirst("%s", repl[i]); + } + return retText; + } + + /* (non-Javadoc) + * @see com.nartex.FileManagerI#log(java.lang.String, java.lang.String) + */ + @Override + public void log(String msg) { + log.debug(msg); + } + + +} \ No newline at end of file diff --git a/connectors/jsp/libraries/java/src/com/nartex/FileManager.java b/connectors/jsp/libraries/java/src/com/nartex/FileManager.java index b5d320c5..9aecb6d6 100644 --- a/connectors/jsp/libraries/java/src/com/nartex/FileManager.java +++ b/connectors/jsp/libraries/java/src/com/nartex/FileManager.java @@ -7,137 +7,60 @@ */ package com.nartex; -import java.awt.Dimension; -import java.awt.Image; import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; -import java.io.FileWriter; import java.io.IOException; -import java.io.InputStream; import java.io.InputStreamReader; -import java.io.OutputStream; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.nio.file.LinkOption; +import java.nio.file.Path; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.swing.ImageIcon; import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileItemFactory; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; -import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.json.JSONException; import org.json.JSONObject; -public class FileManager { - - protected static Properties config = null; - protected static JSONObject language = null; - protected Map get = new HashMap(); - protected Map properties = new HashMap(); - protected Map item = new HashMap(); - protected Map params = new HashMap(); - protected String documentRoot = ""; - protected String fileManagerRoot = ""; - protected String referer = ""; - - protected JSONObject error = null; - - SimpleDateFormat dateFormat; - List files = null; - - public FileManager(ServletContext servletContext, HttpServletRequest request){ - // get document root like in php - String contextPath = request.getContextPath(); - String documentRoot = servletContext.getRealPath("/").replaceAll("\\\\", "/"); - documentRoot = documentRoot.substring(0, documentRoot.indexOf(contextPath)); - - this.referer = request.getHeader("referer"); - this.fileManagerRoot = documentRoot + referer.substring(referer.indexOf(contextPath), referer.indexOf("index.html")); - - // get uploaded file list - FileItemFactory factory = new DiskFileItemFactory(); - ServletFileUpload upload = new ServletFileUpload(factory); - if (ServletFileUpload.isMultipartContent(request)) - try { - files = upload.parseRequest(request); - } catch (Exception e) { // no error handling} - } +/** + * + * + * + * CHANGES + * August 2016 + * - using {@link Path} instead of {@link File} methods + * - added mode replace + * + * @author gkallidis + * + */ +public class FileManager extends AbstractFM { - this.properties.put("Date Created", null); - this.properties.put("Date Modified", null); - this.properties.put("Height", null); - this.properties.put("Width", null); - this.properties.put("Size", null); - - // load config file - loadConfig(); - - if(config.getProperty("doc_root") != null) - this.documentRoot = config.getProperty("doc_root"); - else - this.documentRoot = documentRoot; - - dateFormat = new SimpleDateFormat(config.getProperty("date")); - this.setParams(); - - loadLanguageFile(); - } - public JSONObject error(String msg) { - JSONObject errorInfo = new JSONObject(); - try { - errorInfo.put("Error", msg); - errorInfo.put("Code", "-1"); - errorInfo.put("Properties", this.properties); - } catch (JSONException e) { - this.error("JSONObject error"); - } - this.error = errorInfo; - return error; - } + /** + * + * @param servletContext + * @param request + * @throws IOException + */ - public JSONObject getError(){ - return error; - } - public String lang(String key) { - String text = ""; - try { - text = language.getString(key); - } catch (Exception e) {} - if (text == null || text == "") - text = "Language string error on " + key; - return text; + public FileManager(ServletContext servletContext, HttpServletRequest request) throws IOException { + + super(servletContext,request); } - public boolean setGetVar(String var, String value) { - boolean retval = false; - if(value == null || value == "") { - this.error(sprintf(lang("INVALID_VAR"), var)); - } else { - this.get.put(var, sanitize(value)); - retval = true; - } - return retval; - } - - public JSONObject getInfo() { + @Override + public JSONObject getInfo() throws JSONException { this.item = new HashMap(); this.item.put("properties", this.properties); this.getFileInfo(""); JSONObject array = new JSONObject(); - + try { array.put("Path", this.get.get("path")); array.put("Filename", this.item.get("filename")); @@ -146,22 +69,26 @@ public JSONObject getInfo() { array.put("Properties", this.item.get("properties")); array.put("Error", ""); array.put("Code", 0); - } catch (JSONException e) { + } catch (Exception e) { this.error("JSONObject error"); } return array; } - public JSONObject getFolder() { + @Override + public JSONObject getFolder() throws JSONException, IOException { JSONObject array = null; - File dir = new File(documentRoot + this.get.get("path")); - + //uri + Path root = documentRoot.resolve(this.get.get("path")); + log.debug("path absolute:" + root.toAbsolutePath()); + Path docDir = documentRoot.resolve(this.get.get("path")).toRealPath(LinkOption.NOFOLLOW_LINKS); + File dir = docDir.toFile(); //new File(documentRoot + this.get.get("path")); + File file = null; - if(!dir.isDirectory()) { + if (!dir.isDirectory()) { this.error(sprintf(lang("DIRECTORY_NOT_EXIST"), this.get.get("path"))); - } - else { - if (!dir.canRead()){ + } else { + if (!dir.canRead()) { this.error(sprintf(lang("UNABLE_TO_OPEN_DIRECTORY"), this.get.get("path"))); } else { array = new JSONObject(); @@ -171,552 +98,235 @@ public JSONObject getFolder() { for (int i = 0; i < files.length; i++) { data = new JSONObject(); props = new JSONObject(); - file = new File(documentRoot + this.get.get("path") + files[i]); - if (file.isDirectory() && - !contains(config.getProperty("unallowed_dirs"), files[i])){ - try{ - props.put("Date Created", (String)null); - props.put("Date Modified", (String)null); - props.put("Height", (String)null); - props.put("Width", (String)null); - props.put("Size", (String)null); + file = docDir.resolve(files[i]).toFile(); + //new File(documentRoot + this.get.get("path") + files[i]); + if (file.isDirectory() && !contains(config.getProperty("unallowed_dirs"), files[i])) { + try { + props.put("Date Created", (String) null); + props.put("Date Modified", (String) null); + props.put("Height", (String) null); + props.put("Width", (String) null); + props.put("Size", (String) null); data.put("Path", this.get.get("path") + files[i] + "/"); data.put("Filename", files[i]); data.put("File Type", "dir"); - data.put("Preview", config.getProperty("icons-path") + config.getProperty("icons-directory")); + data.put("Preview", + config.getProperty("icons-path") + config.getProperty("icons-directory")); data.put("Error", ""); data.put("Code", 0); data.put("Properties", props); - + array.put(this.get.get("path") + files[i] + "/", data); - } catch (JSONException e) { + } catch (Exception e) { this.error("JSONObject error"); } - - } else if (!contains(config.getProperty("unallowed_files"), files[i])){ + } else if (file.canRead() && (!contains(config.getProperty("unallowed_files"), files[i])) ) { + //this.item = new HashMap(); this.item = new HashMap(); this.item.put("properties", this.properties); this.getFileInfo(this.get.get("path") + files[i]); - - if (this.params.get("type") == null || (this.params.get("type") != null && (!this.params.get("type").equals("Image") || this.params.get("type").equals("Image") && - contains(config.getProperty("images"), (String)this.item.get("filetype"))))) { - try{ + + //if (this.params.get("type") == null || (this.params.get("type") != null && (!this.params.get("type").equals("Image") || checkImageType()))) { + if (this.params.get("type") == null || + (this.params.get("type") != null && ( (!this.params.get("type").equals("Image") && + !this.params.get("type").equals("Flash")) || + checkImageType() || checkFlashType() ))) { + try { data.put("Path", this.get.get("path") + files[i]); data.put("Filename", this.item.get("filename")); - data.put("File Type", this.item.get("filetype"));; + data.put("File Type", this.item.get("filetype")); data.put("Preview", this.item.get("preview")); data.put("Properties", this.item.get("properties")); data.put("Error", ""); data.put("Code", 0); - + log.debug("data now :"+ data.toString()); + array.put(this.get.get("path") + files[i], data); - } catch (JSONException e) { + } catch (Exception e) { this.error("JSONObject error"); } } + } else { + log.warn( "not allowed file or dir:" +files[i] ); } } } } + log.debug("array size ready:"+ ((array != null)?array.toString():"") ); return array; } - - public JSONObject rename() { - if((this.get.get("old")).endsWith("/")) { - this.get.put("old", (this.get.get("old")).substring(0,((this.get.get("old")).length() - 1))); - } - boolean error = false; - JSONObject array = null; - String tmp[] = (this.get.get("old")).split("/"); - String filename = tmp[tmp.length - 1]; - int pos = this.get.get("old").lastIndexOf("/"); - String path = (this.get.get("old")).substring(0, pos + 1); - File fileFrom = null; - File fileTo = null; - try { - fileFrom = new File(this.documentRoot + this.get.get("old")); - fileTo = new File(this.documentRoot + path + this.get.get("new")); - if(fileTo.exists()) { - if(fileTo.isDirectory()) { - this.error(sprintf(lang("DIRECTORY_ALREADY_EXISTS"),this.get.get("new"))); - error = true; - } - else { // fileTo.isFile - this.error(sprintf(lang("FILE_ALREADY_EXISTS"),this.get.get("new"))); - error = true; - } - } - else if (!fileFrom.renameTo(fileTo)){ - this.error(sprintf(lang("ERROR_RENAMING_DIRECTORY"), filename + "#" + this.get.get("new"))); - error = true; - } - } catch (Exception e) { - if(fileFrom.isDirectory()) { - this.error(sprintf(lang("ERROR_RENAMING_DIRECTORY"), filename + "#" + this.get.get("new"))); - } else { - this.error(sprintf(lang("ERROR_RENAMING_FILE"), filename + "#" + this.get.get("new"))); - } - error = true; - } - if (!error){ - array = new JSONObject(); - try{ - array.put("Error", ""); - array.put("Code", 0); - array.put("Old Path", this.get.get("old")); - array.put("Old Name", filename); - array.put("New Path", path + this.get.get("new")); - array.put("New Name", this.get.get("new")); - } catch (JSONException e) { - this.error("JSONObject error"); - } - } - return array; - } - - public JSONObject delete() { - JSONObject array = null; - File file = new File(this.documentRoot + this.get.get("path")); - if(file.isDirectory()) { - array = new JSONObject(); - this.unlinkRecursive(this.documentRoot + this.get.get("path"), true); - try { - array.put("Error", ""); - array.put("Code", 0); - array.put("Path", this.get.get("path")); - } catch (Exception e) { - this.error("JSONObject error"); - } - } else if(file.exists()) { - array = new JSONObject(); - if (file.delete()){ - try { - array.put("Error", ""); - array.put("Code", 0); - array.put("Path", this.get.get("path")); - } catch (JSONException e) { - this.error("JSONObject error"); - } - } - else - this.error(sprintf(lang("ERROR_DELETING FILE"), this.get.get("path"))); - return array; + + + /* (non-Javadoc) + * @see com.nartex.FileManagerI#download(javax.servlet.http.HttpServletResponse) + */ + @Override + public JSONObject download(HttpServletRequest request, HttpServletResponse resp) { + File file = this.documentRoot.resolve(this.get.get("path")).toFile(); + if (this.get.get("path") != null && file.exists()) { + resp.setHeader("Content-Description", "File Transfer"); + //resp.setHeader("Content-type", "application/force-download"); + //resp.setHeader("Content-Disposition", "inline;filename=\"" + documentRoot.resolve(this.get.get("path")).toString() + "\""); + resp.setHeader("Content-Transfer-Encoding", "Binary"); + resp.setHeader("Content-Length", "" + file.length()); + resp.setHeader("Content-Type", "application/octet-stream"); + resp.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\""); + readFile(resp, file); + this.error = null; + return null; } else { - this.error(lang("INVALID_DIRECTORY_OR_FILE")); + this.error(sprintf(lang("FILE_DOES_NOT_EXIST"), this.get.get("path"))); + return getError(); } - return array; } - + + @Override public JSONObject add() { - JSONObject fileInfo = null; + JSONObject fileInfo = new JSONObject(); Iterator it = this.files.iterator(); String mode = ""; String currentPath = ""; - if (!it.hasNext()){ + boolean error = false; + boolean replace = false; + long size = 0; + if (!it.hasNext()) { this.error(lang("INVALID_FILE_UPLOAD")); - } - else { - String allowed[] = {".","-"}; - FileItem item = null; - String fileName = ""; - try { + } else { + String allowed[] = { ".", "-" }; + String fileName = ""; + FileItem targetItem = null; + try { while (it.hasNext()) { - item = (FileItem) it.next(); - if (item.isFormField()){ - if (item.getFieldName().equals("mode")){ - mode = item.getString(); - if (!mode.equals("add")){ + FileItem item = (FileItem) it.next(); + if (item.isFormField()) { + if (item.getFieldName().equals("mode")) { + mode = item.getString(); + if (!mode.equals("add") && !mode.equals("replace")) { this.error(lang("INVALID_FILE_UPLOAD")); - } - } else if (item.getFieldName().equals("currentpath")){ - currentPath = item.getString(); - } - } - else if (item.getFieldName().equals("newfile")){ - fileName = item.getName(); - // strip possible directory (IE) - int pos = fileName.lastIndexOf(File.separator); - if (pos > 0) - fileName = fileName.substring(pos + 1); - boolean error = false; - long maxSize = 0; - if(config.getProperty("upload-size") != null){ - maxSize = Integer.parseInt(config.getProperty("upload-size")); - if (maxSize != 0 && item.getSize() > (maxSize * 1024 * 1024)){ - this.error(sprintf(lang("UPLOAD_FILES_SMALLER_THAN"), maxSize + "Mb")); - error = true; - } + } + } else if (item.getFieldName().equals("currentpath")) { + currentPath = item.getString(); + } else if (item.getFieldName().equals("newfilepath")){ + currentPath = item.getString(); } - if(!error){ - if (!isImage(fileName) && (config.getProperty("upload-imagesonly") != null && config.getProperty("upload-imagesonly").equals("true") - || this.params.get("type") != null && this.params.get("type").equals("Image"))) { - this.error(lang("UPLOAD_IMAGES_ONLY")); - } else { - fileInfo = new JSONObject(); - LinkedHashMap strList = new LinkedHashMap(); - strList.put("fileName", fileName); - fileName = (String)cleanString(strList, allowed).get("fileName"); - - if(config.getProperty("upload-overwrite").equals("false")) { - fileName = this.checkFilename(this.documentRoot + currentPath, fileName, 0); - } - - File saveTo = new File(this.documentRoot + currentPath + fileName); - item.write(saveTo); + } else if ( item.getFieldName().equals("fileR")) { + replace= true; + size = item.getSize(); + targetItem =item; - fileInfo.put("Path", currentPath); - fileInfo.put("Name", fileName); - fileInfo.put("Error", ""); - fileInfo.put("Code", 0); - } + } else if (item.getFieldName().equals("newfile")) { + fileName = item.getName(); + // strip possible directory (IE) + int pos = fileName.lastIndexOf(File.separator); + if (pos > 0) { + fileName = fileName.substring(pos + 1); } - } - } - } catch (Exception e) { - this.error(lang("INVALID_FILE_UPLOAD")); - } - } - return fileInfo; - - } - - public JSONObject addFolder() { - JSONObject array = null; - String allowed[] = {"-"," "}; - LinkedHashMap strList = new LinkedHashMap(); - strList.put("fileName", this.get.get("name")); - String filename = (String)cleanString(strList, allowed).get("fileName"); - if (filename.length() == 0) // the name existed of only special characters - this.error(sprintf(lang("UNABLE_TO_CREATE_DIRECTORY"), this.get.get("name"))); - else { - File file = new File(this.documentRoot + this.get.get("path") + filename); - if(file.isDirectory()) { - this.error(sprintf(lang("DIRECTORY_ALREADY_EXISTS"), filename)); - } - else if (!file.mkdir()){ - this.error(sprintf(lang("UNABLE_TO_CREATE_DIRECTORY"), filename)); - } - else { - try { - array = new JSONObject(); - array.put("Parent", this.get.get("path")); - array.put("Name", filename); - array.put("Error", ""); - array.put("Code", 0); - } catch (JSONException e) { - this.error("JSONObject error"); - } - } - } - return array; - } - - public void download(HttpServletResponse resp) { - File file = new File(this.documentRoot + this.get.get("path")); - if(this.get.get("path") != null && file.exists()) { - resp.setHeader("Content-type", "application/force-download"); - resp.setHeader("Content-Disposition", "inline;filename=\"" + documentRoot + this.get.get("path") + "\""); - resp.setHeader("Content-Transfer-Encoding", "Binary"); - resp.setHeader("Content-length", "" + file.length()); - resp.setHeader("Content-Type", "application/octet-stream"); - resp.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\""); - readFile(resp, file); - } else { - this.error(sprintf(lang("FILE_DOES_NOT_EXIST"), this.get.get("path"))); - } - } - - private void readFile(HttpServletResponse resp, File file){ - OutputStream os = null; - FileInputStream fis = null; - try { - os = resp.getOutputStream(); - fis = new FileInputStream(file); - byte fileContent[] = new byte[(int)file.length()]; - fis.read(fileContent); - os.write(fileContent); - } catch (Exception e) { - this.error(sprintf(lang("INVALID_DIRECTORY_OR_FILE"), file.getName())); - } - finally { - try { - if (os != null) - os.close(); - } catch (Exception e2) {} - try { - if (fis != null) - fis.close(); - } catch (Exception e2) {} - } - } - - public void preview(HttpServletResponse resp) { - File file = new File(this.documentRoot + this.get.get("path")); - if(this.get.get("path") != null && file.exists()) { - resp.setHeader("Content-type", "image/" + getFileExtension(file.getName())); - resp.setHeader("Content-Transfer-Encoding", "Binary"); - resp.setHeader("Content-length", "" + file.length()); - resp.setHeader("Content-Disposition", "inline; filename=\"" + getFileBaseName(file.getName()) + "\""); - readFile(resp, file); - } else { - error(sprintf(lang("FILE_DOES_NOT_EXIST"),this.get.get("path"))); - } - } - - private String getFileBaseName(String filename){ - String retval = filename; - int pos = filename.lastIndexOf("."); - if (pos > 0) - retval = filename.substring(0, pos); - return retval; - } - - private String getFileExtension(String filename){ - String retval = filename; - int pos = filename.lastIndexOf("."); - if (pos > 0) - retval = filename.substring(pos + 1); - return retval; - } - - private void setParams() { - String[] tmp = this.referer.split("\\?"); - String[] params_tmp = null; - LinkedHashMap params = new LinkedHashMap(); - if(tmp.length > 1 && tmp[1] != "") { - params_tmp = tmp[1].split("&"); - for (int i = 0; i < params_tmp.length; i++) { - tmp = params_tmp[i].split("="); - if(tmp.length > 1 && tmp[1] != "") { - params.put(tmp[0], tmp[1]); + size = item.getSize(); + targetItem =item; + } } - } - } - this.params = params; - } - - public String getConfigString(String key){ - return config.getProperty(key); - } - - public String getDocumentRoot(){ - return this.documentRoot; - } - - private void getFileInfo(String path) { - String pathTmp = path; - if(pathTmp == "") { - pathTmp = this.get.get("path"); - } - String[] tmp = pathTmp.split("/"); - File file = new File(this.documentRoot + pathTmp); - this.item = new HashMap(); - String fileName = tmp[tmp.length - 1]; - this.item.put("filename", fileName); - if (file.isFile()) - this.item.put("filetype", fileName.substring(fileName.lastIndexOf(".") + 1)); - else - this.item.put("filetype", "dir"); - this.item.put("filemtime", "" + file.lastModified()); - this.item.put("filectime", "" + file.lastModified()); - - this.item.put("preview", config.getProperty("icons-path") + "/" + config.getProperty("icons-default")); // @simo - - HashMap props = new HashMap(); - if(file.isDirectory()) { - - this.item.put("preview", config.getProperty("icons-path") + config.getProperty("icons-directory")); - - } - else if (isImage(pathTmp)) - { - this.item.put("preview", "connectors/jsp/filemanager.jsp?mode=preview&path=" + pathTmp); - Dimension imgData = getImageSize(documentRoot + pathTmp); - props.put("Height", "" + imgData.height); - props.put("Width", "" + imgData.width); - props.put("Size", "" + file.length()); - } else { - File icon = new File(fileManagerRoot + config.getProperty("icons-path") + ((String)this.item.get("filetype")).toLowerCase() + ".png"); - if(icon.exists()) { - this.item.put("preview", config.getProperty("icons-path") + ((String)this.item.get("filetype")).toLowerCase() + ".png"); - props.put("Size", "" + file.length()); - } - } - - props.put("Date Modified", dateFormat.format(new Date(new Long((String)this.item.get("filemtime"))))); - this.item.put("properties", props); - } - - private boolean isImage(String fileName){ - boolean isImage = false; - String ext = ""; - int pos = fileName.lastIndexOf("."); - if (pos > 1 && pos != fileName.length()){ - ext = fileName.substring(pos + 1); - isImage = contains(config.getProperty("images"), ext); - } - return isImage; - } - - public boolean contains(String where, String what){ - boolean retval = false; - - String[] tmp = where.split(","); - for (int i = 0; i < tmp.length; i++) { - if (what.equalsIgnoreCase(tmp[i])){ - retval = true; - break; - } - } - return retval; - } - - private Dimension getImageSize(String path){ - Dimension imgData = new Dimension(); - Image img = new ImageIcon(path).getImage(); - imgData.height = img.getHeight(null); - imgData.width = img.getWidth(null); - return imgData; - } - - private void unlinkRecursive(String dir, boolean deleteRootToo) { - File dh = new File(dir); - File fileOrDir = null; - - if(dh.exists()) { - String[] objects = dh.list(); - for (int i = 0; i < objects.length; i++) { - fileOrDir = new File(dir + "/" + objects[i]); - if (fileOrDir.isDirectory()){ - if (!objects[i].equals(".") && !objects[i].equals("..")){ - unlinkRecursive(dir + "/" + objects[i], true); + if (!error) { + if (replace) { + String tmp[] = currentPath.split("/"); + fileName = tmp[tmp.length - 1]; + int pos = fileName.lastIndexOf(File.separator); + if (pos > 0) + fileName = fileName.substring(pos + 1); + if (tmp.length > 1) { + currentPath = currentPath.replace(fileName, ""); + currentPath = currentPath.replace("//", "/"); + } + } else { + if (!isImage(fileName) + && (config.getProperty("upload-imagesonly") != null + && config.getProperty("upload-imagesonly").equals("true") || this.params + .get("type") != null && this.params.get("type").equals("Image"))) { + this.error(lang("UPLOAD_IMAGES_ONLY")); + error =true; + } + LinkedHashMap strList = new LinkedHashMap(); + strList.put("fileName", fileName); + fileName = cleanString(strList, allowed).get("fileName"); + } + long maxSize = 0; + if (config.getProperty("upload-size") != null) { + maxSize = Integer.parseInt(config.getProperty("upload-size")); + if (maxSize != 0 && size > (maxSize * 1024 * 1024)) { + this.error(sprintf(lang("UPLOAD_FILES_SMALLER_THAN"), maxSize + "Mb")); + error = true; + } + } + if (!error) { + if (config.getProperty("upload-overwrite").equals("false")) { + fileName = this.checkFilename(this.documentRoot.resolve(currentPath).toString(), fileName, 0); + } + if (mode.equals("replace")) { + File saveTo = this.documentRoot.resolve(currentPath).resolve(fileName).toFile(); + targetItem.write(saveTo); + log.info("saved "+ saveTo); + } else { + currentPath = currentPath.replace("/", "/").replaceFirst("^/", "");// relative + fileName = fileName.replace("//", "/").replaceFirst("^/", "");// relative + File saveTo = this.documentRoot.resolve(currentPath).resolve(fileName).toFile(); + targetItem.write(saveTo); + log.info("saved "+ saveTo); + } + fileInfo.put("Path", currentPath); + fileInfo.put("Name", fileName); + fileInfo.put("Error", ""); + fileInfo.put("Code", 0); } } - fileOrDir.delete(); - - - } - if (deleteRootToo) { - dh.delete(); - } - } - } - - private HashMap cleanString(HashMap strList, String[] allowed) { - String allow = ""; - HashMap cleaned = null; - Iterator it = null; - String cleanStr = null; - String key = null; - for (int i = 0; i < allowed.length; i++) { - allow += "\\" + allowed[i]; - } - - if (strList != null) { - cleaned = new HashMap(); - it = strList.keySet().iterator(); - while (it.hasNext()) { - key = it.next(); - cleanStr = strList.get(key).replaceAll("[^{" + allow + "}_a-zA-Z0-9]", ""); - cleaned.put(key, cleanStr); - } - } - return cleaned; - } - - private String sanitize(String var) { - String sanitized = var.replaceAll("\\<.*?>",""); - sanitized = sanitized.replaceAll("http://", ""); - sanitized = sanitized.replaceAll("https://", ""); - sanitized = sanitized.replaceAll("\\.\\./", ""); - return sanitized; - } - - private String checkFilename(String path, String filename, int i) { - File file = new File(path + filename); - String i2 = ""; - String[] tmp = null; - if(!file.exists()) { - return filename; - } else { - if (i != 0) - i2 = "" + i; - tmp = filename.split(i2 + "\\."); - i++; - filename = filename.replace(i2 + "." + tmp[tmp.length - 1],i + "." + tmp[tmp.length-1]); - return this.checkFilename(path, filename, i); - } - } - - private void loadConfig(){ - InputStream is; - if (config == null){ - try { - is = new FileInputStream( - this.fileManagerRoot + "connectors/jsp/config.properties"); - config = new Properties(); - config.load(is); } catch (Exception e) { - error("Error loading config file"); + this.error(lang("INVALID_FILE_UPLOAD"),e); } } + return fileInfo; + } - private void loadLanguageFile() { + @Override + public void loadLanguageFile() { // we load langCode var passed into URL if present // else, we use default configuration var - if (language == null){ + if (language == null) { String lang = ""; if (params.get("langCode") != null) lang = this.params.get("langCode"); - else + else lang = config.getProperty("culture"); BufferedReader br = null; InputStreamReader isr = null; String text; StringBuffer contents = new StringBuffer(); try { - isr = new InputStreamReader(new FileInputStream (this.fileManagerRoot + "/scripts/languages/" + lang + ".js"), "UTF-8"); - br = new BufferedReader (isr); + isr = new InputStreamReader( + new FileInputStream( + this.fileManagerRoot + .resolve("scripts/languages/") + .resolve(lang+ ".js").toString() + ), "UTF-8"); + br = new BufferedReader(isr); while ((text = br.readLine()) != null) contents.append(text); language = new JSONObject(contents.toString()); } catch (Exception e) { - this.error("Fatal error: Language file not found."); - } - finally { + this.error("Fatal error: Language file not found."); + } finally { try { if (br != null) br.close(); - } catch (Exception e2) {} + } catch (Exception e2) { + } try { if (isr != null) isr.close(); - } catch (Exception e2) {} + } catch (Exception e2) { + } } } } - - public String sprintf(String text, String params){ - String retText = text; - String[] repl = params.split("#"); - for (int i = 0; i < repl.length; i++) { - retText = retText.replaceFirst("%s", repl[i]); - } - return retText; - } - - public void log(String filename, String msg) - { - try { - BufferedWriter out = new BufferedWriter(new FileWriter(filename, true)); - out.append(msg + "\r\n"); - out.close(); - } - catch (IOException e) - { - e.printStackTrace(); - } - } + + } diff --git a/connectors/jsp/libraries/java/src/com/nartex/FileManagerI.java b/connectors/jsp/libraries/java/src/com/nartex/FileManagerI.java new file mode 100644 index 00000000..1095bace --- /dev/null +++ b/connectors/jsp/libraries/java/src/com/nartex/FileManagerI.java @@ -0,0 +1,54 @@ +package com.nartex; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.json.JSONException; +import org.json.JSONObject; + +/** + * + * created August 2016 + * + * @author gkallidis + * + */ +public interface FileManagerI { + + public abstract JSONObject error(String msg, Throwable ex); + + public abstract JSONObject error(String msg); + + public abstract JSONObject getError(); + + public abstract String lang(String key); + + public void loadLanguageFile(); + + public abstract boolean setGetVar(String var, String value); + + public abstract JSONObject getInfo() throws JSONException; + + public abstract JSONObject getFolder() throws JSONException, IOException; + + public abstract JSONObject rename(); + + public abstract JSONObject delete(); + + public abstract JSONObject add(); + + public abstract JSONObject addFolder(); + + public abstract JSONObject moveItem(); + + public abstract JSONObject download(HttpServletRequest request, HttpServletResponse resp); + + public abstract void preview(HttpServletResponse resp); + + public abstract String getConfigString(String key); + + public abstract void log(String msg); + +} \ No newline at end of file diff --git a/scripts/filemanager.js b/scripts/filemanager.js index 2fd1376d..c4d94cc4 100644 --- a/scripts/filemanager.js +++ b/scripts/filemanager.js @@ -4,1585 +4,1650 @@ * filemanager.js * * @license MIT License - * @author Jason Huck - Core Five Labs + * @author Jason Huck - Core Five Lab * @author Simon Georget + * @author Georg Kallidis * @copyright Authors */ - -(function($) { -// function to retrieve GET params -$.urlParam = function(name){ - var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href); - if (results) - return results[1]; - else - return 0; -}; - -/*-----------------------------------------------------$('#level-up').click---- - Setup, Layout, and Status Functions ----------------------------------------------------------*/ -// We retrieve config settings from filemanager.config.js -var loadConfigFile = function (type) { - var json = null; - type = (typeof type === "undefined") ? "user" : type; +(function($) { - if(type == 'user') { - if($.urlParam('config') != 0) { - var url = './scripts/' + $.urlParam('config'); - userconfig = $.urlParam('config'); - } else { - var url = './scripts/filemanager.config.json'; - userconfig = 'filemanager.config.json'; - } - } else { - var url = './scripts/filemanager.config.default.json'; - } + var fm = {}; + fm.lg = []; + var initConfigLastPromise = jQuery.Deferred(); + // loading default configuration file + var promiseDefault = jQuery.Deferred(); + // loading user configuration file + var promiseUser = jQuery.Deferred(); + // included files collector + var HEAD_included_files = new Array(); + + // function to retrieve GET params + $.urlParam = function(name){ + var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href); + if (results) + return results[1]; + else + return 0; + }; + + /*-----------------------------------------------------$('#level-up').click---- + Setup, Layout, and Status Functions + ---------------------------------------------------------*/ + + // We retrieve config settings from filemanager.config.js + var loadDefaultConfigFile = function () { + var json = null; + var url = './scripts/filemanager.config.default.json'; + + return $.ajax({ + 'url': url, + 'dataType': "json", + cache: false + }); + }; + + var loadUserConfigFile = function (type) { + var json = null; + type = (typeof type === "undefined") ? "user" : type; - $.ajax({ - 'async': false, - 'url': url, - 'dataType': "json", - cache: false, - 'success': function (data) { - json = data; + if(type == 'user') { + if($.urlParam('config') != 0) { + var url = './scripts/' + $.urlParam('config'); + fm.userconfig = $.urlParam('config'); + } else { + var url = './scripts/filemanager.config.json'; + fm.userconfig = 'filemanager.config.json'; + } + } + + return $.ajax({ + 'url': url, + 'dataType': "json", + cache: false + }) ; + }; + + var err = function( req, status, err ) { + alert( '

something went wrong

'+ err ); + }; + + // loading default configuration file + var promiseA = loadDefaultConfigFile(); + promiseA.then( function (data) { + json = data; + promiseDefault.resolve(json); + },err); + // loading user configuration file + var promiseB = loadUserConfigFile('user'); + promiseB.then( function (data) { + json = data; + promiseUser.resolve(json); + }, err); + + + $.when(promiseDefault, promiseUser).done(function(configd,config) { + // we remove version from user config file + if (fm.config != undefined && fm.config !== null) delete fm.config.version; + // we merge default config and user config file + fm.config = $.extend({}, configd, config); + if(fm.config.options.logger) fm.start = new Date().getTime(); + + // Sets paths to connectors based on language selection. + fm.fileConnector = fm.config.options.fileConnector || 'connectors/' + fm.config.options.lang + '/filemanager.' + fm.config.options.lang; + + // Read capabilities from config files if exists + // else apply default settings + fm.capabilities = fm.config.options.capabilities || new Array('select', 'download', 'rename', 'move', 'delete', 'replace'); + // Get localized messages from file + // through culture var or from URL + if($.urlParam('langCode') != 0) { + file_exists ('scripts/languages/' + $.urlParam('langCode') + '.js').done( + function(result) { + if (result) { + fm.config.options.culture = $.urlParam('langCode'); + } else { + fm.urlLang = $.urlParam('langCode').substring(0, 2); + file_exists ('scripts/languages/' + fm.urlLang + '.js').done( + function(result) { + if(result) { + fm.config.options.culture = fm.urlLang; + } + } + ); + } + } + ); } - }); - return json; -}; + wrapperInitConfigLastPromise = $.Deferred(function() { + var self = this; + $.ajax({ + url: 'scripts/languages/' + fm.config.options.culture + '.js', + dataType: 'json' + }).done( function (json) { + fm.lg = json; + initConfigLastPromise.resolve(json); + self.resolve(json); + }); + }).promise(); + }); + + + /** + * function to load a given css file into header + * if not already included + */ + loadCSS = function(href) { + // we check if already included + if($.inArray(href, HEAD_included_files) == -1) { + var cssLink = $(""); + $("head").append(cssLink); + HEAD_included_files.push(href); + } + }; + + /** + * function to load a given js file into header + * if not already included + */ + loadJS = function(src) { + // we check if already included + if($.inArray(src, HEAD_included_files) == -1) { + var jsLink = $("