450 lines
11 KiB
Java
450 lines
11 KiB
Java
package nlib.util;
|
|
|
|
import java.io.UnsupportedEncodingException;
|
|
import java.net.MalformedURLException;
|
|
import java.net.URL;
|
|
import java.net.URLDecoder;
|
|
import java.net.URLEncoder;
|
|
import java.sql.Timestamp;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.Base64;
|
|
import java.util.Base64.Decoder;
|
|
import java.util.Base64.Encoder;
|
|
import java.util.Locale;
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import nlib.cmm.service.NlibProperty;
|
|
|
|
/**
|
|
* <pre>
|
|
* @Class Name : StringUtil.java
|
|
*
|
|
* @Description : 문자열 관련 공통 함수 모음
|
|
*
|
|
*
|
|
* @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
|
|
*
|
|
* </pre>
|
|
*
|
|
* @ ------------ -------- ---------------------------
|
|
* @ 수정일 수정자 수정내용
|
|
* @ ------------ -------- ---------------------------
|
|
* @ 2021. 6. 22. KNKIM 최초 생성
|
|
*
|
|
*
|
|
* @author 이씨플라자 * DIGITALSHIP KNKIM
|
|
* @since 2021. 6. 22.
|
|
* @version 1.0
|
|
*
|
|
*/
|
|
/**
|
|
* <pre>
|
|
* @Class Name : StringUtil.java
|
|
*
|
|
* @Description :
|
|
*
|
|
*
|
|
* @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
|
|
*
|
|
* </pre>
|
|
*
|
|
* @ ------------ -------- ---------------------------
|
|
* @ 수정일 수정자 수정내용
|
|
* @ ------------ -------- ---------------------------
|
|
* @ 2021. 10. 25. KNKIM 최초 생성
|
|
*
|
|
*
|
|
* @author 이씨플라자 * DIGITALSHIP KNKIM
|
|
* @since 2021. 10. 25.
|
|
* @version 1.0
|
|
*
|
|
*/
|
|
public class StringUtil extends StringUtils {
|
|
|
|
private static final Logger log = LoggerFactory.getLogger(StringUtil.class);
|
|
|
|
/**
|
|
* Null 이거나, 빈문자열(공백 포함)인 경우, true를 리턴한다.
|
|
*
|
|
* @param str
|
|
* @return
|
|
*/
|
|
public static boolean isEmpty(final CharSequence cs) {
|
|
return isBlank(cs);
|
|
}
|
|
|
|
/**
|
|
* Null 이거나, 빈문자열(공백 포함)인 경우, replaceStr를 리턴한다.
|
|
*
|
|
* @param str
|
|
* @return
|
|
*/
|
|
public static String getString(String str, String replaceStr) {
|
|
if(isEmpty(str)) return replaceStr;
|
|
else return str;
|
|
}
|
|
|
|
/**
|
|
* 0 이거나, 음수인 경우, replaceInt를 리턴한다.
|
|
*
|
|
* @param str
|
|
* @return
|
|
*/
|
|
public static int getInt(int val, int replaceInt) {
|
|
if(val <= 0) return replaceInt;
|
|
else return val;
|
|
}
|
|
|
|
/**
|
|
* Null이 아니고 빈문자열(공백 포함)이 아닌 일반 문자가 존재하는 , true를 리턴한다.
|
|
*
|
|
* @param str
|
|
* @return
|
|
*/
|
|
public static boolean isNotEmpty(String str) {
|
|
return !isBlank(str);
|
|
}
|
|
|
|
/**
|
|
* 문자열을 정수형으로 변환하여 리턴한다. 만일 문자열이 null 또는 빈 문자열인 경우, -1을 리턴한다.
|
|
*
|
|
* @param str
|
|
* @return
|
|
*/
|
|
public static int toNumber(String str) {
|
|
return toNumber(str, -1);
|
|
}
|
|
|
|
/**
|
|
* 문자열을 정수형으로 변환하여 리턴한다. 만일 문자열이 null 또는 빈 문자열인 경우, 기본값 정보 defaultInt를 리턴한다.
|
|
*
|
|
* @param str
|
|
* @param defaultInt
|
|
* @return
|
|
*/
|
|
public static int toNumber(String str, int defaultInt) {
|
|
if(isEmpty(str)) return defaultInt;
|
|
|
|
try {
|
|
return Integer.parseInt(str.trim());
|
|
} catch(NumberFormatException e) { log.error("toNumber NumberFormatException : " + e.toString()); }
|
|
|
|
return defaultInt;
|
|
}
|
|
|
|
/**
|
|
* 현재 시각을 yyyyMMddhhmmssSSS 형식으로 리턴한다.
|
|
*
|
|
* @return
|
|
*/
|
|
public static String getTimeStamp() {
|
|
|
|
return getTimeStamp(null);
|
|
}
|
|
|
|
public static String getTimeStamp(String pattern) {
|
|
|
|
String rtnStr = null;
|
|
|
|
// 문자열로 변환하기 위한 패턴 설정(년도-월-일 시:분:초:초(자정이후 초))
|
|
if(isEmpty(pattern)) pattern = "yyyyMMddhhmmssSSS";
|
|
|
|
SimpleDateFormat sdfCurrent = new SimpleDateFormat(pattern, Locale.KOREA);
|
|
Timestamp ts = new Timestamp(System.currentTimeMillis());
|
|
|
|
rtnStr = sdfCurrent.format(ts.getTime());
|
|
|
|
return rtnStr;
|
|
}
|
|
|
|
/**
|
|
* URLEncoder로 인코딩한다.
|
|
*
|
|
* @return
|
|
*/
|
|
public static String encodeUrl(String str) {
|
|
|
|
if(isEmpty(str)) return "";
|
|
|
|
String encodedStr = null;
|
|
|
|
try {
|
|
encodedStr = URLEncoder.encode(str, "UTF-8");
|
|
} catch(UnsupportedEncodingException e) {
|
|
log.error("encodeUrl > UnsupportedEncodingException while encoding for [" + str + "] " + e.toString());
|
|
encodedStr = str;
|
|
}
|
|
return encodedStr;
|
|
}
|
|
|
|
/**
|
|
* URLDecoder로 디코딩한다.
|
|
*
|
|
* @return
|
|
*/
|
|
public static String decodeUrl(String str) {
|
|
|
|
if(isEmpty(str)) return "";
|
|
|
|
String decodedStr = null;
|
|
|
|
try {
|
|
decodedStr = URLDecoder.decode(str, "UTF-8");
|
|
} catch(UnsupportedEncodingException e) {
|
|
log.error("encodeUrl > UnsupportedEncodingException while encoding for [" + str + "] " + e.toString());
|
|
decodedStr = str;
|
|
}
|
|
return decodedStr;
|
|
}
|
|
|
|
/**
|
|
* Base64로 인코딩한다.
|
|
*
|
|
* @return
|
|
*/
|
|
public static String encodeBase64(String str) {
|
|
|
|
if(isEmpty(str)) return "";
|
|
|
|
Encoder encoder = Base64.getEncoder();
|
|
return new String(encoder.encode(str.getBytes()));
|
|
}
|
|
|
|
/**
|
|
* Base64로 디코딩한다.
|
|
*
|
|
* @return
|
|
*/
|
|
public static String decodeBase64(String str) {
|
|
|
|
if(isEmpty(str)) return "";
|
|
|
|
Decoder decoder = Base64.getDecoder();
|
|
return new String(decoder.decode(str.getBytes()));
|
|
}
|
|
|
|
/**
|
|
* URL 주소에서 호스트명을 리턴한다.
|
|
*
|
|
* 프로토콜://호스트.도메인/URI 에서 호스트명 리턴
|
|
* (ex) https://seoul.nculture.org/abc/def.do -> seoul 을 리턴한다.
|
|
*
|
|
* @param url
|
|
* @return
|
|
* @throws Exception
|
|
*/
|
|
public static String getHostName(String url) {
|
|
if(isEmpty(url)) return "";
|
|
|
|
String hostName = "";
|
|
|
|
try {
|
|
final URL urlObj = new URL(url);
|
|
hostName = urlObj.getHost();
|
|
if(isEmpty(hostName)) return "";
|
|
} catch(MalformedURLException e) {
|
|
log.error("[ERROR] getHostName(..) : MalformedURLException " + e.toString());
|
|
return "";
|
|
}
|
|
if("|localhost|".contains(hostName)) hostName = NlibProperty.getString("domain.host.localhost", "nlib-dev");
|
|
return (hostName.split("\\."))[0];
|
|
}
|
|
|
|
public static String addWebParamOfUrl(String url, String name, String value) {
|
|
if(isEmpty(url)) return url;
|
|
if(isEmpty(name)) return url;
|
|
|
|
String delim = "?";
|
|
if(url.contains("?")) {
|
|
delim = "&";
|
|
}
|
|
|
|
return url + delim + name + "=" + getString(value, "");
|
|
}
|
|
|
|
public static String getSqlSearchKeyword(String str) {
|
|
|
|
if(isNotEmpty(str)) {
|
|
String ret = str.replaceAll("\\%", "\\\\%");
|
|
ret = ret.replaceAll("_", "\\\\_");
|
|
ret = ret.replaceAll("'", "\\\\'");;
|
|
|
|
return ret;
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
public static String getValidCodeString(String str) {
|
|
|
|
if(isNotEmpty(str)) {
|
|
String ret = str.replaceAll("'", "");
|
|
ret = ret.replaceAll(" ", "");
|
|
ret = ret.replaceAll("\t", "");;
|
|
ret = ret.replaceAll("\n", "");;
|
|
ret = ret.replaceAll("\r", "");;
|
|
|
|
return ret;
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
/**
|
|
* 날짜 문자열(YYYYMMDD)을 받아서 화면 출력용 날짜 형식 문자열(YYYY-MM-DD)로 리턴한다.
|
|
*
|
|
* @param dateStr
|
|
* @param defaultStr
|
|
* @return
|
|
*/
|
|
public static String formatDateStr(String dateStr, String defaultStr) {
|
|
|
|
if(isEmpty(dateStr)) return defaultStr;
|
|
|
|
String tmpDateStr = dateStr.trim();
|
|
if(4 <= tmpDateStr.length() && tmpDateStr.length() < 6) return tmpDateStr.substring(0, 4); // 연도만 있는 경우
|
|
else if(6 <= tmpDateStr.length() && tmpDateStr.length() < 8) return tmpDateStr.substring(0, 4) + "-" + tmpDateStr.substring(4, 6); // YYYY-MM
|
|
else if(8 <= tmpDateStr.length()) return tmpDateStr.substring(0, 4) + "-" + tmpDateStr.substring(4, 6) + "-" + tmpDateStr.substring(6, 8); // YYYY-MM-DD
|
|
|
|
return defaultStr;
|
|
}
|
|
|
|
/**
|
|
* 이메일 masking 후 리턴
|
|
*/
|
|
public static String maskEmail(String email) {
|
|
|
|
if (StringUtils.isEmpty(email) || !email.contains("@")) {
|
|
return email;
|
|
}
|
|
|
|
String[] emailSplited = email.split("@");
|
|
if (emailSplited.length != 2) {
|
|
return email;
|
|
}
|
|
|
|
if (!StringUtils.isEmpty(emailSplited[0]) && emailSplited[0].length() > 2) {
|
|
String str = "";
|
|
for (int i = 2; i < emailSplited[0].length(); i++) {
|
|
str += "*";
|
|
}
|
|
return email.substring(0, 2) + str + "@" + emailSplited[1];
|
|
}
|
|
|
|
return email;
|
|
}
|
|
|
|
/** * 이름 masking 후 리턴<br> * 변환 실패시 입력값 그대로 리턴<br>*/
|
|
public static String maskName(String name) {
|
|
|
|
if (StringUtils.isEmpty(name)) {
|
|
return name;
|
|
}
|
|
|
|
if (name.length() == 1) {
|
|
return "*";
|
|
} else if (name.length() == 2) {
|
|
return name.substring(0, 1) + "*";
|
|
} else if (name.length() > 2) {
|
|
String str = "";
|
|
for (int i = 2; name.length() > i; i++)
|
|
str += "*";
|
|
return name.substring(0, 1) + str + name.substring(name.length() - 1, name.length());
|
|
}
|
|
|
|
return name;
|
|
}
|
|
|
|
public static String getSafeParamData(String value) {
|
|
|
|
if(value == null || value.length() < 1) return value;
|
|
|
|
StringBuffer strBuff = new StringBuffer();
|
|
|
|
for (int i = 0; i < value.length(); i++) {
|
|
char c = value.charAt(i);
|
|
switch (c) {
|
|
case '<':
|
|
if ( checkNextWhiteListTag(i, value) == false )
|
|
strBuff.append("<");
|
|
else
|
|
strBuff.append(c);
|
|
//System.out.println("checkNextWhiteListTag = "+checkNextWhiteListTag(i, value));
|
|
break;
|
|
case '>':
|
|
if ( checkPrevWhiteListTag(i, value) == false )
|
|
strBuff.append(">");
|
|
else
|
|
strBuff.append(c);
|
|
//System.out.println("checkPrevWhiteListTag = "+checkPrevWhiteListTag(i, value));
|
|
break;
|
|
case ' ':
|
|
strBuff.append(" ");
|
|
break;
|
|
case '"':
|
|
strBuff.append(""");
|
|
break;
|
|
case '\'':
|
|
strBuff.append("'");
|
|
break;
|
|
default:
|
|
strBuff.append(c);
|
|
break;
|
|
}
|
|
}
|
|
|
|
value = strBuff.toString();
|
|
|
|
// SQL INJECTION 취약점 보완
|
|
value = value.replaceAll("\\s+[o|O][r|R]\\s+", " o-r ");
|
|
value = value.replaceAll("\\s+[a|A][n|N][d|D]\\s+", " a-n-d ");
|
|
|
|
return value;
|
|
}
|
|
|
|
// Tag 화이트 리스트 ( 허용할 태그 등록 )
|
|
static String[] whiteListTag = { "<p>","</p>","<br />" };
|
|
|
|
private static boolean checkNextWhiteListTag(int index, String data) {
|
|
String extractData = "";
|
|
//int beginIndex = 0;
|
|
int endIndex = 0;
|
|
for(String whiteListData: whiteListTag) {
|
|
//System.out.println("===>>> whiteListData="+whiteListData);
|
|
endIndex = index+whiteListData.length();
|
|
if ( data.length() > endIndex )
|
|
extractData = data.substring(index, endIndex);
|
|
else
|
|
extractData = "";
|
|
//System.out.println("extractData="+extractData);
|
|
if ( whiteListData.equals(extractData) ) return true; // whiteList 대상으로 판정
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static boolean checkPrevWhiteListTag(int index, String data) {
|
|
String extractData = "";
|
|
int beginIndex = 0;
|
|
int endIndex = 0;
|
|
for(String whiteListData: whiteListTag) {
|
|
//System.out.println("===>>> whiteListData="+whiteListData);
|
|
beginIndex = index-whiteListData.length()+1;
|
|
endIndex = index+1;
|
|
//System.out.println(" range ["+beginIndex+" ~ "+endIndex+"]");
|
|
if ( beginIndex >= 0 )
|
|
extractData = data.substring(beginIndex, endIndex);
|
|
else
|
|
extractData = "";
|
|
//System.out.println("extractData="+extractData);
|
|
if ( whiteListData.equals(extractData) ) return true; // whiteList 대상으로 판정
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
}
|