mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
add code
This commit is contained in:
parent
1a0c9a3b51
commit
99eeb30ffe
@ -306,6 +306,7 @@ public class FileUtil extends PathUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建File对象<br>
|
* 创建File对象<br>
|
||||||
|
* 根据的路径构建文件,在Win下直接构建,在Linux下拆分路径单独构建
|
||||||
* 此方法会检查slip漏洞,漏洞说明见http://blog.nsfocus.net/zip-slip-2/
|
* 此方法会检查slip漏洞,漏洞说明见http://blog.nsfocus.net/zip-slip-2/
|
||||||
*
|
*
|
||||||
* @param parent 父文件对象
|
* @param parent 父文件对象
|
||||||
@ -316,7 +317,7 @@ public class FileUtil extends PathUtil {
|
|||||||
if (StrUtil.isBlank(path)) {
|
if (StrUtil.isBlank(path)) {
|
||||||
throw new NullPointerException("File path is blank!");
|
throw new NullPointerException("File path is blank!");
|
||||||
}
|
}
|
||||||
return checkSlip(parent, new File(parent, path));
|
return checkSlip(parent, buildFile(parent, path));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3277,4 +3278,34 @@ public class FileUtil extends PathUtil {
|
|||||||
public static void tail(File file, Charset charset) {
|
public static void tail(File file, Charset charset) {
|
||||||
tail(file, charset, Tailer.CONSOLE_HANDLER);
|
tail(file, charset, Tailer.CONSOLE_HANDLER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据压缩包中的路径构建目录结构,在Win下直接构建,在Linux下拆分路径单独构建
|
||||||
|
*
|
||||||
|
* @param outFile 最外部路径
|
||||||
|
* @param fileName 文件名,可以包含路径
|
||||||
|
* @return 文件或目录
|
||||||
|
* @since 5.0.5
|
||||||
|
*/
|
||||||
|
private static File buildFile(File outFile, String fileName) {
|
||||||
|
// 替换Windows路径分隔符为Linux路径分隔符,便于统一处理
|
||||||
|
fileName = fileName.replace('\\', '/');
|
||||||
|
if (false == FileUtil.isWindows()
|
||||||
|
// 检查文件名中是否包含"/",不考虑以"/"结尾的情况
|
||||||
|
&& fileName.lastIndexOf(CharUtil.SLASH, fileName.length() - 2) > 0) {
|
||||||
|
// 在Linux下多层目录创建存在问题,/会被当成文件名的一部分,此处做处理
|
||||||
|
// 使用/拆分路径(zip中无\),级联创建父目录
|
||||||
|
final List<String> pathParts = StrUtil.split(fileName, '/', false, true);
|
||||||
|
final int lastPartIndex = pathParts.size() - 1;//目录个数
|
||||||
|
for (int i = 0; i < lastPartIndex; i++) {
|
||||||
|
//由于路径拆分,slip不检查,在最后一步检查
|
||||||
|
outFile = new File(outFile, pathParts.get(i));
|
||||||
|
}
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
outFile.mkdirs();
|
||||||
|
// 最后一个部分如果非空,作为文件名
|
||||||
|
fileName = pathParts.get(lastPartIndex);
|
||||||
|
}
|
||||||
|
return new File(outFile, fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -471,7 +471,7 @@ public class ZipUtil {
|
|||||||
while (em.hasMoreElements()) {
|
while (em.hasMoreElements()) {
|
||||||
zipEntry = em.nextElement();
|
zipEntry = em.nextElement();
|
||||||
// FileUtil.file会检查slip漏洞,漏洞说明见http://blog.nsfocus.net/zip-slip-2/
|
// FileUtil.file会检查slip漏洞,漏洞说明见http://blog.nsfocus.net/zip-slip-2/
|
||||||
outItemFile = buildFile(outFile, zipEntry.getName());
|
outItemFile = FileUtil.file(outFile, zipEntry.getName());
|
||||||
if (zipEntry.isDirectory()) {
|
if (zipEntry.isDirectory()) {
|
||||||
// 创建对应目录
|
// 创建对应目录
|
||||||
//noinspection ResultOfMethodCallIgnored
|
//noinspection ResultOfMethodCallIgnored
|
||||||
@ -1106,36 +1106,6 @@ public class ZipUtil {
|
|||||||
throw new IORuntimeException(e);
|
throw new IORuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据压缩包中的路径构建目录结构,在Win下直接构建,在Linux下拆分路径单独构建
|
|
||||||
*
|
|
||||||
* @param outFile 最外部路径
|
|
||||||
* @param fileName 文件名,可以包含路径
|
|
||||||
* @return 文件或目录
|
|
||||||
* @since 5.0.5
|
|
||||||
*/
|
|
||||||
private static File buildFile(File outFile, String fileName) {
|
|
||||||
// 替换Windows路径分隔符为Linux路径分隔符,便于统一处理
|
|
||||||
fileName = fileName.replace('\\', '/');
|
|
||||||
if (false == FileUtil.isWindows()
|
|
||||||
// 检查文件名中是否包含"/",不考虑以"/"结尾的情况
|
|
||||||
&& fileName.lastIndexOf(CharUtil.SLASH, fileName.length() - 2) > 0) {
|
|
||||||
// 在Linux下多层目录创建存在问题,/会被当成文件名的一部分,此处做处理
|
|
||||||
// 使用/拆分路径(zip中无\),级联创建父目录
|
|
||||||
final List<String> pathParts = StrUtil.split(fileName, '/', false, true);
|
|
||||||
final int lastPartIndex = pathParts.size() - 1;//目录个数
|
|
||||||
for (int i = 0; i < lastPartIndex; i++) {
|
|
||||||
//由于路径拆分,slip不检查,在最后一步检查
|
|
||||||
outFile = new File(outFile, pathParts.get(i));
|
|
||||||
}
|
|
||||||
//noinspection ResultOfMethodCallIgnored
|
|
||||||
outFile.mkdirs();
|
|
||||||
// 最后一个部分如果非空,作为文件名
|
|
||||||
fileName = pathParts.get(lastPartIndex);
|
|
||||||
}
|
|
||||||
return FileUtil.file(outFile, fileName);
|
|
||||||
}
|
|
||||||
// ---------------------------------------------------------------------------------------------- Private method end
|
// ---------------------------------------------------------------------------------------------- Private method end
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +0,0 @@
|
|||||||
package cn.hutool.extra.compress;
|
|
||||||
|
|
||||||
public class Extractor {
|
|
||||||
}
|
|
@ -7,7 +7,7 @@ import java.io.File;
|
|||||||
import java.io.FileFilter;
|
import java.io.FileFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据归档封装,归档即将几个文件或目录打成一个压缩包<br>
|
* 数据归档封装,归档即将几个文件或目录打成一个压缩包
|
||||||
*
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
*/
|
*/
|
||||||
|
@ -56,7 +56,7 @@ public class StreamArchiver implements Archiver {
|
|||||||
return new StreamArchiver(charset, archiverName, out);
|
return new StreamArchiver(charset, archiverName, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArchiveOutputStream out;
|
private final ArchiveOutputStream out;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* 基于commons-compress的打包(压缩)封装
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 见:https://commons.apache.org/proper/commons-compress/
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package cn.hutool.extra.compress.archiver;
|
@ -0,0 +1,11 @@
|
|||||||
|
package cn.hutool.extra.compress.extractor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据解包封装,用于将zip、tar等包解包为文件
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
* @since 5.5.0
|
||||||
|
*/
|
||||||
|
public interface Extractor {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package cn.hutool.extra.compress.extractor;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import cn.hutool.core.io.IORuntimeException;
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.hutool.extra.compress.CompressException;
|
||||||
|
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||||
|
import org.apache.commons.compress.archivers.ArchiveException;
|
||||||
|
import org.apache.commons.compress.archivers.ArchiveInputStream;
|
||||||
|
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
public class StreamExtractor {
|
||||||
|
|
||||||
|
private final ArchiveInputStream in;
|
||||||
|
|
||||||
|
public StreamExtractor(Charset charset, InputStream in) {
|
||||||
|
final ArchiveStreamFactory factory = new ArchiveStreamFactory(charset.name());
|
||||||
|
try {
|
||||||
|
this.in = factory.createArchiveInputStream(in);
|
||||||
|
} catch (ArchiveException e) {
|
||||||
|
throw new CompressException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 释放(解压)到指定目录
|
||||||
|
*
|
||||||
|
* @param targetDir 目标目录
|
||||||
|
*/
|
||||||
|
public void extract(File targetDir) {
|
||||||
|
try {
|
||||||
|
extractInternal(targetDir);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IORuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 释放(解压)到指定目录
|
||||||
|
*
|
||||||
|
* @param targetDir 目标目录
|
||||||
|
* @throws IOException IO异常
|
||||||
|
*/
|
||||||
|
private void extractInternal(File targetDir) throws IOException {
|
||||||
|
Assert.isTrue(null != targetDir && targetDir.isDirectory(), "target must be dir.");
|
||||||
|
final ArchiveInputStream in = this.in;
|
||||||
|
ArchiveEntry entry;
|
||||||
|
File outItemFile;
|
||||||
|
while(null != (entry = this.in.getNextEntry())){
|
||||||
|
if(false == in.canReadEntryData(entry)){
|
||||||
|
// 无法读取的文件直接跳过
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
outItemFile = FileUtil.file(targetDir, entry.getName());
|
||||||
|
if(entry.isDirectory()){
|
||||||
|
// 创建对应目录
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
outItemFile.mkdirs();
|
||||||
|
} else {
|
||||||
|
FileUtil.writeFromStream(in, outItemFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* 基于commons-compress的解包(解压缩)封装
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 见:https://commons.apache.org/proper/commons-compress/
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package cn.hutool.extra.compress.extractor;
|
@ -1,7 +1,5 @@
|
|||||||
package cn.hutool.extra.template.engine.freemarker;
|
package cn.hutool.extra.template.engine.freemarker;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.io.IORuntimeException;
|
import cn.hutool.core.io.IORuntimeException;
|
||||||
import cn.hutool.core.util.ClassUtil;
|
import cn.hutool.core.util.ClassUtil;
|
||||||
@ -13,8 +11,11 @@ import freemarker.cache.ClassTemplateLoader;
|
|||||||
import freemarker.cache.FileTemplateLoader;
|
import freemarker.cache.FileTemplateLoader;
|
||||||
import freemarker.template.Configuration;
|
import freemarker.template.Configuration;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Beetl模板引擎封装
|
* FreeMarker模板引擎封装<br>
|
||||||
|
* 见:https://freemarker.apache.org/
|
||||||
*
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
*/
|
*/
|
||||||
@ -23,10 +24,12 @@ public class FreemarkerEngine implements TemplateEngine {
|
|||||||
private Configuration cfg;
|
private Configuration cfg;
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------- Constructor start
|
// --------------------------------------------------------------------------------- Constructor start
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认构造
|
* 默认构造
|
||||||
*/
|
*/
|
||||||
public FreemarkerEngine() {}
|
public FreemarkerEngine() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
@ -49,7 +52,7 @@ public class FreemarkerEngine implements TemplateEngine {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TemplateEngine init(TemplateConfig config) {
|
public TemplateEngine init(TemplateConfig config) {
|
||||||
if(null == config){
|
if (null == config) {
|
||||||
config = TemplateConfig.DEFAULT;
|
config = TemplateConfig.DEFAULT;
|
||||||
}
|
}
|
||||||
init(createCfg(config));
|
init(createCfg(config));
|
||||||
@ -58,22 +61,23 @@ public class FreemarkerEngine implements TemplateEngine {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化引擎
|
* 初始化引擎
|
||||||
|
*
|
||||||
* @param freemarkerCfg Configuration
|
* @param freemarkerCfg Configuration
|
||||||
*/
|
*/
|
||||||
private void init(Configuration freemarkerCfg){
|
private void init(Configuration freemarkerCfg) {
|
||||||
this.cfg = freemarkerCfg;
|
this.cfg = freemarkerCfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Template getTemplate(String resource) {
|
public Template getTemplate(String resource) {
|
||||||
if(null == this.cfg){
|
if (null == this.cfg) {
|
||||||
init(TemplateConfig.DEFAULT);
|
init(TemplateConfig.DEFAULT);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return FreemarkerTemplate.wrap(this.cfg.getTemplate(resource));
|
return FreemarkerTemplate.wrap(this.cfg.getTemplate(resource));
|
||||||
} catch(IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IORuntimeException(e);
|
throw new IORuntimeException(e);
|
||||||
}catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new TemplateException(e);
|
throw new TemplateException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Freemarker实现
|
* Freemarker实现<br>
|
||||||
|
* 见:https://freemarker.apache.org/
|
||||||
*
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
package cn.hutool.extra.template.engine.freemarker;
|
package cn.hutool.extra.template.engine.freemarker;
|
@ -7,10 +7,10 @@ import cn.hutool.extra.template.TemplateEngine;
|
|||||||
import org.apache.velocity.app.Velocity;
|
import org.apache.velocity.app.Velocity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Velocity模板引擎
|
* Velocity模板引擎<br>
|
||||||
|
* 见:http://velocity.apache.org/
|
||||||
*
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class VelocityEngine implements TemplateEngine {
|
public class VelocityEngine implements TemplateEngine {
|
||||||
|
|
||||||
@ -18,10 +18,12 @@ public class VelocityEngine implements TemplateEngine {
|
|||||||
private TemplateConfig config;
|
private TemplateConfig config;
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------- Constructor start
|
// --------------------------------------------------------------------------------- Constructor start
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认构造
|
* 默认构造
|
||||||
*/
|
*/
|
||||||
public VelocityEngine() {}
|
public VelocityEngine() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
@ -44,7 +46,7 @@ public class VelocityEngine implements TemplateEngine {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TemplateEngine init(TemplateConfig config) {
|
public TemplateEngine init(TemplateConfig config) {
|
||||||
if(null == config){
|
if (null == config) {
|
||||||
config = TemplateConfig.DEFAULT;
|
config = TemplateConfig.DEFAULT;
|
||||||
}
|
}
|
||||||
this.config = config;
|
this.config = config;
|
||||||
@ -54,9 +56,10 @@ public class VelocityEngine implements TemplateEngine {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化引擎
|
* 初始化引擎
|
||||||
|
*
|
||||||
* @param engine 引擎
|
* @param engine 引擎
|
||||||
*/
|
*/
|
||||||
private void init(org.apache.velocity.app.VelocityEngine engine){
|
private void init(org.apache.velocity.app.VelocityEngine engine) {
|
||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +75,7 @@ public class VelocityEngine implements TemplateEngine {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Template getTemplate(String resource) {
|
public Template getTemplate(String resource) {
|
||||||
if(null == this.engine){
|
if (null == this.engine) {
|
||||||
init(TemplateConfig.DEFAULT);
|
init(TemplateConfig.DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,15 +83,15 @@ public class VelocityEngine implements TemplateEngine {
|
|||||||
String root;
|
String root;
|
||||||
// 自定义编码
|
// 自定义编码
|
||||||
String charsetStr = null;
|
String charsetStr = null;
|
||||||
if(null != this.config){
|
if (null != this.config) {
|
||||||
root = this.config.getPath();
|
root = this.config.getPath();
|
||||||
charsetStr = this.config.getCharsetStr();
|
charsetStr = this.config.getCharsetStr();
|
||||||
|
|
||||||
// 修正template目录,在classpath或者web_root模式下,按照配置添加默认前缀
|
// 修正template目录,在classpath或者web_root模式下,按照配置添加默认前缀
|
||||||
// 如果用户已经自行添加了前缀,则忽略之
|
// 如果用户已经自行添加了前缀,则忽略之
|
||||||
final TemplateConfig.ResourceMode resourceMode = this.config.getResourceMode();
|
final TemplateConfig.ResourceMode resourceMode = this.config.getResourceMode();
|
||||||
if(TemplateConfig.ResourceMode.CLASSPATH == resourceMode
|
if (TemplateConfig.ResourceMode.CLASSPATH == resourceMode
|
||||||
|| TemplateConfig.ResourceMode.WEB_ROOT == resourceMode){
|
|| TemplateConfig.ResourceMode.WEB_ROOT == resourceMode) {
|
||||||
resource = StrUtil.addPrefixIfNot(resource, StrUtil.addSuffixIfNot(root, "/"));
|
resource = StrUtil.addPrefixIfNot(resource, StrUtil.addSuffixIfNot(root, "/"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Velocity实现
|
* Velocity实现<br>
|
||||||
|
* 见:http://velocity.apache.org/
|
||||||
*
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
package cn.hutool.extra.template.engine.velocity;
|
package cn.hutool.extra.template.engine.velocity;
|
Loading…
x
Reference in New Issue
Block a user