package kr.co.kihyun.io; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import kr.co.kihyun.moumi.MoumiConfig; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import kr.co.kihyun.lang.MString; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MultipartRequest extends HttpServletRequestWrapper { private static final Logger LOG = LoggerFactory.getLogger(MultipartRequest.class); private final Map> formParams = new LinkedHashMap>(); private static final String savePath = MoumiConfig.getFileDirectory().getPath().toString(); //v2. 5.static final 필드 변조 가능성 : Update by KWON,HAN //50.public static을 통한 선언 오류(CWE-500) Update by YOUNGJUN,CHO //public static int maxSize=50; // public static final int maxSize=50; private static final int maxSize=50; //================================================ public MultipartRequest(HttpServletRequest request) throws IOException { this(request, savePath); // this(request, System.getProperty("java.io.tmpdir")); } public MultipartRequest(HttpServletRequest request, String savePath) throws IOException { this(request, savePath, maxSize * 1024 * 1024); } //50.public static을 통한 선언 오류(CWE-500) Add by YOUNGJUN,CHO // maxSize 를 final 로 선언하여, 다른 클래스에서 제한용량을 따로 지정할 경우에 final 값을 변경하지 못하므로 메서드 오버로딩으로 처리함. public MultipartRequest(HttpServletRequest request, long fileSizeMax) throws IOException { this(request, savePath, fileSizeMax); } //++++++++++++++++++++++++++++++++++++++++++++++++ @SuppressWarnings("unchecked") public MultipartRequest(HttpServletRequest request, String savePath, long fileSizeMax) throws IOException { super(request); request.setCharacterEncoding("UTF-8"); DiskFileItemFactory factory = new DiskFileItemFactory(); //파일명을 체크하는 것이 아니므로 오탐이다 // //10.자원 삽입(임의 파일 접근)_CWE-99 : Add by KWON,HAN // LOG.debug("savePath: {}", savePath); // if(savePath.contains("..") || savePath. contains("/")) { // 특수문자열 검증 // //LOG.debug("MultipartRequest MultipartRequest ==="); // //LOG.debug("10.자원 삽입(임의 파일 접근)_CWE-99 : Test OK {}", savePath); // //LOG.debug("====================================="); // throw new IOException("{} 파일명에 특수문자(.. 또는 /)이 존재합니다." + savePath.toString()); // } // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ File tmpDir = new File(savePath); // 43.권한 미설정의 위험성(mkdir)_CWE-379 : Add by YOUNGJUN,CHO tmpDir.setReadable(true, true); tmpDir.setWritable(true, true); tmpDir.setExecutable(true, true); //++++++++++++++++++++++++++++++++++++++++++++++++ factory.setRepository(tmpDir); if (!tmpDir.exists() && !tmpDir.mkdir()) { factory.setRepository(new File(savePath)); } LOG.debug("SAVEPATH: ", factory.getRepository()); ServletFileUpload upload = new ServletFileUpload(factory); upload.setFileSizeMax(fileSizeMax); upload.setSizeMax(-1); try { LOG.debug("request: {}", request); for (FileItem item : (List) upload.parseRequest(request)) { if (formParams.get(item.getFieldName()) != null) { formParams.get(item.getFieldName()).add(item); } else { List list = new ArrayList(); list.add(item); formParams.put(item.getFieldName(), list); } LOG.debug("BUILD MULTIPART REQUEST item {} added for key {}", item, item.getFieldName()); } } catch (FileUploadException fue) { fue.printStackTrace(); throw new IOException("Cannot parse underlying request: " + fue.toString()); } } @Override public Enumeration getParameterNames() { return Collections.enumeration(formParams.keySet()); } @Override public String getParameter(String aName) { List values = formParams.get(aName); if (values == null) { //LOG.debug("values null. param {}: {}", aName, super.getParameter(aName)); return super.getParameter(aName); } else if (values.isEmpty()) { return ""; } else { if (values.get(0).isFormField()) { try { return values.get(0).getString("UTF-8"); } catch (UnsupportedEncodingException e) { LOG.warn("{}, UTF-8 is unsupported. So system default encoding will be used.", e.getMessage()); return values.get(0).getString(); } } else { if (MString.isNull(values.get(0).getName())) return ""; String delim = System.getProperty("file.separator").equals("\\") ? "\\\\" : System .getProperty("file.separator"); String[] fileName = values.get(0).getName().split(delim); return fileName[fileName.length > 1 ? fileName.length - 1 : 0]; } } } @Override public String[] getParameterValues(String aName) { List items = formParams.get(aName); String[] result = null; if (items != null) { result = new String[items.size()]; for (int i = 0; i < result.length; i++) { try { result[i] = items.get(i).getString("UTF-8"); } catch (UnsupportedEncodingException e) { LOG.warn("{}, UTF-8 is unsupported. So system default encoding will be used.", e.getMessage()); result[i] = items.get(i).getString(); } } } return result; } @Override public Map getParameterMap() { Map result = new LinkedHashMap(); for (String paramName : formParams.keySet()) result.put(paramName, this.getParameterValues(paramName)); return result; } public List getFileItems(String aFieldName) { return formParams.get(aFieldName); } public FileItem getFileItem(String aFieldName) { List values = formParams.get(aFieldName); if (values != null && !values.isEmpty()) return values.get(0); return null; } }