├── 23205811_gr0b.png ├── 23205833_rxSV.png ├── src └── main │ ├── java │ └── org │ │ └── grapheco │ │ └── elfinder │ │ ├── service │ │ ├── FsItem.java │ │ ├── FsServiceConfig.java │ │ ├── FsSecurityChecker.java │ │ ├── FsItemFilter.java │ │ ├── FsServiceFactory.java │ │ ├── FsService.java │ │ └── FsVolume.java │ │ ├── controller │ │ ├── executor │ │ │ ├── CommandExecutorFactory.java │ │ │ ├── CommandExecutor.java │ │ │ ├── CommandExecutionContext.java │ │ │ ├── DefaultCommandExecutorFactory.java │ │ │ ├── AbstractJsonCommandExecutor.java │ │ │ ├── FsItemEx.java │ │ │ └── AbstractCommandExecutor.java │ │ ├── FsException.java │ │ ├── executors │ │ │ ├── MissingCommandExecutor.java │ │ │ ├── SearchCommandExecutor.java │ │ │ ├── MkdirCommandExecutor.java │ │ │ ├── GetCommandExecutor.java │ │ │ ├── PutCommandExecutor.java │ │ │ ├── TreeCommandExecutor.java │ │ │ ├── SizeCommandExecutor.java │ │ │ ├── LsCommandExecutor.java │ │ │ ├── RenameCommandExecutor.java │ │ │ ├── RmCommandExecutor.java │ │ │ ├── MkfileCommandExecutor.java │ │ │ ├── ParentsCommandExecutor.java │ │ │ ├── PasteCommandExecutor.java │ │ │ ├── OpenCommandExecutor.java │ │ │ ├── DuplicateCommandExecutor.java │ │ │ ├── TmbCommandExecutor.java │ │ │ ├── DimCommandExecutor.java │ │ │ ├── FileCommandExecutor.java │ │ │ └── UploadCommandExecutor.java │ │ ├── ErrorException.java │ │ ├── MultipleUploadItems.java │ │ └── ConnectorController.java │ │ ├── impl │ │ ├── DefaultFsServiceConfig.java │ │ ├── FsSecurityCheckFilterMapping.java │ │ ├── StaticFsServiceFactory.java │ │ ├── FsSecurityCheckForAll.java │ │ ├── FsSecurityCheckerChain.java │ │ └── DefaultFsService.java │ │ ├── util │ │ ├── FsServiceUtils.java │ │ ├── MimeTypesUtils.java │ │ └── FsItemFilterUtils.java │ │ ├── localfs │ │ ├── LocalFsItem.java │ │ └── LocalFsVolume.java │ │ └── servlet │ │ └── ConnectorServlet.java │ ├── resources │ ├── log4j.properties │ └── mime.types │ └── webapp │ ├── WEB-INF │ ├── web.xml │ ├── web.xml.1 │ └── elfinder-servlet.xml │ └── index.html ├── .gitattributes ├── .github └── FUNDING.yml ├── LICENSE ├── .gitignore ├── pom.xml └── README.md /23205811_gr0b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluejoe2008/elfinder-2.x-servlet/HEAD/23205811_gr0b.png -------------------------------------------------------------------------------- /23205833_rxSV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluejoe2008/elfinder-2.x-servlet/HEAD/23205833_rxSV.png -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/service/FsItem.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.service; 2 | 3 | public interface FsItem 4 | { 5 | FsVolume getVolume(); 6 | } -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/service/FsServiceConfig.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.service; 2 | 3 | public interface FsServiceConfig 4 | { 5 | int getTmbWidth(); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executor/CommandExecutorFactory.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executor; 2 | 3 | public interface CommandExecutorFactory 4 | { 5 | CommandExecutor get(String commandName); 6 | } -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executor/CommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executor; 2 | 3 | public interface CommandExecutor 4 | { 5 | void execute(CommandExecutionContext commandExecutionContext) 6 | throws Exception; 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/FsException.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller; 2 | 3 | import java.io.IOException; 4 | 5 | public class FsException extends IOException 6 | { 7 | 8 | public FsException(String message) 9 | { 10 | super(message); 11 | } 12 | 13 | public FsException(String message, Throwable e) 14 | { 15 | super(message, e); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/service/FsSecurityChecker.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.service; 2 | 3 | import java.io.IOException; 4 | 5 | public interface FsSecurityChecker 6 | { 7 | 8 | boolean isLocked(FsService fsService, FsItem fsi) throws IOException; 9 | 10 | boolean isReadable(FsService fsService, FsItem fsi) throws IOException; 11 | 12 | boolean isWritable(FsService fsService, FsItem fsi) throws IOException; 13 | 14 | } -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/impl/DefaultFsServiceConfig.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.impl; 2 | 3 | import org.grapheco.elfinder.service.FsServiceConfig; 4 | 5 | public class DefaultFsServiceConfig implements FsServiceConfig 6 | { 7 | private int _tmbWidth; 8 | 9 | public void setTmbWidth(int tmbWidth) 10 | { 11 | _tmbWidth = tmbWidth; 12 | } 13 | 14 | @Override 15 | public int getTmbWidth() 16 | { 17 | return _tmbWidth; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Custom for Visual Studio 2 | *.cs diff=csharp 3 | *.sln merge=union 4 | *.csproj merge=union 5 | *.vbproj merge=union 6 | *.fsproj merge=union 7 | *.dbproj merge=union 8 | 9 | # Standard to msysgit 10 | *.doc diff=astextplain 11 | *.DOC diff=astextplain 12 | *.docx diff=astextplain 13 | *.DOCX diff=astextplain 14 | *.dot diff=astextplain 15 | *.DOT diff=astextplain 16 | *.pdf diff=astextplain 17 | *.PDF diff=astextplain 18 | *.rtf diff=astextplain 19 | *.RTF diff=astextplain 20 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/service/FsItemFilter.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.service; 2 | 3 | import org.grapheco.elfinder.controller.executor.FsItemEx; 4 | 5 | /** 6 | * A FsItemFilter tells if a FsItem is matched or not 7 | * 8 | * @author bluejoe 9 | * 10 | */ 11 | public interface FsItemFilter 12 | { 13 | // TODO: bad designs: FsItemEx should not used here 14 | // top level interfaces should only know FsItem instead of FsItemEx 15 | public boolean accepts(FsItemEx item); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # Output pattern : date [thread] priority category - message 2 | log4j.rootLogger=INFO,Console 3 | 4 | #Console 5 | log4j.appender.Console=org.apache.log4j.ConsoleAppender 6 | log4j.appender.Console.Threshold=DEBUG 7 | log4j.appender.Console.layout=org.apache.log4j.PatternLayout 8 | log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n 9 | 10 | #Project default level 11 | log4j.logger.org.grapheco.elfinder=DEBUG 12 | log4j.logger.net.sf=INFO 13 | log4j.logger.org.apache=INFO 14 | log4j.logger.org.springframework=INFO -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executor/CommandExecutionContext.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executor; 2 | 3 | import javax.servlet.ServletContext; 4 | import javax.servlet.http.HttpServletRequest; 5 | import javax.servlet.http.HttpServletResponse; 6 | 7 | import org.grapheco.elfinder.service.FsServiceFactory; 8 | 9 | public interface CommandExecutionContext 10 | { 11 | FsServiceFactory getFsServiceFactory(); 12 | 13 | HttpServletRequest getRequest(); 14 | 15 | HttpServletResponse getResponse(); 16 | 17 | ServletContext getServletContext(); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/util/FsServiceUtils.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.util; 2 | 3 | import java.io.IOException; 4 | 5 | import org.grapheco.elfinder.controller.executor.FsItemEx; 6 | import org.grapheco.elfinder.service.FsItem; 7 | import org.grapheco.elfinder.service.FsService; 8 | 9 | public abstract class FsServiceUtils 10 | { 11 | public static FsItemEx findItem(FsService fsService, String hash) 12 | throws IOException 13 | { 14 | FsItem fsi = fsService.fromHash(hash); 15 | if (fsi == null) 16 | { 17 | return null; 18 | } 19 | 20 | return new FsItemEx(fsi, fsService); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | index.html 5 | index.jsp 6 | 7 | 8 | 9 | 10 | 11 | elfinder 12 | org.springframework.web.servlet.DispatcherServlet 13 | 14 | 15 | 16 | elfinder 17 | /elfinder-servlet/* 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: https://bluejoe2008.github.io/open-source-sponser.png 13 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/web.xml.1: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | index.html 5 | index.jsp 6 | 7 | 8 | 9 | 10 | 11 | elfinder-connector-servlet 12 | org.grapheco.elfinder.servlet.ConnectorServlet 13 | 14 | 15 | 16 | elfinder-connector-servlet 17 | /elfinder-servlet/connector 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/impl/FsSecurityCheckFilterMapping.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.impl; 2 | 3 | import java.util.regex.Pattern; 4 | 5 | import org.grapheco.elfinder.service.FsSecurityChecker; 6 | 7 | public class FsSecurityCheckFilterMapping 8 | { 9 | FsSecurityChecker _checker; 10 | 11 | String _pattern; 12 | 13 | public FsSecurityChecker getChecker() 14 | { 15 | return _checker; 16 | } 17 | 18 | public String getPattern() 19 | { 20 | return _pattern; 21 | } 22 | 23 | public boolean matches(String hash) 24 | { 25 | return Pattern.compile(_pattern).matcher(hash).matches(); 26 | } 27 | 28 | public void setChecker(FsSecurityChecker checker) 29 | { 30 | _checker = checker; 31 | } 32 | 33 | public void setPattern(String pattern) 34 | { 35 | _pattern = pattern; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/localfs/LocalFsItem.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.localfs; 2 | 3 | import java.io.File; 4 | 5 | import org.grapheco.elfinder.service.FsItem; 6 | import org.grapheco.elfinder.service.FsVolume; 7 | 8 | public class LocalFsItem implements FsItem 9 | { 10 | File _file; 11 | 12 | FsVolume _volume; 13 | 14 | public LocalFsItem(LocalFsVolume volume, File file) 15 | { 16 | super(); 17 | _volume = volume; 18 | _file = file; 19 | } 20 | 21 | public File getFile() 22 | { 23 | return _file; 24 | } 25 | 26 | public FsVolume getVolume() 27 | { 28 | return _volume; 29 | } 30 | 31 | public void setFile(File file) 32 | { 33 | _file = file; 34 | } 35 | 36 | public void setVolume(FsVolume volume) 37 | { 38 | _volume = volume; 39 | } 40 | 41 | @Override 42 | public String toString() 43 | { 44 | return "LocalFsVolume [" + _file + "]"; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/impl/StaticFsServiceFactory.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.impl; 2 | 3 | import javax.servlet.ServletContext; 4 | import javax.servlet.http.HttpServletRequest; 5 | 6 | import org.grapheco.elfinder.service.FsService; 7 | import org.grapheco.elfinder.service.FsServiceFactory; 8 | 9 | /** 10 | * A StaticFsServiceFactory always returns one FsService, despite of whatever it 11 | * is requested 12 | * 13 | * @author bluejoe 14 | * 15 | */ 16 | public class StaticFsServiceFactory implements FsServiceFactory 17 | { 18 | FsService _fsService; 19 | 20 | @Override 21 | public FsService getFileService(HttpServletRequest request, 22 | ServletContext servletContext) 23 | { 24 | return _fsService; 25 | } 26 | 27 | public FsService getFsService() 28 | { 29 | return _fsService; 30 | } 31 | 32 | public void setFsService(FsService fsService) 33 | { 34 | _fsService = fsService; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/service/FsServiceFactory.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.service; 2 | 3 | import javax.servlet.ServletContext; 4 | import javax.servlet.http.HttpServletRequest; 5 | 6 | /** 7 | * a factory which creates FsServices 8 | * 9 | * @author bluejoe 10 | * 11 | */ 12 | public interface FsServiceFactory 13 | { 14 | /** 15 | * sometimes a FsService should be constructed dynamically according to 16 | * current web request. e.g users may own separated file spaces in a net 17 | * disk service platform, in this case, getFileService() get user principal 18 | * from current request and offers him/her different file view. 19 | * 20 | * @param request 21 | * The current HttpServletRequest. 22 | * @param servletContext 23 | * The servlet context. 24 | * @return The {@link FsService} for the current request. 25 | */ 26 | FsService getFileService(HttpServletRequest request, 27 | ServletContext servletContext); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/MissingCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import javax.servlet.ServletContext; 4 | import javax.servlet.http.HttpServletRequest; 5 | 6 | import org.grapheco.elfinder.controller.ErrorException; 7 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 8 | import org.json.JSONObject; 9 | 10 | import org.grapheco.elfinder.controller.executor.AbstractJsonCommandExecutor; 11 | import org.grapheco.elfinder.service.FsService; 12 | 13 | /** 14 | * This is a command that should be executed when a matching command can't be 15 | * found. 16 | */ 17 | public class MissingCommandExecutor extends AbstractJsonCommandExecutor 18 | implements CommandExecutor 19 | { 20 | @Override 21 | protected void execute(FsService fsService, HttpServletRequest request, 22 | ServletContext servletContext, JSONObject json) throws Exception 23 | { 24 | String cmd = request.getParameter("cmd"); 25 | throw new ErrorException("errUnknownCmd", cmd); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/ErrorException.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller; 2 | 3 | /** 4 | * This Exception is thrown when the implementation can't complete and wants to 5 | * return an error to the client. 6 | */ 7 | public class ErrorException extends RuntimeException 8 | { 9 | 10 | private final String error; 11 | private final String[] args; 12 | 13 | /** 14 | * See /elfinder/js/i18n/elfinder.??.js for error codes. 15 | * 16 | * @param error 17 | * The error code. 18 | * @param args 19 | * Any arguments needed by the error message. 20 | */ 21 | public ErrorException(String error, String... args) 22 | { 23 | this.error = error; 24 | this.args = args; 25 | } 26 | 27 | /** 28 | * @return The error code that will translated by elfinder to a nice 29 | * message. 30 | */ 31 | public String getError() 32 | { 33 | return error; 34 | } 35 | 36 | /** 37 | * @return The arguments needed by the error message. 38 | */ 39 | public String[] getArgs() 40 | { 41 | return args; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/SearchCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import javax.servlet.ServletContext; 4 | import javax.servlet.http.HttpServletRequest; 5 | 6 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 7 | import org.grapheco.elfinder.util.FsItemFilterUtils; 8 | import org.json.JSONObject; 9 | 10 | import org.grapheco.elfinder.controller.executor.AbstractJsonCommandExecutor; 11 | import org.grapheco.elfinder.service.FsService; 12 | 13 | public class SearchCommandExecutor extends AbstractJsonCommandExecutor 14 | implements CommandExecutor 15 | { 16 | @Override 17 | public void execute(FsService fsService, HttpServletRequest request, 18 | ServletContext servletContext, JSONObject json) throws Exception 19 | { 20 | json.put( 21 | "files", 22 | files2JsonArray(request, FsItemFilterUtils.filterFiles( 23 | fsService.find(FsItemFilterUtils 24 | .createFileNameKeywordFilter(request 25 | .getParameter("q"))), super 26 | .getRequestedFilter(request)))); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/service/FsService.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.service; 2 | 3 | import java.io.IOException; 4 | 5 | import org.grapheco.elfinder.controller.executor.FsItemEx; 6 | 7 | public interface FsService 8 | { 9 | FsItem fromHash(String hash) throws IOException; 10 | 11 | String getHash(FsItem item) throws IOException; 12 | 13 | FsSecurityChecker getSecurityChecker(); 14 | 15 | String getVolumeId(FsVolume volume); 16 | 17 | FsVolume[] getVolumes(); 18 | 19 | FsServiceConfig getServiceConfig(); 20 | 21 | /** 22 | * find files by name pattern, this provides a simple recursively iteration 23 | * based method lucene engines can be introduced to improve it! This 24 | * searches across all volumes. 25 | * 26 | * @param filter 27 | * The filter to apply to select files. 28 | * @return A collection of files that match the filter and gave the root as 29 | * a parent. 30 | */ 31 | // TODO: bad designs: FsItemEx should not used here top level interfaces 32 | // should only know FsItem instead of FsItemEx 33 | FsItemEx[] find(FsItemFilter filter); 34 | } -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/MkdirCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import javax.servlet.ServletContext; 4 | import javax.servlet.http.HttpServletRequest; 5 | 6 | import org.json.JSONObject; 7 | 8 | import org.grapheco.elfinder.controller.executor.AbstractJsonCommandExecutor; 9 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 10 | import org.grapheco.elfinder.controller.executor.FsItemEx; 11 | import org.grapheco.elfinder.service.FsService; 12 | 13 | public class MkdirCommandExecutor extends AbstractJsonCommandExecutor implements 14 | CommandExecutor 15 | { 16 | @Override 17 | public void execute(FsService fsService, HttpServletRequest request, 18 | ServletContext servletContext, JSONObject json) throws Exception 19 | { 20 | String target = request.getParameter("target"); 21 | String name = request.getParameter("name"); 22 | 23 | FsItemEx fsi = super.findItem(fsService, target); 24 | FsItemEx dir = new FsItemEx(fsi, name); 25 | dir.createFolder(); 26 | 27 | json.put("added", new Object[] { getFsItemInfo(request, dir) }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/GetCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import java.io.InputStream; 4 | 5 | import javax.servlet.ServletContext; 6 | import javax.servlet.http.HttpServletRequest; 7 | 8 | import org.apache.commons.io.IOUtils; 9 | import org.grapheco.elfinder.controller.executor.AbstractJsonCommandExecutor; 10 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 11 | import org.grapheco.elfinder.controller.executor.FsItemEx; 12 | import org.json.JSONObject; 13 | 14 | import org.grapheco.elfinder.service.FsService; 15 | 16 | public class GetCommandExecutor extends AbstractJsonCommandExecutor implements 17 | CommandExecutor 18 | { 19 | @Override 20 | public void execute(FsService fsService, HttpServletRequest request, 21 | ServletContext servletContext, JSONObject json) throws Exception 22 | { 23 | String target = request.getParameter("target"); 24 | 25 | FsItemEx fsi = super.findItem(fsService, target); 26 | InputStream is = fsi.openInputStream(); 27 | String content = IOUtils.toString(is, "utf-8"); 28 | is.close(); 29 | json.put("content", content); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/PutCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import java.io.ByteArrayInputStream; 4 | 5 | import javax.servlet.ServletContext; 6 | import javax.servlet.http.HttpServletRequest; 7 | 8 | import org.json.JSONObject; 9 | 10 | import org.grapheco.elfinder.controller.executor.AbstractJsonCommandExecutor; 11 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 12 | import org.grapheco.elfinder.controller.executor.FsItemEx; 13 | import org.grapheco.elfinder.service.FsService; 14 | 15 | public class PutCommandExecutor extends AbstractJsonCommandExecutor implements 16 | CommandExecutor 17 | { 18 | @Override 19 | public void execute(FsService fsService, HttpServletRequest request, 20 | ServletContext servletContext, JSONObject json) throws Exception 21 | { 22 | String target = request.getParameter("target"); 23 | 24 | FsItemEx fsi = super.findItem(fsService, target); 25 | fsi.writeStream(new ByteArrayInputStream(request 26 | .getParameter("content").getBytes("utf-8"))); 27 | json.put("changed", new Object[] { super.getFsItemInfo(request, fsi) }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/TreeCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import javax.servlet.ServletContext; 7 | import javax.servlet.http.HttpServletRequest; 8 | 9 | import org.json.JSONObject; 10 | 11 | import org.grapheco.elfinder.controller.executor.AbstractJsonCommandExecutor; 12 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 13 | import org.grapheco.elfinder.controller.executor.FsItemEx; 14 | import org.grapheco.elfinder.service.FsService; 15 | 16 | public class TreeCommandExecutor extends AbstractJsonCommandExecutor implements 17 | CommandExecutor 18 | { 19 | @Override 20 | public void execute(FsService fsService, HttpServletRequest request, 21 | ServletContext servletContext, JSONObject json) throws Exception 22 | { 23 | String target = request.getParameter("target"); 24 | 25 | Map files = new HashMap(); 26 | FsItemEx fsi = super.findItem(fsService, target); 27 | super.addSubfolders(files, fsi); 28 | 29 | json.put("tree", files2JsonArray(request, files.values())); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/SizeCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import javax.servlet.ServletContext; 4 | import javax.servlet.http.HttpServletRequest; 5 | 6 | import org.json.JSONObject; 7 | 8 | import org.grapheco.elfinder.controller.executor.AbstractJsonCommandExecutor; 9 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 10 | import org.grapheco.elfinder.controller.executor.FsItemEx; 11 | import org.grapheco.elfinder.service.FsService; 12 | 13 | /** 14 | * This calculates the total size of all the supplied targets and returns the 15 | * size in bytes. 16 | */ 17 | public class SizeCommandExecutor extends AbstractJsonCommandExecutor implements 18 | CommandExecutor 19 | { 20 | @Override 21 | protected void execute(FsService fsService, HttpServletRequest request, 22 | ServletContext servletContext, JSONObject json) throws Exception 23 | { 24 | String[] targets = request.getParameterValues("targets[]"); 25 | long size = 0; 26 | for (String target : targets) 27 | { 28 | FsItemEx item = findItem(fsService, target); 29 | size += item.getSize(); 30 | } 31 | json.put("size", size); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/LsCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import javax.servlet.ServletContext; 7 | import javax.servlet.http.HttpServletRequest; 8 | 9 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 10 | import org.json.JSONObject; 11 | 12 | import org.grapheco.elfinder.controller.executor.AbstractJsonCommandExecutor; 13 | import org.grapheco.elfinder.controller.executor.FsItemEx; 14 | import org.grapheco.elfinder.service.FsService; 15 | 16 | public class LsCommandExecutor extends AbstractJsonCommandExecutor implements 17 | CommandExecutor 18 | { 19 | @Override 20 | public void execute(FsService fsService, HttpServletRequest request, 21 | ServletContext servletContext, JSONObject json) throws Exception 22 | { 23 | String target = request.getParameter("target"); 24 | String[] onlyMimes = request.getParameterValues("mimes[]"); 25 | 26 | Map files = new HashMap(); 27 | FsItemEx fsi = super.findItem(fsService, target); 28 | super.addChildren(files, fsi, onlyMimes); 29 | 30 | json.put("list", files2JsonArray(request, files.values())); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/RenameCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import javax.servlet.ServletContext; 4 | import javax.servlet.http.HttpServletRequest; 5 | 6 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 7 | import org.json.JSONObject; 8 | 9 | import org.grapheco.elfinder.controller.executor.AbstractJsonCommandExecutor; 10 | import org.grapheco.elfinder.controller.executor.FsItemEx; 11 | import org.grapheco.elfinder.service.FsService; 12 | 13 | public class RenameCommandExecutor extends AbstractJsonCommandExecutor 14 | implements CommandExecutor 15 | { 16 | @Override 17 | public void execute(FsService fsService, HttpServletRequest request, 18 | ServletContext servletContext, JSONObject json) throws Exception 19 | { 20 | String target = request.getParameter("target"); 21 | String current = request.getParameter("current"); 22 | String name = request.getParameter("name"); 23 | 24 | FsItemEx fsi = super.findItem(fsService, target); 25 | FsItemEx dst = new FsItemEx(fsi.getParent(), name); 26 | fsi.renameTo(dst); 27 | 28 | json.put("added", new Object[] { getFsItemInfo(request, dst) }); 29 | json.put("removed", new String[] { target }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/RmCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import javax.servlet.ServletContext; 7 | import javax.servlet.http.HttpServletRequest; 8 | 9 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 10 | import org.json.JSONObject; 11 | 12 | import org.grapheco.elfinder.controller.executor.AbstractJsonCommandExecutor; 13 | import org.grapheco.elfinder.controller.executor.FsItemEx; 14 | import org.grapheco.elfinder.service.FsService; 15 | 16 | public class RmCommandExecutor extends AbstractJsonCommandExecutor implements 17 | CommandExecutor 18 | { 19 | @Override 20 | public void execute(FsService fsService, HttpServletRequest request, 21 | ServletContext servletContext, JSONObject json) throws Exception 22 | { 23 | String[] targets = request.getParameterValues("targets[]"); 24 | String current = request.getParameter("current"); 25 | List removed = new ArrayList(); 26 | 27 | for (String target : targets) 28 | { 29 | FsItemEx ftgt = super.findItem(fsService, target); 30 | ftgt.delete(); 31 | removed.add(ftgt.getHash()); 32 | } 33 | 34 | json.put("removed", removed.toArray()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/impl/FsSecurityCheckForAll.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.impl; 2 | 3 | import org.grapheco.elfinder.service.FsItem; 4 | import org.grapheco.elfinder.service.FsSecurityChecker; 5 | import org.grapheco.elfinder.service.FsService; 6 | 7 | public class FsSecurityCheckForAll implements FsSecurityChecker 8 | { 9 | boolean _locked = false; 10 | 11 | boolean _readable = true; 12 | 13 | boolean _writable = true; 14 | 15 | public boolean isLocked() 16 | { 17 | return _locked; 18 | } 19 | 20 | @Override 21 | public boolean isLocked(FsService fsService, FsItem fsi) 22 | { 23 | return _locked; 24 | } 25 | 26 | public boolean isReadable() 27 | { 28 | return _readable; 29 | } 30 | 31 | @Override 32 | public boolean isReadable(FsService fsService, FsItem fsi) 33 | { 34 | return _readable; 35 | } 36 | 37 | public boolean isWritable() 38 | { 39 | return _writable; 40 | } 41 | 42 | @Override 43 | public boolean isWritable(FsService fsService, FsItem fsi) 44 | { 45 | return _writable; 46 | } 47 | 48 | public void setLocked(boolean locked) 49 | { 50 | _locked = locked; 51 | } 52 | 53 | public void setReadable(boolean readable) 54 | { 55 | _readable = readable; 56 | } 57 | 58 | public void setWritable(boolean writable) 59 | { 60 | _writable = writable; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/MkfileCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import javax.servlet.ServletContext; 4 | import javax.servlet.http.HttpServletRequest; 5 | 6 | import org.json.JSONObject; 7 | 8 | import org.grapheco.elfinder.controller.executor.AbstractJsonCommandExecutor; 9 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 10 | import org.grapheco.elfinder.controller.executor.FsItemEx; 11 | import org.grapheco.elfinder.service.FsItemFilter; 12 | import org.grapheco.elfinder.service.FsService; 13 | 14 | public class MkfileCommandExecutor extends AbstractJsonCommandExecutor 15 | implements CommandExecutor 16 | { 17 | @Override 18 | public void execute(FsService fsService, HttpServletRequest request, 19 | ServletContext servletContext, JSONObject json) throws Exception 20 | { 21 | String target = request.getParameter("target"); 22 | String name = request.getParameter("name"); 23 | 24 | FsItemEx fsi = super.findItem(fsService, target); 25 | FsItemEx dir = new FsItemEx(fsi, name); 26 | dir.createFile(); 27 | 28 | // if the new file is allowed to be display? 29 | FsItemFilter filter = getRequestedFilter(request); 30 | json.put( 31 | "added", 32 | filter.accepts(dir) ? new Object[] { getFsItemInfo(request, dir) } 33 | : new Object[0]); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, shen zhihong 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | elFinder 2.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 33 | 34 | 35 | 36 | 37 |
38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executor/DefaultCommandExecutorFactory.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executor; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class DefaultCommandExecutorFactory implements CommandExecutorFactory 7 | { 8 | String _classNamePattern; 9 | 10 | private Map _map = new HashMap(); 11 | 12 | private CommandExecutor _fallbackCommand; 13 | 14 | @Override 15 | public CommandExecutor get(String commandName) 16 | { 17 | if (_map.containsKey(commandName)) 18 | return _map.get(commandName); 19 | 20 | try 21 | { 22 | String className = String.format(_classNamePattern, commandName 23 | .substring(0, 1).toUpperCase() + commandName.substring(1)); 24 | return (CommandExecutor) Class.forName(className).newInstance(); 25 | } 26 | catch (Exception e) 27 | { 28 | // not found 29 | return _fallbackCommand; 30 | } 31 | } 32 | 33 | public String getClassNamePattern() 34 | { 35 | return _classNamePattern; 36 | } 37 | 38 | public Map getMap() 39 | { 40 | return _map; 41 | } 42 | 43 | public CommandExecutor getFallbackCommand() 44 | { 45 | return _fallbackCommand; 46 | } 47 | 48 | public void setClassNamePattern(String classNamePattern) 49 | { 50 | _classNamePattern = classNamePattern; 51 | } 52 | 53 | public void setMap(Map map) 54 | { 55 | _map = map; 56 | } 57 | 58 | public void setFallbackCommand(CommandExecutor fallbackCommand) 59 | { 60 | this._fallbackCommand = fallbackCommand; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/ParentsCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import javax.servlet.ServletContext; 7 | import javax.servlet.http.HttpServletRequest; 8 | 9 | import org.grapheco.elfinder.controller.ErrorException; 10 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 11 | import org.json.JSONObject; 12 | 13 | import org.grapheco.elfinder.controller.executor.AbstractJsonCommandExecutor; 14 | import org.grapheco.elfinder.controller.executor.FsItemEx; 15 | import org.grapheco.elfinder.service.FsService; 16 | 17 | public class ParentsCommandExecutor extends AbstractJsonCommandExecutor 18 | implements CommandExecutor 19 | { 20 | // This is a limit on the number of parents so that a badly implemented 21 | // FsService can't 22 | // result in a runaway thread. 23 | final static int LIMIT = 1024; 24 | 25 | @Override 26 | public void execute(FsService fsService, HttpServletRequest request, 27 | ServletContext servletContext, JSONObject json) throws Exception 28 | { 29 | String target = request.getParameter("target"); 30 | 31 | Map files = new HashMap(); 32 | FsItemEx fsi = findItem(fsService, target); 33 | for (int i = 0; !fsi.isRoot(); i++) 34 | { 35 | super.addSubfolders(files, fsi); 36 | fsi = fsi.getParent(); 37 | if (i > LIMIT) 38 | { 39 | throw new ErrorException( 40 | "Reached recursion limit on parents of: " + LIMIT); 41 | } 42 | } 43 | 44 | json.put("tree", files2JsonArray(request, files.values())); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/PasteCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import javax.servlet.ServletContext; 7 | import javax.servlet.http.HttpServletRequest; 8 | 9 | import org.json.JSONObject; 10 | 11 | import org.grapheco.elfinder.controller.executor.AbstractJsonCommandExecutor; 12 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 13 | import org.grapheco.elfinder.controller.executor.FsItemEx; 14 | import org.grapheco.elfinder.service.FsService; 15 | 16 | public class PasteCommandExecutor extends AbstractJsonCommandExecutor implements 17 | CommandExecutor 18 | { 19 | @Override 20 | public void execute(FsService fsService, HttpServletRequest request, 21 | ServletContext servletContext, JSONObject json) throws Exception 22 | { 23 | String[] targets = request.getParameterValues("targets[]"); 24 | String src = request.getParameter("src"); 25 | String dst = request.getParameter("dst"); 26 | boolean cut = "1".equals(request.getParameter("cut")); 27 | 28 | List added = new ArrayList<>(); 29 | List removed = new ArrayList<>(); 30 | 31 | FsItemEx fsrc = super.findItem(fsService, src); 32 | FsItemEx fdst = super.findItem(fsService, dst); 33 | 34 | for (String target : targets) 35 | { 36 | FsItemEx ftgt = super.findItem(fsService, target); 37 | String name = ftgt.getName(); 38 | FsItemEx newFile = new FsItemEx(fdst, name); 39 | super.createAndCopy(ftgt, newFile); 40 | added.add(newFile); 41 | 42 | if (cut) 43 | { 44 | ftgt.delete(); 45 | removed.add(target); 46 | } 47 | } 48 | 49 | json.put("added", files2JsonArray(request, added)); 50 | json.put("removed", removed); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/impl/FsSecurityCheckerChain.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.impl; 2 | 3 | import java.io.IOException; 4 | import java.util.List; 5 | 6 | import org.grapheco.elfinder.service.FsItem; 7 | import org.grapheco.elfinder.service.FsSecurityChecker; 8 | import org.grapheco.elfinder.service.FsService; 9 | 10 | public class FsSecurityCheckerChain implements FsSecurityChecker 11 | { 12 | private static final FsSecurityChecker DEFAULT_SECURITY_CHECKER = new FsSecurityCheckForAll(); 13 | 14 | List _filterMappings; 15 | 16 | private FsSecurityChecker getChecker(FsService fsService, FsItem fsi) 17 | throws IOException 18 | { 19 | String hash = fsService.getHash(fsi); 20 | for (FsSecurityCheckFilterMapping mapping : _filterMappings) 21 | { 22 | if (mapping.matches(hash)) 23 | { 24 | return mapping.getChecker(); 25 | } 26 | } 27 | 28 | return DEFAULT_SECURITY_CHECKER; 29 | } 30 | 31 | public List getFilterMappings() 32 | { 33 | return _filterMappings; 34 | } 35 | 36 | @Override 37 | public boolean isLocked(FsService fsService, FsItem fsi) throws IOException 38 | { 39 | return getChecker(fsService, fsi).isLocked(fsService, fsi); 40 | } 41 | 42 | @Override 43 | public boolean isReadable(FsService fsService, FsItem fsi) 44 | throws IOException 45 | { 46 | return getChecker(fsService, fsi).isReadable(fsService, fsi); 47 | } 48 | 49 | @Override 50 | public boolean isWritable(FsService fsService, FsItem fsi) 51 | throws IOException 52 | { 53 | return getChecker(fsService, fsi).isWritable(fsService, fsi); 54 | } 55 | 56 | public void setFilterMappings( 57 | List filterMappings) 58 | { 59 | _filterMappings = filterMappings; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/util/MimeTypesUtils.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.util; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | import org.springframework.core.io.ClassPathResource; 11 | 12 | public abstract class MimeTypesUtils 13 | { 14 | private static Map _map; 15 | 16 | public static final String UNKNOWN_MIME_TYPE = "application/oct-stream"; 17 | 18 | static 19 | { 20 | _map = new HashMap(); 21 | try 22 | { 23 | load(); 24 | } 25 | catch (Throwable e) 26 | { 27 | e.printStackTrace(); 28 | } 29 | } 30 | 31 | public static String getMimeType(String ext) 32 | { 33 | return _map.get(ext.toLowerCase()); 34 | } 35 | 36 | public static boolean isUnknownType(String mime) 37 | { 38 | return mime == null || UNKNOWN_MIME_TYPE.equals(mime); 39 | } 40 | 41 | private static void load() throws IOException 42 | { 43 | InputStream is = new ClassPathResource("/mime.types").getInputStream(); 44 | BufferedReader fr = new BufferedReader(new InputStreamReader(is)); 45 | String line; 46 | while ((line = fr.readLine()) != null) 47 | { 48 | line = line.trim(); 49 | if (line.startsWith("#") || line.isEmpty()) 50 | { 51 | continue; 52 | } 53 | 54 | String[] tokens = line.split("\\s+"); 55 | if (tokens.length < 2) 56 | continue; 57 | 58 | for (int i = 1; i < tokens.length; i++) 59 | { 60 | putMimeType(tokens[i], tokens[0]); 61 | } 62 | } 63 | 64 | is.close(); 65 | } 66 | 67 | public static void putMimeType(String ext, String type) 68 | { 69 | if (ext == null || type == null) 70 | return; 71 | 72 | _map.put(ext.toLowerCase(), type); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executor/AbstractJsonCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executor; 2 | 3 | import java.io.PrintWriter; 4 | 5 | import javax.servlet.ServletContext; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | 9 | import org.grapheco.elfinder.controller.ErrorException; 10 | import org.json.JSONArray; 11 | import org.json.JSONObject; 12 | 13 | import org.grapheco.elfinder.service.FsService; 14 | 15 | public abstract class AbstractJsonCommandExecutor extends 16 | AbstractCommandExecutor 17 | { 18 | @Override 19 | final public void execute(FsService fsService, HttpServletRequest request, 20 | HttpServletResponse response, ServletContext servletContext) 21 | throws Exception 22 | { 23 | JSONObject json = new JSONObject(); 24 | try 25 | { 26 | execute(fsService, request, servletContext, json); 27 | } 28 | catch (ErrorException e) 29 | { 30 | if (e.getArgs() == null || e.getArgs().length == 0) 31 | { 32 | json.put("error", e.getError()); 33 | } 34 | else 35 | { 36 | JSONArray errors = new JSONArray(); 37 | errors.put(e.getError()); 38 | for (String arg : e.getArgs()) 39 | { 40 | errors.put(arg); 41 | } 42 | json.put("error", errors); 43 | } 44 | } 45 | catch (Exception e) 46 | { 47 | e.printStackTrace(); 48 | json.put("error", e.getMessage()); 49 | } 50 | finally 51 | { 52 | // response.setContentType("application/json; charset=UTF-8"); 53 | response.setContentType("text/html; charset=UTF-8"); 54 | 55 | PrintWriter writer = response.getWriter(); 56 | json.write(writer); 57 | writer.flush(); 58 | writer.close(); 59 | } 60 | } 61 | 62 | protected abstract void execute(FsService fsService, 63 | HttpServletRequest request, ServletContext servletContext, 64 | JSONObject json) throws Exception; 65 | 66 | } -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/OpenCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | 6 | import javax.servlet.ServletContext; 7 | import javax.servlet.http.HttpServletRequest; 8 | 9 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 10 | import org.grapheco.elfinder.service.FsVolume; 11 | import org.json.JSONObject; 12 | 13 | import org.grapheco.elfinder.controller.executor.AbstractJsonCommandExecutor; 14 | import org.grapheco.elfinder.controller.executor.FsItemEx; 15 | import org.grapheco.elfinder.service.FsService; 16 | 17 | public class OpenCommandExecutor extends AbstractJsonCommandExecutor implements 18 | CommandExecutor 19 | { 20 | @Override 21 | public void execute(FsService fsService, HttpServletRequest request, 22 | ServletContext servletContext, JSONObject json) throws Exception 23 | { 24 | boolean init = request.getParameter("init") != null; 25 | boolean tree = request.getParameter("tree") != null; 26 | String target = request.getParameter("target"); 27 | 28 | Map files = new LinkedHashMap(); 29 | if (init) 30 | { 31 | json.put("api", 2.1); 32 | json.put("netDrivers", new Object[0]); 33 | } 34 | 35 | if (tree) 36 | { 37 | for (FsVolume v : fsService.getVolumes()) 38 | { 39 | FsItemEx root = new FsItemEx(v.getRoot(), fsService); 40 | files.put(root.getHash(), root); 41 | addSubfolders(files, root); 42 | } 43 | } 44 | 45 | FsItemEx cwd = findCwd(fsService, target); 46 | files.put(cwd.getHash(), cwd); 47 | String[] onlyMimes = request.getParameterValues("mimes[]"); 48 | addChildren(files, cwd, onlyMimes); 49 | 50 | json.put("files", files2JsonArray(request, files.values())); 51 | json.put("cwd", getFsItemInfo(request, cwd)); 52 | json.put("options", getOptions(request, cwd)); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/DuplicateCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import javax.servlet.ServletContext; 7 | import javax.servlet.http.HttpServletRequest; 8 | 9 | import org.apache.commons.io.FilenameUtils; 10 | import org.grapheco.elfinder.controller.executor.AbstractJsonCommandExecutor; 11 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 12 | import org.grapheco.elfinder.controller.executor.FsItemEx; 13 | import org.json.JSONObject; 14 | 15 | import org.grapheco.elfinder.service.FsService; 16 | 17 | public class DuplicateCommandExecutor extends AbstractJsonCommandExecutor 18 | implements CommandExecutor 19 | { 20 | @Override 21 | public void execute(FsService fsService, HttpServletRequest request, 22 | ServletContext servletContext, JSONObject json) throws Exception 23 | { 24 | String[] targets = request.getParameterValues("targets[]"); 25 | 26 | List added = new ArrayList(); 27 | 28 | for (String target : targets) 29 | { 30 | FsItemEx fsi = super.findItem(fsService, target); 31 | String name = fsi.getName(); 32 | String baseName = FilenameUtils.getBaseName(name); 33 | String extension = FilenameUtils.getExtension(name); 34 | 35 | int i = 1; 36 | FsItemEx newFile = null; 37 | baseName = baseName.replaceAll("\\(\\d+\\)$", ""); 38 | 39 | while (true) 40 | { 41 | String newName = String.format("%s(%d)%s", baseName, i, 42 | (extension == null || extension.isEmpty() ? "" : "." 43 | + extension)); 44 | newFile = new FsItemEx(fsi.getParent(), newName); 45 | if (!newFile.exists()) 46 | { 47 | break; 48 | } 49 | i++; 50 | } 51 | 52 | createAndCopy(fsi, newFile); 53 | added.add(newFile); 54 | } 55 | 56 | json.put("added", files2JsonArray(request, added)); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/service/FsVolume.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.service; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.Map; 6 | 7 | public interface FsVolume 8 | { 9 | void createFile(FsItem fsi) throws IOException; 10 | 11 | void createFolder(FsItem fsi) throws IOException; 12 | 13 | void deleteFile(FsItem fsi) throws IOException; 14 | 15 | void deleteFolder(FsItem fsi) throws IOException; 16 | 17 | boolean exists(FsItem newFile); 18 | 19 | FsItem fromPath(String relativePath); 20 | 21 | String getDimensions(FsItem fsi); 22 | 23 | long getLastModified(FsItem fsi); 24 | 25 | String getMimeType(FsItem fsi); 26 | 27 | String getName(); 28 | 29 | String getName(FsItem fsi); 30 | 31 | FsItem getParent(FsItem fsi); 32 | 33 | String getPath(FsItem fsi) throws IOException; 34 | 35 | FsItem getRoot(); 36 | 37 | long getSize(FsItem fsi) throws IOException; 38 | 39 | String getThumbnailFileName(FsItem fsi); 40 | 41 | boolean hasChildFolder(FsItem fsi); 42 | 43 | boolean isFolder(FsItem fsi); 44 | 45 | boolean isRoot(FsItem fsi); 46 | 47 | FsItem[] listChildren(FsItem fsi); 48 | 49 | InputStream openInputStream(FsItem fsi) throws IOException; 50 | 51 | void writeStream(FsItem f, InputStream is) throws IOException; 52 | 53 | void rename(FsItem src, FsItem dst) throws IOException; 54 | 55 | /** 56 | * Gets the URL for the supplied item. 57 | * 58 | * @param f 59 | * The item to get the URL for. 60 | * @return An absolute URL or null if we should not send back a 61 | * URL. 62 | */ 63 | String getURL(FsItem f); 64 | 65 | /** 66 | * This allows volumes to change the options returned to the client for a 67 | * particular item. Implementations should update the map they are passed. 68 | * 69 | * @param f 70 | * The item to filter the options for. 71 | * @param map 72 | * The options that are going to be returned. 73 | */ 74 | void filterOptions(FsItem f, Map map); 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/TmbCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.InputStream; 6 | import java.util.Calendar; 7 | 8 | import javax.imageio.ImageIO; 9 | import javax.servlet.ServletContext; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | 13 | import org.apache.commons.lang3.time.DateUtils; 14 | 15 | import org.grapheco.elfinder.controller.executor.AbstractCommandExecutor; 16 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 17 | import org.grapheco.elfinder.controller.executor.FsItemEx; 18 | import org.grapheco.elfinder.service.FsService; 19 | 20 | import com.mortennobel.imagescaling.DimensionConstrain; 21 | import com.mortennobel.imagescaling.ResampleOp; 22 | 23 | public class TmbCommandExecutor extends AbstractCommandExecutor implements 24 | CommandExecutor 25 | { 26 | @Override 27 | public void execute(FsService fsService, HttpServletRequest request, 28 | HttpServletResponse response, ServletContext servletContext) 29 | throws Exception 30 | { 31 | String target = request.getParameter("target"); 32 | FsItemEx fsi = super.findItem(fsService, target); 33 | InputStream is = fsi.openInputStream(); 34 | BufferedImage image = ImageIO.read(is); 35 | int width = fsService.getServiceConfig().getTmbWidth(); 36 | ResampleOp rop = new ResampleOp(DimensionConstrain.createMaxDimension( 37 | width, -1)); 38 | rop.setNumberOfThreads(4); 39 | BufferedImage b = rop.filter(image, null); 40 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 41 | ImageIO.write(b, "png", baos); 42 | byte[] bytesOut = baos.toByteArray(); 43 | is.close(); 44 | 45 | response.setHeader("Last-Modified", 46 | DateUtils.addDays(Calendar.getInstance().getTime(), 2 * 360) 47 | .toGMTString()); 48 | response.setHeader("Expires", 49 | DateUtils.addDays(Calendar.getInstance().getTime(), 2 * 360) 50 | .toGMTString()); 51 | 52 | ImageIO.write(b, "png", response.getOutputStream()); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/util/FsItemFilterUtils.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.grapheco.elfinder.controller.executor.FsItemEx; 7 | import org.grapheco.elfinder.service.FsItemFilter; 8 | 9 | public abstract class FsItemFilterUtils 10 | { 11 | public static FsItemFilter FILTER_ALL = new FsItemFilter() 12 | { 13 | @Override 14 | public boolean accepts(FsItemEx item) 15 | { 16 | return true; 17 | } 18 | }; 19 | 20 | public static FsItemFilter FILTER_FOLDER = new FsItemFilter() 21 | { 22 | @Override 23 | public boolean accepts(FsItemEx item) 24 | { 25 | return item.isFolder(); 26 | } 27 | }; 28 | 29 | public static FsItemFilter createFileNameKeywordFilter(final String keyword) 30 | { 31 | return new FsItemFilter() 32 | { 33 | @Override 34 | public boolean accepts(FsItemEx item) 35 | { 36 | return item.getName().contains(keyword); 37 | } 38 | }; 39 | } 40 | 41 | public static FsItemEx[] filterFiles(FsItemEx[] sourceFiles, 42 | FsItemFilter filter) 43 | { 44 | List filtered = new ArrayList(); 45 | for (FsItemEx file : sourceFiles) 46 | { 47 | if (filter.accepts(file)) 48 | filtered.add(file); 49 | } 50 | 51 | return filtered.toArray(new FsItemEx[0]); 52 | } 53 | 54 | /** 55 | * returns a FsItemFilter according to given mimeFilters 56 | * 57 | * @param mimeFilters 58 | * An array of MIME types, if null no filtering is 59 | * done 60 | * @return A filter that only accepts the supplied MIME types. 61 | */ 62 | public static FsItemFilter createMimeFilter(final String[] mimeFilters) 63 | { 64 | if (mimeFilters == null || mimeFilters.length == 0) 65 | return FILTER_ALL; 66 | 67 | return new FsItemFilter() 68 | { 69 | @Override 70 | public boolean accepts(FsItemEx item) 71 | { 72 | String mimeType = item.getMimeType().toUpperCase(); 73 | 74 | for (String mf : mimeFilters) 75 | { 76 | mf = mf.toUpperCase(); 77 | if (mimeType.startsWith(mf + "/") || mimeType.equals(mf)) 78 | return true; 79 | } 80 | return false; 81 | } 82 | }; 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/DimCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | 7 | import javax.imageio.ImageIO; 8 | import javax.servlet.ServletContext; 9 | import javax.servlet.http.HttpServletRequest; 10 | 11 | import org.json.JSONObject; 12 | 13 | import org.grapheco.elfinder.controller.executor.AbstractJsonCommandExecutor; 14 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 15 | import org.grapheco.elfinder.controller.executor.FsItemEx; 16 | import org.grapheco.elfinder.service.FsService; 17 | 18 | /** 19 | * This returns the dimensions on an image. 20 | */ 21 | public class DimCommandExecutor extends AbstractJsonCommandExecutor implements 22 | CommandExecutor 23 | { 24 | @Override 25 | protected void execute(FsService fsService, HttpServletRequest request, 26 | ServletContext servletContext, JSONObject json) throws Exception 27 | { 28 | String target = request.getParameter("target"); 29 | FsItemEx item = findItem(fsService, target); 30 | // If it's not an image then just return empty JSON. 31 | if (item.getMimeType().startsWith("image")) 32 | { 33 | InputStream inputStream = null; 34 | try 35 | { 36 | inputStream = item.openInputStream(); 37 | BufferedImage image = ImageIO.read(inputStream); 38 | int width = image.getWidth(); 39 | int height = image.getHeight(); 40 | json.put("dim", String.format("%dx%d", width, height)); 41 | } 42 | catch (IOException ioe) 43 | { 44 | String message = "Failed load image to get dimensions: " 45 | + item.getPath(); 46 | if (LOG.isDebugEnabled()) 47 | { 48 | LOG.debug(message, ioe); 49 | } 50 | else 51 | { 52 | LOG.warn(message); 53 | } 54 | 55 | } 56 | finally 57 | { 58 | if (inputStream != null) 59 | { 60 | try 61 | { 62 | inputStream.close(); 63 | } 64 | catch (IOException ioe) 65 | { 66 | LOG.debug( 67 | "Failed to close stream to: " + item.getPath(), 68 | ioe); 69 | } 70 | } 71 | } 72 | 73 | } 74 | else 75 | { 76 | LOG.debug("dim command called on non-image: " + item.getPath()); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | /target/ 217 | /.idea/ 218 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/FileCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.io.UnsupportedEncodingException; 7 | import java.net.URLEncoder; 8 | 9 | import javax.mail.internet.MimeUtility; 10 | import javax.servlet.ServletContext; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | 14 | import org.apache.commons.io.IOUtils; 15 | 16 | import org.grapheco.elfinder.controller.executor.AbstractCommandExecutor; 17 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 18 | import org.grapheco.elfinder.controller.executor.FsItemEx; 19 | import org.grapheco.elfinder.service.FsService; 20 | import org.grapheco.elfinder.util.MimeTypesUtils; 21 | 22 | public class FileCommandExecutor extends AbstractCommandExecutor implements 23 | CommandExecutor 24 | { 25 | @Override 26 | public void execute(FsService fsService, HttpServletRequest request, 27 | HttpServletResponse response, ServletContext servletContext) 28 | throws Exception 29 | { 30 | String target = request.getParameter("target"); 31 | boolean download = "1".equals(request.getParameter("download")); 32 | FsItemEx fsi = super.findItem(fsService, target); 33 | String mime = fsi.getMimeType(); 34 | 35 | response.setCharacterEncoding("utf-8"); 36 | response.setContentType(mime); 37 | // String fileUrl = getFileUrl(fileTarget); 38 | // String fileUrlRelative = getFileUrl(fileTarget); 39 | 40 | // a folder! 41 | if (fsi.isFolder()) 42 | { 43 | response.sendRedirect(request.getHeader("Referer") + "#elf_" 44 | + fsi.getHash()); 45 | return; 46 | } 47 | 48 | String fileName = fsi.getName(); 49 | // fileName = new String(fileName.getBytes("utf-8"), "ISO8859-1"); 50 | if (download || MimeTypesUtils.isUnknownType(mime)) 51 | { 52 | response.setHeader( 53 | "Content-Disposition", 54 | "attachments; " 55 | + getAttachementFileName(fileName, 56 | request.getHeader("USER-AGENT"))); 57 | // response.setHeader("Content-Location", fileUrlRelative); 58 | response.setHeader("Content-Transfer-Encoding", "binary"); 59 | } 60 | 61 | OutputStream out = response.getOutputStream(); 62 | InputStream is = null; 63 | response.setContentLength((int) fsi.getSize()); 64 | try 65 | { 66 | // serve file 67 | is = fsi.openInputStream(); 68 | IOUtils.copy(is, out); 69 | out.flush(); 70 | out.close(); 71 | } 72 | finally 73 | { 74 | if (is != null) 75 | { 76 | try 77 | { 78 | is.close(); 79 | } 80 | catch (IOException e) 81 | { 82 | e.printStackTrace(); 83 | } 84 | } 85 | } 86 | } 87 | 88 | private String getAttachementFileName(String fileName, String userAgent) 89 | throws UnsupportedEncodingException 90 | { 91 | if (userAgent != null) 92 | { 93 | userAgent = userAgent.toLowerCase(); 94 | 95 | if (userAgent.indexOf("msie") != -1) 96 | { 97 | return "filename=\"" + URLEncoder.encode(fileName, "UTF8") 98 | + "\""; 99 | } 100 | 101 | // Opera浏览器只能采用filename* 102 | if (userAgent.indexOf("opera") != -1) 103 | { 104 | return "filename*=UTF-8''" 105 | + URLEncoder.encode(fileName, "UTF8"); 106 | } 107 | // Safari浏览器,只能采用ISO编码的中文输出 108 | if (userAgent.indexOf("safari") != -1) 109 | { 110 | return "filename=\"" 111 | + new String(fileName.getBytes("UTF-8"), "ISO8859-1") 112 | + "\""; 113 | } 114 | // Chrome浏览器,只能采用MimeUtility编码或ISO编码的中文输出 115 | if (userAgent.indexOf("applewebkit") != -1) 116 | { 117 | return "filename=\"" 118 | + MimeUtility.encodeText(fileName, "UTF8", "B") + "\""; 119 | } 120 | // FireFox浏览器,可以使用MimeUtility或filename*或ISO编码的中文输出 121 | if (userAgent.indexOf("mozilla") != -1) 122 | { 123 | return "filename*=UTF-8''" 124 | + URLEncoder.encode(fileName, "UTF8"); 125 | } 126 | } 127 | 128 | return "filename=\"" + URLEncoder.encode(fileName, "UTF8") + "\""; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/MultipleUploadItems.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller; 2 | 3 | import org.apache.commons.fileupload.FileItemStream; 4 | import org.apache.commons.fileupload.FileUploadException; 5 | import org.apache.commons.io.IOUtils; 6 | import org.apache.log4j.Logger; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | import java.io.*; 10 | import java.lang.reflect.InvocationHandler; 11 | import java.lang.reflect.Method; 12 | import java.lang.reflect.Proxy; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | /** 17 | * this class stores upload files in the request attributes for later usage 18 | * 19 | * @author bluejoe 20 | */ 21 | public class MultipleUploadItems { 22 | Logger _logger = Logger.getLogger(this.getClass()); 23 | List _items = new ArrayList(); 24 | File _tempDir; 25 | 26 | public List items() { 27 | return _items; 28 | } 29 | 30 | public MultipleUploadItems(File tempDir) { 31 | _tempDir = tempDir; 32 | } 33 | 34 | /** 35 | * find items with given form field name 36 | * 37 | * @param fieldName 38 | * @return 39 | */ 40 | public List items(String fieldName) { 41 | List filteredItems = new ArrayList(); 42 | for (FileItemStream fis : _items) { 43 | if (fis.getFieldName().equals(fieldName)) 44 | filteredItems.add(fis); 45 | } 46 | 47 | return filteredItems; 48 | } 49 | 50 | public void addItem(FileItemStream fis) { 51 | _items.add(fis); 52 | } 53 | 54 | public void addItemProxy(final FileItemStream item) throws IOException { 55 | InputStream stream = item.openStream(); 56 | //ByteArrayOutputStream os = new ByteArrayOutputStream(); 57 | //create a temp source 58 | final File source = File.createTempFile("elfinder_upload_", "", _tempDir); 59 | FileOutputStream os = new FileOutputStream(source); 60 | IOUtils.copy(stream, os); 61 | os.close(); 62 | //final byte[] bs = os.toByteArray(); 63 | stream.close(); 64 | _logger.debug(String.format("saving item: %s", source.getCanonicalPath())); 65 | addItem((FileItemStream) Proxy.newProxyInstance(this.getClass() 66 | .getClassLoader(), new Class[]{FileItemStream.class, Finalizable.class}, 67 | new InvocationHandler() { 68 | @Override 69 | public Object invoke(Object proxy, Method method, 70 | Object[] args) throws Throwable { 71 | if ("openStream".equals(method.getName())) { 72 | //return new ByteArrayInputStream(bs); 73 | return new FileInputStream(source); 74 | } 75 | if ("finalize".equals(method.getName())) { 76 | source.delete(); 77 | _logger.debug(String.format("removing item: %s", source.getCanonicalPath())); 78 | return null; 79 | } 80 | return method.invoke(item, args); 81 | } 82 | })); 83 | } 84 | 85 | public void writeInto(HttpServletRequest request) 86 | throws FileUploadException, IOException { 87 | // store items for compatablity 88 | request.setAttribute(FileItemStream.class.getName(), _items); 89 | request.setAttribute(MultipleUploadItems.class.getName(), this); 90 | } 91 | 92 | public static MultipleUploadItems loadFrom(HttpServletRequest request) { 93 | return (MultipleUploadItems) request 94 | .getAttribute(MultipleUploadItems.class.getName()); 95 | } 96 | 97 | public static void finalize(HttpServletRequest request) { 98 | MultipleUploadItems mui = loadFrom(request); 99 | if (mui != null) { 100 | for (FileItemStream fis : mui.items()) { 101 | if (fis instanceof Finalizable) { 102 | ((Finalizable) fis).finalize(); 103 | } 104 | } 105 | } 106 | } 107 | 108 | interface Finalizable { 109 | void finalize(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/servlet/ConnectorServlet.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.servlet; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | 6 | import javax.servlet.ServletConfig; 7 | import javax.servlet.ServletException; 8 | import javax.servlet.http.HttpServlet; 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | 12 | import org.grapheco.elfinder.controller.ConnectorController; 13 | import org.grapheco.elfinder.controller.executor.CommandExecutorFactory; 14 | import org.grapheco.elfinder.controller.executor.DefaultCommandExecutorFactory; 15 | import org.grapheco.elfinder.controller.executors.MissingCommandExecutor; 16 | import org.grapheco.elfinder.impl.DefaultFsService; 17 | import org.grapheco.elfinder.impl.DefaultFsServiceConfig; 18 | import org.grapheco.elfinder.impl.FsSecurityCheckForAll; 19 | import org.grapheco.elfinder.impl.StaticFsServiceFactory; 20 | import org.grapheco.elfinder.localfs.LocalFsVolume; 21 | 22 | /** 23 | * ConnectorServlet is an example servlet 24 | * it creates a ConnectorController on init() and use it to handle requests on doGet()/doPost() 25 | * 26 | * users should extend from this servlet and customize required protected methods 27 | * 28 | * @author bluejoe 29 | * 30 | */ 31 | public class ConnectorServlet extends HttpServlet 32 | { 33 | // core member of this Servlet 34 | ConnectorController _connectorController; 35 | 36 | /** 37 | * create a command executor factory 38 | * 39 | * @param config 40 | * @return 41 | */ 42 | protected CommandExecutorFactory createCommandExecutorFactory( 43 | ServletConfig config) 44 | { 45 | DefaultCommandExecutorFactory defaultCommandExecutorFactory = new DefaultCommandExecutorFactory(); 46 | defaultCommandExecutorFactory 47 | .setClassNamePattern("cn.bluejoe.elfinder.controller.executors.%sCommandExecutor"); 48 | defaultCommandExecutorFactory 49 | .setFallbackCommand(new MissingCommandExecutor()); 50 | return defaultCommandExecutorFactory; 51 | } 52 | 53 | /** 54 | * create a connector controller 55 | * 56 | * @param config 57 | * @return 58 | */ 59 | protected ConnectorController createConnectorController(ServletConfig config) 60 | { 61 | ConnectorController connectorController = new ConnectorController(); 62 | 63 | connectorController 64 | .setCommandExecutorFactory(createCommandExecutorFactory(config)); 65 | connectorController.setFsServiceFactory(createServiceFactory(config)); 66 | 67 | return connectorController; 68 | } 69 | 70 | protected DefaultFsService createFsService() 71 | { 72 | DefaultFsService fsService = new DefaultFsService(); 73 | fsService.setSecurityChecker(new FsSecurityCheckForAll()); 74 | 75 | DefaultFsServiceConfig serviceConfig = new DefaultFsServiceConfig(); 76 | serviceConfig.setTmbWidth(80); 77 | 78 | fsService.setServiceConfig(serviceConfig); 79 | 80 | fsService.addVolume("A", 81 | createLocalFsVolume("My Files", new File("/tmp/a"))); 82 | fsService.addVolume("B", 83 | createLocalFsVolume("Shared", new File("/tmp/b"))); 84 | 85 | return fsService; 86 | } 87 | 88 | private LocalFsVolume createLocalFsVolume(String name, File rootDir) 89 | { 90 | LocalFsVolume localFsVolume = new LocalFsVolume(); 91 | localFsVolume.setName(name); 92 | localFsVolume.setRootDir(rootDir); 93 | return localFsVolume; 94 | } 95 | 96 | /** 97 | * create a service factory 98 | * 99 | * @param config 100 | * @return 101 | */ 102 | protected StaticFsServiceFactory createServiceFactory(ServletConfig config) 103 | { 104 | StaticFsServiceFactory staticFsServiceFactory = new StaticFsServiceFactory(); 105 | DefaultFsService fsService = createFsService(); 106 | 107 | staticFsServiceFactory.setFsService(fsService); 108 | return staticFsServiceFactory; 109 | } 110 | 111 | @Override 112 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) 113 | throws ServletException, IOException 114 | { 115 | _connectorController.connector(req, resp); 116 | } 117 | 118 | @Override 119 | protected void doPost(HttpServletRequest req, HttpServletResponse resp) 120 | throws ServletException, IOException 121 | { 122 | _connectorController.connector(req, resp); 123 | } 124 | 125 | @Override 126 | public void init(ServletConfig config) throws ServletException 127 | { 128 | _connectorController = createConnectorController(config); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/elfinder-servlet.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | 19 | 21 | 22 | 24 | 25 | 26 | 27 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executor/FsItemEx.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executor; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | import org.grapheco.elfinder.service.FsItem; 10 | import org.grapheco.elfinder.service.FsItemFilter; 11 | import org.grapheco.elfinder.service.FsService; 12 | import org.grapheco.elfinder.service.FsVolume; 13 | 14 | /** 15 | * FsItemEx is a helper class of a FsItem, A FsItemEx wraps a FsItem and its 16 | * context including FsService, FsVolume, etc 17 | * 18 | * @author bluejoe 19 | * 20 | */ 21 | public class FsItemEx 22 | { 23 | private FsItem _f; 24 | 25 | private FsService _s; 26 | 27 | private FsVolume _v; 28 | 29 | public FsItemEx(FsItem fsi, FsService fsService) 30 | { 31 | _f = fsi; 32 | _v = fsi.getVolume(); 33 | _s = fsService; 34 | } 35 | 36 | public FsItemEx(FsItemEx parent, String name) throws IOException 37 | { 38 | _v = parent._v; 39 | _s = parent._s; 40 | // Directories may already have a trailing slash on them so we make sure 41 | // we don't double up 42 | String path = _v.getPath(parent._f); 43 | if (path != null) 44 | { 45 | if (!path.endsWith("/")) 46 | { 47 | path = path + "/"; 48 | } 49 | path = path + name; 50 | } 51 | else 52 | { 53 | path = name; 54 | } 55 | _f = _v.fromPath(path); 56 | } 57 | 58 | public FsItemEx createChild(String name) throws IOException 59 | { 60 | return new FsItemEx(this, name); 61 | } 62 | 63 | public void createFile() throws IOException 64 | { 65 | _v.createFile(_f); 66 | } 67 | 68 | public void createFolder() throws IOException 69 | { 70 | _v.createFolder(_f); 71 | } 72 | 73 | public void delete() throws IOException 74 | { 75 | if (_v.isFolder(_f)) 76 | { 77 | _v.deleteFolder(_f); 78 | } 79 | else 80 | { 81 | _v.deleteFile(_f); 82 | } 83 | } 84 | 85 | public void deleteFile() throws IOException 86 | { 87 | _v.deleteFile(_f); 88 | } 89 | 90 | public void deleteFolder() throws IOException 91 | { 92 | _v.deleteFolder(_f); 93 | } 94 | 95 | public boolean exists() 96 | { 97 | return _v.exists(_f); 98 | } 99 | 100 | public String getHash() throws IOException 101 | { 102 | return _s.getHash(_f); 103 | } 104 | 105 | public long getLastModified() 106 | { 107 | return _v.getLastModified(_f); 108 | } 109 | 110 | public String getMimeType() 111 | { 112 | return _v.getMimeType(_f); 113 | } 114 | 115 | public String getName() 116 | { 117 | return _v.getName(_f); 118 | } 119 | 120 | public FsItemEx getParent() 121 | { 122 | return new FsItemEx(_v.getParent(_f), _s); 123 | } 124 | 125 | public String getPath() throws IOException 126 | { 127 | return _v.getPath(_f); 128 | } 129 | 130 | public long getSize() throws IOException 131 | { 132 | return _v.getSize(_f); 133 | } 134 | 135 | public String getVolumeId() 136 | { 137 | return _s.getVolumeId(_v); 138 | } 139 | 140 | public String getVolumnName() 141 | { 142 | return _v.getName(); 143 | } 144 | 145 | public boolean hasChildFolder() 146 | { 147 | return _v.hasChildFolder(_f); 148 | } 149 | 150 | public boolean isFolder() 151 | { 152 | return _v.isFolder(_f); 153 | } 154 | 155 | public boolean isLocked(FsItemEx fsi) throws IOException 156 | { 157 | return _s.getSecurityChecker().isLocked(_s, _f); 158 | } 159 | 160 | public boolean isReadable(FsItemEx fsi) throws IOException 161 | { 162 | return _s.getSecurityChecker().isReadable(_s, _f); 163 | } 164 | 165 | public boolean isRoot() 166 | { 167 | return _v.isRoot(_f); 168 | } 169 | 170 | public boolean isWritable(FsItemEx fsi) throws IOException 171 | { 172 | return _s.getSecurityChecker().isWritable(_s, _f); 173 | } 174 | 175 | public List listChildren() 176 | { 177 | List list = new ArrayList(); 178 | for (FsItem child : _v.listChildren(_f)) 179 | { 180 | list.add(new FsItemEx(child, _s)); 181 | } 182 | return list; 183 | } 184 | 185 | public InputStream openInputStream() throws IOException 186 | { 187 | return _v.openInputStream(_f); 188 | } 189 | 190 | public void writeStream(InputStream is) throws IOException 191 | { 192 | _v.writeStream(_f, is); 193 | } 194 | 195 | public void renameTo(FsItemEx dst) throws IOException 196 | { 197 | _v.rename(_f, dst._f); 198 | } 199 | 200 | public List listChildren(FsItemFilter filter) 201 | { 202 | List list = new ArrayList(); 203 | for (FsItem child : _v.listChildren(_f)) 204 | { 205 | FsItemEx childEx = new FsItemEx(child, _s); 206 | if (filter.accepts(childEx)) 207 | { 208 | list.add(childEx); 209 | } 210 | } 211 | return list; 212 | } 213 | 214 | public String getURL() 215 | { 216 | return _v.getURL(_f); 217 | } 218 | 219 | public void filterOptions(Map map) 220 | { 221 | _v.filterOptions(_f, map); 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/impl/DefaultFsService.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.impl; 2 | 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | import java.util.Collection; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.Map.Entry; 10 | 11 | import org.apache.commons.codec.binary.Base64; 12 | import org.apache.log4j.Logger; 13 | 14 | import org.grapheco.elfinder.controller.executor.FsItemEx; 15 | import org.grapheco.elfinder.service.FsItem; 16 | import org.grapheco.elfinder.service.FsItemFilter; 17 | import org.grapheco.elfinder.service.FsSecurityChecker; 18 | import org.grapheco.elfinder.service.FsService; 19 | import org.grapheco.elfinder.service.FsServiceConfig; 20 | import org.grapheco.elfinder.service.FsVolume; 21 | 22 | public class DefaultFsService implements FsService 23 | { 24 | FsSecurityChecker _securityChecker; 25 | 26 | FsServiceConfig _serviceConfig; 27 | 28 | Map _volumeMap = new HashMap(); 29 | 30 | // special characters should be encoded, avoid to be processed as a part of 31 | // URL 32 | String[][] escapes = { { "+", "_P" }, { "-", "_M" }, { "/", "_S" }, 33 | { ".", "_D" }, { "=", "_E" } }; 34 | 35 | @Override 36 | /** 37 | * find files by name pattern, this provides a simple recursively iteration based method 38 | * lucene engines can be introduced to improve it! 39 | * This searches across all volumes. 40 | * 41 | * @param filter The filter to apply to select files. 42 | * @return A collection of files that match the filter and gave the root as a parent. 43 | */ 44 | public FsItemEx[] find(FsItemFilter filter) 45 | { 46 | List results = new ArrayList(); 47 | for (FsVolume vol : _volumeMap.values()) 48 | { 49 | FsItem root = vol.getRoot(); 50 | results.addAll(findRecursively(filter, root)); 51 | } 52 | 53 | return results.toArray(new FsItemEx[0]); 54 | } 55 | 56 | /** 57 | * find files recursively in specific folder 58 | * 59 | * @param filter 60 | * The filter to apply to select files. 61 | * @param root 62 | * The location in the hierarchy to search from. 63 | * @return A collection of files that match the filter and have the root as 64 | * a parent. 65 | */ 66 | private Collection findRecursively(FsItemFilter filter, 67 | FsItem root) 68 | { 69 | List results = new ArrayList(); 70 | FsVolume vol = root.getVolume(); 71 | for (FsItem child : vol.listChildren(root)) 72 | { 73 | if (vol.isFolder(child)) 74 | { 75 | results.addAll(findRecursively(filter, child)); 76 | } 77 | else 78 | { 79 | FsItemEx item = new FsItemEx(child, this); 80 | if (filter.accepts(item)) 81 | results.add(item); 82 | } 83 | } 84 | 85 | return results; 86 | } 87 | 88 | @Override 89 | public FsItem fromHash(String hash) 90 | { 91 | for (FsVolume v : _volumeMap.values()) 92 | { 93 | String prefix = getVolumeId(v) + "_"; 94 | 95 | if (hash.equals(prefix)) 96 | { 97 | return v.getRoot(); 98 | } 99 | 100 | if (hash.startsWith(prefix)) 101 | { 102 | String localHash = hash.substring(prefix.length()); 103 | 104 | for (String[] pair : escapes) 105 | { 106 | localHash = localHash.replace(pair[1], pair[0]); 107 | } 108 | 109 | String relativePath = new String(Base64.decodeBase64(localHash)); 110 | return v.fromPath(relativePath); 111 | } 112 | } 113 | 114 | return null; 115 | } 116 | 117 | @Override 118 | public String getHash(FsItem item) throws IOException 119 | { 120 | String relativePath = item.getVolume().getPath(item); 121 | String base = new String(Base64.encodeBase64(relativePath.getBytes())); 122 | 123 | for (String[] pair : escapes) 124 | { 125 | base = base.replace(pair[0], pair[1]); 126 | } 127 | 128 | return getVolumeId(item.getVolume()) + "_" + base; 129 | } 130 | 131 | public FsSecurityChecker getSecurityChecker() 132 | { 133 | return _securityChecker; 134 | } 135 | 136 | public FsServiceConfig getServiceConfig() 137 | { 138 | return _serviceConfig; 139 | } 140 | 141 | @Override 142 | public String getVolumeId(FsVolume volume) 143 | { 144 | for (Entry en : _volumeMap.entrySet()) 145 | { 146 | if (en.getValue() == volume) 147 | return en.getKey(); 148 | } 149 | 150 | return null; 151 | } 152 | 153 | public Map getVolumeMap() 154 | { 155 | return _volumeMap; 156 | } 157 | 158 | public FsVolume[] getVolumes() 159 | { 160 | return _volumeMap.values().toArray(new FsVolume[0]); 161 | } 162 | 163 | public void setSecurityChecker(FsSecurityChecker securityChecker) 164 | { 165 | _securityChecker = securityChecker; 166 | } 167 | 168 | public void setServiceConfig(FsServiceConfig serviceConfig) 169 | { 170 | _serviceConfig = serviceConfig; 171 | } 172 | 173 | public void setVolumeMap(Map volumeMap) 174 | { 175 | for (Entry en : volumeMap.entrySet()) 176 | { 177 | addVolume(en.getKey(), en.getValue()); 178 | } 179 | } 180 | 181 | /** 182 | * @deprecated {@link #setVolumeMap(Map)} 183 | * @param volumes 184 | * The volumes available. 185 | * @throws IOException 186 | * If there is a problem with using one of the volumes. 187 | */ 188 | public void setVolumes(FsVolume[] volumes) throws IOException 189 | { 190 | Logger.getLogger(getClass()) 191 | .warn("calling setVolumes() is deprecated, please use setVolumeMap() to specify volume id explicitly"); 192 | char vid = 'A'; 193 | for (FsVolume volume : volumes) 194 | { 195 | _volumeMap.put("" + vid, volume); 196 | Logger.getLogger(this.getClass()).info( 197 | String.format("mounted %s: %s", "" + vid, volume)); 198 | vid++; 199 | } 200 | } 201 | 202 | public void addVolume(String name, FsVolume fsVolume) 203 | { 204 | _volumeMap.put(name, fsVolume); 205 | Logger.getLogger(this.getClass()).info( 206 | String.format("mounted %s: %s", name, fsVolume)); 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executor/AbstractCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executor; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.Collection; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | import javax.servlet.ServletContext; 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | 16 | import org.apache.log4j.Logger; 17 | 18 | import org.grapheco.elfinder.service.FsItemFilter; 19 | import org.grapheco.elfinder.service.FsService; 20 | import org.grapheco.elfinder.util.FsItemFilterUtils; 21 | import org.grapheco.elfinder.util.FsServiceUtils; 22 | 23 | public abstract class AbstractCommandExecutor implements CommandExecutor 24 | { 25 | protected static Logger LOG = Logger 26 | .getLogger(AbstractCommandExecutor.class); 27 | 28 | protected FsItemFilter getRequestedFilter(HttpServletRequest request) 29 | { 30 | String[] onlyMimes = request.getParameterValues("mimes[]"); 31 | if (onlyMimes == null) 32 | return FsItemFilterUtils.FILTER_ALL; 33 | 34 | return FsItemFilterUtils.createMimeFilter(onlyMimes); 35 | } 36 | 37 | protected void addChildren(Map map, FsItemEx fsi, 38 | String[] mimeFilters) throws IOException 39 | { 40 | FsItemFilter filter = FsItemFilterUtils.createMimeFilter(mimeFilters); 41 | addChildren(map, fsi, filter); 42 | } 43 | 44 | private void addChildren(Map map, FsItemEx fsi, 45 | FsItemFilter filter) throws IOException 46 | { 47 | for (FsItemEx f : fsi.listChildren(filter)) 48 | { 49 | map.put(f.getHash(), f); 50 | } 51 | } 52 | 53 | protected void addSubfolders(Map map, FsItemEx fsi) 54 | throws IOException 55 | { 56 | addChildren(map, fsi, FsItemFilterUtils.FILTER_FOLDER); 57 | } 58 | 59 | protected void createAndCopy(FsItemEx src, FsItemEx dst) throws IOException 60 | { 61 | if (src.isFolder()) 62 | { 63 | createAndCopyFolder(src, dst); 64 | } 65 | else 66 | { 67 | createAndCopyFile(src, dst); 68 | } 69 | } 70 | 71 | protected void createAndCopyFile(FsItemEx src, FsItemEx dst) 72 | throws IOException 73 | { 74 | dst.createFile(); 75 | InputStream is = src.openInputStream(); 76 | dst.writeStream(is); 77 | } 78 | 79 | protected void createAndCopyFolder(FsItemEx src, FsItemEx dst) 80 | throws IOException 81 | { 82 | dst.createFolder(); 83 | 84 | for (FsItemEx c : src.listChildren()) 85 | { 86 | if (c.isFolder()) 87 | { 88 | createAndCopyFolder(c, new FsItemEx(dst, c.getName())); 89 | } 90 | else 91 | { 92 | createAndCopyFile(c, new FsItemEx(dst, c.getName())); 93 | } 94 | } 95 | } 96 | 97 | @Override 98 | public void execute(CommandExecutionContext ctx) throws Exception 99 | { 100 | FsService fileService = ctx.getFsServiceFactory().getFileService( 101 | ctx.getRequest(), ctx.getServletContext()); 102 | execute(fileService, ctx.getRequest(), ctx.getResponse(), 103 | ctx.getServletContext()); 104 | } 105 | 106 | public abstract void execute(FsService fsService, 107 | HttpServletRequest request, HttpServletResponse response, 108 | ServletContext servletContext) throws Exception; 109 | 110 | protected Object[] files2JsonArray(HttpServletRequest request, 111 | Collection list) throws IOException 112 | { 113 | return files2JsonArray(request, list.toArray(new FsItemEx[0])); 114 | } 115 | 116 | protected Object[] files2JsonArray(HttpServletRequest request, 117 | FsItemEx[] list) throws IOException 118 | { 119 | List> los = new ArrayList>(); 120 | for (FsItemEx fi : list) 121 | { 122 | los.add(getFsItemInfo(request, fi)); 123 | } 124 | 125 | return los.toArray(); 126 | } 127 | 128 | protected FsItemEx findCwd(FsService fsService, String target) 129 | throws IOException 130 | { 131 | // current selected directory 132 | FsItemEx cwd = null; 133 | if (target != null) 134 | { 135 | cwd = findItem(fsService, target); 136 | } 137 | 138 | if (cwd == null) 139 | cwd = new FsItemEx(fsService.getVolumes()[0].getRoot(), fsService); 140 | 141 | return cwd; 142 | } 143 | 144 | protected FsItemEx findItem(FsService fsService, String hash) 145 | throws IOException 146 | { 147 | return FsServiceUtils.findItem(fsService, hash); 148 | } 149 | 150 | protected Map getFsItemInfo(HttpServletRequest request, 151 | FsItemEx fsi) throws IOException 152 | { 153 | Map info = new HashMap(); 154 | info.put("hash", fsi.getHash()); 155 | info.put("mime", fsi.getMimeType()); 156 | info.put("ts", fsi.getLastModified()); 157 | info.put("size", fsi.getSize()); 158 | info.put("read", fsi.isReadable(fsi) ? 1 : 0); 159 | info.put("write", fsi.isWritable(fsi) ? 1 : 0); 160 | info.put("locked", fsi.isLocked(fsi) ? 1 : 0); 161 | 162 | if (fsi.getMimeType().startsWith("image")) 163 | { 164 | StringBuffer qs = request.getRequestURL(); 165 | info.put("tmb", qs.append(String.format("?cmd=tmb&target=%s", 166 | fsi.getHash()))); 167 | } 168 | 169 | if (fsi.isRoot()) 170 | { 171 | info.put("name", fsi.getVolumnName()); 172 | info.put("volumeid", fsi.getVolumeId()); 173 | } 174 | else 175 | { 176 | info.put("name", fsi.getName()); 177 | info.put("phash", fsi.getParent().getHash()); 178 | } 179 | if (fsi.isFolder()) 180 | { 181 | info.put("dirs", fsi.hasChildFolder() ? 1 : 0); 182 | } 183 | String url = fsi.getURL(); 184 | if (url != null) 185 | { 186 | info.put("url", url); 187 | } 188 | 189 | return info; 190 | } 191 | 192 | protected String getMimeDisposition(String mime) 193 | { 194 | String[] parts = mime.split("/"); 195 | String disp = ("image".equals(parts[0]) || "text".equals(parts[0]) ? "inline" 196 | : "attachments"); 197 | return disp; 198 | } 199 | 200 | protected Map getOptions(HttpServletRequest request, 201 | FsItemEx cwd) throws IOException 202 | { 203 | Map map = new HashMap(); 204 | map.put("path", cwd.getPath()); 205 | map.put("disabled", new String[0]); 206 | map.put("separator", "/"); 207 | map.put("copyOverwrite", 1); 208 | map.put("archivers", new Object[0]); 209 | // Currently we don't support chunked uploads which came in with a newer 210 | // version of elfinder 2.1 211 | map.put("uploadMaxConn", "-1"); 212 | // We don't have an implementation of zipdl at the moment. 213 | map.put("disabled", Arrays.asList(new String[] { "zipdl" })); 214 | String url = cwd.getURL(); 215 | if (url != null) 216 | { 217 | map.put("url", url); 218 | } 219 | cwd.filterOptions(map); 220 | 221 | return map; 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | org.grapheco 4 | elfinder-servlet-2 5 | 1.4 6 | elfinder-servlet-2 7 | Java backend for "elFinder". 8 | https://github.com/bluejoe2008/elfinder-2.x-servlet 9 | 10 | 11 | BSD 2-clause License 12 | http://opensource.org/licenses/BSD-2-Clause 13 | 14 | 15 | 16 | 17 | shenzhihong 18 | bluejoe2008@gmail.com 19 | 20 | 21 | 22 | scm:git:git@github.com:bluejoe2008/elfinder-2.x-servlet.git 23 | scm:git:git@github.com:bluejoe2008/elfinder-2.x-servlet.git 24 | https://github.com/bluejoe2008/elfinder-2.x-servlet.git 25 | HEAD 26 | 27 | war 28 | 29 | UTF-8 30 | 1.7 31 | 1.7 32 | 33 | true 34 | 35 | 36 | 37 | commons-codec 38 | commons-codec 39 | 1.9 40 | 41 | 42 | commons-io 43 | commons-io 44 | 2.4 45 | 46 | 47 | commons-fileupload 48 | commons-fileupload 49 | 1.3.1 50 | 51 | 52 | org.apache.commons 53 | commons-lang3 54 | 3.3.2 55 | 56 | 57 | org.springframework 58 | spring-webmvc 59 | 3.2.3.RELEASE 60 | 61 | 62 | javax.servlet 63 | javax.servlet-api 64 | 3.0.1 65 | provided 66 | 67 | 68 | org.json 69 | json 70 | 20090211 71 | 72 | 73 | com.mortennobel 74 | java-image-scaling 75 | 0.8.6 76 | 77 | 78 | javax.mail 79 | mail 80 | 1.4.5 81 | 82 | 83 | log4j 84 | log4j 85 | 1.2.17 86 | 87 | 88 | org.webjars.bower 89 | elfinder 90 | 2.1.11 91 | 92 | 93 | 94 | jquery-ui 95 | org.webjars.bower 96 | 97 | 98 | jquery 99 | org.webjars.bower 100 | 101 | 102 | 103 | 104 | org.webjars 105 | jquery 106 | 1.12.4 107 | 108 | 109 | org.webjars 110 | jquery-ui 111 | 1.11.4 112 | 113 | 114 | org.webjars 115 | jquery-ui-themes 116 | 1.11.4 117 | 118 | 119 | 120 | 121 | 122 | release 123 | 124 | 125 | 126 | org.apache.maven.plugins 127 | maven-source-plugin 128 | 2.2.1 129 | 130 | 131 | attach-sources 132 | 133 | jar-no-fork 134 | 135 | 136 | 137 | 138 | 139 | net.alchim31.maven 140 | scala-maven-plugin 141 | 3.3.2 142 | 143 | 144 | attach-javadocs 145 | 146 | doc-jar 147 | 148 | 149 | 150 | 151 | 152 | org.apache.maven.plugins 153 | maven-gpg-plugin 154 | 1.5 155 | 156 | 157 | sign-artifacts 158 | verify 159 | 160 | sign 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | oss 171 | https://oss.sonatype.org/content/repositories/snapshots 172 | 173 | 174 | oss 175 | https://oss.sonatype.org/service/local/staging/deploy/maven2 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | org.eclipse.jetty 184 | jetty-maven-plugin 185 | 9.2.6.v20141205 186 | 187 | 188 | maven-war-plugin 189 | 2.6 190 | 191 | true 192 | 193 | 194 | 195 | org.apache.maven.plugins 196 | maven-release-plugin 197 | 2.5 198 | 199 | true 200 | false 201 | release 202 | deploy 203 | 204 | @{project.version} 205 | 206 | 207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/localfs/LocalFsVolume.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.localfs; 2 | 3 | import java.io.File; 4 | import java.io.FileFilter; 5 | import java.io.FileInputStream; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.io.OutputStream; 10 | import java.nio.file.FileVisitResult; 11 | import java.nio.file.Files; 12 | import java.nio.file.Path; 13 | import java.nio.file.SimpleFileVisitor; 14 | import java.nio.file.attribute.BasicFileAttributes; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | import org.apache.commons.io.FileUtils; 20 | import org.apache.commons.io.FilenameUtils; 21 | import org.apache.commons.io.IOUtils; 22 | 23 | import org.grapheco.elfinder.service.FsItem; 24 | import org.grapheco.elfinder.service.FsVolume; 25 | import org.grapheco.elfinder.util.MimeTypesUtils; 26 | 27 | public class LocalFsVolume implements FsVolume 28 | { 29 | /** 30 | * Used to calculate total file size when walking the tree. 31 | */ 32 | private static class FileSizeFileVisitor extends SimpleFileVisitor 33 | { 34 | 35 | private long totalSize; 36 | 37 | public long getTotalSize() 38 | { 39 | return totalSize; 40 | } 41 | 42 | @Override 43 | public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) 44 | throws IOException 45 | { 46 | totalSize += file.toFile().length(); 47 | return FileVisitResult.CONTINUE; 48 | } 49 | 50 | } 51 | 52 | String _name; 53 | 54 | File _rootDir; 55 | 56 | private File asFile(FsItem fsi) 57 | { 58 | return ((LocalFsItem) fsi).getFile(); 59 | } 60 | 61 | @Override 62 | public void createFile(FsItem fsi) throws IOException 63 | { 64 | asFile(fsi).createNewFile(); 65 | } 66 | 67 | @Override 68 | public void createFolder(FsItem fsi) throws IOException 69 | { 70 | asFile(fsi).mkdirs(); 71 | } 72 | 73 | @Override 74 | public void deleteFile(FsItem fsi) throws IOException 75 | { 76 | File file = asFile(fsi); 77 | if (!file.isDirectory()) 78 | { 79 | file.delete(); 80 | } 81 | } 82 | 83 | @Override 84 | public void deleteFolder(FsItem fsi) throws IOException 85 | { 86 | File file = asFile(fsi); 87 | if (file.isDirectory()) 88 | { 89 | FileUtils.deleteDirectory(file); 90 | } 91 | } 92 | 93 | @Override 94 | public boolean exists(FsItem newFile) 95 | { 96 | return asFile(newFile).exists(); 97 | } 98 | 99 | private LocalFsItem fromFile(File file) 100 | { 101 | if (!file.getAbsolutePath().startsWith(_rootDir.getAbsolutePath())) 102 | { 103 | String message = String.format( 104 | "Item (%s) can't be outside the root directory (%s)", 105 | file.getAbsolutePath(), _rootDir.getAbsolutePath()); 106 | throw new IllegalArgumentException(message); 107 | } 108 | return new LocalFsItem(this, file); 109 | } 110 | 111 | @Override 112 | public FsItem fromPath(String relativePath) 113 | { 114 | return fromFile(new File(_rootDir, relativePath)); 115 | } 116 | 117 | @Override 118 | public String getDimensions(FsItem fsi) 119 | { 120 | return null; 121 | } 122 | 123 | @Override 124 | public long getLastModified(FsItem fsi) 125 | { 126 | return asFile(fsi).lastModified() / 1000; 127 | } 128 | 129 | @Override 130 | public String getMimeType(FsItem fsi) 131 | { 132 | File file = asFile(fsi); 133 | if (file.isDirectory()) 134 | return "directory"; 135 | 136 | String ext = FilenameUtils.getExtension(file.getName()); 137 | if (ext != null && !ext.isEmpty()) 138 | { 139 | String mimeType = MimeTypesUtils.getMimeType(ext); 140 | return mimeType == null ? MimeTypesUtils.UNKNOWN_MIME_TYPE 141 | : mimeType; 142 | } 143 | 144 | return MimeTypesUtils.UNKNOWN_MIME_TYPE; 145 | } 146 | 147 | public String getName() 148 | { 149 | return _name; 150 | } 151 | 152 | @Override 153 | public String getName(FsItem fsi) 154 | { 155 | return asFile(fsi).getName(); 156 | } 157 | 158 | @Override 159 | public FsItem getParent(FsItem fsi) 160 | { 161 | return fromFile(asFile(fsi).getParentFile()); 162 | } 163 | 164 | @Override 165 | public String getPath(FsItem fsi) throws IOException 166 | { 167 | String fullPath = asFile(fsi).getCanonicalPath(); 168 | String rootPath = _rootDir.getCanonicalPath(); 169 | String relativePath = fullPath.substring(rootPath.length()); 170 | return relativePath.replace('\\', '/'); 171 | } 172 | 173 | @Override 174 | public FsItem getRoot() 175 | { 176 | return fromFile(_rootDir); 177 | } 178 | 179 | public File getRootDir() 180 | { 181 | return _rootDir; 182 | } 183 | 184 | @Override 185 | public long getSize(FsItem fsi) throws IOException 186 | { 187 | if (isFolder(fsi)) 188 | { 189 | // This recursively walks down the tree 190 | Path folder = asFile(fsi).toPath(); 191 | FileSizeFileVisitor visitor = new FileSizeFileVisitor(); 192 | Files.walkFileTree(folder, visitor); 193 | return visitor.getTotalSize(); 194 | } 195 | else 196 | { 197 | return asFile(fsi).length(); 198 | } 199 | } 200 | 201 | @Override 202 | public String getThumbnailFileName(FsItem fsi) 203 | { 204 | return null; 205 | } 206 | 207 | @Override 208 | public String getURL(FsItem f) 209 | { 210 | // We are just happy to not supply a custom URL. 211 | return null; 212 | } 213 | 214 | @Override 215 | public void filterOptions(FsItem f, Map map) 216 | { 217 | // Don't do anything 218 | } 219 | 220 | @Override 221 | public boolean hasChildFolder(FsItem fsi) 222 | { 223 | return asFile(fsi).isDirectory() 224 | && asFile(fsi).listFiles(new FileFilter() 225 | { 226 | 227 | @Override 228 | public boolean accept(File arg0) 229 | { 230 | return arg0.isDirectory(); 231 | } 232 | }).length > 0; 233 | } 234 | 235 | @Override 236 | public boolean isFolder(FsItem fsi) 237 | { 238 | return asFile(fsi).isDirectory(); 239 | } 240 | 241 | @Override 242 | public boolean isRoot(FsItem fsi) 243 | { 244 | return _rootDir.equals(asFile(fsi)); 245 | } 246 | 247 | @Override 248 | public FsItem[] listChildren(FsItem fsi) 249 | { 250 | List list = new ArrayList(); 251 | File[] cs = asFile(fsi).listFiles(); 252 | if (cs == null) 253 | { 254 | return new FsItem[0]; 255 | } 256 | 257 | for (File c : cs) 258 | { 259 | list.add(fromFile(c)); 260 | } 261 | 262 | return list.toArray(new FsItem[0]); 263 | } 264 | 265 | @Override 266 | public InputStream openInputStream(FsItem fsi) throws IOException 267 | { 268 | return new FileInputStream(asFile(fsi)); 269 | } 270 | 271 | @Override 272 | public void rename(FsItem src, FsItem dst) throws IOException 273 | { 274 | asFile(src).renameTo(asFile(dst)); 275 | } 276 | 277 | public void setName(String name) 278 | { 279 | _name = name; 280 | } 281 | 282 | public void setRootDir(File rootDir) 283 | { 284 | if (!rootDir.exists()) 285 | { 286 | rootDir.mkdirs(); 287 | } 288 | 289 | _rootDir = rootDir; 290 | } 291 | 292 | @Override 293 | public String toString() 294 | { 295 | return "LocalFsVolume [" + _rootDir + "]"; 296 | } 297 | 298 | @Override 299 | public void writeStream(FsItem fsi, InputStream is) throws IOException 300 | { 301 | OutputStream os = null; 302 | try 303 | { 304 | os = new FileOutputStream(asFile(fsi)); 305 | IOUtils.copy(is, os); 306 | } 307 | finally 308 | { 309 | if (is != null) 310 | { 311 | is.close(); 312 | } 313 | if (os != null) 314 | { 315 | os.close(); 316 | } 317 | } 318 | } 319 | } 320 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/executors/UploadCommandExecutor.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller.executors; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.regex.Matcher; 10 | import java.util.regex.Pattern; 11 | 12 | import javax.servlet.ServletContext; 13 | import javax.servlet.http.HttpServletRequest; 14 | 15 | import org.apache.commons.fileupload.FileItemStream; 16 | import org.apache.log4j.Logger; 17 | import org.json.JSONObject; 18 | 19 | import org.grapheco.elfinder.controller.MultipleUploadItems; 20 | import org.grapheco.elfinder.controller.executor.AbstractJsonCommandExecutor; 21 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 22 | import org.grapheco.elfinder.controller.executor.FsItemEx; 23 | import org.grapheco.elfinder.service.FsItemFilter; 24 | import org.grapheco.elfinder.service.FsService; 25 | 26 | public class UploadCommandExecutor extends AbstractJsonCommandExecutor 27 | implements CommandExecutor 28 | { 29 | Logger _logger = Logger.getLogger(this.getClass()); 30 | 31 | // large file will be splitted into many parts 32 | class Part 33 | { 34 | long _start; 35 | long _size; 36 | FileItemStream _content; 37 | 38 | public Part(long start, long size, FileItemStream fileItemStream) 39 | { 40 | super(); 41 | this._start = start; 42 | this._size = size; 43 | this._content = fileItemStream; 44 | } 45 | } 46 | 47 | // a large file with many parts 48 | static class Parts 49 | { 50 | public static synchronized Parts getOrCreate( 51 | HttpServletRequest request, String chunkId, String fileName, 52 | long total, long totalSize) 53 | { 54 | //chunkId is not an unique number for files uploaded in one upload form 55 | String key = String.format("chunk_%s_%s", chunkId, fileName); 56 | // stores chunks in application context 57 | Parts parts = (Parts) request.getServletContext().getAttribute(key); 58 | 59 | if (parts == null) 60 | { 61 | parts = new Parts(chunkId, fileName, total, totalSize); 62 | request.getServletContext().setAttribute(key, parts); 63 | } 64 | 65 | return parts; 66 | } 67 | 68 | private String _chunkId; 69 | // number of parts 70 | private long _numberOfParts; 71 | private long _totalSize; 72 | 73 | private String _fileName; 74 | 75 | // all chunks 76 | Map _parts = new HashMap(); 77 | 78 | public Parts(String chunkId, String fileName, long numberOfParts, 79 | long totalSize) 80 | { 81 | _chunkId = chunkId; 82 | _fileName = fileName; 83 | _numberOfParts = numberOfParts; 84 | _totalSize = totalSize; 85 | } 86 | 87 | public synchronized void addPart(long partIndex, Part part) 88 | { 89 | _parts.put(partIndex, part); 90 | } 91 | 92 | public boolean isReady() 93 | { 94 | return _parts.size() == _numberOfParts; 95 | } 96 | 97 | public InputStream openInputStream() throws IOException 98 | { 99 | return new InputStream() 100 | { 101 | long partIndex = 0; 102 | Part part = _parts.get(partIndex); 103 | InputStream is = part._content.openStream(); 104 | 105 | @Override 106 | public int read() throws IOException 107 | { 108 | while (true) 109 | { 110 | // current part is not read completely 111 | int c = is.read(); 112 | if (c != -1) 113 | { 114 | return c; 115 | } 116 | 117 | // next part? 118 | if (partIndex == _numberOfParts - 1) 119 | { 120 | is.close(); 121 | return -1; 122 | } 123 | 124 | part = _parts.get(++partIndex); 125 | is.close(); 126 | is = part._content.openStream(); 127 | } 128 | } 129 | }; 130 | } 131 | 132 | public void checkParts() throws IOException 133 | { 134 | long totalSize = 0; 135 | 136 | for (long i = 0; i < _numberOfParts; i++) 137 | { 138 | Part part = _parts.get(i); 139 | totalSize += part._size; 140 | } 141 | 142 | if (totalSize != _totalSize) 143 | throw new IOException(String.format( 144 | "invalid file size: excepted %d, but is %d", 145 | _totalSize, totalSize)); 146 | } 147 | 148 | public void removeFromApplicationContext(HttpServletRequest request) 149 | { 150 | String key = String.format("chunk_%s_%s", _chunkId, _fileName); 151 | request.getServletContext().removeAttribute(key); 152 | } 153 | } 154 | 155 | interface FileWriter 156 | { 157 | FsItemEx createAndSave(String fileName, InputStream is) 158 | throws IOException; 159 | } 160 | 161 | @Override 162 | public void execute(FsService fsService, HttpServletRequest request, 163 | ServletContext servletContext, JSONObject json) throws Exception 164 | { 165 | MultipleUploadItems uploads = MultipleUploadItems.loadFrom(request); 166 | 167 | final List added = new ArrayList(); 168 | 169 | String target = request.getParameter("target"); 170 | final FsItemEx dir = super.findItem(fsService, target); 171 | final FsItemFilter filter = getRequestedFilter(request); 172 | 173 | FileWriter fw = new FileWriter() 174 | { 175 | @Override 176 | public FsItemEx createAndSave(String fileName, InputStream is) 177 | throws IOException 178 | { 179 | // fis.getName() returns full path such as 'C:\temp\abc.txt' in 180 | // IE10 181 | // while returns 'abc.txt' in Chrome 182 | // see 183 | // https://github.com/bluejoe2008/elfinder-2.x-servlet/issues/22 184 | java.nio.file.Path p = java.nio.file.Paths.get(fileName); 185 | FsItemEx newFile = new FsItemEx(dir, p.getFileName().toString()); 186 | 187 | /* 188 | * String fileName = fis.getName(); FsItemEx newFile = new 189 | * FsItemEx(dir, fileName); 190 | */ 191 | newFile.createFile(); 192 | newFile.writeStream(is); 193 | 194 | if (filter.accepts(newFile)) 195 | added.add(newFile); 196 | 197 | return newFile; 198 | } 199 | }; 200 | 201 | // chunked upload 202 | if (request.getParameter("cid") != null) 203 | { 204 | processChunkUpload(request, uploads, fw); 205 | } 206 | else 207 | { 208 | processUpload(uploads, fw); 209 | } 210 | 211 | json.put("added", files2JsonArray(request, added)); 212 | } 213 | 214 | private void processChunkUpload(HttpServletRequest request, 215 | MultipleUploadItems uploads, FileWriter fw) 216 | throws NumberFormatException, IOException 217 | { 218 | // cid : unique id of chunked uploading file 219 | String cid = request.getParameter("cid"); 220 | // solr-5.5.2.tgz.48_65.part 221 | String chunk = request.getParameter("chunk"); 222 | 223 | // 100270176,2088962,136813192 224 | String range = request.getParameter("range"); 225 | String[] tokens = range.split(","); 226 | 227 | Matcher m = Pattern.compile("(.*)\\.([0-9]+)\\_([0-9]+)\\.part") 228 | .matcher(chunk); 229 | 230 | if (m.find()) 231 | { 232 | String fileName = m.group(1); 233 | long index = Long.parseLong(m.group(2)); 234 | long total = Long.parseLong(m.group(3)); 235 | 236 | Parts parts = Parts.getOrCreate(request, cid, fileName, total + 1, 237 | Long.parseLong(tokens[2])); 238 | 239 | long start = Long.parseLong(tokens[0]); 240 | long size = Long.parseLong(tokens[1]); 241 | 242 | _logger.debug(String.format("uploaded part(%d/%d) of file: %s", 243 | index, total, fileName)); 244 | 245 | parts.addPart(index, new Part(start, size, uploads 246 | .items("upload[]").get(0))); 247 | _logger.debug(String.format(">>>>%d", parts._parts.size())); 248 | if (parts.isReady()) 249 | { 250 | parts.checkParts(); 251 | 252 | _logger.debug(String.format("file is uploadded completely: %s", 253 | fileName)); 254 | 255 | fw.createAndSave(fileName, parts.openInputStream()); 256 | 257 | // remove from application context 258 | parts.removeFromApplicationContext(request); 259 | } 260 | } 261 | } 262 | 263 | private void processUpload(MultipleUploadItems uploads, FileWriter fw) 264 | throws IOException 265 | { 266 | for (FileItemStream fis : uploads.items("upload[]")) 267 | { 268 | fw.createAndSave(fis.getName(), fis.openStream()); 269 | } 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /src/main/java/org/grapheco/elfinder/controller/ConnectorController.java: -------------------------------------------------------------------------------- 1 | package org.grapheco.elfinder.controller; 2 | 3 | import org.grapheco.elfinder.controller.executor.CommandExecutionContext; 4 | import org.grapheco.elfinder.controller.executor.CommandExecutor; 5 | import org.grapheco.elfinder.controller.executor.CommandExecutorFactory; 6 | import org.grapheco.elfinder.service.FsServiceFactory; 7 | import org.apache.commons.fileupload.FileItemIterator; 8 | import org.apache.commons.fileupload.FileItemStream; 9 | import org.apache.commons.fileupload.servlet.ServletFileUpload; 10 | import org.apache.commons.fileupload.util.Streams; 11 | import org.apache.log4j.Logger; 12 | import org.springframework.stereotype.Controller; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | 15 | import javax.annotation.Resource; 16 | import javax.servlet.ServletContext; 17 | import javax.servlet.http.HttpServletRequest; 18 | import javax.servlet.http.HttpServletResponse; 19 | import java.io.File; 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.lang.reflect.InvocationHandler; 23 | import java.lang.reflect.Method; 24 | import java.lang.reflect.Proxy; 25 | import java.util.ArrayList; 26 | import java.util.HashMap; 27 | import java.util.List; 28 | import java.util.Map; 29 | 30 | @Controller 31 | @RequestMapping("connector") 32 | public class ConnectorController { 33 | Logger _logger = Logger.getLogger(this.getClass()); 34 | @Resource(name = "commandExecutorFactory") 35 | private CommandExecutorFactory _commandExecutorFactory; 36 | 37 | @Resource(name = "fsServiceFactory") 38 | private FsServiceFactory _fsServiceFactory; 39 | 40 | private File _tempDir = null; 41 | String _tempDirPath = "./tmp"; 42 | 43 | /** 44 | * set temp file dir path, relative path is allowed (web root as base dir) 45 | * 46 | * @param value 47 | */ 48 | public void setTempDirPath(String value) { 49 | _tempDirPath = value; 50 | } 51 | 52 | @RequestMapping 53 | public void connector(HttpServletRequest request, 54 | final HttpServletResponse response) throws IOException { 55 | try { 56 | request = parseMultipartContent(request); 57 | } catch (Exception e) { 58 | throw new IOException(e.getMessage()); 59 | } 60 | 61 | String cmd = request.getParameter("cmd"); 62 | CommandExecutor ce = _commandExecutorFactory.get(cmd); 63 | 64 | if (ce == null) { 65 | // This shouldn't happen as we should have a fallback command set. 66 | throw new FsException(String.format("unknown command: %s", cmd)); 67 | } 68 | 69 | try { 70 | final HttpServletRequest finalRequest = request; 71 | ce.execute(new CommandExecutionContext() { 72 | 73 | @Override 74 | public FsServiceFactory getFsServiceFactory() { 75 | return _fsServiceFactory; 76 | } 77 | 78 | @Override 79 | public HttpServletRequest getRequest() { 80 | return finalRequest; 81 | } 82 | 83 | @Override 84 | public HttpServletResponse getResponse() { 85 | return response; 86 | } 87 | 88 | @Override 89 | public ServletContext getServletContext() { 90 | return finalRequest.getSession().getServletContext(); 91 | } 92 | }); 93 | 94 | //clean temp files, cached objects... 95 | MultipleUploadItems.finalize(request); 96 | } catch (Exception e) { 97 | throw new FsException("unknown error", e); 98 | } 99 | } 100 | 101 | public CommandExecutorFactory getCommandExecutorFactory() { 102 | return _commandExecutorFactory; 103 | } 104 | 105 | public FsServiceFactory getFsServiceFactory() { 106 | return _fsServiceFactory; 107 | } 108 | 109 | private HttpServletRequest parseMultipartContent( 110 | final HttpServletRequest request) throws Exception { 111 | if (!ServletFileUpload.isMultipartContent(request)) 112 | return request; 113 | 114 | // non-file parameters 115 | final Map requestParams = new HashMap(); 116 | 117 | // Parse the request 118 | ServletFileUpload sfu = new ServletFileUpload(); 119 | String characterEncoding = request.getCharacterEncoding(); 120 | if (characterEncoding == null) { 121 | characterEncoding = "UTF-8"; 122 | } 123 | 124 | sfu.setHeaderEncoding(characterEncoding); 125 | FileItemIterator iter = sfu.getItemIterator(request); 126 | MultipleUploadItems uploads = new MultipleUploadItems(getTempDir(request)); 127 | 128 | while (iter.hasNext()) { 129 | FileItemStream item = iter.next(); 130 | 131 | // not a file 132 | if (item.isFormField()) { 133 | InputStream stream = item.openStream(); 134 | requestParams.put(item.getFieldName(), 135 | Streams.asString(stream, characterEncoding)); 136 | stream.close(); 137 | } else { 138 | // it is a file! 139 | String fileName = item.getName(); 140 | if (fileName != null && !"".equals(fileName.trim())) { 141 | uploads.addItemProxy(item); 142 | } 143 | } 144 | } 145 | 146 | uploads.writeInto(request); 147 | 148 | // 'getParameter()' method can not be called on original request object 149 | // after parsing 150 | // so we stored the request values and provide a delegate request object 151 | return (HttpServletRequest) Proxy.newProxyInstance(this.getClass() 152 | .getClassLoader(), new Class[]{HttpServletRequest.class}, 153 | new InvocationHandler() { 154 | @Override 155 | public Object invoke(Object arg0, Method arg1, Object[] arg2) 156 | throws Throwable { 157 | // we replace getParameter() and getParameterValues() 158 | // methods 159 | if ("getParameter".equals(arg1.getName())) { 160 | String paramName = (String) arg2[0]; 161 | return requestParams.get(paramName); 162 | } 163 | 164 | if ("getParameterValues".equals(arg1.getName())) { 165 | String paramName = (String) arg2[0]; 166 | 167 | // normalize name 'key[]' to 'key' 168 | if (paramName.endsWith("[]")) 169 | paramName = paramName.substring(0, 170 | paramName.length() - 2); 171 | 172 | if (requestParams.containsKey(paramName)) 173 | return new String[]{requestParams 174 | .get(paramName)}; 175 | 176 | // if contains key[1], key[2]... 177 | int i = 0; 178 | List paramValues = new ArrayList(); 179 | while (true) { 180 | String name2 = String.format("%s[%d]", 181 | paramName, i++); 182 | if (requestParams.containsKey(name2)) { 183 | paramValues.add(requestParams.get(name2)); 184 | } else { 185 | break; 186 | } 187 | } 188 | 189 | return paramValues.isEmpty() ? new String[0] 190 | : paramValues.toArray(new String[0]); 191 | } 192 | 193 | return arg1.invoke(request, arg2); 194 | } 195 | }); 196 | } 197 | 198 | public void setCommandExecutorFactory( 199 | CommandExecutorFactory _commandExecutorFactory) { 200 | this._commandExecutorFactory = _commandExecutorFactory; 201 | } 202 | 203 | public void setFsServiceFactory(FsServiceFactory _fsServiceFactory) { 204 | this._fsServiceFactory = _fsServiceFactory; 205 | } 206 | 207 | private File getTempDir(HttpServletRequest request) throws IOException { 208 | if (_tempDir != null) 209 | return _tempDir; 210 | 211 | _tempDir = new File(_tempDirPath); 212 | if (!_tempDir.isAbsolute()) { 213 | _tempDir = new File(request.getServletContext().getRealPath(_tempDirPath)); 214 | } 215 | 216 | _tempDir.mkdirs(); 217 | _logger.info(String.format("using temp dir: %s", _tempDir.getCanonicalPath())); 218 | return _tempDir; 219 | } 220 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | what's elfinder-2.x-servlet 2 | ==================== 3 | 4 | [![GitHub issues](https://img.shields.io/github/issues/bluejoe2008/elfinder-2.x-servlet.svg)](https://github.com/bluejoe2008/elfinder-2.x-servlet/issues) 5 | [![GitHub forks](https://img.shields.io/github/forks/bluejoe2008/elfinder-2.x-servlet.svg)](https://github.com/bluejoe2008/elfinder-2.x-servlet/network) 6 | [![GitHub stars](https://img.shields.io/github/stars/bluejoe2008/elfinder-2.x-servlet.svg)](https://github.com/bluejoe2008/elfinder-2.x-servlet/stargazers) 7 | [![GitHub license](https://img.shields.io/github/license/bluejoe2008/elfinder-2.x-servlet.svg)](https://github.com/bluejoe2008/elfinder-2.x-servlet/blob/master/LICENSE) 8 | 9 | elfinder-2.x-servlet implements a java servlet for elfinder-2.x connector 10 | 11 | elfinder is an Open-source file manager for web, written in JavaScript using jQuery and jQuery UI. 12 | see also http://elfinder.org 13 | 14 | 15 | 16 | 17 | 18 | for elfinder-1.2 users, please go to https://github.com/Studio-42/elfinder-servlet. 19 | 20 | importing elfinder-2.x-servlet 21 | ==================== 22 | this project is released as an artifact on the central repostory 23 | 24 | use 25 | 26 | 27 |     org.grapheco 28 |     elfinder-servlet-2 29 |     1.4 30 |     classes 31 | 32 | 33 | to add dependency in your pom.xml 34 | 35 | building elfinder-2.x-servlet 36 | ==================== 37 | the source files includes: 38 | 39 | * src/main/webapp : a normal j2ee application includes elfinder, WEB-INF... 40 | * src/main/java: source codes for elfinder-servlet 41 | * src/main/resources: source codes for elfinder-servlet 42 | 43 | To build this project with maven run: 44 | 45 | mvn install 46 | 47 | to run this project within a jetty container use: 48 | 49 | mvn jetty:run 50 | 51 | using elfinder-2.x-servlet in your web apps 52 | ==================== 53 | just use following codes to tell elfinder to connect with server-side servlet: 54 | 55 | 62 | 63 | in your web.xml, following codes should be added to enable the servlet: 64 | 65 | 66 | elfinder 67 | org.springframework.web.servlet.DispatcherServlet 68 | 69 | 70 | 71 | 72 | elfinder 73 | /elfinder-servlet/* 74 | 75 | 76 | yes! elfinder-2.x-servlet is developed upon SpringFramework (http://springframework.org) 77 | 78 | an example elfinder-servlet.xml configuration is shown below: 79 | 80 | 81 | 83 | 85 | 86 | 87 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | A ConnectorServlet is provided for people who do not use spring framework: 154 | 155 | 156 | elfinder-connector-servlet 157 | org.grapheco.elfinder.servlet.ConnectorServlet 158 | 159 | 160 | 161 | elfinder-connector-servlet 162 | /elfinder-servlet/connector 163 | 164 | 165 | If you want to customize behavior of ConnectorServlet(see https://github.com/bluejoe2008/elfinder-2.x-servlet/blob/0.9/src/main/java/cn/bluejoe/elfinder/servlet/ConnectorServlet.java), you may need to create a derivided servlet class based on ConnectorServlet. 166 | 167 | features 168 | ================ 169 | * __easy to use__: just define a servlet in your web.xml, or configure the XML file in spring IOC format, and then start your web application 170 | * __easy to import__: an artifact on the central repostory is provided, use maven to manage the dependency 171 | * __logic file views__: a local file system is not necessary, you can define your FsService 172 | * __easy to personalize__: different file views are allowed for different users, just provide a custom FsServiceFactory 173 | * __easy to modify and extend__: provide your own CommandExecutors to respond new commands 174 | 175 | Command, CommandExecutor, CommandExecutorManager 176 | ================ 177 | 178 | elfinder-2.x-servlet implements file management commands including: 179 | 180 | * DIM 181 | * DUPLICATE 182 | * FILE 183 | * GET 184 | * LS 185 | * MKDIR 186 | * MKFILE 187 | * OPEN 188 | * PARENT 189 | * PASTE 190 | * PUT 191 | * RENAME 192 | * RM 193 | * SEARCH 194 | * SIZE 195 | * TMB 196 | * TREE 197 | * UPLOAD(CHUNK supported!!!) 198 | 199 | Each command corresponds to a CommandExecutor class, for example, the TREE command is implemented by the class TreeCommandExecutor(see https://github.com/bluejoe2008/elfinder-2.x-servlet/src/main/java/cn/bluejoe/elfinder/controller/executors/TreeCommandExecutor.java). Users can modify existing class or entend new executor class by following this naming rule. 200 | 201 | Furthermore, this rule can even be modified via setting the commandExecutorFactory in elfinder-servlet.xml, in which default factory is DefaultCommandExecutorFactory(see https://github.com/bluejoe2008/elfinder-2.x-servlet/src/main/java/cn/bluejoe/elfinder/controller/executor/DefaultCommandExecutorFactory.java). A CommandExecutorFactory tells how to locate the command executor(TreeCommandExecutor as an example) by a given command name("TREE" as an example), it is designed as an interface: 202 | 203 | public interface CommandExecutorFactory 204 | { 205 | CommandExecutor get(String commandName); 206 | } 207 | 208 | 209 | FsItem, FsVolume, FsService, FsServiceFactory 210 | ================ 211 | Each file is represented as a FsItem. And the root of a file is represented as a FsVolume. A FsVolume tells parent-children relations between all FsItems and implements all file operation (for example, create/delete). 212 | 213 | A FsService may have many FsVolumes. Users can create a FsService via a FsServiceFactory: 214 | 215 | public interface FsServiceFactory 216 | { 217 | FsService getFileService(HttpServletRequest request, ServletContext servletContext); 218 | } 219 | 220 | A simple (and stupid) StaticFsServiceFactory is provided in https://github.com/bluejoe2008/elfinder-2.x-servlet/src/main/java/cn/bluejoe/elfinder/impl/StaticFsServiceFactory.java, which always returns a fixed FsService, despite of whatever it is requested. However, sometimes a FsService should be constructed dynamically according to current Web request. For example, users may own separated file spaces in a network disk service platform, in this case, getFileService() get user principal from current request and offers him/her different file view. 221 | -------------------------------------------------------------------------------- /src/main/resources/mime.types: -------------------------------------------------------------------------------- 1 | # This file controls what Internet media types are sent to the client for 2 | # given file extension(s). Sending the correct media type to the client 3 | # is important so they know how to handle the content of the file. 4 | # For more information about Internet media types, please read 5 | # RFC 2045, 2046, 2047, 2048, and 2077. The Internet media type 6 | # registry is at . 7 | 8 | # MIME type Extension 9 | application/andrew-inset ez 10 | application/chemtool cht 11 | application/dicom dcm 12 | application/docbook+xml docbook 13 | application/ecmascript ecma 14 | application/flash-video flv 15 | application/illustrator ai 16 | application/javascript js 17 | application/mac-binhex40 18 | application/mathematica nb 19 | application/msword doc 20 | application/octet-stream bin 21 | application/oda oda 22 | application/ogg ogg 23 | application/pdf pdf 24 | application/pgp pgp 25 | application/pgp-encrypted 26 | application/pgp-encrypted pgp gpg 27 | application/pgp-keys 28 | application/pgp-keys skr pkr 29 | application/pgp-signature 30 | application/pgp-signature sig 31 | application/pkcs7-mime 32 | application/pkcs7-signature p7s 33 | application/postscript ps 34 | application/rtf rtf 35 | application/sdp sdp 36 | application/smil smil smi sml 37 | application/stuffit sit 38 | application/vnd.corel-draw cdr 39 | application/vnd.hp-hpgl hpgl 40 | application/vnd.hp-pcl pcl 41 | application/vnd.lotus-1-2-3 123 wk1 wk3 wk4 wks 42 | application/vnd.mozilla.xul+xml xul 43 | application/vnd.ms-excel xls xlc xll xlm xlw xla xlt xld 44 | application/vnd.ms-powerpoint ppz ppt pps pot 45 | application/vnd.oasis.opendocument.chart odc 46 | application/vnd.oasis.opendocument.database odb 47 | application/vnd.oasis.opendocument.formula odf 48 | application/vnd.oasis.opendocument.graphics odg 49 | application/vnd.oasis.opendocument.graphics-template otg 50 | application/vnd.oasis.opendocument.image odi 51 | application/vnd.oasis.opendocument.presentation odp 52 | application/vnd.oasis.opendocument.presentation-template otp 53 | application/vnd.oasis.opendocument.spreadsheet ods 54 | application/vnd.oasis.opendocument.spreadsheet-template ots 55 | application/vnd.oasis.opendocument.text odt 56 | application/vnd.oasis.opendocument.text-master odm 57 | application/vnd.oasis.opendocument.text-template ott 58 | application/vnd.oasis.opendocument.text-web oth 59 | application/vnd.palm pdb 60 | application/vnd.rn-realmedia 61 | application/vnd.rn-realmedia rm 62 | application/vnd.rn-realmedia-secure rms 63 | application/vnd.rn-realmedia-vbr rmvb 64 | application/vnd.stardivision.calc sdc 65 | application/vnd.stardivision.chart sds 66 | application/vnd.stardivision.draw sda 67 | application/vnd.stardivision.impress sdd sdp 68 | application/vnd.stardivision.mail smd 69 | application/vnd.stardivision.math smf 70 | application/vnd.stardivision.writer sdw vor sgl 71 | application/vnd.sun.xml.calc sxc 72 | application/vnd.sun.xml.calc.template stc 73 | application/vnd.sun.xml.draw sxd 74 | application/vnd.sun.xml.draw.template std 75 | application/vnd.sun.xml.impress sxi 76 | application/vnd.sun.xml.impress.template sti 77 | application/vnd.sun.xml.math sxm 78 | application/vnd.sun.xml.writer sxw 79 | application/vnd.sun.xml.writer.global sxg 80 | application/vnd.sun.xml.writer.template stw 81 | application/vnd.wordperfect wpd 82 | application/x-abiword abw abw.CRASHED abw.gz zabw 83 | application/x-amipro sam 84 | application/x-anjuta-project prj 85 | application/x-applix-spreadsheet as 86 | application/x-applix-word aw 87 | application/x-arc 88 | application/x-archive a 89 | application/x-arj arj 90 | application/x-asax asax 91 | application/x-ascx ascx 92 | application/x-ashx ashx 93 | application/x-asix asix 94 | application/x-asmx asmx 95 | application/x-asp asp 96 | application/x-awk 97 | application/x-axd axd 98 | application/x-bcpio bcpio 99 | application/x-bittorrent torrent 100 | application/x-blender blender blend BLEND 101 | application/x-bzip bz bz2 102 | application/x-bzip bz2 bz 103 | application/x-bzip-compressed-tar tar.bz tar.bz2 104 | application/x-bzip-compressed-tar tar.bz tar.bz2 tbz tbz2 105 | application/x-cd-image iso 106 | application/x-cgi cgi 107 | application/x-chess-pgn pgn 108 | application/x-chm chm 109 | application/x-class-file 110 | application/x-cmbx cmbx 111 | application/x-compress Z 112 | application/x-compressed-tar tar.gz tar.Z tgz taz 113 | application/x-compressed-tar tar.gz tgz 114 | application/x-config config 115 | application/x-core 116 | application/x-cpio cpio 117 | application/x-cpio-compressed cpio.gz 118 | application/x-csh csh 119 | application/x-cue cue 120 | application/x-dbase dbf 121 | application/x-dbm 122 | application/x-dc-rom dc 123 | application/x-deb deb 124 | application/x-designer ui 125 | application/x-desktop desktop kdelnk 126 | application/x-devhelp devhelp 127 | application/x-dia-diagram dia 128 | application/x-disco disco 129 | application/x-dvi dvi 130 | application/x-e-theme etheme 131 | application/x-egon egon 132 | application/x-executable exe 133 | application/x-font-afm afm 134 | application/x-font-bdf bdf 135 | application/x-font-dos 136 | application/x-font-framemaker 137 | application/x-font-libgrx 138 | application/x-font-linux-psf psf 139 | application/x-font-otf 140 | application/x-font-pcf pcf 141 | application/x-font-pcf pcf.gz 142 | application/x-font-speedo spd 143 | application/x-font-sunos-news 144 | application/x-font-tex 145 | application/x-font-tex-tfm 146 | application/x-font-ttf ttc TTC 147 | application/x-font-ttf ttf 148 | application/x-font-type1 pfa pfb gsf pcf.Z 149 | application/x-font-vfont 150 | application/x-frame 151 | application/x-frontline aop 152 | application/x-gameboy-rom gb 153 | application/x-gdbm 154 | application/x-gdesklets-display display 155 | application/x-genesis-rom gen md 156 | application/x-gettext-translation gmo 157 | application/x-glabels glabels 158 | application/x-glade glade 159 | application/x-gmc-link 160 | application/x-gnome-db-connection connection 161 | application/x-gnome-db-database database 162 | application/x-gnome-stones caves 163 | application/x-gnucash gnucash gnc xac 164 | application/x-gnumeric gnumeric 165 | application/x-graphite gra 166 | application/x-gtar gtar 167 | application/x-gtktalog 168 | application/x-gzip gz 169 | application/x-gzpostscript ps.gz 170 | application/x-hdf hdf 171 | application/x-ica ica 172 | application/x-ipod-firmware 173 | application/x-jamin jam 174 | application/x-jar jar 175 | application/x-java class 176 | application/x-java-archive jar ear war 177 | 178 | application/x-jbuilder-project jpr jpx 179 | application/x-karbon karbon 180 | application/x-kchart chrt 181 | application/x-kformula kfo 182 | application/x-killustrator kil 183 | application/x-kivio flw 184 | application/x-kontour kon 185 | application/x-kpovmodeler kpm 186 | application/x-kpresenter kpr kpt 187 | application/x-krita kra 188 | application/x-kspread ksp 189 | application/x-kspread-crypt 190 | application/x-ksysv-package 191 | application/x-kugar kud 192 | application/x-kword kwd kwt 193 | application/x-kword-crypt 194 | application/x-lha lha lzh 195 | application/x-lha lzh 196 | application/x-lhz lhz 197 | application/x-linguist ts 198 | application/x-lyx lyx 199 | application/x-lzop lzo 200 | application/x-lzop-compressed-tar tar.lzo tzo 201 | application/x-macbinary 202 | application/x-machine-config 203 | application/x-magicpoint mgp 204 | application/x-master-page master 205 | application/x-matroska mkv 206 | application/x-mdp mdp 207 | application/x-mds mds 208 | application/x-mdsx mdsx 209 | application/x-mergeant mergeant 210 | application/x-mif mif 211 | application/x-mozilla-bookmarks 212 | application/x-mps mps 213 | application/x-ms-dos-executable exe 214 | application/x-mswinurl 215 | application/x-mswrite wri 216 | application/x-msx-rom msx 217 | application/x-n64-rom n64 218 | application/x-nautilus-link 219 | application/x-nes-rom nes 220 | application/x-netcdf cdf nc 221 | application/x-netscape-bookmarks 222 | application/x-object o 223 | application/x-ole-storage 224 | application/x-oleo oleo 225 | application/x-palm-database 226 | application/x-palm-database pdb prc 227 | application/x-par2 PAR2 par2 228 | application/x-pef-executable 229 | application/x-perl pl pm al perl 230 | application/x-php php php3 php4 231 | application/x-pkcs12 p12 pfx 232 | application/x-planner planner mrproject 233 | application/x-planperfect pln 234 | application/x-prjx prjx 235 | application/x-profile 236 | application/x-ptoptimizer-script pto 237 | application/x-pw pw 238 | application/x-python-bytecode pyc pyo 239 | application/x-quattro-pro wb1 wb2 wb3 240 | application/x-quattropro wb1 wb2 wb3 241 | application/x-qw qif 242 | application/x-rar rar 243 | application/x-rar-compressed rar 244 | application/x-rdp rdp 245 | application/x-reject rej 246 | application/x-remoting rem 247 | application/x-resources resources 248 | application/x-resourcesx resx 249 | application/x-rpm rpm 250 | application/x-ruby 251 | application/x-sc 252 | application/x-sc sc 253 | application/x-scribus sla sla.gz scd scd.gz 254 | application/x-shar shar 255 | application/x-shared-library-la la 256 | application/x-sharedlib so 257 | application/x-shellscript sh 258 | application/x-shockwave-flash swf 259 | application/x-siag siag 260 | application/x-slp 261 | application/x-smil kino 262 | application/x-smil smi smil 263 | application/x-sms-rom sms gg 264 | application/x-soap-remoting soap 265 | application/x-streamingmedia ssm 266 | application/x-stuffit 267 | application/x-stuffit bin sit 268 | application/x-sv4cpio sv4cpio 269 | application/x-sv4crc sv4crc 270 | application/x-tar tar 271 | application/x-tarz tar.Z 272 | application/x-tex-gf gf 273 | application/x-tex-pk k 274 | application/x-tgif obj 275 | application/x-theme theme 276 | application/x-toc toc 277 | application/x-toutdoux 278 | application/x-trash bak old sik 279 | application/x-troff tr roff t 280 | application/x-troff-man man 281 | application/x-troff-man-compressed 282 | application/x-tzo tar.lzo tzo 283 | application/x-ustar ustar 284 | application/x-wais-source src 285 | application/x-web-config 286 | application/x-wpg wpg 287 | application/x-wsdl wsdl 288 | application/x-x509-ca-cert der cer crt cert pem 289 | application/x-xbel xbel 290 | application/x-zerosize 291 | application/x-zoo zoo 292 | application/xhtml+xml xhtml 293 | application/zip zip 294 | audio/ac3 ac3 295 | audio/basic au snd 296 | audio/midi mid midi 297 | audio/mpeg mp3 298 | audio/prs.sid sid psid 299 | audio/vnd.rn-realaudio ra 300 | audio/x-aac aac 301 | audio/x-adpcm 302 | audio/x-aifc 303 | audio/x-aiff aif aiff 304 | audio/x-aiff aiff aif aifc 305 | audio/x-aiffc 306 | audio/x-flac flac 307 | audio/x-m4a m4a 308 | audio/x-mod mod ult uni XM m15 mtm 669 309 | audio/x-mp3-playlist 310 | audio/x-mpeg 311 | audio/x-mpegurl m3u 312 | audio/x-ms-asx 313 | audio/x-pn-realaudio ra ram rm 314 | audio/x-pn-realaudio ram rmm 315 | audio/x-riff 316 | audio/x-s3m s3m 317 | audio/x-scpls pls 318 | audio/x-scpls pls xpl 319 | audio/x-stm stm 320 | audio/x-voc voc 321 | audio/x-wav wav 322 | audio/x-xi xi 323 | audio/x-xm xm 324 | image/bmp bmp 325 | image/cgm cgm 326 | image/dpx 327 | image/fax-g3 g3 328 | image/g3fax 329 | image/gif gif 330 | image/ief ief 331 | image/jpeg jpeg jpg jpe 332 | image/jpeg2000 jp2 333 | image/png png 334 | image/rle rle 335 | image/svg+xml svg 336 | image/tiff tif tiff 337 | image/vnd.djvu djvu djv 338 | image/vnd.dwg dwg 339 | image/vnd.dxf dxf 340 | image/x-3ds 3ds 341 | image/x-applix-graphics ag 342 | image/x-cmu-raster ras 343 | image/x-compressed-xcf xcf.gz xcf.bz2 344 | image/x-dcraw bay BAY bmq BMQ cr2 CR2 crw CRW cs1 CS1 dc2 DC2 dcr DCR fff FFF k25 K25 kdc KDC mos MOS mrw MRW nef NEF orf ORF pef PEF raf RAF rdc RDC srf SRF x3f X3F 345 | image/x-dib 346 | image/x-eps eps epsi epsf 347 | image/x-fits fits 348 | image/x-fpx 349 | image/x-icb icb 350 | image/x-ico ico 351 | image/x-iff iff 352 | image/x-ilbm ilbm 353 | image/x-jng jng 354 | image/x-lwo lwo lwob 355 | image/x-lws lws 356 | image/x-msod msod 357 | image/x-niff 358 | image/x-pcx 359 | image/x-photo-cd pcd 360 | image/x-pict pict pict1 pict2 361 | image/x-portable-anymap pnm 362 | image/x-portable-bitmap pbm 363 | image/x-portable-graymap pgm 364 | image/x-portable-pixmap ppm 365 | image/x-psd psd 366 | image/x-rgb rgb 367 | image/x-sgi sgi 368 | image/x-sun-raster sun 369 | image/x-tga tga 370 | image/x-win-bitmap cur 371 | image/x-wmf wmf 372 | image/x-xbitmap xbm 373 | image/x-xcf xcf 374 | image/x-xfig fig 375 | image/x-xpixmap xpm 376 | image/x-xwindowdump xwd 377 | inode/blockdevice 378 | inode/chardevice 379 | inode/directory 380 | inode/fifo 381 | inode/mount-point 382 | inode/socket 383 | inode/symlink 384 | message/delivery-status 385 | message/disposition-notification 386 | message/external-body 387 | message/news 388 | message/partial 389 | message/rfc822 390 | message/x-gnu-rmail 391 | model/vrml wrl 392 | multipart/alternative 393 | multipart/appledouble 394 | multipart/digest 395 | multipart/encrypted 396 | multipart/mixed 397 | multipart/related 398 | multipart/report 399 | multipart/signed 400 | multipart/x-mixed-replace 401 | text/calendar vcs ics 402 | text/css css CSSL 403 | text/directory vcf vct gcrd 404 | text/enriched 405 | text/html html htm 406 | text/htmlh 407 | text/mathml mml 408 | text/plain txt asc 409 | text/rdf rdf 410 | text/rfc822-headers 411 | text/richtext rtx 412 | text/rss rss 413 | text/sgml sgml sgm 414 | text/spreadsheet sylk slk 415 | text/tab-separated-values tsv 416 | text/vnd.rn-realtext rt 417 | text/vnd.wap.wml wml 418 | text/x-adasrc adb ads 419 | text/x-authors 420 | text/x-bibtex bib 421 | text/x-boo boo 422 | text/x-c++hdr hh 423 | text/x-c++src cpp cxx cc C c++ 424 | text/x-chdr h h++ hp 425 | text/x-comma-separated-values csv 426 | text/x-copying 427 | text/x-credits 428 | text/x-csrc c 429 | text/x-dcl dcl 430 | text/x-dsl dsl 431 | text/x-dsrc d 432 | text/x-dtd dtd 433 | text/x-emacs-lisp el 434 | text/x-fortran f 435 | text/x-gettext-translation po 436 | text/x-gettext-translation-template pot 437 | text/x-gtkrc 438 | text/x-haskell hs 439 | text/x-idl idl 440 | text/x-install 441 | text/x-java java 442 | text/x-js js 443 | text/x-ksysv-log 444 | text/x-literate-haskell lhs 445 | text/x-log log 446 | text/x-makefile 447 | text/x-moc moc 448 | text/x-msil il 449 | text/x-nemerle n 450 | text/x-objcsrc m 451 | text/x-pascal p pas 452 | text/x-patch diff patch 453 | text/x-python py 454 | text/x-readme 455 | text/x-rng rng 456 | text/x-scheme scm 457 | text/x-setext etx 458 | text/x-speech 459 | text/x-sql sql 460 | text/x-suse-ymp ymp 461 | text/x-suse-ymu ymu 462 | text/x-tcl tcl tk 463 | text/x-tex tex ltx sty cls 464 | text/x-texinfo texi texinfo 465 | text/x-texmacs tm ts 466 | text/x-troff-me me 467 | text/x-troff-mm mm 468 | text/x-troff-ms ms 469 | text/x-uil uil 470 | text/x-uri uri url 471 | text/x-vb vb 472 | text/x-xds xds 473 | text/x-xmi xmi 474 | text/x-xsl xsl 475 | text/x-xslfo fo xslfo 476 | text/x-xslt xslt xsl 477 | text/xmcd 478 | text/xml xml 479 | video/3gpp 3gp 480 | video/dv dv dif 481 | video/isivideo 482 | video/mpeg mpeg mpg mp2 mpe vob dat 483 | video/quicktime qt mov moov qtvr 484 | video/vivo 485 | video/vnd.rn-realvideo rv 486 | video/wavelet 487 | video/x-3gpp2 3g2 488 | video/x-anim anim[1-9j] 489 | video/x-avi 490 | video/x-flic fli flc 491 | video/x-mng mng 492 | video/x-ms-asf asf asx 493 | video/x-ms-wmv wmv 494 | video/x-msvideo avi 495 | video/x-nsv nsv NSV 496 | video/x-real-video 497 | video/x-sgi-movie movie 498 | application/x-java-jnlp-file jnlp 499 | application/vnd.openxmlformats-officedocument.wordprocessingml.document docx 500 | application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx 501 | application/vnd.ms-word.document.macroEnabled.12 docm 502 | application/vnd.ms-word.template.macroEnabled.12 dotm 503 | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx 504 | application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx 505 | application/vnd.ms-excel.sheet.macroEnabled.12 xlsm 506 | application/vnd.ms-excel.template.macroEnabled.12 xltm 507 | application/vnd.ms-excel.addin.macroEnabled.12 xlam 508 | application/vnd.ms-excel.sheet.binary.macroEnabled.12 xlsb 509 | application/vnd.openxmlformats-officedocument.presentationml.presentation pptx 510 | application/vnd.openxmlformats-officedocument.presentationml.template potx 511 | application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx 512 | application/vnd.ms-powerpoint.addin.macroEnabled.12 ppam 513 | --------------------------------------------------------------------------------