//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.huawei.it.jalor5.upload.support.impl;
import com.huawei.his.jalor.helper.StoreHelper;
import com.huawei.it.env.support.EnvHolder;
import com.huawei.it.jalor5.core.annotation.JalorOperation;
import com.huawei.it.jalor5.core.annotation.SecurityPolicy;
import com.huawei.it.jalor5.core.config.ApplicationConfigProperties;
import com.huawei.it.jalor5.core.exception.ApplicationException;
import com.huawei.it.jalor5.core.exception.ExceptionHandler;
import com.huawei.it.jalor5.core.io.CheckResult;
import com.huawei.it.jalor5.core.io.FileInfoVO;
import com.huawei.it.jalor5.core.io.IFileContentHandler;
import com.huawei.it.jalor5.core.ioc.Jalor;
import com.huawei.it.jalor5.core.log.ILogger;
import com.huawei.it.jalor5.core.log.JalorLoggerFactory;
import com.huawei.it.jalor5.core.util.CollectionUtil;
import com.huawei.it.jalor5.core.util.FileUtil;
import com.huawei.it.jalor5.core.util.JsonUtil;
import com.huawei.it.jalor5.core.util.PathUtil;
import com.huawei.it.jalor5.core.util.StringUtil;
import com.huawei.it.jalor5.core.util.XssStringUtil;
import com.huawei.it.jalor5.htmlarea.HtmlAreaApplicationException;
import com.huawei.it.jalor5.logs.LogVO;
import com.huawei.it.jalor5.logs.service.ILogService;
import com.huawei.it.jalor5.registry.RegistryVO;
import com.huawei.it.jalor5.registry.service.IRegistryQueryService;
import com.huawei.it.jalor5.upload.support.FolderSplitType;
import com.huawei.it.jalor5.upload.support.IUploadFileConsumer;
import com.huawei.it.jalor5.upload.support.IUploadSupportService;
import com.huawei.it.jalor5.upload.support.UploadException;
import com.huawei.it.jalor5.upload.support.UploadSettingVO;
import com.huawei.it.jalor5.web.support.internal.impl.RequestUtil;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileCountLimitExceededException;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.RequestContext;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.servlet.ServletRequestContext;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("/servlet/upload")
public class UploadServlet extends HttpServlet {
private static final String UPLOAD_ERROR = "huawei.jalor5.upload.support.00010001";
private static final Set<String> FILE_TYPE = new HashSet(Arrays.asList("der", "cer", "txt", "sql", "pfx", "jks", "crl", "pem"));
private static final int FORM_BUFFER_SIZE = 2000;
private static final long serialVersionUID = -460601782542501990L;
private static int currentUploading = 0;
private static int defaultMaxUploading = 10000;
private static final ILogger LOGGER = JalorLoggerFactory.getLogger(UploadServlet.class);
@Autowired(
required = false
)
private transient IUploadSupportService uploadSupportService;
@Autowired(
required = false
)
private transient ILogService logService;
@Autowired(
required = false
)
private transient IRegistryQueryService registryService;
public UploadServlet() {
}
@JalorOperation(
policy = SecurityPolicy.AllSystemUser
)
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
HttpServletRequest httpRequest = RequestUtil.getHttpServletRequest(request);
LOGGER.debug("Upload Query String:{0}", new Object[]{httpRequest.getQueryString()});
String uploadType = request.getParameter("ulType");
Map<String, String> queryParams = RequestUtil.getRequestQueryParams(httpRequest);
try {
this.checkUploadingTimes();
Map<String, String> convertedMap = CollectionUtil.convert(request.getParameterMap());
convertedMap.put("taskType", queryParams.get("taskType"));
Object obj = this.processUpload(httpRequest, uploadType, convertedMap);
String json = JsonUtil.getJsonString(obj);
LOGGER.debug("Object return:{0}", new Object[]{json});
String pattern = null;
String uploadCleanXSS = "false";
if (null != this.registryService) {
RegistryVO registryVO = this.registryService.findRegistryByPathNoAssertInternal("App.Security.XssFilterMatcher", false);
if (null != registryVO) {
pattern = registryVO.getValue();
}
uploadCleanXSS = this.registryService.findValueByPath("App.Security.UploadCleanXSS", false, "false");
}
response.setContentType("text/html");
if ("true".equalsIgnoreCase(uploadCleanXSS)) {
response.getWriter().write(XssStringUtil.cleanXSS(json, pattern));
} else {
response.getWriter().write(json);
}
} catch (UploadException ex) {
LOGGER.error(ex);
throw new ServletException(ex);
} catch (ApplicationException ex) {
LOGGER.error(ex);
throw new ServletException(new UploadException("huawei.jalor5.upload.support.00010001", ex));
} catch (RuntimeException | FileUploadException ex) {
LOGGER.error(ex);
throw new ServletException(new UploadException("huawei.jalor5.upload.support.00010001", ex, ExceptionHandler.getFriendlyFault(ex).getMessage()));
} finally {
this.completeUploadingTimes();
}
}
private void completeUploadingTimes() {
synchronized(UploadServlet.class) {
if (currentUploading > 0) {
--currentUploading;
}
}
}
private void checkUploadingTimes() {
if (null != this.registryService) {
int maxTimes = Integer.parseInt(this.registryService.findValueByPath("App.Security.MaxUploadingTimes", true, defaultMaxUploading));
synchronized(UploadServlet.class) {
++currentUploading;
if (currentUploading > maxTimes) {
throw new IllegalArgumentException("当前系统正在处理的上传次数超过最大上限,若需要加大上限,请修改数据字典App.Security.MaxUploadingTimes值");
}
}
}
}
private Object processUpload(HttpServletRequest request, String uploadType, Map<String, String> parameters) throws ApplicationException, FileUploadException {
IUploadFileConsumer uls = this.uploadSupportService.findUploadConsumer(uploadType);
if (!uls.validatePrivilege(parameters)) {
throw new UploadException("huawei.jalor5.security.00010001");
} else {
DiskFileItemFactory factory = new DiskFileItemFactory();
UploadSettingVO uploadSetting = uls.getUploadSetting(parameters);
factory.setSizeThreshold(uploadSetting.getMaxMemory());
File file = new File(uploadSetting.getTempRepository());
PathUtil.makeDirs(file);
factory.setRepository(file);
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setSizeMax(uploadSetting.getMaxFileSize() + 2000L);
if ("HtmlAreaImage".equals(uploadType)) {
String value = this.registryService.findValueByPath("App.Security.HtmlArea", false, "1");
if ("1".equals(value)) {
throw new HtmlAreaApplicationException("huawei.jalor5.Htmlarea.00020007");
}
}
RequestContext requestContext = new ServletRequestContext(request);
long rLength = (long)requestContext.getContentLength();
long setLength = upload.getSizeMax();
LOGGER.debug("Upload image ok?:realLength={0},set={1}", new Object[]{rLength, setLength});
if (rLength > setLength) {
throw new UploadException("huawei.jalor5.upload.support.00010004", new Object[]{rLength, setLength});
} else {
List<FileItem> items = upload.parseRequest(request);
this.validateFileCount(items, uploadSetting.getMaxFileCount());
return this.processFileItems(parameters, uploadSetting, uls, items);
}
}
}
private void validateFileCount(List<FileItem> items, int maxFileCount) throws FileCountLimitExceededException {
if (!CollectionUtil.isNullOrEmpty(items) && maxFileCount != -1) {
long fileCount = 0L;
for(FileItem fileItem : items) {
if (!fileItem.isFormField()) {
++fileCount;
}
if (fileCount > (long)maxFileCount) {
throw new FileCountLimitExceededException("attachment", (long)maxFileCount);
}
}
}
}
private Object processFileItems(Map<String, String> parameters, UploadSettingVO uploadSetting, IUploadFileConsumer consumer, List<FileItem> items) throws ApplicationException {
Iterator<FileItem> iter = items.iterator();
List<FileInfoVO> files = new ArrayList();
while(iter.hasNext()) {
FileItem item = (FileItem)iter.next();
if (!item.isFormField()) {
if (item.getSize() == 0L) {
throw new UploadException("huawei.jalor5.upload.support.00010003");
}
this.validateExtention(uploadSetting, item);
FileInfoVO fileInfo = new FileInfoVO();
String fileStorePath = MessageFormat.format("{0}/{1}", consumer.getUploadSetting(parameters).getRepository(), this.generatePathPart(uploadSetting));
PathUtil.makeDirs(fileStorePath);
String fileStore = MessageFormat.format("{0}/{1}.jlr", fileStorePath, UUID.randomUUID().toString());
File uploadedFile = FileUtils.getFile(new String[]{fileStore});
Map<String, IFileContentHandler> downloadHandlersMap = Jalor.getContext().getBeansOfType(IFileContentHandler.class);
if (downloadHandlersMap.size() > 0) {
try {
item.write(uploadedFile);
fileInfo.setDisplayName(FileUtil.getFileName(item.getName()));
fileInfo.setFileSize(item.getSize());
if (fileStore.contains("..")) {
throw new IllegalArgumentException("fileStore path [" + fileStore + "] not support string [..]");
}
fileInfo.setFilePath(fileStore);
} catch (Exception ex) {
LOGGER.error2("写文件异常,fileName:[{0}],exception:[{1}]", new Object[]{item.getName(), ex.getMessage()});
}
}
this.executeFileContentHandler(parameters, fileInfo, uploadedFile, downloadHandlersMap);
fileStore = this.writeFile(item, uploadedFile);
fileInfo.setDisplayName(FileUtil.getFileName(item.getName()));
fileInfo.setFileSize(item.getSize());
fileInfo.setFilePath(fileStore);
files.add(fileInfo);
}
}
this.sendlogMessage((String)parameters.get("ulType"), files);
return consumer.processFiles(parameters, files);
}
private void executeFileContentHandler(Map<String, String> parameters, FileInfoVO fileInfo, File uploadedFile, Map<String, IFileContentHandler> downloadHandlersMap) throws ApplicationException {
for(Map.Entry<String, IFileContentHandler> entry : downloadHandlersMap.entrySet()) {
Object result = ((IFileContentHandler)entry.getValue()).handler(parameters, fileInfo, "upload");
if (result != null && result instanceof CheckResult) {
CheckResult reslut = (CheckResult)result;
if (!reslut.isContinuation()) {
if (uploadedFile.exists()) {
uploadedFile.delete();
}
throw new UploadException("huawei.jalor5.upload.support.00010006");
}
}
}
}
private void sendlogMessage(String type, List<FileInfoVO> files) throws ApplicationException {
LogVO logVO = new LogVO();
logVO.buildAotoAttribute();
logVO.setClazz("UploadServlet");
logVO.setOperation("Upload");
logVO.setLogType(0);
StringBuffer message = new StringBuffer();
for(FileInfoVO fileInfoVO : files) {
message.append(", " + fileInfoVO.getDisplayName());
}
String mess = null;
if (message.length() > 1) {
mess = message.substring(1, message.length());
}
logVO.setStatus(1);
logVO.setModule(type + " Upload");
logVO.setServerName(RequestUtil.getServerName());
logVO.setMessage("upload file name is " + mess);
if (this.logService != null) {
this.logService.asyncCreateLog(logVO);
} else {
try {
LOGGER.info("logMessage: " + JsonUtil.objectToJson(logVO));
} catch (IOException ex) {
LOGGER.info(ex);
}
}
}
private String writeFile(FileItem item, File uploadedFile) throws UploadException {
try {
if (!uploadedFile.exists()) {
item.write(uploadedFile);
}
String region = "";
String bucketName = "";
try {
PathUtil.canonicalPath(uploadedFile.getPath());
return StoreHelper.store(uploadedFile.getPath());
} catch (Exception ex) {
LOGGER.error(ex);
return uploadedFile.getPath();
}
} catch (Exception ex) {
throw new UploadException("huawei.jalor5.upload.support.00010001", ex);
}
}
private void validateExtention(UploadSettingVO uploadSetting, FileItem item) throws UploadException {
if (!this.isFileTypesAllowed(item.getName(), uploadSetting.getFileTypesAllowed())) {
LOGGER.debug("File type {0} is not valid for {1}", new Object[]{FileUtil.getExtension(item.getName()), item.getName()});
throw new UploadException("huawei.jalor5.upload.support.00010002", StringUtil.join(uploadSetting.getFileTypesAllowed(), ","));
} else if (PathUtil.isInvalidPath(item.getName())) {
throw new UploadException("huawei.jalor5.upload.support.00010002", "Path contains ..");
} else if ("true".equals(ApplicationConfigProperties.getContextProperty("checkRealsFile")) && !this.checkRealFileType(uploadSetting, item)) {
throw new UploadException("huawei.jalor5.upload.support.00010002", StringUtil.join(uploadSetting.getFileTypesAllowed(), ","));
}
}
private boolean isFileTypesAllowed(String fileName, List<String> fileTypesAllowed) {
for(String fileType : fileTypesAllowed) {
if (StringUtil.toLower(fileName).endsWith("." + StringUtil.toLower(fileType))) {
return true;
}
}
return false;
}
private String generatePathPart(UploadSettingVO uploadSetting) {
if (uploadSetting.getFileSplitType().equals(FolderSplitType.ByDay)) {
SimpleDateFormat dayFormat = new SimpleDateFormat("yyyy-MM-dd");
return dayFormat.format(new Date());
} else {
return com.huawei.it.jalor5.core.request.impl.RequestContext.getCurrent().getUser().getUserAccount();
}
}
private boolean checkRealFileType(UploadSettingVO uploadSetting, FileItem item) {
LOGGER.info("check file real_code.");
InputStream inputStream = null;
label183: {
boolean ex;
try {
if (!this.fileTypeInWhitelist(item)) {
inputStream = item.getInputStream();
byte[] byt = new byte[4];
inputStream.read(byt, 0, byt.length);
String code = this.bytesToHexString(byt);
LOGGER.info("The file real_code is :" + code);
inputStream.close();
HashMap<String, String> mimeTypeMap = null;
try {
mimeTypeMap = (HashMap)Jalor.getContext().getBean("HashMap." + EnvHolder.getApplication(), HashMap.class);
} catch (Exception var24) {
LOGGER.info("can't find Hash.Bean, We will load from local! Now,loading from HashMap.default..");
mimeTypeMap = (HashMap)Jalor.getContext().getBean("HashMap.default", HashMap.class);
}
String realType = (String)mimeTypeMap.get(code);
if (StringUtil.isNullOrEmpty(realType)) {
LOGGER.error("The file real_code cannot be discovered. Please configure it.");
boolean var29 = false;
return var29;
}
List<String> allowFileType = uploadSetting.getFileTypesAllowed();
boolean checkFirstStep = StringUtil.isNullOrEmpty(realType) ? false : this.checkFileType(realType, allowFileType);
if (!checkFirstStep) {
break label183;
}
boolean var10 = true;
return var10;
}
ex = true;
} catch (Exception ex) {
LOGGER.error("UploadServlet check file real Type ERROR,the message is :" + ex);
break label183;
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException var23) {
}
}
}
return ex;
}
LOGGER.error("The file real_code error ,Please configure it.");
return false;
}
private boolean fileTypeInWhitelist(FileItem item) {
String endItem = StringUtil.toLower(item.getName().substring(item.getName().lastIndexOf(".") + 1));
String whitelist = ApplicationConfigProperties.getContextProperty("whiteListUlType");
if (!StringUtil.isNullOrEmpty(whitelist) && whitelist.indexOf(endItem) != -1) {
return true;
} else {
return FILE_TYPE.contains(endItem);
}
}
private boolean checkFileType(String type, List<String> allowType) {
boolean result = false;
if (!StringUtil.isNullOrEmpty(type) && allowType.size() >= 1) {
for(String t : allowType) {
if (type.toLowerCase(Locale.ROOT).contains(t.toLowerCase(Locale.ROOT))) {
result = true;
break;
}
}
return result;
} else {
return result;
}
}
private String bytesToHexString(byte[] src) {
StringBuilder sbBuilder = new StringBuilder();
if (src != null && src.length > 0) {
for(int i = 0; i < src.length; ++i) {
String str = Integer.toHexString(src[i] & 255).toUpperCase(Locale.getDefault());
if (str.length() < 2) {
sbBuilder.append(0);
}
sbBuilder.append(str);
}
return sbBuilder.toString();
} else {
return null;
}
}
}