/**********************************************************************************
 * 프로그램명 : HttpFileUpload.java 작 성 자 : 강원중 작 성 일 : 2003. 7.23 최신변경일 : 2003. 5.14
 ***********************************************************************************/

package kr.co.kihyun.beans.totsys.board;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.co.kihyun.beans.user.HttpSSOLogin;
import kr.co.kihyun.io.FileUtil;
import kr.co.kihyun.io.MultipartRequest;
import kr.co.kihyun.lang.MLong;
import kr.co.kihyun.lang.MString;
import kr.co.kihyun.moumi.MoumiConfig;
//import kr.co.kihyun.text.html.ServletUtil;
import kr.co.kihyun.util.MRandom;

import org.apache.commons.fileupload.FileItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@WebServlet("/servlet/kr.co.kihyun.beans.totsys.board.HttpFileUpload")
public class HttpFileUpload extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static final Logger LOG = LoggerFactory.getLogger(HttpFileUpload.class);

	@Override
	public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

		res.setContentType("text/html;charset=UTF-8");
		PrintWriter out = res.getWriter();

		MultipartRequest multi = null;
		String svrFilename = "";
		String usrFilename = "";
		String boardGroupID = "";
		String connURL = "";
		String mode = "";
		String usID = HttpSSOLogin.getLoginID(req);
		String dtID = HttpSSOLogin.getDeptID(req);
		Long docID = null;
		Long reportID = null;
                String boardID="";
                String msg="";
                String maxSize="1";
                String checkSize="";
                boolean isExtNullOk = true;   //7.+++
                boolean isExtFileOk = true;   //7.+++
                boolean isDirectoryOk = true;  //3.+++
                
		try {

                        maxSize=req.getParameter("maxSize");
                        if(maxSize==null || maxSize.equals("")) maxSize="10";
                        int tmpSize=Integer.parseInt(maxSize)*1024*1024; //사이즈를 정해준다.
                        checkSize=String.valueOf(tmpSize);

                        //MultipartRequest.maxSize=Integer.parseInt(maxSize);
                        //multi = new MultipartRequest(req);                                                                     
                        multi = new MultipartRequest(req, tmpSize);
			//multi.setMaxSize(Integer.parseInt(maxSize));
                        //System.out.println("====> HttpFileUpload.java multi.getMaxSize() : " + multi.getMaxSize());
                        
	      //LOG.debug("req.appendFile: {}", req.getParameter("appendFile"));
			mode = MString.checkNull(multi.getParameter("mode"));
			boardGroupID = multi.getParameter("boardGroupID");
			usrFilename = multi.getParameter("appendFile");
                        
                        //7.위험한 형식 파일 업로드(MultipartRequest)_CWE-434 : Add by KWON,HAN
                        int extIndex = 0 ;
                        extIndex = usrFilename.lastIndexOf('.');
                        if(extIndex < 0 ) {
                            //LOG.debug("7.위험한 형식 파일 업로드(MultipartRequest)_CWE-434 : Test OK / usrFilename: {}", usrFilename);
                            //out.print("<script language='javascript'>alert('확장자가 없는 파일입니다.');</script>");   
                            isExtNullOk = false;
                            return;
                        }
                        
                        //v2 22.정수형 오버플로우_CWE-190 : Update by YOUNGJUN,CHO
                        if (extIndex < Integer.MAX_VALUE) {
                            //String file_ext = usrFilename.substring(usrFilename.lastIndexOf('.') + 1); 
                            String file_ext = usrFilename.substring(extIndex + 1); 
                            
                            if( file_ext.equalsIgnoreCase("exe") || file_ext.equalsIgnoreCase("bat") || file_ext.equalsIgnoreCase("sh") ) { 
                                //LOG.debug("7.위험한 형식 파일 업로드(MultipartRequest)_CWE-434 : Test OK / usrFilename: {}", usrFilename);
                                //out.print("<script language='javascript'>alert('확장자가 [exe, bat, sh]는 업로드가 제한된 파일입니다.');</script>");         
                                isExtFileOk = false;
                                return;
                            }
                        } else {
                            //LOG.debug("v2 22.정수형 오버플로우_CWE-190 : Test OK / usrFilename: {}", usrFilename);
                            isExtFileOk = false;
                            return;
                        }
                        //================================================ v2 22.정수형 오버플로우_CWE-190 : Update by YOUNGJUN,CHO
                        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7.위험한 형식 파일 업로드(MultipartRequest)_CWE-434 : Add by KWON,HAN
                        
			docID = MLong.parseLong(multi.getParameter("docID"));
			reportID = MLong.parseLong(multi.getParameter("reportID"));
			boardID = MString.checkNull(multi.getParameter("boardID"));

			//LOG.debug("docID: {}, boardID: {}, mode: {}", new Object[] {docID, boardID, mode});
                        
			if (!MString.isNull(usrFilename)) {
				String[] usrFilenamePath = usrFilename.split("\\\\");
				usrFilename = usrFilenamePath[usrFilenamePath.length - 1];

                String imsi="";
                //String[] filter_word = {" ","\\?","\\/","\\~","\\!","\\@","\\#","\\$","\\%","\\^","\\&","\\*","\\(","\\)","\\+","\\=","\\|","\\\\","\\}","\\]","\\{","\\[","\\\"","\\'","\\:","\\;","\\<","\\,","\\>","\\?","\\/"};
                // 공백은 _ 제외
                String[] filter_word = {"\\?","\\/","\\~","\\!","\\@","\\#","\\$","\\%","\\^","\\&","\\*","\\+","\\=","\\|","\\\\","\\\"","\\'","\\:","\\;","\\,"};
//                String[] filter_word = {"\\?","\\/","\\~","\\!","\\@","\\#","\\$","\\%","\\^","\\&","\\*","\\(","\\)","\\+","\\=","\\|","\\\\","\\}","\\]","\\{","\\[","\\\"","\\'","\\:","\\;","\\<","\\,","\\>","\\?","\\/"};
                //String[] filter_word = {"\\?","\\/","\\*","\\|","\\\\","\\'","\\:","\\<","\\>"}; // 파일이름에 포함되면 안되는 문자열
                for(int ii=0;ii<filter_word.length;ii++)
                {
                    imsi=usrFilename.replaceAll(filter_word[ii],"_");   // 필터링한 문자를 _ 로 처리
                    usrFilename=imsi;
                }

				LOG.debug("usrFilename: {}", usrFilename);
			}
                     
//                                        if("sysadm".equals(mode)){          // 공지사항,자료실의 경우 난수를 붙이지 않음
//                                            svrFilename    =   usrFilename;
//                                        }else{
                                            svrFilename = FileUtil.getName(usrFilename, Integer.toString(MRandom.getInt(100))); //두자리의 랜덤 수치를 얻음
//                                        }

			File path;
			if (docID != null) {
				path = MoumiConfig.getFileDirectory();
				LOG.debug("MoumiConfig.getFileDirectory(): " + MoumiConfig.getFileDirectory());
			} else if (reportID != null) {
				path = MoumiConfig.getFileDirectory();
				LOG.debug("MoumiConfig.getFileDirectory(): " + MoumiConfig.getFileDirectory());
//			} else if (!MString.isNull(boardID)) {
//				path = new File(MoumiConfig.getBoardFileRoot(), boardID.toString());
//				LOG.debug("MoumiConfig.getBoardFileRoot(): " + MoumiConfig.getBoardFileRoot());
			} else if ("csv".equals(mode)) {
				path = MoumiConfig.getCsvFileRoot();
				LOG.debug("MoumiConfig.getCsvFileRoot(): " + MoumiConfig.getCsvFileRoot());
			} else {
				path = MoumiConfig.getFileDirectory();
				LOG.debug("MoumiConfig.getFileDirectory(): " + MoumiConfig.getFileDirectory());
			}
			if (!path.isDirectory())
				if (!path.mkdirs())
					throw new ServletException(path + " is not a directory.");
			FileItem upFile = multi.getFileItem("appendFile");
			LOG.debug("UPFILE: {}", upFile);
                        
                        //3.디렉토리 경로 조작(getParameter)_CWE-22/23/36 : Add by KWON,HAN
                        LOG.debug("svrFilename: {}", svrFilename); 
                        if(svrFilename.contains("..") || svrFilename. contains("/")) { // 특수문자열 검증
                            //LOG.debug("3.디렉토리 경로 조작(getParameter)_CWE-22/23/36 : Test OK {}", svrFilename);
                            isDirectoryOk = false;
                            return;
                        }
                        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                        
                        upFile.write(new File(path, svrFilename));                                           
			LOG.debug("UPFILE writed to svrFilename: {}/{}", path, svrFilename);

			svrFilename = URLEncoder.encode(svrFilename, "UTF-8");
			usrFilename = URLEncoder.encode(usrFilename, "UTF-8");

             return;
		} 
                catch (IOException ex)
                {
                     msg=ex.getMessage();
                     if(msg.indexOf(checkSize)>0) msg="-99";
                     else msg="-88";                                         
		     ex.printStackTrace();
		} 
                catch (Exception ex)
                {
                     msg=ex.getMessage();
                     if(msg.indexOf(checkSize)>0) msg="-99";
                     else msg="-88";
                     ex.printStackTrace();                       
		}
                finally
                {       
                    connURL="/totsys/common/inc/board/doc/write_file_upload.jsp?execMode=up&svrFilename="
					+ svrFilename + "&usrFilename=" + usrFilename + "&boardGroupID=" + boardGroupID + "&docID=" + docID
					+ "&reportID=" + reportID + "&boardID=" + boardID + "&mode=" + mode+"&MSG="+msg+"&maxSize="+maxSize;
                    if(connURL.length()>2047) { msg="-77"; }
                    if(!isExtNullOk) { 
                        msg="-33";  
                    } //7.+++  
                    if(!isExtFileOk) { 
                        msg="-55";  
                    } //7.+++  
                    if(!isDirectoryOk) { 
                        msg="-44"; 
                    }  //3.+++  
                    if(!msg.equals("")){  svrFilename=usrFilename=""; } 
                    
                    //v2. 1.HTTP 응답분할 : Update by KWON,HAN                               
//                        connURL="/totsys/common/inc/board/doc/write_file_upload.jsp?execMode=up&svrFilename="
//					+ svrFilename + "&usrFilename=" + usrFilename + "&boardGroupID=" + boardGroupID + "&docID=" + docID
//					+ "&reportID=" + reportID + "&boardID=" + boardID + "&mode=" + mode+"&MSG="+msg+"&maxSize="+maxSize;

                    if (svrFilename != null || usrFilename != null) {               
                        // 수정 : 외부 입력값 필터링
                        String filtered_svrFilename = svrFilename.replaceAll("\r","").replaceAll("\n","");      
                        String filtered_usrFilename = usrFilename.replaceAll("\r","").replaceAll("\n","");      
                        //LOG.debug("v2 1.HTTP 응답분할 : HttpFileUpload.doPost() filtered_svrFilename={} : Test OK", filtered_svrFilename);
                        //LOG.debug("v2 1.HTTP 응답분할 : HttpFileUpload.doPost() filtered_usrFilename={} : Test OK", filtered_usrFilename);
                        
                        //v2. 3.신뢰되지 않는 URL 주소로 자동 접속 연결_CWE-601 : Update by KWON,HAN     
//                        connURL="/totsys/common/inc/board/doc/write_file_upload.jsp?execMode=up&svrFilename="
//                                        + filtered_svrFilename + "&usrFilename=" + filtered_usrFilename + "&boardGroupID=" + boardGroupID + "&docID=" + docID
//                                        + "&reportID=" + reportID + "&boardID=" + boardID + "&mode=" + mode+"&MSG="+msg+"&maxSize="+maxSize;
                        
                        // 다른 페이지 이동하는 URL 리스트를 만듬
                        String allowURL[] = { "/totsys/common/inc/board/doc/write_file_upload.jsp" };
                        connURL=allowURL[0] + "?execMode=up&svrFilename="
                                        + filtered_svrFilename + "&usrFilename=" + filtered_usrFilename + "&boardGroupID=" + boardGroupID + "&docID=" + docID
                                        + "&reportID=" + reportID + "&boardID=" + boardID + "&mode=" + mode+"&MSG="+msg+"&maxSize="+maxSize;   
                        //LOG.debug("v2 3.신뢰되지 않는 URL 주소로 자동 접속 연결_CWE-601 : HttpFileUpload.doPost() connURL={} : Test OK", connURL);
                        //=========================================================================
                    }                        
                    //========================================                         
                    res.sendRedirect(connURL);    
                }
	}
}
