diff --git a/legacy/nlib/.classpath b/legacy/nlib/.classpath new file mode 100644 index 00000000..805d53df --- /dev/null +++ b/legacy/nlib/.classpath @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/legacy/nlib/.gitignore b/legacy/nlib/.gitignore new file mode 100644 index 00000000..f1041d03 --- /dev/null +++ b/legacy/nlib/.gitignore @@ -0,0 +1,120 @@ + +# Created by https://www.toptal.com/developers/gitignore/api/java,windows,eclipse +# Edit at https://www.toptal.com/developers/gitignore?templates=java,windows,eclipse + +### Eclipse ### +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +.settings/ +.settings/* +.loadpath +.recommenders +target/ +build/ + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ +.apt_generated_test/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +# Uncomment this line if you wish to ignore the project description file. +# Typically, this file would be tracked if it contains build/dependency configurations: +#.project + +### Eclipse Patch ### +# Spring Boot Tooling +.sts4-cache/ + +### Java ### +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.toptal.com/developers/gitignore/api/java,windows,eclipse + +### nLib ### +!RESTfulAPI.server/**/* +!RESTfulAPI.server/bin/* +!src/main/webapp/WEB-INF/lib/*.* diff --git a/legacy/nlib/.project b/legacy/nlib/.project new file mode 100644 index 00000000..7d7d83c3 --- /dev/null +++ b/legacy/nlib/.project @@ -0,0 +1,49 @@ + + + nlib + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + org.springframework.ide.eclipse.core.springbuilder + + + + + org.springframework.ide.eclipse.boot.validation.springbootbuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.jdt.core.javanature + org.springframework.ide.eclipse.core.springnature + egovframework.dev.imp.ide.natures.egovnature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/legacy/nlib/data/.gitignore b/legacy/nlib/data/.gitignore new file mode 100644 index 00000000..24a5a6b8 --- /dev/null +++ b/legacy/nlib/data/.gitignore @@ -0,0 +1 @@ +/fileupload/ diff --git a/legacy/nlib/data/fileupload/bbs/qna/.gitignore b/legacy/nlib/data/fileupload/bbs/qna/.gitignore new file mode 100644 index 00000000..33662f55 --- /dev/null +++ b/legacy/nlib/data/fileupload/bbs/qna/.gitignore @@ -0,0 +1 @@ +/* diff --git a/legacy/nlib/pom.xml b/legacy/nlib/pom.xml new file mode 100644 index 00000000..1bc8bf0c --- /dev/null +++ b/legacy/nlib/pom.xml @@ -0,0 +1,636 @@ + + + 4.0.0 + nlib + nlib + war + 1.0.0 + nlib + http://www.egovframe.go.kr + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + 4.3.16.RELEASE + 3.8.0 + 4.2.5.RELEASE + 1.7.2 + 2.15.0 + + + + + mvn2 + http://repo1.maven.org/maven2/ + + true + + + true + + + + egovframe + http://www.egovframe.go.kr/maven/ + + true + + + false + + + + egovframe2 + http://maven.egovframe.kr:8080/maven/ + + true + + + false + + + + + + + + egovframework.rte + egovframework.rte.ptl.mvc + ${egovframework.rte.version} + + + commons-logging + commons-logging + + + + + egovframework.rte + egovframework.rte.psl.dataaccess + ${egovframework.rte.version} + + + egovframework.rte + egovframework.rte.fdl.idgnr + ${egovframework.rte.version} + + + egovframework.rte + egovframework.rte.fdl.property + ${egovframework.rte.version} + + + egovframework.rte + egovframework.rte.fdl.security + ${egovframework.rte.version} + + + + javax.servlet + servlet-api + provided + 2.5 + + + + javax.servlet + jstl + 1.2 + + + + taglibs + standard + 1.1.2 + + + + org.antlr + antlr + 3.5 + + + + commons-codec + commons-codec + 1.9 + + + + egovframework.rte + egovframework.rte.fdl.crypto + ${egovframework.rte.version} + + + + org.apache.poi + poi + 5.0.0 + + + org.apache.poi + poi-ooxml + 3.9 + + + commons-httpclient + commons-httpclient + 3.1 + + + + org.springframework + spring-core + ${spring.maven.artifact.version} + + + + org.springframework + spring-expression + ${spring.maven.artifact.version} + + + + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.slf4j + jcl-over-slf4j + ${slf4j.version} + runtime + + + org.slf4j + slf4j-log4j12 + ${slf4j.version} + runtime + + + org.apache.logging.log4j + log4j-core + ${log4j.version} + + + + + commons-fileupload + commons-fileupload + 1.3.1 + + + + + + + org.springframework.webflow + spring-faces + 2.4.1.RELEASE + + + org.springframework.security + spring-security-web + ${spring-security.version} + + + org.springframework.security + spring-security-core + ${spring-security.version} + + + org.springframework.security + spring-security-config + ${spring-security.version} + + + org.springframework.security + spring-security-taglibs + ${spring-security.version} + + + + + com.ibm.icu + icu4j + 53.1 + + + + + + org.jasypt + jasypt-spring3 + 1.9.2 + + + + com.googlecode.json-simple + json-simple + 1.1.1 + + + + org.apache.httpcomponents + httpcore + 4.4.6 + + + org.apache.httpcomponents + httpclient + 4.5.3 + + + + com.google.zxing + core + 3.3.0 + + + com.google.zxing + javase + 3.3.0 + + + + + org.apache.tiles + tiles-extras + 3.0.8 + + + org.apache.tiles + tiles-servlet + 3.0.8 + + + org.apache.tiles + tiles-jsp + 3.0.8 + + + + + com.fasterxml.jackson.core + jackson-core + 2.12.1 + + + com.fasterxml.jackson.core + jackson-annotations + 2.12.1 + + + com.fasterxml.jackson.core + jackson-databind + 2.12.1 + + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + 2.12.1 + + + + + org.springframework + spring-jdbc + ${spring.maven.artifact.version} + + + org.mariadb.jdbc + mariadb-java-client + 2.2.5 + + + commons-dbcp + commons-dbcp + 1.4 + + + org.lazyluke + log4jdbc-remix + 0.2.7 + + + org.projectlombok + lombok + 1.18.20 + provided + + + + + com.google.code.gson + gson + 2.8.7 + + + org.json + json + 20201115 + + + + + com.github.scribejava + scribejava-apis + + 8.3.1 + + + + + com.github.scribejava + scribejava-core + 8.3.1 + + + + org.springframework.social + spring-social-core + 1.1.4.RELEASE + + + org.springframework.social + spring-social-web + 1.1.4.RELEASE + + + org.apache.commons + commons-lang3 + 3.3.2 + + + + + com.googlecode.owasp-java-html-sanitizer + owasp-java-html-sanitizer + 20211018.2 + + + + + + install + ${basedir}/target + ${artifactId}-${version} + + + + org.apache.tomcat.maven + tomcat7-maven-plugin + 2.2 + + 80 + / + + -Xms256m -Xmx768m -XX:MaxPermSize=256m + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + UTF-8 + + + + org.codehaus.mojo + hibernate3-maven-plugin + 2.1 + + + + hbm2ddl + annotationconfiguration + + + + + + org.hsqldb + hsqldb + 2.3.2 + + + + + + org.codehaus.mojo + emma-maven-plugin + 1.0-alpha-3 + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.1 + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + once + xml + + **/Abstract*.java + **/*Suite.java + + + **/*Test.java + + + + + org.codehaus.mojo + emma-maven-plugin + true + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + + + ${basedir}/target/site + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.7 + + + sunlink + + javadoc + + true + + + http://docs.oracle.com/javase/6/docs/api/ + + + + + + + + org.codehaus.mojo + emma-maven-plugin + true + + + org.codehaus.mojo + surefire-report-maven-plugin + true + + + + report-only + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + 128m + 512m + ${encoding} + ${encoding} + ${encoding} + + + + + org.apache.maven.plugins + maven-jxr-plugin + + ${encoding} + ${encoding} + true + apidocs + + + + + + + + + + + opr + + opr + nlibhome + + + ${profile.final.name} + + + org.apache.maven.plugins + maven-war-plugin + 2.4 + + + + + + css/, favicon/, fonts/, images/, js/, index.html + + + + + maven-antrun-plugin + + + test + + run + + + + + + + + + + + + + + + + + + + + + + + maven-assembly-plugin + 2.2-beta-5 + + + + src/main/assembly/static-contents.xml + + + + + make-assembly + package + + single + + + + + + + + + + diff --git a/legacy/nlib/src/main/assembly/static-contents.xml b/legacy/nlib/src/main/assembly/static-contents.xml new file mode 100644 index 00000000..5797bd1c --- /dev/null +++ b/legacy/nlib/src/main/assembly/static-contents.xml @@ -0,0 +1,24 @@ + + static + / + + zip + + + + ${project.basedir}/target/${profile.final.name}/ + / + + css/** + favicon/** + fonts/** + images/** + js/** + index.html + + true + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/ComDefaultCodeVO.java b/legacy/nlib/src/main/java/egovframework/com/cmm/ComDefaultCodeVO.java new file mode 100644 index 00000000..04e5518a --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/ComDefaultCodeVO.java @@ -0,0 +1,185 @@ +package egovframework.com.cmm; + +import java.io.Serializable; + +import org.apache.commons.lang3.builder.ToStringBuilder; + +/** + * 클래스 + * @author 공통서비스개발팀 이삼섭 + * @since 2009.06.01 + * @version 1.0 + * @see + * + *
+ * << 개정이력(Modification Information) >>
+ *   
+ *   수정일      수정자           수정내용
+ *  -------       --------    ---------------------------
+ *   2009.3.11   이삼섭          최초 생성
+ *
+ * 
+ */ +@SuppressWarnings("serial") +public class ComDefaultCodeVO implements Serializable { + /** 코드 ID */ + private String codeId = ""; + + /** 상세코드 */ + private String code = ""; + + /** 코드명 */ + private String codeNm = ""; + + /** 코드설명 */ + private String codeDc = ""; + + /** 특정테이블명 */ + private String tableNm = ""; //특정테이블에서 코드정보를추출시 사용 + + /** 상세 조건 여부 */ + private String haveDetailCondition = "N"; + + /** 상세 조건 */ + private String detailCondition = ""; + + /** + * codeId attribute를 리턴한다. + * + * @return the codeId + */ + public String getCodeId() { + return codeId; + } + + /** + * codeId attribute 값을 설정한다. + * + * @param codeId + * the codeId to set + */ + public void setCodeId(String codeId) { + this.codeId = codeId; + } + + /** + * code attribute를 리턴한다. + * + * @return the code + */ + public String getCode() { + return code; + } + + /** + * code attribute 값을 설정한다. + * + * @param code + * the code to set + */ + public void setCode(String code) { + this.code = code; + } + + /** + * codeNm attribute를 리턴한다. + * + * @return the codeNm + */ + public String getCodeNm() { + return codeNm; + } + + /** + * codeNm attribute 값을 설정한다. + * + * @param codeNm + * the codeNm to set + */ + public void setCodeNm(String codeNm) { + this.codeNm = codeNm; + } + + /** + * codeDc attribute를 리턴한다. + * + * @return the codeDc + */ + public String getCodeDc() { + return codeDc; + } + + /** + * codeDc attribute 값을 설정한다. + * + * @param codeDc + * the codeDc to set + */ + public void setCodeDc(String codeDc) { + this.codeDc = codeDc; + } + + /** + * tableNm attribute를 리턴한다. + * + * @return the tableNm + */ + public String getTableNm() { + return tableNm; + } + + /** + * tableNm attribute 값을 설정한다. + * + * @param tableNm + * the tableNm to set + */ + public void setTableNm(String tableNm) { + this.tableNm = tableNm; + } + + /** + * haveDetailCondition attribute를 리턴한다. + * + * @return the haveDetailCondition + */ + public String getHaveDetailCondition() { + return haveDetailCondition; + } + + /** + * haveDetailCondition attribute 값을 설정한다. + * + * @param haveDetailCondition + * the haveDetailCondition to set + */ + public void setHaveDetailCondition(String haveDetailCondition) { + this.haveDetailCondition = haveDetailCondition; + } + + /** + * detailCondition attribute를 리턴한다. + * + * @return the detailCondition + */ + public String getDetailCondition() { + return detailCondition; + } + + /** + * detailCondition attribute 값을 설정한다. + * + * @param detailCondition + * the detailCondition to set + */ + public void setDetailCondition(String detailCondition) { + this.detailCondition = detailCondition; + } + + /** + * toString 메소드를 대치한다. + */ + public String toString() { + return ToStringBuilder.reflectionToString(this); + } +} diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/EgovComExcepHndlr.java b/legacy/nlib/src/main/java/egovframework/com/cmm/EgovComExcepHndlr.java new file mode 100644 index 00000000..77c9c8b7 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/EgovComExcepHndlr.java @@ -0,0 +1,52 @@ +/* + * Copyright 2008-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package egovframework.com.cmm; + +import egovframework.rte.fdl.cmmn.exception.handler.ExceptionHandler; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @Class Name : EgovSampleExcepHndlr.java + * @Description : EgovSampleExcepHndlr Class + * @Modification Information + * @ + * @ 수정일 수정자 수정내용 + * @ --------- --------- ------------------------------- + * @ 2009.03.16 최초생성 + * + * @author 개발프레임웍크 실행환경 개발팀 + * @since 2009. 03.16 + * @version 1.0 + * @see + * + * Copyright (C) by MOPAS All right reserved. + */ +public class EgovComExcepHndlr implements ExceptionHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(EgovComExcepHndlr.class); + + /** + * @param ex + * @param packageName + * @see 개발프레임웍크 실행환경 개발팀 + */ + @Override + public void occur(Exception ex, String packageName) { + LOGGER.debug(" EgovServiceExceptionHandler run..............."); + } +} diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/EgovComOthersExcepHndlr.java b/legacy/nlib/src/main/java/egovframework/com/cmm/EgovComOthersExcepHndlr.java new file mode 100644 index 00000000..70c263dd --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/EgovComOthersExcepHndlr.java @@ -0,0 +1,68 @@ +/* + * Copyright 2008-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * Copyright 2008-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package egovframework.com.cmm; + +import egovframework.rte.fdl.cmmn.exception.handler.ExceptionHandler; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @Class Name : EgovSampleOthersExcepHndlr.java + * @Description : EgovSampleOthersExcepHndlr Class + * @Modification Information + * @ + * @ 수정일 수정자 수정내용 + * @ --------- --------- ------------------------------- + * @ 2009.03.16 최초생성 + * + * @author 개발프레임웍크 실행환경 개발팀 + * @since 2009. 03.16 + * @version 1.0 + * @see + * + * Copyright (C) by MOPAS All right reserved. + */ +public class EgovComOthersExcepHndlr implements ExceptionHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(EgovComOthersExcepHndlr.class); + + /** + * @param exception + * @param packageName + * @see 개발프레임웍크 실행환경 개발팀 + */ + @Override + public void occur(Exception exception, String packageName) { + LOGGER.debug(" EgovServiceExceptionHandler run..............."); + } + +} diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/EgovMessageSource.java b/legacy/nlib/src/main/java/egovframework/com/cmm/EgovMessageSource.java new file mode 100644 index 00000000..77e3d311 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/EgovMessageSource.java @@ -0,0 +1,87 @@ +package egovframework.com.cmm; + +import java.util.Locale; + +import org.springframework.context.MessageSource; +import org.springframework.context.support.ReloadableResourceBundleMessageSource; + +/** + * 메시지 리소스 사용을 위한 MessageSource 인터페이스 및 ReloadableResourceBundleMessageSource 클래스의 구현체 + * @author 공통서비스 개발팀 이문준 + * @since 2009.06.01 + * @version 1.0 + * @see + * + *
+ * << 개정이력(Modification Information) >>
+ *   
+ *   수정일      수정자           수정내용
+ *  -------    --------    ---------------------------
+ *   2009.03.11  이문준          최초 생성
+ *   2017.07.21  장동한 			args, locale 설정
+ *
+ * 
+ */ + +public class EgovMessageSource extends ReloadableResourceBundleMessageSource implements MessageSource { + + private ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource; + + /** + * getReloadableResourceBundleMessageSource() + * @param reloadableResourceBundleMessageSource - resource MessageSource + * @return ReloadableResourceBundleMessageSource + */ + public void setReloadableResourceBundleMessageSource(ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource) { + this.reloadableResourceBundleMessageSource = reloadableResourceBundleMessageSource; + } + + /** + * getReloadableResourceBundleMessageSource() + * @return ReloadableResourceBundleMessageSource + */ + public ReloadableResourceBundleMessageSource getReloadableResourceBundleMessageSource() { + return reloadableResourceBundleMessageSource; + } + + /** + * 정의된 메세지 조회 + * @param code - 메세지 코드 + * @return String + */ + public String getMessage(String code) { + return getReloadableResourceBundleMessageSource().getMessage(code, null, Locale.getDefault()); + } + + /** + * 정의된 메세지 조회 + * @param code - 메세지 코드 + * @param locale - 로케일 + * @return String + */ + public String getMessage(String code, Locale locale) { + return getReloadableResourceBundleMessageSource().getMessage(code, null, locale); + } + + /** + * 정의된 메세지 조회 + * @param code - 메세지 코드 + * @param args - 매개변수 + * @return String + */ + public String getMessageArgs(String code, Object[] args) { + return getReloadableResourceBundleMessageSource().getMessage(code, args, Locale.getDefault()); + } + + /** + * 정의된 메세지 조회 + * @param code - 메세지 코드 + * @param args - 매개변수 + * @param locale - 로케일 + * @return String + */ + public String getMessageArgsLocale(String code, Object[] args, Locale locale) { + return getReloadableResourceBundleMessageSource().getMessage(code, args, locale); + } + +} diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/EgovWebUtil.java b/legacy/nlib/src/main/java/egovframework/com/cmm/EgovWebUtil.java new file mode 100644 index 00000000..ea31a084 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/EgovWebUtil.java @@ -0,0 +1,125 @@ +package egovframework.com.cmm; + +import java.util.regex.Pattern; + +/** + * 교차접속 스크립트 공격 취약성 방지(파라미터 문자열 교체) + * + *
+ * << 개정이력(Modification Information) >>
+ *
+ *   수정일              수정자           수정내용
+ *  -----------  --------  ---------------------------
+ *   2011.10.10  한성곤           최초 생성
+ *	 2017-02-07   이정은           시큐어코딩(ES) - 시큐어코딩 경로 조작 및 자원 삽입[CWE-22, CWE-23, CWE-95, CWE-99]
+ *   2018.08.17  신용호           filePathBlackList 수정
+ *   2018.10.10  신용호           . => \\.으로 수정
+ * 
+ */ + +public class EgovWebUtil { + public static String clearXSSMinimum(String value) { + if (value == null || value.trim().equals("")) { + return ""; + } + + String returnValue = value; + + returnValue = returnValue.replaceAll("&", "&"); + returnValue = returnValue.replaceAll("<", "<"); + returnValue = returnValue.replaceAll(">", ">"); + returnValue = returnValue.replaceAll("\"", """); + returnValue = returnValue.replaceAll("\'", "'"); + returnValue = returnValue.replaceAll("\\.", "."); + returnValue = returnValue.replaceAll("%2E", "."); + returnValue = returnValue.replaceAll("%2F", "/"); + return returnValue; + } + + public static String clearXSSMaximum(String value) { + String returnValue = value; + returnValue = clearXSSMinimum(returnValue); + + returnValue = returnValue.replaceAll("%00", null); + + returnValue = returnValue.replaceAll("%", "%"); + + // \\. => . + + returnValue = returnValue.replaceAll("\\.\\./", ""); // ../ + returnValue = returnValue.replaceAll("\\.\\.\\\\", ""); // ..\ + returnValue = returnValue.replaceAll("\\./", ""); // ./ + returnValue = returnValue.replaceAll("%2F", ""); + + return returnValue; + } + + public static String filePathBlackList(String value) { + String returnValue = value; + if (returnValue == null || returnValue.trim().equals("")) { + return ""; + } + + returnValue = returnValue.replaceAll("\\.\\.", ""); + + return returnValue; + } + + /** + * 행안부 보안취약점 점검 조치 방안. + * + * @param value + * @return + */ + public static String filePathReplaceAll(String value) { + String returnValue = value; + if (returnValue == null || returnValue.trim().equals("")) { + return ""; + } + + returnValue = returnValue.replaceAll("/", ""); + returnValue = returnValue.replaceAll("\\", ""); + returnValue = returnValue.replaceAll("\\.\\.", ""); // .. + returnValue = returnValue.replaceAll("&", ""); + + return returnValue; + } + + public static String fileInjectPathReplaceAll(String value) { + String returnValue = value; + if (returnValue == null || returnValue.trim().equals("")) { + return ""; + } + + + returnValue = returnValue.replaceAll("/", ""); + returnValue = returnValue.replaceAll("\\..", ""); // .. + returnValue = returnValue.replaceAll("\\\\", "");// \ + returnValue = returnValue.replaceAll("&", ""); + + return returnValue; + } + + public static String filePathWhiteList(String value) { + return value; + } + + public static boolean isIPAddress(String str) { + Pattern ipPattern = Pattern.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"); + + return ipPattern.matcher(str).matches(); + } + + public static String removeCRLF(String parameter) { + return parameter.replaceAll("\r", "").replaceAll("\n", ""); + } + + public static String removeSQLInjectionRisk(String parameter) { + return parameter.replaceAll("\\p{Space}", "").replaceAll("\\*", "").replaceAll("%", "").replaceAll(";", "").replaceAll("-", "").replaceAll("\\+", "").replaceAll(",", ""); + } + + public static String removeOSCmdRisk(String parameter) { + return parameter.replaceAll("\\p{Space}", "").replaceAll("\\*", "").replaceAll("|", "").replaceAll(";", ""); + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/NlibLoginSuccessHandler.java b/legacy/nlib/src/main/java/egovframework/com/cmm/NlibLoginSuccessHandler.java new file mode 100644 index 00000000..bcd1848d --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/NlibLoginSuccessHandler.java @@ -0,0 +1,57 @@ +package egovframework.com.cmm; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; + +import nlib.user.web.LoginController; + +public class NlibLoginSuccessHandler implements AuthenticationSuccessHandler { + + private static final Logger log = LoggerFactory.getLogger(LoginController.class); + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, + Authentication authentication) throws IOException, ServletException { + + log.warn("login Test..."); + // 권한을 넣을 리스트를 만듭니다 + List authList = new ArrayList<>(); + + // 디버깅 테스트 + log.debug("getCredential : " + authentication.getCredentials()); + log.debug("principal : " + authentication.getPrincipal()); + log.debug("들어오는 사용자 : " + authentication.getName()); + log.debug("가진 권한 : " + authentication.getAuthorities()); + + // 들어온 사용자의 권한을 authList에 추가 (여러개일 수 있으므로 하나씩 담음.) + authentication.getAuthorities().forEach(auth -> { + authList.add(auth.getAuthority()); + }); + + // 관리자 일 경우 + if (authList.contains("ROLE_ADMIN")) { + log.debug("관리자 입니다."); + response.sendRedirect("/login/admin.do"); + return; + } + // 회원가입한 사용자일 경우. + if (authList.contains("ROLE_MEMBER")) { + log.warn("회원가입된 사용자 입니다."); + response.sendRedirect("/login/member.do"); + return; + } + // 실패했을 경우 그대로 loginPage.jsp로 돌아갑니다. + response.sendRedirect("/"); + } + +} diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/service/CmmnDetailCode.java b/legacy/nlib/src/main/java/egovframework/com/cmm/service/CmmnDetailCode.java new file mode 100644 index 00000000..7d16307e --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/service/CmmnDetailCode.java @@ -0,0 +1,217 @@ +package egovframework.com.cmm.service; + +import java.io.Serializable; + +/** + * 공통상세코드 모델 클래스 + * @author 공통서비스 개발팀 이중호 + * @since 2009.04.01 + * @version 1.0 + * @see + * + *
+ * << 개정이력(Modification Information) >>
+ *
+ *   수정일      수정자           수정내용
+ *  -------    --------    ---------------------------
+ *   2009.04.01  이중호          최초 생성
+ *   2017.09.07	이정은		표준프레임워크 v3.7 개선(clCode 추가)
+ *
+ * 
+ */ +public class CmmnDetailCode implements Serializable { + + private static final long serialVersionUID = 1L; + + /* + * 분류코드 + */ + private String clCode = ""; + + /* + * 코드ID + */ + private String codeId = ""; + + /* + * 코드ID명 + */ + private String codeIdNm = ""; + + /* + * 상세코드 + */ + private String code = ""; + + /* + * 상세코드명 + */ + private String codeNm = ""; + + /* + * 상세코드설명 + */ + private String codeDc = ""; + + /* + * 사용여부 + */ + private String useAt = ""; + + /* + * 최초등록자ID + */ + private String frstRegisterId = ""; + + /* + * 최종수정자ID + */ + private String lastUpdusrId = ""; + + + /** + * clCode attribute 를 리턴한다. + * @return String + */ + public String getClCode() { + return clCode; + } + + /** + * clCode attribute 값을 설정한다. + * @param clCode String + */ + public void setClCode(String clCode) { + this.clCode = clCode; + } + + /** + * codeId attribute 를 리턴한다. + * @return String + */ + public String getCodeId() { + return codeId; + } + + /** + * codeId attribute 값을 설정한다. + * @param codeId String + */ + public void setCodeId(String codeId) { + this.codeId = codeId; + } + + /** + * codeIdNm attribute 를 리턴한다. + * @return String + */ + public String getCodeIdNm() { + return codeIdNm; + } + + /** + * codeIdNm attribute 값을 설정한다. + * @param codeIdNm String + */ + public void setCodeIdNm(String codeIdNm) { + this.codeIdNm = codeIdNm; + } + + /** + * code attribute 를 리턴한다. + * @return String + */ + public String getCode() { + return code; + } + + /** + * code attribute 값을 설정한다. + * @param code String + */ + public void setCode(String code) { + this.code = code; + } + + /** + * codeNm attribute 를 리턴한다. + * @return String + */ + public String getCodeNm() { + return codeNm; + } + + /** + * codeNm attribute 값을 설정한다. + * @param codeNm String + */ + public void setCodeNm(String codeNm) { + this.codeNm = codeNm; + } + + /** + * codeDc attribute 를 리턴한다. + * @return String + */ + public String getCodeDc() { + return codeDc; + } + + /** + * codeDc attribute 값을 설정한다. + * @param codeDc String + */ + public void setCodeDc(String codeDc) { + this.codeDc = codeDc; + } + + /** + * useAt attribute 를 리턴한다. + * @return String + */ + public String getUseAt() { + return useAt; + } + + /** + * useAt attribute 값을 설정한다. + * @param useAt String + */ + public void setUseAt(String useAt) { + this.useAt = useAt; + } + + /** + * frstRegisterId attribute 를 리턴한다. + * @return String + */ + public String getFrstRegisterId() { + return frstRegisterId; + } + + /** + * frstRegisterId attribute 값을 설정한다. + * @param frstRegisterId String + */ + public void setFrstRegisterId(String frstRegisterId) { + this.frstRegisterId = frstRegisterId; + } + + /** + * lastUpdusrId attribute 를 리턴한다. + * @return String + */ + public String getLastUpdusrId() { + return lastUpdusrId; + } + + /** + * lastUpdusrId attribute 값을 설정한다. + * @param lastUpdusrId String + */ + public void setLastUpdusrId(String lastUpdusrId) { + this.lastUpdusrId = lastUpdusrId; + } + + +} diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/service/EgovCmmUseService.java b/legacy/nlib/src/main/java/egovframework/com/cmm/service/EgovCmmUseService.java new file mode 100644 index 00000000..54a0d032 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/service/EgovCmmUseService.java @@ -0,0 +1,64 @@ +package egovframework.com.cmm.service; + +import java.util.List; +import java.util.Map; + +import egovframework.com.cmm.ComDefaultCodeVO; + + + +/** + * + * 공통코드등 전체 업무에서 공용해서 사용해야 하는 서비스를 정의하기 위한 서비스 인터페이스 + * @author 공통서비스 개발팀 이삼섭 + * @since 2009.04.01 + * @version 1.0 + * @see + * + *
+ * << 개정이력(Modification Information) >>
+ *
+ *   수정일      수정자           수정내용
+ *  -------    --------    ---------------------------
+ *   2009.03.11  이삼섭          최초 생성
+ *
+ * 
+ */ +public interface EgovCmmUseService { + + /** + * 공통코드를 조회한다. + * + * @param vo + * @return List(코드) + * @throws Exception + */ + public List selectCmmCodeDetail(ComDefaultCodeVO vo) throws Exception; + + /** + * ComDefaultCodeVO의 리스트를 받아서 여러개의 코드 리스트를 맵에 담아서 리턴한다. + * + * @param voList + * @return Map(코드) + * @throws Exception + */ + public Map> selectCmmCodeDetails(List voList) throws Exception; + + /** + * 조직정보를 코드형태로 리턴한다. + * + * @param 조회조건정보 vo + * @return 조직정보 List + * @throws Exception + */ + public List selectOgrnztIdDetail(ComDefaultCodeVO vo) throws Exception; + + /** + * 그룹정보를 코드형태로 리턴한다. + * + * @param 조회조건정보 vo + * @return 그룹정보 List + * @throws Exception + */ + public List selectGroupIdDetail(ComDefaultCodeVO vo) throws Exception; +} diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/service/EgovProperties.java b/legacy/nlib/src/main/java/egovframework/com/cmm/service/EgovProperties.java new file mode 100644 index 00000000..56b208da --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/service/EgovProperties.java @@ -0,0 +1,222 @@ +package egovframework.com.cmm.service; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import egovframework.com.cmm.EgovWebUtil; +import egovframework.com.cmm.util.EgovResourceCloseHelper; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class Name : EgovProperties.java + * Description : properties값들을 파일로부터 읽어와 Globals클래스의 정적변수로 로드시켜주는 클래스로 + * 문자열 정보 기준으로 사용할 전역변수를 시스템 재시작으로 반영할 수 있도록 한다. + * Modification Information + * + * 수정일 수정자 수정내용 + * ---------- -------- --------------------------- + * 2009.01.19 박지욱 최초 생성 + * 2011.07.20 서준식 Globals파일의 상대경로를 읽은 메서드 추가 + * 2014.10.13 이기하 Globals.properties 값이 null일 경우 오류처리 + * 2019.04.26 신용호 RELATIVE_PATH_PREFIX Path 적용 방식 개선 + * @author 공통 서비스 개발팀 박지욱 + * @since 2009. 01. 19 + * @version 1.0 + * @see + * + */ + +public class EgovProperties { + + private static final Logger LOGGER = LoggerFactory.getLogger(EgovProperties.class); + + //파일구분자 + final static String FILE_SEPARATOR = System.getProperty("file.separator"); + + //프로퍼티 파일의 물리적 위치 + //public static final String GLOBALS_PROPERTIES_FILE = System.getProperty("user.home") + FILE_SEPARATOR + "egovProps" +FILE_SEPARATOR + "globals.properties"; + + public static final String RELATIVE_PATH_PREFIX = EgovProperties.class.getResource("").getPath().substring(0, EgovProperties.class.getResource("").getPath().lastIndexOf("com")); + //public static final String RELATIVE_PATH_PREFIX = EgovProperties.class.getProtectionDomain().getCodeSource().getLocation().getPath().substring(0,EgovProperties.class.getProtectionDomain().getCodeSource().getLocation().getPath().indexOf("WEB-INF/classes/")+"WEB-INF/classes/".length())+"egovframework/"; + + public static final String GLOBALS_PROPERTIES_FILE = RELATIVE_PATH_PREFIX + "egovProps" + FILE_SEPARATOR + "globals.properties"; + + /** + * 인자로 주어진 문자열을 Key값으로 하는 상대경로 프로퍼티 값을 절대경로로 반환한다(Globals.java 전용) + * @param keyName String + * @return String + */ + public static String getPathProperty(String keyName) { + String value = ""; + + LOGGER.debug("getPathProperty : {} = {}", GLOBALS_PROPERTIES_FILE, keyName); + + FileInputStream fis = null; + try { + Properties props = new Properties(); + + fis = new FileInputStream(EgovWebUtil.filePathBlackList(GLOBALS_PROPERTIES_FILE)); + props.load(new BufferedInputStream(fis)); + + value = props.getProperty(keyName); + value = (value == null) ? "" : value.trim();//KISA 보안약점 조치 (2018-10-29, 윤창원) + value = RELATIVE_PATH_PREFIX + "egovProps" + System.getProperty("file.separator") + value; + } catch (FileNotFoundException fne) { + LOGGER.debug("Property file not found.", fne); + throw new RuntimeException("Property file not found", fne); + } catch (IOException ioe) { + LOGGER.debug("Property file IO exception", ioe); + throw new RuntimeException("Property file IO exception", ioe); + } finally { + EgovResourceCloseHelper.close(fis); + } + + return value; + } + + /** + * 인자로 주어진 문자열을 Key값으로 하는 프로퍼티 값을 반환한다(Globals.java 전용) + * @param keyName String + * @return String + */ + public static String getProperty(String keyName) { + String value = ""; + + LOGGER.debug("===>>> getProperty"+EgovProperties.class.getProtectionDomain().getCodeSource().getLocation().getPath()); + LOGGER.debug("getProperty : {} = {}", GLOBALS_PROPERTIES_FILE, keyName); + + FileInputStream fis = null; + try { + Properties props = new Properties(); + + fis = new FileInputStream(EgovWebUtil.filePathBlackList(GLOBALS_PROPERTIES_FILE)); + + props.load(new BufferedInputStream(fis)); + if (props.getProperty(keyName) == null) { + return ""; + } + value = props.getProperty(keyName).trim(); + } catch (FileNotFoundException fne) { + LOGGER.debug("Property file not found.", fne); + throw new RuntimeException("Property file not found", fne); + } catch (IOException ioe) { + LOGGER.debug("Property file IO exception", ioe); + throw new RuntimeException("Property file IO exception", ioe); + } finally { + EgovResourceCloseHelper.close(fis); + } + + return value; + } + + /** + * 주어진 파일에서 인자로 주어진 문자열을 Key값으로 하는 프로퍼티 상대 경로값을 절대 경로값으로 반환한다 + * @param fileName String + * @param key String + * @return String + */ + public static String getPathProperty(String fileName, String key) { + FileInputStream fis = null; + try { + Properties props = new Properties(); + + fis = new FileInputStream(EgovWebUtil.filePathBlackList(fileName)); + props.load(new BufferedInputStream(fis)); + fis.close(); + + String value = props.getProperty(key); + value = RELATIVE_PATH_PREFIX + "egovProps" + System.getProperty("file.separator") + value; + + return value; + } catch (FileNotFoundException fne) { + LOGGER.debug("Property file not found.", fne); + throw new RuntimeException("Property file not found", fne); + } catch (IOException ioe) { + LOGGER.debug("Property file IO exception", ioe); + throw new RuntimeException("Property file IO exception", ioe); + } finally { + EgovResourceCloseHelper.close(fis); + } + } + + /** + * 주어진 파일에서 인자로 주어진 문자열을 Key값으로 하는 프로퍼티 값을 반환한다 + * @param fileName String + * @param key String + * @return String + */ + public static String getProperty(String fileName, String key) { + FileInputStream fis = null; + try { + Properties props = new Properties(); + + fis = new FileInputStream(EgovWebUtil.filePathBlackList(fileName)); + props.load(new BufferedInputStream(fis)); + fis.close(); + + String value = props.getProperty(key); + + return value; + } catch (FileNotFoundException fne) { + LOGGER.debug("Property file not found.", fne); + throw new RuntimeException("Property file not found", fne); + } catch (IOException ioe) { + LOGGER.debug("Property file IO exception", ioe); + throw new RuntimeException("Property file IO exception", ioe); + } finally { + EgovResourceCloseHelper.close(fis); + } + } + + /** + * 주어진 프로파일의 내용을 파싱하여 (key-value) 형태의 구조체 배열을 반환한다. + * @param property String + * @return ArrayList + */ + public static ArrayList> loadPropertyFile(String property) { + + // key - value 형태로 된 배열 결과 + ArrayList> keyList = new ArrayList>(); + + String src = property.replace('\\', File.separatorChar).replace('/', File.separatorChar); + FileInputStream fis = null; + try { + + File srcFile = new File(EgovWebUtil.filePathBlackList(src)); + if (srcFile.exists()) { + + Properties props = new Properties(); + fis = new FileInputStream(src); + props.load(new BufferedInputStream(fis)); + fis.close(); + + Enumeration plist = props.propertyNames(); + if (plist != null) { + while (plist.hasMoreElements()) { + Map map = new HashMap(); + String key = (String) plist.nextElement(); + map.put(key, props.getProperty(key)); + keyList.add(map); + } + } + } + } catch (IOException ex) { + LOGGER.debug("IO Exception", ex); + throw new RuntimeException(ex); + } finally { + EgovResourceCloseHelper.close(fis); + } + + return keyList; + } +} diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/service/EgovUserDetailsService.java b/legacy/nlib/src/main/java/egovframework/com/cmm/service/EgovUserDetailsService.java new file mode 100644 index 00000000..796f5ef5 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/service/EgovUserDetailsService.java @@ -0,0 +1,26 @@ +package egovframework.com.cmm.service; + +import java.util.List; + +public interface EgovUserDetailsService { + + /** + * 인증된 사용자객체를 VO형식으로 가져온다. + * @return Object - 사용자 ValueObject + */ + public Object getAuthenticatedUser(); + + /** + * 인증된 사용자의 권한 정보를 가져온다. + * 예) [ROLE_ADMIN, ROLE_USER, ROLE_A, ROLE_B, ROLE_RESTRICTED, IS_AUTHENTICATED_FULLY, IS_AUTHENTICATED_REMEMBERED, IS_AUTHENTICATED_ANONYMOUSLY] + * @return List - 사용자 권한정보 목록 + */ + public List getAuthorities(); + + /** + * 인증된 사용자 여부를 체크한다. + * @return Boolean - 인증된 사용자 여부(TRUE / FALSE) + */ + public Boolean isAuthenticated(); + +} diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/service/FileVO.java b/legacy/nlib/src/main/java/egovframework/com/cmm/service/FileVO.java new file mode 100644 index 00000000..6f5e0f3f --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/service/FileVO.java @@ -0,0 +1,240 @@ +package egovframework.com.cmm.service; + +import java.io.Serializable; + +import org.apache.commons.lang3.builder.ToStringBuilder; + +/** + * @Class Name : FileVO.java + * @Description : 파일정보 처리를 위한 VO 클래스 + * @Modification Information + * + * 수정일 수정자 수정내용 + * ------- ------- ------------------- + * 2009. 3. 25. 이삼섭 + * + * @author 공통 서비스 개발팀 이삼섭 + * @since 2009. 3. 25. + * @version + * @see + * + */ +@SuppressWarnings("serial") +public class FileVO implements Serializable { + + /** + * 첨부파일 아이디 + */ + public String atchFileId = ""; + /** + * 생성일자 + */ + public String creatDt = ""; + /** + * 파일내용 + */ + public String fileCn = ""; + /** + * 파일확장자 + */ + public String fileExtsn = ""; + /** + * 파일크기 + */ + public String fileMg = ""; + /** + * 파일연번 + */ + public String fileSn = ""; + /** + * 파일저장경로 + */ + public String fileStreCours = ""; + /** + * 원파일명 + */ + public String orignlFileNm = ""; + /** + * 저장파일명 + */ + public String streFileNm = ""; + + /** + * atchFileId attribute를 리턴한다. + * + * @return the atchFileId + */ + public String getAtchFileId() { + return atchFileId; + } + + /** + * atchFileId attribute 값을 설정한다. + * + * @param atchFileId + * the atchFileId to set + */ + public void setAtchFileId(String atchFileId) { + this.atchFileId = atchFileId; + } + + /** + * creatDt attribute를 리턴한다. + * + * @return the creatDt + */ + public String getCreatDt() { + return creatDt; + } + + /** + * creatDt attribute 값을 설정한다. + * + * @param creatDt + * the creatDt to set + */ + public void setCreatDt(String creatDt) { + this.creatDt = creatDt; + } + + /** + * fileCn attribute를 리턴한다. + * + * @return the fileCn + */ + public String getFileCn() { + return fileCn; + } + + /** + * fileCn attribute 값을 설정한다. + * + * @param fileCn + * the fileCn to set + */ + public void setFileCn(String fileCn) { + this.fileCn = fileCn; + } + + /** + * fileExtsn attribute를 리턴한다. + * + * @return the fileExtsn + */ + public String getFileExtsn() { + return fileExtsn; + } + + /** + * fileExtsn attribute 값을 설정한다. + * + * @param fileExtsn + * the fileExtsn to set + */ + public void setFileExtsn(String fileExtsn) { + this.fileExtsn = fileExtsn; + } + + /** + * fileMg attribute를 리턴한다. + * + * @return the fileMg + */ + public String getFileMg() { + return fileMg; + } + + /** + * fileMg attribute 값을 설정한다. + * + * @param fileMg + * the fileMg to set + */ + public void setFileMg(String fileMg) { + this.fileMg = fileMg; + } + + /** + * fileSn attribute를 리턴한다. + * + * @return the fileSn + */ + public String getFileSn() { + return fileSn; + } + + /** + * fileSn attribute 값을 설정한다. + * + * @param fileSn + * the fileSn to set + */ + public void setFileSn(String fileSn) { + this.fileSn = fileSn; + } + + /** + * fileStreCours attribute를 리턴한다. + * + * @return the fileStreCours + */ + public String getFileStreCours() { + return fileStreCours; + } + + /** + * fileStreCours attribute 값을 설정한다. + * + * @param fileStreCours + * the fileStreCours to set + */ + public void setFileStreCours(String fileStreCours) { + this.fileStreCours = fileStreCours; + } + + /** + * orignlFileNm attribute를 리턴한다. + * + * @return the orignlFileNm + */ + public String getOrignlFileNm() { + return orignlFileNm; + } + + /** + * orignlFileNm attribute 값을 설정한다. + * + * @param orignlFileNm + * the orignlFileNm to set + */ + public void setOrignlFileNm(String orignlFileNm) { + this.orignlFileNm = orignlFileNm; + } + + /** + * streFileNm attribute를 리턴한다. + * + * @return the streFileNm + */ + public String getStreFileNm() { + return streFileNm; + } + + /** + * streFileNm attribute 값을 설정한다. + * + * @param streFileNm + * the streFileNm to set + */ + public void setStreFileNm(String streFileNm) { + this.streFileNm = streFileNm; + } + + /** + * toString 메소드를 대치한다. + */ + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + +} diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/service/Globals.java b/legacy/nlib/src/main/java/egovframework/com/cmm/service/Globals.java new file mode 100644 index 00000000..ae7674b1 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/service/Globals.java @@ -0,0 +1,58 @@ +package egovframework.com.cmm.service; + +/** + * Class Name : Globals.java + * Description : 시스템 구동 시 프로퍼티를 통해 사용될 전역변수를 정의한다. + * Modification Information + * + * 수정일 수정자 수정내용 + * ------- -------- --------------------------- + * 2009.01.19 박지욱 최초 생성 + * + * @author 공통 서비스 개발팀 박지욱 + * @since 2009. 01. 19 + * @version 1.0 + * @see + * + */ + +public class Globals { + //OS 유형 + public static final String OS_TYPE = EgovProperties.getProperty("Globals.OsType"); + //DB 유형 + public static final String DB_TYPE = EgovProperties.getProperty("Globals.DbType"); + //메인 페이지 + public static final String MAIN_PAGE = EgovProperties.getProperty("Globals.MainPage"); + //ShellFile 경로 + public static final String SHELL_FILE_PATH = EgovProperties.getPathProperty("Globals.ShellFilePath"); + //퍼로퍼티 파일 위치 + public static final String CONF_PATH = EgovProperties.getPathProperty("Globals.ConfPath"); + //Server정보 프로퍼티 위치 + public static final String SERVER_CONF_PATH = EgovProperties.getPathProperty("Globals.ServerConfPath"); + //Client정보 프로퍼티 위치 + public static final String CLIENT_CONF_PATH = EgovProperties.getPathProperty("Globals.ClientConfPath"); + //파일포맷 정보 프로퍼티 위치 + public static final String FILE_FORMAT_PATH = EgovProperties.getPathProperty("Globals.FileFormatPath"); + + //파일 업로드 원 파일명 + public static final String ORIGIN_FILE_NM = "originalFileName"; + //파일 확장자 + public static final String FILE_EXT = "fileExtension"; + //파일크기 + public static final String FILE_SIZE = "fileSize"; + //업로드된 파일명 + public static final String UPLOAD_FILE_NM = "uploadFileName"; + //파일경로 + public static final String FILE_PATH = "filePath"; + + //메일발송요청 XML파일경로 + public static final String MAIL_REQUEST_PATH = EgovProperties.getPathProperty("Globals.MailRequestPath"); + //메일발송응답 XML파일경로 + public static final String MAIL_RESPONSE_PATH = EgovProperties.getPathProperty("Globals.MailRResponsePath"); + + // G4C 연결용 IP (localhost) + public static final String LOCAL_IP = EgovProperties.getProperty("Globals.LocalIp"); + + + +} diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/service/impl/CmmUseDAO.java b/legacy/nlib/src/main/java/egovframework/com/cmm/service/impl/CmmUseDAO.java new file mode 100644 index 00000000..62a284ce --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/service/impl/CmmUseDAO.java @@ -0,0 +1,62 @@ +package egovframework.com.cmm.service.impl; + +import java.util.List; + +import egovframework.com.cmm.ComDefaultCodeVO; +import egovframework.com.cmm.service.CmmnDetailCode; + +import org.springframework.stereotype.Repository; + +/** + * @Class Name : CmmUseDAO.java + * @Description : 공통코드등 전체 업무에서 공용해서 사용해야 하는 서비스를 정의하기위한 데이터 접근 클래스 + * @Modification Information + * + * 수정일 수정자 수정내용 + * ------- ------- ------------------- + * 2009. 3. 11. 이삼섭 + * + * @author 공통 서비스 개발팀 이삼섭 + * @since 2009. 3. 11. + * @version + * @see + * + */ +@Repository("cmmUseDAO") +public class CmmUseDAO extends EgovComAbstractDAO { + + /** + * 주어진 조건에 따른 공통코드를 불러온다. + * + * @param vo + * @return + * @throws Exception + */ + @SuppressWarnings("unchecked") + public List selectCmmCodeDetail(ComDefaultCodeVO vo) throws Exception { + return (List) list("CmmUseDAO.selectCmmCodeDetail", vo); + } + + /** + * 공통코드로 사용할 조직정보를 를 불러온다. + * + * @param vo + * @return + * @throws Exception + */ + @SuppressWarnings("unchecked") + public List selectOgrnztIdDetail(ComDefaultCodeVO vo) throws Exception { + return (List) list("CmmUseDAO.selectOgrnztIdDetail", vo); + } + + /** + * 공통코드로 사용할그룹정보를 를 불러온다. + * @param vo + * @return + * @throws Exception + */ + @SuppressWarnings("unchecked") + public List selectGroupIdDetail(ComDefaultCodeVO vo) throws Exception { + return (List) list("CmmUseDAO.selectGroupIdDetail", vo); + } +} diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/service/impl/EgovCmmUseServiceImpl.java b/legacy/nlib/src/main/java/egovframework/com/cmm/service/impl/EgovCmmUseServiceImpl.java new file mode 100644 index 00000000..680be705 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/service/impl/EgovCmmUseServiceImpl.java @@ -0,0 +1,91 @@ +package egovframework.com.cmm.service.impl; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import egovframework.com.cmm.ComDefaultCodeVO; +import egovframework.com.cmm.service.CmmnDetailCode; +import egovframework.com.cmm.service.EgovCmmUseService; + +import egovframework.rte.fdl.cmmn.EgovAbstractServiceImpl; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Service; + +/** + * @Class Name : EgovCmmUseServiceImpl.java + * @Description : 공통코드등 전체 업무에서 공용해서 사용해야 하는 서비스를 정의하기위한 서비스 구현 클래스 + * @Modification Information + * + * 수정일 수정자 수정내용 + * ------- ------- ------------------- + * 2009. 3. 11. 이삼섭 + * + * @author 공통 서비스 개발팀 이삼섭 + * @since 2009. 3. 11. + * @version + * @see + * + */ +@Service("EgovCmmUseService") +public class EgovCmmUseServiceImpl extends EgovAbstractServiceImpl implements EgovCmmUseService { + + @Resource(name = "cmmUseDAO") + private CmmUseDAO cmmUseDAO; + + /** + * 공통코드를 조회한다. + * + * @param vo + * @return + * @throws Exception + */ + public List selectCmmCodeDetail(ComDefaultCodeVO vo) throws Exception { + return cmmUseDAO.selectCmmCodeDetail(vo); + } + + /** + * ComDefaultCodeVO의 리스트를 받아서 여러개의 코드 리스트를 맵에 담아서 리턴한다. + * + * @param voList + * @return + * @throws Exception + */ + public Map> selectCmmCodeDetails(List voList) throws Exception { + ComDefaultCodeVO vo; + Map> map = new HashMap>(); + + Iterator iter = voList.iterator(); + while (iter.hasNext()) { + vo = (ComDefaultCodeVO)iter.next(); + map.put(vo.getCodeId(), cmmUseDAO.selectCmmCodeDetail(vo)); + } + + return map; + } + + /** + * 조직정보를 코드형태로 리턴한다. + * + * @param 조회조건정보 vo + * @return 조직정보 List + * @throws Exception + */ + public List selectOgrnztIdDetail(ComDefaultCodeVO vo) throws Exception { + return cmmUseDAO.selectOgrnztIdDetail(vo); + } + + /** + * 그룹정보를 코드형태로 리턴한다. + * + * @param 조회조건정보 vo + * @return 그룹정보 List + * @throws Exception + */ + public List selectGroupIdDetail(ComDefaultCodeVO vo) throws Exception { + return cmmUseDAO.selectGroupIdDetail(vo); + } +} diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/service/impl/EgovComAbstractDAO.java b/legacy/nlib/src/main/java/egovframework/com/cmm/service/impl/EgovComAbstractDAO.java new file mode 100644 index 00000000..882fe135 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/service/impl/EgovComAbstractDAO.java @@ -0,0 +1,306 @@ +/** + * + */ +package egovframework.com.cmm.service.impl; + +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.RowBounds; +import org.apache.ibatis.session.SqlSessionFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import egovframework.rte.psl.dataaccess.EgovAbstractMapper; +/** + * EgovComAbstractDAO.java 클래스 + * + * @author 서준식 + * @since 2011. 9. 23. + * @version 1.0 + * @see + * + *
+ * << 개정이력(Modification Information) >>
+ *
+ *   수정일      수정자           수정내용
+ *  -------    -------------    ----------------------
+ *   2011. 9. 23.   서준식        최초 생성
+ *   2016. 5. 11.   장동한        myBatis 방식 적용
+ * 
+ */ +public abstract class EgovComAbstractDAO extends EgovAbstractMapper{ + + private final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); + + @Resource(name="egov.sqlSession") + public void setSqlSessionFactory(SqlSessionFactory sqlSession) { + super.setSqlSessionFactory(sqlSession); + } + + /** + * 입력 처리 SQL mapping 을 실행한다. + * + * @param queryId - 입력 처리 SQL mapping 쿼리 ID + * + * @return DBMS가 지원하는 경우 insert 적용 결과 count + */ + @Override + public int insert(String queryId) { + LOGGER.debug("queryId = "+queryId); + return getSqlSession().insert(queryId); + } + + /** + * 입력 처리 SQL mapping 을 실행한다. + * + * @param queryId - 입력 처리 SQL mapping 쿼리 ID + * @param parameterObject - 입력 처리 SQL mapping 입력 데이터를 세팅한 파라메터 객체(보통 VO 또는 Map) + * + * @return DBMS가 지원하는 경우 insert 적용 결과 count + */ + @Override + public int insert(String queryId, Object parameterObject) { + LOGGER.debug("queryId = "+queryId); + return getSqlSession().insert(queryId, parameterObject); + } + + /** + * 수정 처리 SQL mapping 을 실행한다. + * + * @param queryId - 수정 처리 SQL mapping 쿼리 ID + * + * @return DBMS가 지원하는 경우 update 적용 결과 count + */ + @Override + public int update(String queryId) { + LOGGER.debug("queryId = "+queryId); + return getSqlSession().update(queryId); + } + + /** + * 수정 처리 SQL mapping 을 실행한다. + * + * @param queryId - 수정 처리 SQL mapping 쿼리 ID + * @param parameterObject - 수정 처리 SQL mapping 입력 데이터(key 조건 및 변경 데이터)를 세팅한 파라메터 객체(보통 VO 또는 Map) + * + * @return DBMS가 지원하는 경우 update 적용 결과 count + */ + @Override + public int update(String queryId, Object parameterObject) { + LOGGER.debug("queryId = "+queryId); + return getSqlSession().update(queryId, parameterObject); + } + + /** + * 삭제 처리 SQL mapping 을 실행한다. + * + * @param queryId - 삭제 처리 SQL mapping 쿼리 ID + * + * @return DBMS가 지원하는 경우 delete 적용 결과 count + */ + @Override + public int delete(String queryId) { + LOGGER.debug("queryId = "+queryId); + return getSqlSession().delete(queryId); + } + + /** + * 삭제 처리 SQL mapping 을 실행한다. + * + * @param queryId - 삭제 처리 SQL mapping 쿼리 ID + * @param parameterObject - 삭제 처리 SQL mapping 입력 데이터(일반적으로 key 조건)를 세팅한 파라메터 객체(보통 VO 또는 Map) + * + * @return DBMS가 지원하는 경우 delete 적용 결과 count + */ + @Override + public int delete(String queryId, Object parameterObject) { + LOGGER.debug("queryId = "+queryId); + return getSqlSession().delete(queryId, parameterObject); + } + + //CHECKSTYLE:OFF + /** + * 명명규칙에 맞춰 selectOne()로 변경한다. + * @deprecated select() 메소드로 대체 + * + * @see EgovAbstractMapper.selectOne() + */ + //CHECKSTYLE:ON + @Deprecated + public Object selectByPk(String queryId, Object parameterObject) { + LOGGER.debug("queryId = "+queryId); + return getSqlSession().selectOne(queryId, parameterObject); + } + + /** + * 단건조회 처리 SQL mapping 을 실행한다. + * + * @param queryId - 단건 조회 처리 SQL mapping 쿼리 ID + * + * @return 결과 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 단일 결과 객체(보통 VO 또는 Map) + */ + @Override + public T selectOne(String queryId) { + LOGGER.debug("queryId = "+queryId); + return getSqlSession().selectOne(queryId); + } + + /** + * 단건조회 처리 SQL mapping 을 실행한다. + * + * @param queryId - 단건 조회 처리 SQL mapping 쿼리 ID + * @param parameterObject - 단건 조회 처리 SQL mapping 입력 데이터(key)를 세팅한 파라메터 객체(보통 VO 또는 Map) + * + * @return 결과 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 단일 결과 객체(보통 VO 또는 Map) + */ + @Override + public T selectOne(String queryId, Object parameterObject) { + LOGGER.debug("queryId = "+queryId); + return getSqlSession().selectOne(queryId, parameterObject); + } + + /** + * 결과 목록을 Map 을 변환한다. + * 모든 구문이 파라미터를 필요로 하지는 않기 때문에, 파라미터 객체를 요구하지 않는 형태로 오버로드되었다. + * + * @param queryId - 단건 조회 처리 SQL mapping 쿼리 ID + * @param mapKey - 결과 객체의 프로퍼티 중 하나를 키로 사용 + * + * @return 결과 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 단일 결과 객체(보통 VO 또는 Map)의 Map + */ + @Override + public Map selectMap(String queryId, String mapKey) { + LOGGER.debug("queryId = "+queryId); + return getSqlSession().selectMap(queryId, mapKey); + } + + /** + * 결과 목록을 Map 을 변환한다. + * 모든 구문이 파라미터를 필요로 하지는 않기 때문에, 파라미터 객체를 요구하지 않는 형태로 오버로드되었다. + * + * @param queryId - 단건 조회 처리 SQL mapping 쿼리 ID + * @param parameterObject - 맵 조회 처리 SQL mapping 입력 데이터(조회 조건)를 세팅한 파라메터 객체(보통 VO 또는 Map) + * @param mapKey - 결과 객체의 프로퍼티 중 하나를 키로 사용 + * + * @return 결과 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 단일 결과 객체(보통 VO 또는 Map)의 Map + */ + @Override + public Map selectMap(String queryId, Object parameterObject, String mapKey) { + LOGGER.debug("queryId = "+queryId); + return getSqlSession().selectMap(queryId, parameterObject, mapKey); + } + + /** + * 결과 목록을 Map 을 변환한다. + * 모든 구문이 파라미터를 필요로 하지는 않기 때문에, 파라미터 객체를 요구하지 않는 형태로 오버로드되었다. + * + * @param queryId - 단건 조회 처리 SQL mapping 쿼리 ID + * @param parameterObject - 맵 조회 처리 SQL mapping 입력 데이터(조회 조건)를 세팅한 파라메터 객체(보통 VO 또는 Map) + * @param mapKey - 결과 객체의 프로퍼티 중 하나를 키로 사용 + * @param rowBounds - 특정 개수 만큼의 레코드를 건너띄게 함 + * + * @return 결과 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 단일 결과 객체(보통 VO 또는 Map)의 Map + */ + @Override + public Map selectMap(String queryId, Object parameterObject, String mapKey, RowBounds rowBounds) { + LOGGER.debug("queryId = "+queryId); + return getSqlSession().selectMap(queryId, parameterObject, mapKey, rowBounds); + } + + //CHECKSTYLE:OFF + /** + * 명명규칙에 맞춰 selectList()로 변경한다. + * + * @see EgovAbstractMapper.selectList() + * @deprecated List 메소드로 대체 + */ + //CHECKSTYLE:ON + @Deprecated + public List list(String queryId, Object parameterObject) { + LOGGER.debug("queryId = "+queryId); + return getSqlSession().selectList(queryId, parameterObject); + } + + /** + * 리스트 조회 처리 SQL mapping 을 실행한다. + * + * @param queryId - 리스트 조회 처리 SQL mapping 쿼리 ID + * + * @return 결과 List 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 결과 객체(보통 VO 또는 Map)의 List + */ + @Override + public List selectList(String queryId) { + LOGGER.debug("queryId = "+queryId); + return getSqlSession().selectList(queryId); + } + + /** + * 리스트 조회 처리 SQL mapping 을 실행한다. + * + * @param queryId - 리스트 조회 처리 SQL mapping 쿼리 ID + * @param parameterObject - 리스트 조회 처리 SQL mapping 입력 데이터(조회 조건)를 세팅한 파라메터 객체(보통 VO 또는 Map) + * + * @return 결과 List 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 결과 객체(보통 VO 또는 Map)의 List + */ + @Override + public List selectList(String queryId, Object parameterObject) { + LOGGER.debug("queryId = "+queryId); + return getSqlSession().selectList(queryId, parameterObject); + } + + /** + * 리스트 조회 처리 SQL mapping 을 실행한다. + * + * @param queryId - 리스트 조회 처리 SQL mapping 쿼리 ID + * @param parameterObject - 리스트 조회 처리 SQL mapping 입력 데이터(조회 조건)를 세팅한 파라메터 객체(보통 VO 또는 Map) + * @param rowBounds - 특정 개수 만큼의 레코드를 건너띄게 함 + * + * @return 결과 List 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 결과 객체(보통 VO 또는 Map)의 List + */ + @Override + public List selectList(String queryId, Object parameterObject, RowBounds rowBounds) { + LOGGER.debug("queryId = "+queryId); + return getSqlSession().selectList(queryId, parameterObject, rowBounds); + } + + /** + * 부분 범위 리스트 조회 처리 SQL mapping 을 실행한다. + * (부분 범위 - pageIndex 와 pageSize 기반으로 현재 부분 범위 조회를 위한 skipResults, maxResults 를 계산하여 ibatis 호출) + * + * @param queryId - 리스트 조회 처리 SQL mapping 쿼리 ID + * @param parameterObject - 리스트 조회 처리 SQL mapping 입력 데이터(조회 조건)를 세팅한 파라메터 객체(보통 VO 또는 Map) + * @param pageIndex - 현재 페이지 번호 + * @param pageSize - 한 페이지 조회 수(pageSize) + * + * @return 부분 범위 결과 List 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 부분 범위 결과 객체(보통 VO 또는 Map) List + */ + @Override + public List listWithPaging(String queryId, Object parameterObject, int pageIndex, int pageSize) { + LOGGER.debug("queryId = "+queryId); + int skipResults = pageIndex * pageSize; + //int maxResults = (pageIndex * pageSize) + pageSize; + + RowBounds rowBounds = new RowBounds(skipResults, pageSize); + + return getSqlSession().selectList(queryId, parameterObject, rowBounds); + } + + /** + * SQL 조회 결과를 ResultHandler를 이용해서 출력한다. + * ResultHandler를 상속해 구현한 커스텀 핸들러의 handleResult() 메서드에 따라 실행된다. + * + * @param queryId - 리스트 조회 처리 SQL mapping 쿼리 ID + * @param handler - 조회 결과를 제어하기 위해 구현한 ResultHandler + * @return + * + * @return 결과 List 객체 - SQL mapping 파일에서 지정한 resultType/resultMap 에 의한 결과 객체(보통 VO 또는 Map)의 List + */ + @Override + public void listToOutUsingResultHandler(String queryId, ResultHandler handler) { + LOGGER.debug("queryId = "+queryId); + getSqlSession().select(queryId, handler); + } +} diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/util/EgovBasicLogger.java b/legacy/nlib/src/main/java/egovframework/com/cmm/util/EgovBasicLogger.java new file mode 100644 index 00000000..59112613 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/util/EgovBasicLogger.java @@ -0,0 +1,83 @@ +package egovframework.com.cmm.util; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Utility class to support to logging information + * @author Vincent Han + * @since 2014.09.18 + * @version 1.0 + * @see + * + *
+ * << 개정이력(Modification Information) >>
+ *   
+ *   수정일        수정자       수정내용
+ *  -------       --------    ---------------------------
+ *   2014.09.18	표준프레임워크센터	최초 생성
+ *
+ * 
+ */ +public class EgovBasicLogger { + private static final Level IGNORE_INFO_LEVEL = Level.OFF; + private static final Level DEBUG_INFO_LEVEL = Level.FINEST; + private static final Level INFO_INFO_LEVEL = Level.INFO; + + private static final Logger ignoreLogger = Logger.getLogger("ignore"); + private static final Logger debugLogger = Logger.getLogger("debug"); + private static final Logger infoLogger = Logger.getLogger("info"); + + /** + * 기록이나 처리가 불필요한 경우 사용. + * @param message + * @param exception + */ + public static void ignore(String message, Exception exception) { + if (exception == null) { + ignoreLogger.log(IGNORE_INFO_LEVEL, message); + } else { + ignoreLogger.log(IGNORE_INFO_LEVEL, message, exception); + } + } + + /** + * 기록이나 처리가 불필요한 경우 사용. + * @param message + * @param exception + */ + public static void ignore(String message) { + ignore(message, null); + } + + /** + * 디버그 정보를 기록하는 경우 사용. + * @param message + * @param exception + */ + public static void debug(String message, Exception exception) { + if (exception == null) { + debugLogger.log(DEBUG_INFO_LEVEL, message); + } else { + debugLogger.log(DEBUG_INFO_LEVEL, message, exception); + } + } + + /** + * 디버그 정보를 기록하는 경우 사용. + * @param message + * @param exception + */ + public static void debug(String message) { + debug(message, null); + } + + /** + * 일반적이 정보를 기록하는 경우 사용. + * @param message + * @param exception + */ + public static void info(String message) { + infoLogger.log(INFO_INFO_LEVEL, message); + } +} diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/util/EgovResourceCloseHelper.java b/legacy/nlib/src/main/java/egovframework/com/cmm/util/EgovResourceCloseHelper.java new file mode 100644 index 00000000..4901b153 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/util/EgovResourceCloseHelper.java @@ -0,0 +1,146 @@ +package egovframework.com.cmm.util; + +import java.io.Closeable; +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Wrapper; + +/** + * Utility class to support to close resources + * @author Vincent Han + * @since 2014.09.18 + * @version 1.0 + * @see + * + *
+ * << 개정이력(Modification Information) >>
+ *   
+ *   수정일        수정자       수정내용
+ *  -------       --------    ---------------------------
+ *   2014.09.18	표준프레임워크센터	최초 생성
+ *
+ * 
+ */ +public class EgovResourceCloseHelper { + /** + * Resource close 처리. + * @param resources + */ + public static void close(Closeable ... resources) { + for (Closeable resource : resources) { + if (resource != null) { + try { + resource.close(); + } catch (IOException ignore) {//KISA 보안약점 조치 (2018-10-29, 윤창원) + EgovBasicLogger.ignore("Occurred IOException to close resource is ingored!!"); + } catch (Exception ignore) { + EgovBasicLogger.ignore("Occurred Exception to close resource is ingored!!"); + } + } + } + } + + /** + * JDBC 관련 resource 객체 close 처리 + * @param objects + */ + public static void closeDBObjects(Wrapper ... objects) { + for (Object object : objects) { + if (object != null) { + if (object instanceof ResultSet) { + try { + ((ResultSet)object).close(); + } catch (SQLException ignore) {//KISA 보안약점 조치 (2018-10-29, 윤창원) + EgovBasicLogger.ignore("Occurred SQLException to close resource is ingored!!"); + } catch (Exception ignore) { + EgovBasicLogger.ignore("Occurred Exception to close resource is ingored!!"); + } + } else if (object instanceof Statement) { + try { + ((Statement)object).close(); + } catch (SQLException ignore) {//KISA 보안약점 조치 (2018-10-29, 윤창원) + EgovBasicLogger.ignore("Occurred SQLException to close resource is ingored!!"); + } catch (Exception ignore) { + EgovBasicLogger.ignore("Occurred Exception to close resource is ingored!!"); + } + } else if (object instanceof Connection) { + try { + ((Connection)object).close(); + } catch (SQLException ignore) { + EgovBasicLogger.ignore("Occurred SQLException to close resource is ingored!!"); + } catch (Exception ignore) { + EgovBasicLogger.ignore("Occurred Exception to close resource is ingored!!"); + } + } else { + throw new IllegalArgumentException("Wrapper type is not found : " + object.toString()); + } + } + } + } + + /** + * Socket 관련 resource 객체 close 처리 + * @param objects + */ + public static void closeSocketObjects(Socket socket, ServerSocket server) { + if (socket != null) { + try { + socket.shutdownOutput(); + } catch (IOException ignore) { + EgovBasicLogger.ignore("Occurred IOException to close resource is ingored!!"); + } catch (Exception ignore) { + EgovBasicLogger.ignore("Occurred Exception to shutdown ouput is ignored!!"); + } + + try { + socket.close(); + } catch (IOException ignore) { + EgovBasicLogger.ignore("Occurred IOException to close resource is ingored!!"); + } catch (Exception ignore) { + EgovBasicLogger.ignore("Occurred Exception to close resource is ignored!!"); + } + } + + if (server != null) { + try { + server.close(); + } catch (IOException ignore) { + EgovBasicLogger.ignore("Occurred IOException to close resource is ingored!!"); + } catch (Exception ignore) { + EgovBasicLogger.ignore("Occurred Exception to close resource is ignored!!"); + } + } + } + + /** + * Socket 관련 resource 객체 close 처리 + * + * @param sockets + */ + public static void closeSockets(Socket ... sockets) { + for (Socket socket : sockets) { + if (socket != null) { + try { + socket.shutdownOutput(); + } catch (IOException ignore) { + EgovBasicLogger.ignore("Occurred IOException to close resource is ingored!!"); + } catch (Exception ignore) { + EgovBasicLogger.ignore("Occurred Exception to shutdown ouput is ignored!!"); + } + + try { + socket.close(); + } catch (IOException ignore) { + EgovBasicLogger.ignore("Occurred IOException to close resource is ingored!!"); + } catch (Exception ignore) { + EgovBasicLogger.ignore("Occurred Exception to close resource is ignored!!"); + } + } + } + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/util/EgovUserDetailsHelper.java b/legacy/nlib/src/main/java/egovframework/com/cmm/util/EgovUserDetailsHelper.java new file mode 100644 index 00000000..0f67b141 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/util/EgovUserDetailsHelper.java @@ -0,0 +1,61 @@ +package egovframework.com.cmm.util; + +import java.util.List; + +import egovframework.com.cmm.service.EgovUserDetailsService; + +/** + * EgovUserDetails Helper 클래스 + * + * @author sjyoon + * @since 2009.06.01 + * @version 1.0 + * @see + * + *
+ * << 개정이력(Modification Information) >>
+ *
+ *   수정일      수정자           수정내용
+ *  -------    -------------    ----------------------
+ *   2009.03.10  sjyoon         최초 생성
+ *   2011.07.01	 서준식          interface 생성후 상세 로직의 분리
+ * 
+ */ + +public class EgovUserDetailsHelper { + + static EgovUserDetailsService egovUserDetailsService; + + public EgovUserDetailsService getEgovUserDetailsService() { + return egovUserDetailsService; + } + + public void setEgovUserDetailsService(EgovUserDetailsService egovUserDetailsService) { + EgovUserDetailsHelper.egovUserDetailsService = egovUserDetailsService; + } + + /** + * 인증된 사용자객체를 VO형식으로 가져온다. + * @return Object - 사용자 ValueObject + */ + public static Object getAuthenticatedUser() { + return egovUserDetailsService.getAuthenticatedUser(); + } + + /** + * 인증된 사용자의 권한 정보를 가져온다. + * + * @return List - 사용자 권한정보 목록 + */ + public static List getAuthorities() { + return egovUserDetailsService.getAuthorities(); + } + + /** + * 인증된 사용자 여부를 체크한다. + * @return Boolean - 인증된 사용자 여부(TRUE / FALSE) + */ + public static Boolean isAuthenticated() { + return egovUserDetailsService.isAuthenticated(); + } +} diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/web/EgovBindingInitializer.java b/legacy/nlib/src/main/java/egovframework/com/cmm/web/EgovBindingInitializer.java new file mode 100644 index 00000000..f8227ee2 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/web/EgovBindingInitializer.java @@ -0,0 +1,60 @@ +/* + * Copyright 2008-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package egovframework.com.cmm.web; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import org.springframework.beans.propertyeditors.CustomDateEditor; +import org.springframework.beans.propertyeditors.StringTrimmerEditor; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.support.WebBindingInitializer; +import org.springframework.web.context.request.WebRequest; + +/** + * @Class Name : EgovBindingInitializer.java + * @Description : EgovBindingInitializer Class + * @Modification Information + * @ + * @ 수정일 수정자 수정내용 + * @ --------- --------- ------------------------------- + * @ 2009.03.16 최초생성 + * + * @author 개발프레임웍크 실행환경 개발팀 + * @since 2009. 03.16 + * @version 1.0 + * @see + * + * Copyright (C) by MOPAS All right reserved. + */ +public class EgovBindingInitializer implements WebBindingInitializer { + + /** + * initBinder + * @param binder + * @param request + * @see 개발프레임웍크 실행환경 개발팀 + */ + @Override + public void initBinder(WebDataBinder binder, WebRequest request) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); + dateFormat.setLenient(false); + binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false)); + binder.registerCustomEditor(String.class, new StringTrimmerEditor(false)); + } + +} diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/web/EgovComUtlController.java b/legacy/nlib/src/main/java/egovframework/com/cmm/web/EgovComUtlController.java new file mode 100644 index 00000000..6eff9fcc --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/web/EgovComUtlController.java @@ -0,0 +1,93 @@ +package egovframework.com.cmm.web; + +import java.util.List; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import egovframework.com.cmm.EgovWebUtil; +import egovframework.rte.fdl.property.EgovPropertyService; + +/** + * @Class Name : EgovComUtlController.java + * @Description : 공통유틸리티성 작업을 위한 Controller + * @Modification Information + * @ + * @ 수정일 수정자 수정내용 + * @ ---------- -------- --------------------------- + * 2009.03.02 조재영 최초 생성 + * 2011.10.07 이기하 .action -> .do로 변경하면서 동일 매핑이 되어 삭제처리 + * 2015.11.12 김연호 한국인터넷진흥원 웹 취약점 개선 + * 2019.04.25 신용호 moveToPage() 화이트리스트 처리 + * + * @author 공통서비스 개발팀 조재영 + * @since 2009.03.02 + * @version 1.0 + * @see + * + */ +@Controller +public class EgovComUtlController { + + //@Resource(name = "egovUserManageService") + //private EgovUserManageService egovUserManageService; + private static final Logger LOGGER = LoggerFactory.getLogger(EgovComUtlController.class); + + @Resource(name = "egovPageLinkWhitelist") + protected List egovWhitelist; + + /** EgovPropertyService */ + @Resource(name = "propertiesService") + protected EgovPropertyService propertiesService; + + /** + * JSP 호출작업만 처리하는 공통 함수 + */ + @RequestMapping(value="/EgovPageLink.do") + public String moveToPage(@RequestParam("link") String linkPage){ + String link = linkPage; + link = link.replace(";", ""); + link = link.replace(".", ""); + + // service 사용하여 리턴할 결과값 처리하는 부분은 생략하고 단순 페이지 링크만 처리함 + if (linkPage==null || linkPage.equals("")){ + link="egovframework/com/cmm/egovError"; + } + + // 화이트 리스트 처리 + // whitelist목록에 있는 경우 결과가 true, 결과가 false인경우 FAIL처리 + if (egovWhitelist.contains(linkPage) == false) { + LOGGER.debug("Page Link WhiteList Error! Please check whitelist!"); + link="egovframework/com/cmm/egovError"; + } + + // 안전한 경로 문자열로 조치 + link = EgovWebUtil.filePathBlackList(link); + + return link; + } + + /** + * 모달조회 + * @return String + * @exception Exception + */ + @RequestMapping(value="/EgovModal.do") + public String selectUtlJsonInquire() throws Exception { + return "egovframework/com/cmm/EgovModal"; + } + + /** + * validato rule dynamic Javascript + */ + @RequestMapping("/validator.do") + public String validate(){ + return "egovframework/com/cmm/validator"; + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/egovframework/com/cmm/web/EgovImgPaginationRenderer.java b/legacy/nlib/src/main/java/egovframework/com/cmm/web/EgovImgPaginationRenderer.java new file mode 100644 index 00000000..dc7e97ae --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/cmm/web/EgovImgPaginationRenderer.java @@ -0,0 +1,68 @@ +/* + * Copyright 2008-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package egovframework.com.cmm.web; + +import egovframework.rte.ptl.mvc.tags.ui.pagination.AbstractPaginationRenderer; + +import javax.servlet.ServletContext; + +import org.springframework.web.context.ServletContextAware; + +/** + * @Class Name : ImagePaginationRenderer.java + * @Description : ImagePaginationRenderer Class + * @Modification Information + * @ + * @ 수정일 수정자 수정내용 + * @ --------- --------- ------------------------------- + * @ 2009.03.16 최초생성 + * + * @author 개발프레임웍크 실행환경 개발팀 + * @since 2009. 03.16 + * @version 1.0 + * @see + * + * Copyright (C) by MOPAS All right reserved. + */ +public class EgovImgPaginationRenderer extends AbstractPaginationRenderer implements ServletContextAware{ + + private ServletContext servletContext; + + public EgovImgPaginationRenderer() { + // no-op + } + + /** + * PaginationRenderer + * + * @see 개발프레임웍크 실행환경 개발팀 + */ + public void initVariables() { + + firstPageLabel = "" + " "; + previousPageLabel = "" + " "; + currentPageLabel = "{0} "; + otherPageLabel = "{2} "; + nextPageLabel = "" + " "; + lastPageLabel = "" + " "; + } + + @Override + public void setServletContext(ServletContext servletContext) { + this.servletContext = servletContext; + initVariables(); + } +} diff --git a/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/EgovSignupService.java b/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/EgovSignupService.java new file mode 100644 index 00000000..6c43b314 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/EgovSignupService.java @@ -0,0 +1,52 @@ +/* + * eGovFrame OAuth + * Copyright The eGovFrame Open Community (http://open.egovframe.go.kr)). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @author 이기하(슈퍼개발자K3) + */ +package egovframework.com.ext.oauth.service; + +import org.springframework.social.connect.UserProfile; +import org.springframework.web.context.request.WebRequest; + +/** + * 소셜 계정으로 일반회원 가입을 처리하는 비즈니스 인터페이스 클래스 + * @author 이기하 + * @since 2014.10.08 + * @version 1.0 + * @see + * + *
+ * << 개정이력(Modification Information) >>
+ *
+ *   수정일     	수정자          수정내용
+ *  -----------    --------    ---------------------------
+ *  2014.10.08		이기하          최초 생성
+ *  
+ */ + +public interface EgovSignupService { + + /** + * 소셜 계정으로 일반회원 가입을 처리한다 + * @param UserProfile profile + * @param WebRequest request + * @param String key + * @return String + * @exception Exception + */ + public String signup(UserProfile profile, WebRequest request, String key) throws Exception; + +} diff --git a/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/KakaoAPI20.java b/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/KakaoAPI20.java new file mode 100644 index 00000000..9cfaddf0 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/KakaoAPI20.java @@ -0,0 +1,54 @@ +package egovframework.com.ext.oauth.service; + +import java.util.Map; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.ParameterList; + +public class KakaoAPI20 extends DefaultApi20 implements OAuthConfig { + + private String apiKey = ""; + private KakaoAPI20() { + } + + private static class InstanceHolder { + private static final KakaoAPI20 INSTANCE = new KakaoAPI20(); + } + + public static KakaoAPI20 instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return KAKAO_ACCESS_TOKEN+apiKey; + } + + @Override + protected String getAuthorizationBaseUrl() { + return KAKAO_AUTH; + } + + public String getAuthorizationUrl(String responseType, String apiKey, String callback, String scope, String state, + Map additionalParams) { + this.apiKey = apiKey; + final ParameterList parameters = new ParameterList(additionalParams); + parameters.add(OAuthConstants.RESPONSE_TYPE, responseType); + parameters.add(OAuthConstants.CLIENT_ID, apiKey); + + if (callback != null) { + parameters.add(OAuthConstants.REDIRECT_URI, callback); + } + + if (scope != null) { + parameters.add(OAuthConstants.SCOPE, scope); + } + + if (state != null) { + parameters.add(OAuthConstants.STATE, state); + } + return parameters.appendTo(getAuthorizationBaseUrl()); + } + +} diff --git a/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/NaverAPI20.java b/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/NaverAPI20.java new file mode 100644 index 00000000..6f92b0a0 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/NaverAPI20.java @@ -0,0 +1,50 @@ +package egovframework.com.ext.oauth.service; + +import java.util.Map; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.ParameterList; + +public class NaverAPI20 extends DefaultApi20 implements OAuthConfig { + private NaverAPI20() { + } + + private static class InstanceHolder { + private static final NaverAPI20 INSTANCE = new NaverAPI20(); + } + + public static NaverAPI20 instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return NAVER_ACCESS_TOKEN; + } + + @Override + protected String getAuthorizationBaseUrl() { + return NAVER_AUTH; + } + + public String getAuthorizationUrl(String responseType, String apiKey, String callback, String scope, String state, + Map additionalParams) { + final ParameterList parameters = new ParameterList(additionalParams); + parameters.add(OAuthConstants.RESPONSE_TYPE, responseType); + parameters.add(OAuthConstants.CLIENT_ID, apiKey); + + if (callback != null) { + parameters.add(OAuthConstants.REDIRECT_URI, callback); + } + + if (scope != null) { + parameters.add(OAuthConstants.SCOPE, scope); + } + + if (state != null) { + parameters.add(OAuthConstants.STATE, state); + } + return parameters.appendTo(getAuthorizationBaseUrl()); + } +} diff --git a/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/OAuthConfig.java b/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/OAuthConfig.java new file mode 100644 index 00000000..9195236e --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/OAuthConfig.java @@ -0,0 +1,21 @@ +package egovframework.com.ext.oauth.service; + +import nlib.cmm.service.NlibProperty; + +public interface OAuthConfig { + + static final String GOOGLE_SERVICE_NAME = NlibProperty.getString("oauth2.client.provider.google.name"); + static final String GOOGLE_PROFILE_URL = NlibProperty.getString("oauth2.client.provider.google.user-info-uri"); // "https://www.googleapis.com/plus/v1/people/me"; + + static final String NAVER_SERVICE_NAME = NlibProperty.getString("oauth2.client.provider.naver.name"); + static final String NAVER_PROFILE_URL = NlibProperty.getString("oauth2.client.provider.naver.user-info-uri"); // "https://openapi.naver.com/v1/nid/me"; + static final String NAVER_ACCESS_TOKEN = NlibProperty.getString("oauth2.client.provider.naver.token-uri"); // "https://nid.naver.com/oauth2.0/token?grant_type=authorization_code"; + static final String NAVER_AUTH = NlibProperty.getString("oauth2.client.provider.naver.authorization-uri"); // "https://nid.naver.com/oauth2.0/authorize"; + + static final String KAKAO_SERVICE_NAME = NlibProperty.getString("oauth2.client.provider.kakao.name"); + static final String KAKAO_PROFILE_URL = NlibProperty.getString("oauth2.client.provider.kakao.user-info-uri"); // "https://kapi.kakao.com/v2/user/me"; + static final String KAKAO_ACCESS_TOKEN = NlibProperty.getString("oauth2.client.provider.kakao.token-uri"); // "https://kauth.kakao.com/oauth/token?client_id="; + static final String KAKAO_AUTH = NlibProperty.getString("oauth2.client.provider.kakao.authorization-uri"); // "https://kauth.kakao.com/oauth/authorize"; + +} + diff --git a/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/OAuthLogin.java b/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/OAuthLogin.java new file mode 100644 index 00000000..26df92ed --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/OAuthLogin.java @@ -0,0 +1,223 @@ +package egovframework.com.ext.oauth.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.scribejava.core.builder.ScopeBuilder; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +import nlib.user.web.LoginController; +import nlib.util.StringUtil; + + +public class OAuthLogin { + + /** SNS 호출 시, URL callType 대체 문자열 */ + public static final String CALL_TYPE_LOGIN = "login"; + public static final String CALL_TYPE_MEMBER = "member"; + private static final Logger log = LoggerFactory.getLogger(OAuthLogin.class); + + private OAuth20Service oauthService; + private OAuthVO oauthVO; + + public OAuthLogin(OAuthVO oauthVO, String callType) { + this(oauthVO, callType, null); + } + + public OAuthLogin(OAuthVO oauthVO, String callType, String councilJsessionId) { + + if(oauthVO.getService().equals("google")) + { + ScopeBuilder scope = new ScopeBuilder(); + scope.withScope("profile"); + scope.withScope("openid"); + scope.withScope("email"); + //scope.withScope("https://www.googleapis.com/auth/user.phonenumbers.read"); + //scope.withScope("https://www.googleapis.com/auth/user.birthday.read"); + + this.oauthService = new ServiceBuilder(oauthVO.getClientId()) + .apiSecret(oauthVO.getClientSecret()) + .callback(oauthVO.getRedirectUrl(callType, councilJsessionId)) + .defaultScope(scope) + //.scope("profile") + .build(oauthVO.getApi20Instance()); + + } else if(oauthVO.getService().equals("kakao") || oauthVO.getService().equals("naver")) { + + this.oauthService = new ServiceBuilder(oauthVO.getClientId()) + .apiSecret(oauthVO.getClientSecret()) + .callback(oauthVO.getRedirectUrl(callType, councilJsessionId)) + //.scope("profile") + .build(oauthVO.getApi20Instance()); + } + + this.oauthVO = oauthVO; + } + + public String getOAuthURL(String state) { + return this.oauthService.getAuthorizationUrl(state); + } + + public OAuthUniversalUser getUserProfile(String code) throws Exception { + log.debug("getUserProfile > getAccessToken"); + OAuth2AccessToken accessToken = oauthService.getAccessToken(code); + log.debug("getUserProfile > getAccessToken2"); + OAuthRequest request = new OAuthRequest(Verb.GET, this.oauthVO.getProfileUrl()); + oauthService.signRequest(accessToken, request); + + Response response = oauthService.execute(request); + return parseJson(response.getBody()); + } + + private OAuthUniversalUser parseJson(String body) throws Exception { + + OAuthUniversalUser user = new OAuthUniversalUser(); + + ObjectMapper mapper = new ObjectMapper(); + JsonNode rootNode = mapper.readTree(body); + + if (this.oauthVO.isNaver()) { + //------------------------------------ + // 네이버 + //------------------------------------ + user.setSnsType(OAuthConfig.NAVER_SERVICE_NAME); + JsonNode resNode = rootNode.get("response"); + + // 사용자 내부 고유 ID (예: kh3lhfSg2v7TnJLmdhH7a0HyL-1zExIS4cF1mD4Hi4Y) + user.setSnsId(resNode.get("id").asText()); + + // 사용자로그인ID (메일형식) : 네이버 계정 제공하지 않으므로 연락처 이메일을 기본 메일 계정으로 설정 + if (resNode.has("email")) { + user.setSnsUserId(StringUtil.getString(resNode.get("email").asText(), "")); + + // 메일주소 + user.setSnsEmail(StringUtil.getString(resNode.get("email").asText(), "")); + } + + // 사용자명 (예: 홍길동) + if (resNode.has("name")) { + user.setSnsName(StringUtil.getString(resNode.get("name").asText(), "")); + } + + // 생년월일 + String birthday ="0000"; + String birthyear = "0000"; + if (resNode.has("birthday")) { + birthday = StringUtil.getString(resNode.get("birthday").asText(), "0000"); + } + if (resNode.has("birthyear")) { + birthyear = StringUtil.getString(resNode.get("birthyear").asText(), "0000"); + } + birthday = birthday.replaceAll("-", ""); + if(birthday.length() != 4) birthday = "0000"; + if(birthyear.length() != 4) birthyear = "0000"; + user.setSnsBirthday(birthyear + birthday); + + // 성별 + if (resNode.has("gender")) { + user.setSnsGender(StringUtil.getString(resNode.get("gender").asText(), "")); + } + + //휴대폰번호 + if (resNode.has("mobile")) { + String mobile = StringUtil.getString(resNode.get("mobile").asText(), ""); + if(mobile != "") + { + mobile = mobile.replaceAll("-", ""); + user.setSnsMobileNo(mobile); + } + } + // 로그인 성공 + user.setValidLogin(true); + + } else if (this.oauthVO.isGoogle()) { + //------------------------------------ + // 구글 + //------------------------------------ + user.setSnsType(OAuthConfig.GOOGLE_SERVICE_NAME); + if (rootNode.has("sub")) + user.setSnsId(StringUtil.getString(rootNode.get("sub").asText(), "")); + + if (rootNode.has("email")) + user.setSnsUserId(StringUtil.getString(rootNode.get("email").asText(), "")); + + if (rootNode.has("name")) + user.setSnsName(StringUtil.getString(rootNode.get("name").asText(), "")); + + } else if (this.oauthVO.isKakao()) { + //------------------------------------ + // 카카오 + //------------------------------------ + user.setSnsType(OAuthConfig.KAKAO_SERVICE_NAME); + JsonNode resNode = rootNode.get("kakao_account"); + + if(rootNode.has("id")) { + user.setSnsId((rootNode.get("id").asText() == null) ? "" : rootNode.get("id").asText()); + } + + if (resNode.has("email")) { + user.setSnsUserId(StringUtil.getString(resNode.get("email").asText(), "")); + user.setSnsEmail(StringUtil.getString(resNode.get("email").asText(), "")); + } + if (resNode.has("gender")) + { + user.setSnsGender(StringUtil.getString(resNode.get("gender").asText(), "")); + if(user.getSnsGender().equals("male")) + { + user.setSnsGender("M"); + }else if(user.getSnsGender().equals("female")) + { + user.setSnsGender("F"); + } + } + // 생년월일 + String birthday ="0000"; + String birthyear = "0000"; + if (resNode.has("birthday")) { + birthday = StringUtil.getString(resNode.get("birthday").asText(), "0000"); + } + if (resNode.has("birthyear")) { + birthyear = StringUtil.getString(resNode.get("birthyear").asText(), "0000"); + } + birthday = birthday.replaceAll("-", ""); + if(birthday.length() != 4) birthday = "0000"; + if(birthyear.length() != 4) birthyear = "0000"; + user.setSnsBirthday(birthyear + birthday); + + if (resNode.has("phone_number")) + user.setSnsMobileNo(StringUtil.getString(resNode.get("phone_number").asText(), "")); + + } + + return user; + } + + /** + * URL에 매개변수를 GET 방식으로 추가하여 리턴한다. + * + * @param url + * @param paramName + * @param paramValue + * @return + */ + public String appendUrlParam(String url, String paramName, String paramValue) { + if(StringUtil.isEmpty(url)) return ""; + if(StringUtil.isEmpty(paramName)) return url; + + if(StringUtil.isEmpty(paramValue)) paramValue = ""; + + if(url.contains("?")) url += "&"; + else url += "?"; + + url += paramName + "=" + paramValue; + + return url; + } +} diff --git a/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/OAuthUniversalUser.java b/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/OAuthUniversalUser.java new file mode 100644 index 00000000..a0119a47 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/OAuthUniversalUser.java @@ -0,0 +1,202 @@ +package egovframework.com.ext.oauth.service; + +import java.util.Date; + +import nlib.user.service.NlibLoginVO; +import nlib.util.StringUtil; + +public class OAuthUniversalUser { + + private String mbSnsId; + private String mbInfoId; + private String snsId; + + private String snsEmail; + private String snsUserId; + private String snsName; + private String snsNickName; + + private String snsBirthday; + private String snsGender; + + private String snsType; + private String snsMobileNo; + + private String loginIp; + private Date lastLogin; + + private String regDd; + private NlibLoginVO nlibVO; + + + private String councilJsessionId; /* 로그인 접속 문화원 코드 */ + private String councilHomeUrl; /* 로그인 접속 문화원 홈 URL */ + + + private boolean isValidLogin = false; + + public boolean isValid() { + return StringUtil.isNotEmpty(snsId); + } + + public String getMbInfoId() { + return mbInfoId; + } + + public void setMbInfoId(String mbInfoId) { + this.mbInfoId = mbInfoId; + } + + public String getSnsId() { + return snsId; + } + + public void setSnsId(String snsId) { + this.snsId = snsId; + } + + public String getSnsEmail() { + return snsEmail; + } + + public void setSnsEmail(String email) { + this.snsEmail = email; + } + + public String getSnsUserId() { + return snsUserId; + } + + public void setSnsUserId(String snsUserId) { + this.snsUserId = snsUserId; + } + + public String getSnsName() { + return snsName; + } + + public void setSnsName(String snsName) { + this.snsName = snsName; + } + + public String getSnsNickName() { + return snsNickName; + } + + public void setSnsNickName(String snsNickName) { + this.snsNickName = snsNickName; + } + + public String getSnsType() { + return snsType; + } + + public void setSnsType(String snsType) { + this.snsType = snsType; + } + + public String getLoginip() { + return loginIp; + } + + public void setLoginip(String loginIp) { + this.loginIp = loginIp; + } + + public Date getLastlogin() { + return lastLogin; + } + + public void setLastlogin(Date lastLogin) { + this.lastLogin = lastLogin; + } + + public String getSnsBirthday() { + return snsBirthday; + } + + public void setSnsBirthday(String snsBirthday) { + this.snsBirthday = snsBirthday; + } + + public String getLoginIp() { + return loginIp; + } + + public void setLoginIp(String loginIp) { + this.loginIp = loginIp; + } + + public Date getLastLogin() { + return lastLogin; + } + + public void setLastLogin(Date lastLogin) { + this.lastLogin = lastLogin; + } + + public String getSnsGender() { + return snsGender; + } + + public void setSnsGender(String snsGender) { + this.snsGender = snsGender; + } + + public boolean isValidLogin() { + return isValidLogin; + } + + public void setValidLogin(boolean isValidLogin) { + this.isValidLogin = isValidLogin; + } + + public String getSnsMobileNo() { + return snsMobileNo; + } + + public void setSnsMobileNo(String snsMobileNo) { + this.snsMobileNo = snsMobileNo; + } + + public NlibLoginVO getNlibVO() { + return nlibVO; + } + + public void setNlibVO(NlibLoginVO nlibVO) { + this.nlibVO = nlibVO; + } + + public String getMbSnsId() { + return mbSnsId; + } + + public void setMbSnsId(String mbSnsId) { + this.mbSnsId = mbSnsId; + } + + public String getRegDd() { + return regDd; + } + + public void setRegDd(String regDd) { + this.regDd = regDd; + } + + public String getCouncilJsessionId() { + return councilJsessionId; + } + + public void setCouncilJsessionId(String councilJsessionId) { + this.councilJsessionId = councilJsessionId; + } + + public String getCouncilHomeUrl() { + return councilHomeUrl; + } + + public void setCouncilHomeUrl(String councilHomeUrl) { + this.councilHomeUrl = councilHomeUrl; + } + +} diff --git a/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/OAuthVO.java b/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/OAuthVO.java new file mode 100644 index 00000000..25010259 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/ext/oauth/service/OAuthVO.java @@ -0,0 +1,130 @@ +package egovframework.com.ext.oauth.service; + +import com.github.scribejava.apis.GoogleApi20; +import com.github.scribejava.core.builder.api.DefaultApi20; + +import nlib.cmm.crypto.AriaCrypto; +import nlib.util.StringUtil; + +public class OAuthVO implements OAuthConfig { + + private String serviceName; + private String clientId; + private String clientSecret; + private String redirectUrl; + private String state; + private DefaultApi20 api20Instance; + private String profileUrl; + + private boolean isNaver; + private boolean isGoogle; + private boolean isKakao; + + public OAuthVO(String serviceName, String clientId, String clientSecret, String redirectUrl) { + this.serviceName = serviceName; + this.clientId = clientId; + this.clientSecret = clientSecret; + this.redirectUrl = redirectUrl; + this.state = state; + this.isGoogle = StringUtil.equalsIgnoreCase(GOOGLE_SERVICE_NAME, serviceName); + this.isNaver = StringUtil.equalsIgnoreCase(NAVER_SERVICE_NAME, serviceName); + this.isKakao = StringUtil.equalsIgnoreCase(KAKAO_SERVICE_NAME, serviceName); + + if (isGoogle) { + this.api20Instance = GoogleApi20.instance(); + this.profileUrl = GOOGLE_PROFILE_URL; + } else if (isNaver) { + this.api20Instance = NaverAPI20.instance(); + this.profileUrl = NAVER_PROFILE_URL; + } else if (isKakao) { + this.api20Instance = KakaoAPI20.instance(); + this.profileUrl = KAKAO_PROFILE_URL; + } + } + + // GET / SET + public String getService() { + return serviceName; + } + + public void setService(String service) { + this.serviceName = service; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getClientSecret() { + return clientSecret; + } + + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } + + public String getRedirectUrl(String callType, String councilJsessionId) { + String retUrl = redirectUrl.replaceAll("\\{callType\\}", callType); + retUrl = retUrl.replaceAll("\\{oauthServiceName\\}", getService()); + String encCouncilJsessionId = AriaCrypto.encode(councilJsessionId); + retUrl = retUrl.replaceAll("\\{councilJsessionId\\}", (councilJsessionId == null ? "" : encCouncilJsessionId)); + return retUrl; + } + + public void setRedirectUrl(String redirectUrl) { + this.redirectUrl = redirectUrl; + } + + public DefaultApi20 getApi20Instance() { + return api20Instance; + } + + public void setApi20Instance(DefaultApi20 api20Instance) { + this.api20Instance = api20Instance; + } + + public String getProfileUrl() { + return profileUrl; + } + + public void setProfileUrl(String profileUrl) { + this.profileUrl = profileUrl; + } + + public boolean isGoogle() { + return isGoogle; + } + + public boolean isNaver() { + return isNaver; + } + + public boolean isKakao() { + return isKakao; + } + + public void setGoogle(boolean isGoogle) { + this.isGoogle = isGoogle; + } + + public void setNaver(boolean isNaver) { + this.isNaver = isNaver; + } + + public void setKakao(boolean isKakao) { + this.isKakao = isKakao; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + +} diff --git a/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovDateFormat.java b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovDateFormat.java new file mode 100644 index 00000000..53c94287 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovDateFormat.java @@ -0,0 +1,146 @@ +package egovframework.com.utl.fcc.service; + +import java.text.DateFormat; +import java.util.Date; +import java.util.Locale; + +/** + * 날짜 및 시간에 대한 변환을 수행하는 클래스 + */ +public class EgovDateFormat { + + /** + * 기본 Locale에 해당하는 형식으로 날짜를 변환한다. + * + * @param date 날짜 + * @return 날짜 문자열 + */ + public static String formatDate(Date date) { + return DateFormat.getDateInstance().format(date); + } + + /** + * Locale에 해당하는 형식으로 날짜를 변환한다. + * + * @param locale 로케일 + * @param date 날짜 + * @return 날짜 문자열 + */ + public static String formatDate(Locale locale, Date date) { + return DateFormat.getDateInstance(DateFormat.DEFAULT, locale).format(date); + } + + /** + * 주어진 스타일에 따라, 기본 Locale에 해당하는 형식으로 날짜를 변환한다. + * + * @param style 날짜 스타일 (사용 가능한 값 : {@link DateFormat#FULL}, {@link DateFormat#LONG}, {@link DateFormat#MEDIUM}, {@link DateFormat#SHORT}, {@link DateFormat#DEFAULT}) + * @param date 날짜 + * @return 날짜 문자열 + */ + public static String formatDate(int style, Date date) { + return DateFormat.getDateInstance(style).format(date); + } + + /** + * 주어진 스타일에 따라, Locale에 해당하는 형식으로 날짜를 변환한다. + * + * @param style 날짜 스타일 (사용 가능한 값 : {@link DateFormat#FULL}, {@link DateFormat#LONG}, {@link DateFormat#MEDIUM}, {@link DateFormat#SHORT}, {@link DateFormat#DEFAULT}) + * @param locale 로케일 + * @param date 날짜 + * @return 날짜 문자열 + */ + public static String formatDate(int style, Locale locale, Date date) { + return DateFormat.getDateInstance(style, locale).format(date); + } + + /** + * 기본 Locale에 해당하는 형식으로 날짜 및 시간을 변환한다. + * + * @param date 날짜 및 시간 + * @return 날짜 및 시간 문자열 + */ + public static String formatDateTime(Date date) { + return DateFormat.getDateTimeInstance().format(date); + } + + /** + * Locale에 해당하는 형식으로 날짜 및 시간을 변환한다. + * + * @param locale 로케일 + * @param date 날짜 및 시간 + * @return 날짜 및 시간 문자열 + */ + public static String formatDateTime(Locale locale, Date date) { + return DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, locale).format(date); + } + + /** + * 주어진 스타일에 따라, 기본 Locale에 해당하는 형식으로 날짜 및 시간을 변환한다. + * + * @param dateStyle 날짜 스타일 (사용 가능한 값 : {@link DateFormat#FULL}, {@link DateFormat#LONG}, {@link DateFormat#MEDIUM}, {@link DateFormat#SHORT}, {@link DateFormat#DEFAULT}) + * @param timeStyle 시간 스타일 (사용 가능한 값 : {@link DateFormat#FULL}, {@link DateFormat#LONG}, {@link DateFormat#MEDIUM}, {@link DateFormat#SHORT}, {@link DateFormat#DEFAULT}) + * @param date 날짜 및 시간 + * @return 날짜 및 시간 문자열 + */ + public static String formatDateTime(int dateStyle, int timeStyle, Date date) { + return DateFormat.getDateTimeInstance(dateStyle, timeStyle).format(date); + } + + /** + * 주어진 스타일에 따라, Locale에 해당하는 형식으로 날짜 및 시간을 변환한다. + * + * @param dateStyle 날짜 스타일 (사용 가능한 값 : {@link DateFormat#FULL}, {@link DateFormat#LONG}, {@link DateFormat#MEDIUM}, {@link DateFormat#SHORT}, {@link DateFormat#DEFAULT}) + * @param timeStyle 시간 스타일 (사용 가능한 값 : {@link DateFormat#FULL}, {@link DateFormat#LONG}, {@link DateFormat#MEDIUM}, {@link DateFormat#SHORT}, {@link DateFormat#DEFAULT}) + * @param locale 로케일 + * @param date 날짜 및 시간 + * @return 날짜 및 시간 문자열 + */ + public static String formatDateTime(int dateStyle, int timeStyle, Locale locale, Date date) { + return DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale).format(date); + } + + /** + * 기본 Locale에 해당하는 형식으로 시간을 변환한다. + * + * @param date 시간 + * @return 시간 문자열 + */ + public static String formatTime(Date date) { + return DateFormat.getTimeInstance().format(date); + } + + /** + * Locale에 해당하는 형식으로 시간을 변환한다. + * + * @param locale 로케일 + * @param date 시간 + * @return 시간 문자열 + */ + public static String formatTime(Locale locale, Date date) { + return DateFormat.getTimeInstance(DateFormat.DEFAULT, locale).format(date); + } + + /** + * 주어진 스타일에 따라, 기본 Locale에 해당하는 형식으로 시간을 변환한다. + * + * @param style 시간 스타일 (사용 가능한 값 : {@link DateFormat#FULL}, {@link DateFormat#LONG}, {@link DateFormat#MEDIUM}, {@link DateFormat#SHORT}, {@link DateFormat#DEFAULT}) + * @param date 시간 + * @return 시간 문자열 + */ + public static String formatTime(int style, Date date) { + return DateFormat.getTimeInstance(style).format(date); + } + + /** + * 주어진 스타일에 따라, Locale에 해당하는 형식으로 시간을 변환한다. + * + * @param style 시간 스타일 (사용 가능한 값 : {@link DateFormat#FULL}, {@link DateFormat#LONG}, {@link DateFormat#MEDIUM}, {@link DateFormat#SHORT}, {@link DateFormat#DEFAULT}) + * @param locale 로케일 + * @param date 시간 + * @return 시간 문자열 + */ + public static String formatTime(int style, Locale locale, Date date) { + return DateFormat.getTimeInstance(style, locale).format(date); + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovDateUtil.java b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovDateUtil.java new file mode 100644 index 00000000..91c5857d --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovDateUtil.java @@ -0,0 +1,865 @@ +package egovframework.com.utl.fcc.service; + +import java.security.SecureRandom; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.TimeZone; + +import com.ibm.icu.util.ChineseCalendar; + +/** + * + * Date 에 대한 Util 클래스 + * @author 공통서비스 개발팀 이중호 + * @since 2009.02.01 + * @version 1.0 + * @see + * + *
+ * << 개정이력(Modification Information) >>
+ *
+ *   수정일      수정자           수정내용
+ *  -------    --------    ---------------------------
+ *   2009.02.01  이중호          최초 생성
+ *
+ * 
+ */ +public class EgovDateUtil { + + /** + *

yyyyMMdd 혹은 yyyy-MM-dd 형식의 날짜 문자열을 입력 받아 년, 월, 일을 + * 증감한다. 년, 월, 일은 가감할 수를 의미하며, 음수를 입력할 경우 감한다.

+ * + *
+	 * DateUtil.addYearMonthDay("19810828", 0, 0, 19)  = "19810916"
+	 * DateUtil.addYearMonthDay("20060228", 0, 0, -10) = "20060218"
+	 * DateUtil.addYearMonthDay("20060228", 0, 0, 10)  = "20060310"
+	 * DateUtil.addYearMonthDay("20060228", 0, 0, 32)  = "20060401"
+	 * DateUtil.addYearMonthDay("20050331", 0, -1, 0)  = "20050228"
+	 * DateUtil.addYearMonthDay("20050301", 0, 2, 30)  = "20050531"
+	 * DateUtil.addYearMonthDay("20050301", 1, 2, 30)  = "20060531"
+	 * DateUtil.addYearMonthDay("20040301", 2, 0, 0)   = "20060301"
+	 * DateUtil.addYearMonthDay("20040229", 2, 0, 0)   = "20060228"
+	 * DateUtil.addYearMonthDay("20040229", 2, 0, 1)   = "20060301"
+	 * 
+ * + * @param dateStr 날짜 문자열(yyyyMMdd, yyyy-MM-dd의 형식) + * @param year 가감할 년. 0이 입력될 경우 가감이 없다 + * @param month 가감할 월. 0이 입력될 경우 가감이 없다 + * @param day 가감할 일. 0이 입력될 경우 가감이 없다 + * @return yyyyMMdd 형식의 날짜 문자열 + * @throws IllegalArgumentException 날짜 포맷이 정해진 바와 다를 경우. + * 입력 값이 null인 경우. + */ + public static String addYearMonthDay(String sDate, int year, int month, int day) { + + String dateStr = validChkDate(sDate); + + Calendar cal = Calendar.getInstance(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd", Locale.getDefault()); + try { + cal.setTime(sdf.parse(dateStr)); + } catch (ParseException e) { + throw new IllegalArgumentException("Invalid date format: " + dateStr); + } + + if (year != 0) { + cal.add(Calendar.YEAR, year); + } + if (month != 0) { + cal.add(Calendar.MONTH, month); + } + if (day != 0) { + cal.add(Calendar.DATE, day); + } + + return sdf.format(cal.getTime()); + } + + /** + *

yyyyMMdd 혹은 yyyy-MM-dd 형식의 날짜 문자열을 입력 받아 년을 + * 증감한다. year는 가감할 수를 의미하며, 음수를 입력할 경우 감한다.

+ * + *
+	 * DateUtil.addYear("20000201", 62)  = "20620201"
+	 * DateUtil.addYear("20620201", -62) = "20000201"
+	 * DateUtil.addYear("20040229", 2)   = "20060228"
+	 * DateUtil.addYear("20060228", -2)  = "20040228"
+	 * DateUtil.addYear("19000101", 200) = "21000101"
+	 * 
+ * + * @param dateStr 날짜 문자열(yyyyMMdd, yyyy-MM-dd의 형식) + * @param year 가감할 년. 0이 입력될 경우 가감이 없다 + * @return yyyyMMdd 형식의 날짜 문자열 + * @throws IllegalArgumentException 날짜 포맷이 정해진 바와 다를 경우. + * 입력 값이 null인 경우. + */ + public static String addYear(String dateStr, int year) { + return addYearMonthDay(dateStr, year, 0, 0); + } + + /** + *

yyyyMMdd 혹은 yyyy-MM-dd 형식의 날짜 문자열을 입력 받아 월을 + * 증감한다. month는 가감할 수를 의미하며, 음수를 입력할 경우 감한다.

+ * + *
+	 * DateUtil.addMonth("20010201", 12)  = "20020201"
+	 * DateUtil.addMonth("19800229", 12)  = "19810228"
+	 * DateUtil.addMonth("20040229", 12)  = "20050228"
+	 * DateUtil.addMonth("20050228", -12) = "20040228"
+	 * DateUtil.addMonth("20060131", 1)   = "20060228"
+	 * DateUtil.addMonth("20060228", -1)  = "20060128"
+	 * 
+ * + * @param dateStr 날짜 문자열(yyyyMMdd, yyyy-MM-dd의 형식) + * @param month 가감할 월. 0이 입력될 경우 가감이 없다 + * @return yyyyMMdd 형식의 날짜 문자열 + * @throws IllegalArgumentException 날짜 포맷이 정해진 바와 다를 경우. + * 입력 값이 null인 경우. + */ + public static String addMonth(String dateStr, int month) { + return addYearMonthDay(dateStr, 0, month, 0); + } + + /** + *

yyyyMMdd 혹은 yyyy-MM-dd 형식의 날짜 문자열을 입력 받아 일(day)를 + * 증감한다. day는 가감할 수를 의미하며, 음수를 입력할 경우 감한다. + *

+ * 위에 정의된 addDays 메서드는 사용자가 ParseException을 반드시 처리해야 하는 불편함이 + * 있기 때문에 추가된 메서드이다.

+ * + *
+	 * DateUtil.addDay("19991201", 62) = "20000201"
+	 * DateUtil.addDay("20000201", -62) = "19991201"
+	 * DateUtil.addDay("20050831", 3) = "20050903"
+	 * DateUtil.addDay("20050831", 3) = "20050903"
+	 * // 2006년 6월 31일은 실제로 존재하지 않는 날짜이다 -> 20060701로 간주된다
+	 * DateUtil.addDay("20060631", 1) = "20060702"
+	 * 
+ * + * @param dateStr 날짜 문자열(yyyyMMdd, yyyy-MM-dd의 형식) + * @param day 가감할 일. 0이 입력될 경우 가감이 없다 + * @return yyyyMMdd 형식의 날짜 문자열 + * @throws IllegalArgumentException 날짜 포맷이 정해진 바와 다를 경우. + * 입력 값이 null인 경우. + */ + public static String addDay(String dateStr, int day) { + return addYearMonthDay(dateStr, 0, 0, day); + } + + /** + *

yyyyMMdd 혹은 yyyy-MM-dd 형식의 날짜 문자열 dateStr1 + * dateStr2 사이의 일 수를 구한다.
+ * dateStr2dateStr1 보다 과거 날짜일 경우에는 + * 음수를 반환한다. 동일한 경우에는 0을 반환한다.

+ * + *
+	 * DateUtil.getDaysDiff("20060228","20060310") = 10
+	 * DateUtil.getDaysDiff("20060101","20070101") = 365
+	 * DateUtil.getDaysDiff("19990228","19990131") = -28
+	 * DateUtil.getDaysDiff("20060801","20060802") = 1
+	 * DateUtil.getDaysDiff("20060801","20060801") = 0
+	 * 
+ * + * @param dateStr1 날짜 문자열(yyyyMMdd, yyyy-MM-dd의 형식) + * @param dateStr2 날짜 문자열(yyyyMMdd, yyyy-MM-dd의 형식) + * @return 일 수 차이. + * @throws IllegalArgumentException 날짜 포맷이 정해진 바와 다를 경우. + * 입력 값이 null인 경우. + */ + public static int getDaysDiff(String sDate1, String sDate2) { + String dateStr1 = validChkDate(sDate1); + String dateStr2 = validChkDate(sDate2); + + if (!checkDate(sDate1) || !checkDate(sDate2)) { + throw new IllegalArgumentException("Invalid date format: args[0]=" + sDate1 + " args[1]=" + sDate2); + } + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd", Locale.getDefault()); + + Date date1 = null; + Date date2 = null; + try { + date1 = sdf.parse(dateStr1); + date2 = sdf.parse(dateStr2); + } catch (ParseException e) { + throw new IllegalArgumentException("Invalid date format: args[0]=" + dateStr1 + " args[1]=" + dateStr2); + } + + if (date1 != null && date2 != null) { + int days1 = (int) ((date1.getTime() / 3600000) / 24); + int days2 = (int) ((date2.getTime() / 3600000) / 24); + return days2 - days1; + } else { + return 0; + } + + } + + /** + *

yyyyMMdd 혹은 yyyy-MM-dd 형식의 날짜 문자열을 입력 받아 유효한 날짜인지 검사.

+ * + *
+	 * DateUtil.checkDate("1999-02-35") = false
+	 * DateUtil.checkDate("2000-13-31") = false
+	 * DateUtil.checkDate("2006-11-31") = false
+	 * DateUtil.checkDate("2006-2-28")  = false
+	 * DateUtil.checkDate("2006-2-8")   = false
+	 * DateUtil.checkDate("20060228")   = true
+	 * DateUtil.checkDate("2006-02-28") = true
+	 * 
+ * + * @param dateStr 날짜 문자열(yyyyMMdd, yyyy-MM-dd의 형식) + * @return 유효한 날짜인지 여부 + */ + public static boolean checkDate(String sDate) { + String dateStr = validChkDate(sDate); + + String year = dateStr.substring(0, 4); + String month = dateStr.substring(4, 6); + String day = dateStr.substring(6); + + return checkDate(year, month, day); + } + + /** + *

입력한 년, 월, 일이 유효한지 검사.

+ * + * @param year 연도 + * @param month 월 + * @param day 일 + * @return 유효한 날짜인지 여부 + */ + public static boolean checkDate(String year, String month, String day) { + try { + SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd", Locale.getDefault()); + + Date result = formatter.parse(year + "." + month + "." + day); + String resultStr = formatter.format(result); + if (resultStr.equalsIgnoreCase(year + "." + month + "." + day)) + return true; + else + return false; + } catch (ParseException e) { + return false; + } + } + + /** + * 날짜형태의 String의 날짜 포맷 및 TimeZone을 변경해 주는 메서드 + * + * @param strSource 바꿀 날짜 String + * @param fromDateFormat 기존의 날짜 형태 + * @param toDateFormat 원하는 날짜 형태 + * @param strTimeZone 변경할 TimeZone(""이면 변경 안함) + * @return 소스 String의 날짜 포맷을 변경한 String + */ + public static String convertDate(String strSource, String fromDateFormat, String toDateFormat, String strTimeZone) { + SimpleDateFormat simpledateformat = null; + Date date = null; + String fromFormat = ""; + String toFormat = ""; + + if (EgovStringUtil.isNullToString(strSource).trim().equals("")) { + return ""; + } + if (EgovStringUtil.isNullToString(fromDateFormat).trim().equals("")) + fromFormat = "yyyyMMddHHmmss"; // default값 + if (EgovStringUtil.isNullToString(toDateFormat).trim().equals("")) + toFormat = "yyyy-MM-dd HH:mm:ss"; // default값 + + try { + simpledateformat = new SimpleDateFormat(fromFormat, Locale.getDefault()); + date = simpledateformat.parse(strSource); + if (!EgovStringUtil.isNullToString(strTimeZone).trim().equals("")) { + simpledateformat.setTimeZone(TimeZone.getTimeZone(strTimeZone)); + } + simpledateformat = new SimpleDateFormat(toFormat, Locale.getDefault()); + } catch (ParseException exception) { + throw new RuntimeException(exception); + } + + return simpledateformat.format(date); + + } + + /** + * yyyyMMdd 형식의 날짜문자열을 원하는 캐릭터(ch)로 쪼개 돌려준다
+ *
+	* ex) 20030405, ch(.) -> 2003.04.05
+	* ex) 200304, ch(.) -> 2003.04
+	* ex) 20040101,ch(/) --> 2004/01/01 로 리턴
+	* 
+ * + * @param date yyyyMMdd 형식의 날짜문자열 + * @param ch 구분자 + * @return 변환된 문자열 + */ + public static String formatDate(String sDate, String ch) { + String dateStr = validChkDate(sDate); + + String str = dateStr.trim(); + String yyyy = ""; + String mm = ""; + String dd = ""; + + if (str.length() == 8) { + yyyy = str.substring(0, 4); + if (yyyy.equals("0000")) { + return ""; + } + + mm = str.substring(4, 6); + if (mm.equals("00")) { + return yyyy; + } + + dd = str.substring(6, 8); + if (dd.equals("00")) { + return yyyy + ch + mm; + } + + return yyyy + ch + mm + ch + dd; + + } else if (str.length() == 6) { + yyyy = str.substring(0, 4); + if (yyyy.equals("0000")) { + return ""; + } + + mm = str.substring(4, 6); + if (mm.equals("00")) { + return yyyy; + } + + return yyyy + ch + mm; + + } else if (str.length() == 4) { + yyyy = str.substring(0, 4); + if (yyyy.equals("0000")) { + return ""; + } else { + return yyyy; + } + } else { + return ""; + } + } + + /** + * HH24MISS 형식의 시간문자열을 원하는 캐릭터(ch)로 쪼개 돌려준다
+ *
+	 *     ex) 151241, ch(/) -> 15/12/31
+	 * 
+ * + * @param str HH24MISS 형식의 시간문자열 + * @param ch 구분자 + * @return 변환된 문자열 + */ + public static String formatTime(String sTime, String ch) { + String timeStr = validChkTime(sTime); + return timeStr.substring(0, 2) + ch + timeStr.substring(2, 4) + ch + timeStr.substring(4, 6); + } + + /** + * 연도를 입력 받아 해당 연도 2월의 말일(일수)를 문자열로 반환한다. + * + * @param year + * @return 해당 연도 2월의 말일(일수) + */ + public String leapYear(int year) { + if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { + return "29"; + } + + return "28"; + } + + /** + *

입력받은 연도가 윤년인지 아닌지 검사한다.

+ * + *
+	 * DateUtil.isLeapYear(2004) = false
+	 * DateUtil.isLeapYear(2005) = true
+	 * DateUtil.isLeapYear(2006) = true
+	 * 
+ * + * @param year 연도 + * @return 윤년 여부 + */ + public static boolean isLeapYear(int year) { + if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { + return false; + } + return true; + } + + /** + * 현재(한국기준) 날짜정보를 얻는다.
+ * 표기법은 yyyy-mm-dd
+ * @return String yyyymmdd형태의 현재 한국시간.
+ */ + public static String getToday() { + return getCurrentDate(""); + } + + /** + * 현재(한국기준) 날짜정보를 얻는다.
+ * 표기법은 yyyy-mm-dd
+ * @return String yyyymmdd형태의 현재 한국시간.
+ */ + public static String getCurrentDate(String dateType) { + Calendar aCalendar = Calendar.getInstance(); + + int year = aCalendar.get(Calendar.YEAR); + int month = aCalendar.get(Calendar.MONTH) + 1; + int date = aCalendar.get(Calendar.DATE); + String strDate = Integer.toString(year) + + ((month < 10) ? "0" + Integer.toString(month) : Integer.toString(month)) + + ((date < 10) ? "0" + Integer.toString(date) : Integer.toString(date)); + + if (!"".equals(dateType)) { + strDate = convertDate(strDate, "yyyyMMdd", dateType); + } + + return strDate; + } + + /** + * 날짜형태의 String의 날짜 포맷만을 변경해 주는 메서드 + * @param sDate 날짜 + * @param sTime 시간 + * @param sFormatStr 포멧 스트링 문자열 + * @return 지정한 날짜/시간을 지정한 포맷으로 출력 + * @See Letter Date or Time Component Presentation Examples + G Era designator Text AD + y Year Year 1996; 96 + M Month in year Month July; Jul; 07 + w Week in year Number 27 + W Week in month Number 2 + D Day in year Number 189 + d Day in month Number 10 + F Day of week in month Number 2 + E Day in week Text Tuesday; Tue + a Am/pm marker Text PM + H Hour in day (0-23) Number 0 + k Hour in day (1-24) Number 24 + K Hour in am/pm (0-11) Number 0 + h Hour in am/pm (1-12) Number 12 + m Minute in hour Number 30 + s Second in minute Number 55 + S Millisecond Number 978 + z Time zone General time zone Pacific Standard Time; PST; GMT-08:00 + Z Time zone RFC 822 time zone -0800 + + Date and Time Pattern Result + "yyyy.MM.dd G 'at' HH:mm:ss z" 2001.07.04 AD at 12:08:56 PDT + "EEE, MMM d, ''yy" Wed, Jul 4, '01 + "h:mm a" 12:08 PM + "hh 'o''clock' a, zzzz" 12 o'clock PM, Pacific Daylight Time + "K:mm a, z" 0:08 PM, PDT + "yyyyy.MMMMM.dd GGG hh:mm aaa" 02001.July.04 AD 12:08 PM + "EEE, d MMM yyyy HH:mm:ss Z" Wed, 4 Jul 2001 12:08:56 -0700 + "yyMMddHHmmssZ" 010704120856-0700 + + */ + public static String convertDate(String sDate, String sTime, String sFormatStr) { + String dateStr = validChkDate(sDate); + String timeStr = validChkTime(sTime); + + Calendar cal = null; + cal = Calendar.getInstance(); + + cal.set(Calendar.YEAR, Integer.parseInt(dateStr.substring(0, 4))); + cal.set(Calendar.MONTH, Integer.parseInt(dateStr.substring(4, 6)) - 1); + cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dateStr.substring(6, 8))); + cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(timeStr.substring(0, 2))); + cal.set(Calendar.MINUTE, Integer.parseInt(timeStr.substring(2, 4))); + + SimpleDateFormat sdf = new SimpleDateFormat(sFormatStr, Locale.ENGLISH); + + return sdf.format(cal.getTime()); + } + + /** + * 입력받은 일자 사이의 임의의 일자를 반환 + * @param sDate1 시작일자 + * @param sDate2 종료일자 + * @return 임의일자 + */ + public static String getRandomDate(String sDate1, String sDate2) { + String dateStr1 = validChkDate(sDate1); + String dateStr2 = validChkDate(sDate2); + + String randomDate = null; + + int sYear, sMonth, sDay; + int eYear, eMonth, eDay; + + sYear = Integer.parseInt(dateStr1.substring(0, 4)); + sMonth = Integer.parseInt(dateStr1.substring(4, 6)); + sDay = Integer.parseInt(dateStr1.substring(6, 8)); + + eYear = Integer.parseInt(dateStr2.substring(0, 4)); + eMonth = Integer.parseInt(dateStr2.substring(4, 6)); + eDay = Integer.parseInt(dateStr2.substring(6, 8)); + + GregorianCalendar beginDate = new GregorianCalendar(sYear, sMonth - 1, sDay, 0, 0); + GregorianCalendar endDate = new GregorianCalendar(eYear, eMonth - 1, eDay, 23, 59); + + if (endDate.getTimeInMillis() < beginDate.getTimeInMillis()) { + throw new IllegalArgumentException("Invalid input date : " + sDate1 + "~" + sDate2); + } + + SecureRandom r = new SecureRandom(); + + r.setSeed(new Date().getTime()); + + long rand = ((r.nextLong() >>> 1) % (endDate.getTimeInMillis() - beginDate.getTimeInMillis() + 1)) + beginDate.getTimeInMillis(); + + GregorianCalendar cal = new GregorianCalendar(); + //SimpleDateFormat calformat = new SimpleDateFormat("yyyy-MM-dd"); + SimpleDateFormat calformat = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH); + cal.setTimeInMillis(rand); + randomDate = calformat.format(cal.getTime()); + + // 랜덤문자열를 리턴 + return randomDate; + } + + /** + * 입력받은 양력일자를 변환하여 음력일자로 반환 + * @param sDate 양력일자 + * @return 음력일자 + */ + public static Map toLunar(String sDate) { + String dateStr = validChkDate(sDate); + + Map hm = new HashMap(); + hm.put("day", ""); + hm.put("leap", "0"); + + if (dateStr.length() != 8) { + return hm; + } + + Calendar cal; + ChineseCalendar lcal; + + cal = Calendar.getInstance(); + lcal = new ChineseCalendar(); + + cal.set(Calendar.YEAR, Integer.parseInt(dateStr.substring(0, 4))); + cal.set(Calendar.MONTH, Integer.parseInt(dateStr.substring(4, 6)) - 1); + cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dateStr.substring(6, 8))); + + lcal.setTimeInMillis(cal.getTimeInMillis()); + + String year = String.valueOf(lcal.get(ChineseCalendar.EXTENDED_YEAR) - 2637); + String month = String.valueOf(lcal.get(ChineseCalendar.MONTH) + 1); + String day = String.valueOf(lcal.get(ChineseCalendar.DAY_OF_MONTH)); + String leap = String.valueOf(lcal.get(ChineseCalendar.IS_LEAP_MONTH)); + + String pad4Str = "0000"; + String pad2Str = "00"; + + String retYear = (pad4Str + year).substring(year.length()); + String retMonth = (pad2Str + month).substring(month.length()); + String retDay = (pad2Str + day).substring(day.length()); + + String SDay = retYear + retMonth + retDay; + + hm.put("day", SDay); + hm.put("leap", leap); + + return hm; + } + + /** + * 입력받은 음력일자를 변환하여 양력일자로 반환 + * @param sDate 음력일자 + * @param iLeapMonth 음력윤달여부(IS_LEAP_MONTH) + * @return 양력일자 + */ + public static String toSolar(String sDate, int iLeapMonth) { + String dateStr = validChkDate(sDate); + + Calendar cal; + ChineseCalendar lcal; + + cal = Calendar.getInstance(); + lcal = new ChineseCalendar(); + + lcal.set(ChineseCalendar.EXTENDED_YEAR, Integer.parseInt(dateStr.substring(0, 4)) + 2637); + lcal.set(ChineseCalendar.MONTH, Integer.parseInt(dateStr.substring(4, 6)) - 1); + lcal.set(ChineseCalendar.DAY_OF_MONTH, Integer.parseInt(dateStr.substring(6, 8))); + lcal.set(ChineseCalendar.IS_LEAP_MONTH, iLeapMonth); + + cal.setTimeInMillis(lcal.getTimeInMillis()); + + String year = String.valueOf(cal.get(Calendar.YEAR)); + String month = String.valueOf(cal.get(Calendar.MONTH) + 1); + String day = String.valueOf(cal.get(Calendar.DAY_OF_MONTH)); + + String pad4Str = "0000"; + String pad2Str = "00"; + + String retYear = (pad4Str + year).substring(year.length()); + String retMonth = (pad2Str + month).substring(month.length()); + String retDay = (pad2Str + day).substring(day.length()); + + return retYear + retMonth + retDay; + } + + /** + * 입력받은 요일의 영문명을 국문명의 요일로 반환 + * @param sWeek 영문 요일명 + * @return 국문 요일명 + */ + public static String convertWeek(String sWeek) { + String retStr = null; + + if (sWeek.equals("SUN")) { + retStr = "일요일"; + } else if (sWeek.equals("MON")) { + retStr = "월요일"; + } else if (sWeek.equals("TUE")) { + retStr = "화요일"; + } else if (sWeek.equals("WED")) { + retStr = "수요일"; + } else if (sWeek.equals("THR")) { + retStr = "목요일"; + } else if (sWeek.equals("FRI")) { + retStr = "금요일"; + } else if (sWeek.equals("SAT")) { + retStr = "토요일"; + } + + return retStr; + } + + /** + * 입력일자의 유효 여부를 확인 + * @param sDate 일자 + * @return 유효 여부 + */ + public static boolean validDate(String sDate) { + String dateStr = validChkDate(sDate); + + Calendar cal; + boolean ret = false; + + cal = Calendar.getInstance(); + + cal.set(Calendar.YEAR, Integer.parseInt(dateStr.substring(0, 4))); + cal.set(Calendar.MONTH, Integer.parseInt(dateStr.substring(4, 6)) - 1); + cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dateStr.substring(6, 8))); + + String year = String.valueOf(cal.get(Calendar.YEAR)); + String month = String.valueOf(cal.get(Calendar.MONTH) + 1); + String day = String.valueOf(cal.get(Calendar.DAY_OF_MONTH)); + + String pad4Str = "0000"; + String pad2Str = "00"; + + String retYear = (pad4Str + year).substring(year.length()); + String retMonth = (pad2Str + month).substring(month.length()); + String retDay = (pad2Str + day).substring(day.length()); + + String retYMD = retYear + retMonth + retDay; + + if (sDate.equals(retYMD)) { + ret = true; + } + + return ret; + } + + /** + * 입력일자, 요일의 유효 여부를 확인 + * @param sDate 일자 + * @param sWeek 요일 (DAY_OF_WEEK) + * @return 유효 여부 + */ + public static boolean validDate(String sDate, int sWeek) { + String dateStr = validChkDate(sDate); + + Calendar cal; + boolean ret = false; + + cal = Calendar.getInstance(); + + cal.set(Calendar.YEAR, Integer.parseInt(dateStr.substring(0, 4))); + cal.set(Calendar.MONTH, Integer.parseInt(dateStr.substring(4, 6)) - 1); + cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dateStr.substring(6, 8))); + + int Week = cal.get(Calendar.DAY_OF_WEEK); + + if (validDate(sDate)) { + if (sWeek == Week) { + ret = true; + } + } + + return ret; + } + + /** + * 입력시간의 유효 여부를 확인 + * @param sTime 입력시간 + * @return 유효 여부 + */ + public static boolean validTime(String sTime) { + String timeStr = validChkTime(sTime); + + Calendar cal; + boolean ret = false; + + cal = Calendar.getInstance(); + + cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(timeStr.substring(0, 2))); + cal.set(Calendar.MINUTE, Integer.parseInt(timeStr.substring(2, 4))); + + String HH = String.valueOf(cal.get(Calendar.HOUR_OF_DAY)); + String MM = String.valueOf(cal.get(Calendar.MINUTE)); + + String pad2Str = "00"; + + String retHH = (pad2Str + HH).substring(HH.length()); + String retMM = (pad2Str + MM).substring(MM.length()); + + String retTime = retHH + retMM; + + if (sTime.equals(retTime)) { + ret = true; + } + + return ret; + } + + /** + * 입력된 일자에 연, 월, 일을 가감한 날짜의 요일을 반환 + * @param sDate 날짜 + * @param year 연 + * @param month 월 + * @param day 일 + * @return 계산된 일자의 요일(DAY_OF_WEEK) + */ + public static String addYMDtoWeek(String sDate, int year, int month, int day) { + String dateStr = validChkDate(sDate); + + dateStr = addYearMonthDay(dateStr, year, month, day); + + Calendar cal = Calendar.getInstance(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH); + try { + cal.setTime(sdf.parse(dateStr)); + } catch (ParseException e) { + throw new IllegalArgumentException("Invalid date format: " + dateStr); + } + + SimpleDateFormat rsdf = new SimpleDateFormat("E", Locale.ENGLISH); + + return rsdf.format(cal.getTime()); + } + + /** + * 입력된 일자에 연, 월, 일, 시간, 분을 가감한 날짜, 시간을 포멧스트링 형식으로 반환 + * @param sDate 날짜 + * @param sTime 시간 + * @param year 연 + * @param month 월 + * @param day 일 + * @param hour 시간 + * @param minute 분 + * @param formatStr 포멧스트링 + * @return + */ + public static String addYMDtoDayTime(String sDate, String sTime, int year, int month, int day, int hour, int minute, String formatStr) { + String dateStr = validChkDate(sDate); + String timeStr = validChkTime(sTime); + + dateStr = addYearMonthDay(dateStr, year, month, day); + + dateStr = convertDate(dateStr, timeStr, "yyyyMMddHHmm"); + + Calendar cal = Calendar.getInstance(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm", Locale.ENGLISH); + + try { + cal.setTime(sdf.parse(dateStr)); + } catch (ParseException e) { + throw new IllegalArgumentException("Invalid date format: " + dateStr); + } + + if (hour != 0) { + cal.add(Calendar.HOUR, hour); + } + + if (minute != 0) { + cal.add(Calendar.MINUTE, minute); + } + + SimpleDateFormat rsdf = new SimpleDateFormat(formatStr, Locale.ENGLISH); + + return rsdf.format(cal.getTime()); + } + + /** + * 입력된 일자를 int 형으로 반환 + * @param sDate 일자 + * @return int(일자) + */ + public static int datetoInt(String sDate) { + return Integer.parseInt(convertDate(sDate, "0000", "yyyyMMdd")); + } + + /** + * 입력된 시간을 int 형으로 반환 + * @param sTime 시간 + * @return int(시간) + */ + public static int timetoInt(String sTime) { + return Integer.parseInt(convertDate("00000101", sTime, "HHmm")); + } + + /** + * 입력된 일자 문자열을 확인하고 8자리로 리턴 + * @param sDate + * @return + */ + public static String validChkDate(String dateStr) { + if (dateStr == null || !(dateStr.trim().length() == 8 || dateStr.trim().length() == 10)) { + throw new IllegalArgumentException("Invalid date format: " + dateStr); + } + + if (dateStr.length() == 10) { + return EgovStringUtil.removeMinusChar(dateStr); + } + + return dateStr; + } + + /** + * 입력된 일자 문자열을 확인하고 8자리로 리턴 + * @param sDate + * @return + */ + public static String validChkTime(String timeStr) { + if (timeStr == null || !(timeStr.trim().length() == 4)) { + throw new IllegalArgumentException("Invalid time format: " + timeStr); + } + + if (timeStr.length() == 5) { + timeStr = EgovStringUtil.remove(timeStr, ':'); + } + + return timeStr; + } + +} diff --git a/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovFileUploadUtil.java b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovFileUploadUtil.java new file mode 100644 index 00000000..bd943a5c --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovFileUploadUtil.java @@ -0,0 +1,159 @@ +package egovframework.com.utl.fcc.service; + +import java.io.File; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import egovframework.com.cmm.EgovWebUtil; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +/** + * @Class Name : EgovFileUploadUtil.java + * @Description : Spring 기반 File Upload 유틸리티 + * @Modification Information + * + * 수정일 수정자 수정내용 + * ---------- -------- --------------------------- + * 2009.08.26 한성곤 최초 생성 + * 2018.08.17 신용호 uploadFilesExt(확장자 기록) 추가 + * + * @author 공통컴포넌트 개발팀 한성곤 + * @since 2009.08.26 + * @version 1.0 + * @see + */ +public class EgovFileUploadUtil extends EgovFormBasedFileUtil { + /** + * 파일을 Upload 처리한다. + * + * @param request + * @param where + * @param maxFileSize + * @return + * @throws Exception + */ + public static List uploadFiles(HttpServletRequest request, String where, long maxFileSize) throws Exception { + List list = new ArrayList(); + + MultipartHttpServletRequest mptRequest = (MultipartHttpServletRequest) request; + Iterator fileIter = mptRequest.getFileNames(); + + while (fileIter.hasNext()) { + MultipartFile mFile = mptRequest.getFile((String) fileIter.next()); + + EgovFormBasedFileVo vo = new EgovFormBasedFileVo(); + + String tmp = mFile.getOriginalFilename(); + + if (tmp.lastIndexOf("\\") >= 0) { + tmp = tmp.substring(tmp.lastIndexOf("\\") + 1); + } + + vo.setFileName(tmp); + vo.setContentType(mFile.getContentType()); + vo.setServerSubPath(getTodayString()); + vo.setPhysicalName(getPhysicalFileName()); + vo.setSize(mFile.getSize()); + + if (tmp.lastIndexOf(".") >= 0) { + vo.setPhysicalName(vo.getPhysicalName()); // 2012.11 KISA 보안조치 + } + + if (mFile.getSize() > 0) { + InputStream is = null; + + try { + is = mFile.getInputStream(); + saveFile(is, new File(EgovWebUtil.filePathBlackList(where + SEPERATOR + vo.getServerSubPath() + SEPERATOR + vo.getPhysicalName()))); + } finally { + if (is != null) { + is.close(); + } + } + list.add(vo); + } + } + + return list; + } + + /** + * 파일을 Upload(확장명 저장 및 확장자 제한) 처리한다. + * + * @param request + * @param where + * @param maxFileSize + * @return + * @throws Exception + */ + public static List uploadFilesExt(HttpServletRequest request, String where, long maxFileSize, String extensionWhiteList) throws Exception { + List list = new ArrayList(); + + MultipartHttpServletRequest mptRequest = (MultipartHttpServletRequest) request; + Iterator fileIter = mptRequest.getFileNames(); + + while (fileIter.hasNext()) { + MultipartFile mFile = mptRequest.getFile((String) fileIter.next()); + + EgovFormBasedFileVo vo = new EgovFormBasedFileVo(); + + String tmp = mFile.getOriginalFilename(); + + if (tmp.lastIndexOf("\\") >= 0) { + tmp = tmp.substring(tmp.lastIndexOf("\\") + 1); + } + String ext = ""; + if ( tmp.lastIndexOf(".") > 0 ) + ext = getFileExtension(tmp).toLowerCase(); + else + throw new SecurityException("Unacceptable file extension."); // 허용되지 않는 확장자 처리 + if ( extensionWhiteList.indexOf(ext) < 0 ) + throw new SecurityException("Unacceptable file extension."); // 허용되지 않는 확장자 처리 + + vo.setFileName(tmp); + vo.setContentType(mFile.getContentType()); + vo.setServerSubPath(getTodayString()); + vo.setPhysicalName(getPhysicalFileName()+"."+ext); + vo.setSize(mFile.getSize()); + + if (tmp.lastIndexOf(".") >= 0) { + vo.setPhysicalName(vo.getPhysicalName()); // 2012.11 KISA 보안조치 + } + + if (mFile.getSize() > 0) { + InputStream is = null; + + try { + is = mFile.getInputStream(); + saveFile(is, new File(EgovWebUtil.filePathBlackList(where + SEPERATOR + vo.getServerSubPath() + SEPERATOR + vo.getPhysicalName()))); + } finally { + if (is != null) { + is.close(); + } + } + list.add(vo); + } + } + + return list; + } + + /** + * 파일 확장자를 추출한다. + * + * @param fileNamePath + * @return + */ + public static String getFileExtension(String fileNamePath) { + + String ext = fileNamePath.substring(fileNamePath.lastIndexOf(".") + 1,fileNamePath.length()); + + return (ext == null) ? "" : ext; + } +} diff --git a/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovFormBasedFileUtil.java b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovFormBasedFileUtil.java new file mode 100644 index 00000000..4e0db437 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovFormBasedFileUtil.java @@ -0,0 +1,295 @@ +package egovframework.com.utl.fcc.service; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import egovframework.com.cmm.EgovWebUtil; +import egovframework.com.cmm.util.EgovResourceCloseHelper; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.fileupload.FileItemIterator; +import org.apache.commons.fileupload.FileItemStream; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.apache.commons.fileupload.util.Streams; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @Class Name : EgovFormBasedFileUtil.java + * @Description : Form-based File Upload 유틸리티 + * @Modification Information + * + * 수정일 수정자 수정내용 + * ------- -------- --------------------------- + * 2009.08.26 한성곤 최초 생성 + * 2017.03.03 조성원 시큐어코딩(ES)-부적절한 예외 처리[CWE-253, CWE-440, CWE-754] + * + * @author 공통컴포넌트 개발팀 한성곤 + * @since 2009.08.26 + * @version 1.0 + * @see + */ +public class EgovFormBasedFileUtil { + /** Buffer size */ + public static final int BUFFER_SIZE = 8192; + + public static final String SEPERATOR = File.separator; + + private static final Logger LOGGER = LoggerFactory.getLogger(EgovFormBasedFileUtil.class); + + /** + * 오늘 날짜 문자열 취득. + * ex) 20090101 + * @return + */ + public static String getTodayString() { + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.getDefault()); + + return format.format(new Date()); + } + + /** + * 물리적 파일명 생성. + * @return + */ + public static String getPhysicalFileName() { + return EgovFormBasedUUID.randomUUID().toString().replaceAll("-", "").toUpperCase(); + } + + /** + * 파일명 변환. + * @param filename String + * @return + * @throws Exception + */ + protected static String convert(String filename) throws Exception { + //return java.net.URLEncoder.encode(filename, "utf-8"); + return filename; + } + + /** + * Stream으로부터 파일을 저장함. + * @param is InputStream + * @param file File + * @throws IOException + */ + public static long saveFile(InputStream is, File file) throws IOException { + //KISA 보안약점 조치 (2018-10-29, 윤창원) + if (file.getParentFile() == null) { + LOGGER.debug("file.getParentFile() is null"); + throw new RuntimeException("file.getParentFile() is null"); + } + + // 디렉토리 생성 + if (!file.getParentFile().exists()) { + //2017.03.03 조성원 시큐어코딩(ES)-부적절한 예외 처리[CWE-253, CWE-440, CWE-754] + if(file.getParentFile().mkdirs()){ + LOGGER.debug("[file.mkdirs] file : Directory Creation Success"); + }else{ + LOGGER.error("[file.mkdirs] file : Directory Creation Fail"); + } + } + + OutputStream os = null; + long size = 0L; + + try { + os = new FileOutputStream(file); + + int bytesRead = 0; + byte[] buffer = new byte[BUFFER_SIZE]; + + while ((bytesRead = is.read(buffer, 0, BUFFER_SIZE)) != -1) { + size += bytesRead; + os.write(buffer, 0, bytesRead); + } + } finally { + EgovResourceCloseHelper.close(os); + } + + return size; + } + + /** + * 파일을 Upload 처리한다. + * + * @param request + * @param where + * @param maxFileSize + * @return + * @throws Exception + */ + public static List uploadFiles(HttpServletRequest request, String where, long maxFileSize) throws Exception { + List list = new ArrayList(); + + // Check that we have a file upload request + boolean isMultipart = ServletFileUpload.isMultipartContent(request); + + if (isMultipart) { + // Create a new file upload handler + ServletFileUpload upload = new ServletFileUpload(); + upload.setFileSizeMax(maxFileSize); // SizeLimitExceededException + + // Parse the request + FileItemIterator iter = upload.getItemIterator(request); + while (iter.hasNext()) { + FileItemStream item = iter.next(); + String name = item.getFieldName(); + InputStream stream = item.openStream(); + if (item.isFormField()) { + LOGGER.info("Form field '{}' with value '{}' detected.", name, Streams.asString(stream)); + } else { + LOGGER.info("File field '{}' with file name '{}' detected.", name, item.getName()); + + if ("".equals(item.getName())) { + continue; + } + + // Process the input stream + EgovFormBasedFileVo vo = new EgovFormBasedFileVo(); + + String tmp = item.getName(); + + if (tmp.lastIndexOf("\\") >= 0) { + tmp = tmp.substring(tmp.lastIndexOf("\\") + 1); + } + + vo.setFileName(tmp); + vo.setContentType(item.getContentType()); + vo.setServerSubPath(getTodayString()); + vo.setPhysicalName(getPhysicalFileName()); + + if (tmp.lastIndexOf(".") >= 0) { + vo.setPhysicalName(vo.getPhysicalName() + tmp.substring(tmp.lastIndexOf("."))); + } + + long size = saveFile(stream, new File(EgovWebUtil.filePathBlackList(where) + SEPERATOR + vo.getServerSubPath() + SEPERATOR + vo.getPhysicalName())); + + vo.setSize(size); + + list.add(vo); + } + } + } else { + throw new IOException("form's 'enctype' attribute have to be 'multipart/form-data'"); + } + + return list; + } + + /** + * 파일을 Download 처리한다. + * + * @param response + * @param where + * @param serverSubPath + * @param physicalName + * @param original + * @throws Exception + */ + public static void downloadFile(HttpServletResponse response, String where, String serverSubPath, String physicalName, String original) throws Exception { + String downFileName = where + SEPERATOR + serverSubPath + SEPERATOR + physicalName; + + File file = new File(EgovWebUtil.filePathBlackList(downFileName)); + + if (!file.exists()) { + throw new FileNotFoundException(downFileName); + } + + if (!file.isFile()) { + throw new FileNotFoundException(downFileName); + } + + byte[] b = new byte[BUFFER_SIZE]; + + original = original.replaceAll("\r", "").replaceAll("\n", ""); + response.setContentType("application/octet-stream"); + response.setHeader("Content-Disposition", "attachment; filename=\"" + convert(original) + "\";"); + response.setHeader("Content-Transfer-Encoding", "binary"); + response.setHeader("Pragma", "no-cache"); + response.setHeader("Expires", "0"); + + BufferedInputStream fin = null; + BufferedOutputStream outs = null; + + try { + fin = new BufferedInputStream(new FileInputStream(file)); + outs = new BufferedOutputStream(response.getOutputStream()); + + int read = 0; + + while ((read = fin.read(b)) != -1) { + outs.write(b, 0, read); + } + } finally { + EgovResourceCloseHelper.close(outs, fin); + } + } + + /** + * 이미지에 대한 미리보기 기능을 제공한다. + * + * mimeType의 경우는 JSP 상에서 다음과 같이 얻을 수 있다. + * getServletConfig().getServletContext().getMimeType(name); + * + * @param response + * @param where + * @param serverSubPath + * @param physicalName + * @param mimeType + * @throws Exception + */ + public static void viewFile(HttpServletResponse response, String where, String serverSubPath, String physicalName, String mimeTypeParam) throws Exception { + String mimeType = mimeTypeParam; + String downFileName = where + SEPERATOR + serverSubPath + SEPERATOR + physicalName; + + File file = new File(EgovWebUtil.filePathBlackList(downFileName)); + + if (!file.exists()) { + throw new FileNotFoundException(downFileName); + } + + if (!file.isFile()) { + throw new FileNotFoundException(downFileName); + } + + byte[] b = new byte[BUFFER_SIZE]; + + if (mimeType == null) { + mimeType = "application/octet-stream;"; + } + + response.setContentType(EgovWebUtil.removeCRLF(mimeType)); + response.setHeader("Content-Disposition", "filename=image;"); + + BufferedInputStream fin = null; + BufferedOutputStream outs = null; + + try { + fin = new BufferedInputStream(new FileInputStream(file)); + outs = new BufferedOutputStream(response.getOutputStream()); + + int read = 0; + + while ((read = fin.read(b)) != -1) { + outs.write(b, 0, read); + } + } finally { + EgovResourceCloseHelper.close(outs, fin); + } + } +} diff --git a/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovFormBasedFileVo.java b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovFormBasedFileVo.java new file mode 100644 index 00000000..48512db3 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovFormBasedFileVo.java @@ -0,0 +1,104 @@ +package egovframework.com.utl.fcc.service; + +import java.io.Serializable; + +/** + * @Class Name : EgovFormBasedFileVo.java + * @Description : Form-based File Upload VO + * @Modification Information + * + * 수정일 수정자 수정내용 + * ------- -------- --------------------------- + * 2009.08.26 한성곤 최초 생성 + * + * @author 공통컴포넌트 개발팀 한성곤 + * @since 2009.08.26 + * @version 1.0 + * @see + * + * Copyright (C) 2008 by MOPAS All right reserved. + */ +@SuppressWarnings("serial") +public class EgovFormBasedFileVo implements Serializable { + /** 파일명 */ + private String fileName = ""; + /** ContextType */ + private String contentType = ""; + /** 하위 디렉토리 지정 */ + private String serverSubPath = ""; + /** 물리적 파일명 */ + private String physicalName = ""; + /** 파일 사이즈 */ + private long size = 0L; + + /** + * fileName attribute를 리턴한다. + * @return the fileName + */ + public String getFileName() { + return fileName; + } + /** + * fileName attribute 값을 설정한다. + * @param fileName the fileName to set + */ + public void setFileName(String fileName) { + this.fileName = fileName; + } + /** + * contentType attribute를 리턴한다. + * @return the contentType + */ + public String getContentType() { + return contentType; + } + /** + * contentType attribute 값을 설정한다. + * @param contentType the contentType to set + */ + public void setContentType(String contentType) { + this.contentType = contentType; + } + /** + * serverSubPath attribute를 리턴한다. + * @return the serverSubPath + */ + public String getServerSubPath() { + return serverSubPath; + } + /** + * serverSubPath attribute 값을 설정한다. + * @param serverSubPath the serverSubPath to set + */ + public void setServerSubPath(String serverSubPath) { + this.serverSubPath = serverSubPath; + } + /** + * physicalName attribute를 리턴한다. + * @return the physicalName + */ + public String getPhysicalName() { + return physicalName; + } + /** + * physicalName attribute 값을 설정한다. + * @param physicalName the physicalName to set + */ + public void setPhysicalName(String physicalName) { + this.physicalName = physicalName; + } + /** + * size attribute를 리턴한다. + * @return the size + */ + public long getSize() { + return size; + } + /** + * size attribute 값을 설정한다. + * @param size the size to set + */ + public void setSize(long size) { + this.size = size; + } +} diff --git a/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovFormBasedUUID.java b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovFormBasedUUID.java new file mode 100644 index 00000000..6df377b5 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovFormBasedUUID.java @@ -0,0 +1,521 @@ +package egovframework.com.utl.fcc.service; + +import java.io.Serializable; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +/** + * + * A class that represents an immutable universally unique identifier (UUID). A + * UUID represents a 128-bit value. + * + *

+ * There exist different variants of these global identifiers. The methods of + * this class are for manipulating the Leach-Salz variant, although the + * constructors allow the creation of any variant of UUID (described below). + * + *

+ * The layout of a variant 2 (Leach-Salz) UUID is as follows: + * + * The most significant long consists of the following unsigned fields: + * + *

+ *   0xFFFFFFFF00000000 time_low
+ *   0x00000000FFFF0000 time_mid
+ *   0x000000000000F000 version
+ *   0x0000000000000FFF time_hi
+ * 
+ * + * The least significant long consists of the following unsigned fields: + * + *
+ *   0xC000000000000000 variant
+ *   0x3FFF000000000000 clock_seq
+ *   0x0000FFFFFFFFFFFF node
+ * 
+ * + *

+ * The variant field contains a value which identifies the layout of the + * UUID. The bit layout described above is valid only for a + * UUID with a variant value of 2, which indicates the Leach-Salz + * variant. + * + *

+ * The version field holds a value that describes the type of this UUID. + * There are four different basic types of UUIDs: time-based, DCE security, + * name-based, and randomly generated UUIDs. These types have a version value of + * 1, 2, 3 and 4, respectively. + * + *

+ * For more information including algorithms used to create UUIDs, + * see the Internet-Draft UUIDs + * and GUIDs or the standards body definition at ISO/IEC 11578:1996. + * + * @version 1.14, 07/12/04 + * @since 1.5 + */ +@SuppressWarnings("serial") +public class EgovFormBasedUUID implements Serializable { + /* + * The most significant 64 bits of this UUID. + * + * @serial + */ + private final long mostSigBits; + + /* + * The least significant 64 bits of this UUID. + * + * @serial + */ + private final long leastSigBits; + + /* + * The version number associated with this UUID. Computed on demand. + */ + private transient int version = -1; + + /* + * The variant number associated with this UUID. Computed on demand. + */ + private transient int variant = -1; + + /* + * The timestamp associated with this UUID. Computed on demand. + */ + private transient volatile long timestamp = -1; + + /* + * The clock sequence associated with this UUID. Computed on demand. + */ + private transient int sequence = -1; + + /* + * The node number associated with this UUID. Computed on demand. + */ + private transient long node = -1; + + /* + * The hashcode of this UUID. Computed on demand. + */ + private transient int hashCode = -1; + + /* + * The random number generator used by this class to create random based + * UUIDs. + */ + private static volatile SecureRandom numberGenerator = null; + + // Constructors and Factories + + /* + * Private constructor which uses a byte array to construct the new UUID. + */ + private EgovFormBasedUUID(byte[] data) { + long msb = 0; + long lsb = 0; + for (int i = 0; i < 8; i++) + msb = (msb << 8) | (data[i] & 0xff); + for (int i = 8; i < 16; i++) + lsb = (lsb << 8) | (data[i] & 0xff); + this.mostSigBits = msb; + this.leastSigBits = lsb; + } + + /** + * Constructs a new UUID using the specified data. + * mostSigBits is used for the most significant 64 bits of the + * UUID and leastSigBits becomes the least significant + * 64 bits of the UUID. + * + * @param mostSigBits + * @param leastSigBits + */ + public EgovFormBasedUUID(long mostSigBits, long leastSigBits) { + this.mostSigBits = mostSigBits; + this.leastSigBits = leastSigBits; + } + + /** + * Static factory to retrieve a type 4 (pseudo randomly generated) UUID. + * + * The UUID is generated using a cryptographically strong + * pseudo random number generator. + * + * @return a randomly generated UUID. + */ + public static EgovFormBasedUUID randomUUID() { + SecureRandom ng = numberGenerator; + if (ng == null) { + numberGenerator = ng = new SecureRandom(); + } + + byte[] randomBytes = new byte[16]; + ng.nextBytes(randomBytes); + randomBytes[6] &= 0x0f; /* clear version */ + randomBytes[6] |= 0x40; /* set to version 4 */ + randomBytes[8] &= 0x3f; /* clear variant */ + randomBytes[8] |= 0x80; /* set to IETF variant */ + + return new EgovFormBasedUUID(randomBytes); + } + + /** + * Static factory to retrieve a type 3 (name based) UUID based on + * the specified byte array. + * + * @param name + * a byte array to be used to construct a UUID. + * @return a UUID generated from the specified array. + */ + public static EgovFormBasedUUID nameUUIDFromBytes(byte[] name) { + MessageDigest md; + try { + // 2011.10.10 보안점검 후속조치 암호화 알고리즘 변경(MD5 -> SHA-256) + //md = MessageDigest.getInstance("MD5"); + md = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException nsae) { + //throw new InternalError("MD5 not supported"); + throw new InternalError("SHA-256 not supported"); + } + // 2011.10.10 보안점검 후속조치 + if (md == null) { + throw new RuntimeException("MessageDigest is null!!"); + } + // 2014.09.20 보안점검 후속 조치 + // Random 방식의 salt 추가 + SecureRandom ng = new SecureRandom(); + byte[] randomBytes = new byte[16]; + ng.nextBytes(randomBytes); + + md.reset(); + md.update(randomBytes); + byte[] sha = md.digest(name); + + + byte[] md5Bytes = new byte[8]; + System.arraycopy(sha, 0, md5Bytes, 0, 8); + //2011.10.10 보안점검 후속조치 끝 + + md5Bytes[6] &= 0x0f; /* clear version */ + md5Bytes[6] |= 0x30; /* set to version 3 */ + md5Bytes[8] &= 0x3f; /* clear variant */ + md5Bytes[8] |= 0x80; /* set to IETF variant */ + + return new EgovFormBasedUUID(md5Bytes); + } + + /** + * Creates a UUID from the string standard representation as + * described in the {@link #toString} method. + * + * @param name + * a string that specifies a UUID. + * @return a UUID with the specified value. + * @throws IllegalArgumentException + * if name does not conform to the string representation as + * described in {@link #toString}. + */ + public static EgovFormBasedUUID fromString(String name) { + String[] components = name.split("-"); + if (components.length != 5) + throw new IllegalArgumentException("Invalid UUID string: " + name); + for (int i = 0; i < 5; i++) + components[i] = "0x" + components[i]; + + long mostSigBits = Long.decode(components[0]).longValue(); + mostSigBits <<= 16; + mostSigBits |= Long.decode(components[1]).longValue(); + mostSigBits <<= 16; + mostSigBits |= Long.decode(components[2]).longValue(); + + long leastSigBits = Long.decode(components[3]).longValue(); + leastSigBits <<= 48; + leastSigBits |= Long.decode(components[4]).longValue(); + + return new EgovFormBasedUUID(mostSigBits, leastSigBits); + } + + // Field Accessor Methods + + /** + * Returns the least significant 64 bits of this UUID's 128 bit value. + * + * @return the least significant 64 bits of this UUID's 128 bit value. + */ + public long getLeastSignificantBits() { + return leastSigBits; + } + + /** + * Returns the most significant 64 bits of this UUID's 128 bit value. + * + * @return the most significant 64 bits of this UUID's 128 bit value. + */ + public long getMostSignificantBits() { + return mostSigBits; + } + + /** + * The version number associated with this UUID. The version + * number describes how this UUID was generated. + * + * The version number has the following meaning: + *

+ *

    + *
  • 1 Time-based UUID + *
  • 2 DCE security UUID + *
  • 3 Name-based UUID + *
  • 4 Randomly generated UUID + *
+ * + * @return the version number of this UUID. + */ + public int version() { + if (version < 0) { + // Version is bits masked by 0x000000000000F000 in MS long + version = (int) ((mostSigBits >> 12) & 0x0f); + } + return version; + } + + /** + * The variant number associated with this UUID. The variant + * number describes the layout of the UUID. + * + * The variant number has the following meaning: + *

+ *

    + *
  • 0 Reserved for NCS backward compatibility + *
  • 2 The Leach-Salz variant (used by this class) + *
  • 6 Reserved, Microsoft Corporation backward compatibility + *
  • 7 Reserved for future definition + *
+ * + * @return the variant number of this UUID. + */ + public int variant() { + if (variant < 0) { + // This field is composed of a varying number of bits + if ((leastSigBits >>> 63) == 0) { + variant = 0; + } else if ((leastSigBits >>> 62) == 2) { + variant = 2; + } else { + variant = (int) (leastSigBits >>> 61); + } + } + return variant; + } + + /** + * The timestamp value associated with this UUID. + * + *

+ * The 60 bit timestamp value is constructed from the time_low, time_mid, + * and time_hi fields of this UUID. The resulting timestamp is + * measured in 100-nanosecond units since midnight, October 15, 1582 UTC. + *

+ * + * The timestamp value is only meaningful in a time-based UUID, which has + * version type 1. If this UUID is not a time-based UUID then + * this method throws UnsupportedOperationException. + * + * @throws UnsupportedOperationException + * if this UUID is not a version 1 UUID. + */ + public long timestamp() { + if (version() != 1) { + throw new UnsupportedOperationException("Not a time-based UUID"); + } + long result = timestamp; + if (result < 0) { + result = (mostSigBits & 0x0000000000000FFFL) << 48; + result |= ((mostSigBits >> 16) & 0xFFFFL) << 32; + result |= mostSigBits >>> 32; + timestamp = result; + } + return result; + } + + /** + * The clock sequence value associated with this UUID. + * + *

+ * The 14 bit clock sequence value is constructed from the clock sequence + * field of this UUID. The clock sequence field is used to guarantee + * temporal uniqueness in a time-based UUID. + *

+ * + * The clockSequence value is only meaningful in a time-based UUID, which + * has version type 1. If this UUID is not a time-based UUID then this + * method throws UnsupportedOperationException. + * + * @return the clock sequence of this UUID. + * @throws UnsupportedOperationException + * if this UUID is not a version 1 UUID. + */ + public int clockSequence() { + if (version() != 1) { + throw new UnsupportedOperationException("Not a time-based UUID"); + } + if (sequence < 0) { + sequence = (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48); + } + return sequence; + } + + /** + * The node value associated with this UUID. + * + *

+ * The 48 bit node value is constructed from the node field of this UUID. + * This field is intended to hold the IEEE 802 address of the machine that + * generated this UUID to guarantee spatial uniqueness. + *

+ * + * The node value is only meaningful in a time-based UUID, which has version + * type 1. If this UUID is not a time-based UUID then this method throws + * UnsupportedOperationException. + * + * @return the node value of this UUID. + * @throws UnsupportedOperationException + * if this UUID is not a version 1 UUID. + */ + public long node() { + if (version() != 1) { + throw new UnsupportedOperationException("Not a time-based UUID"); + } + if (node < 0) { + node = leastSigBits & 0x0000FFFFFFFFFFFFL; + } + return node; + } + + // Object Inherited Methods + + /** + * Returns a String object representing this + * UUID. + * + *

+ * The UUID string representation is as described by this BNF : + * + *

+     *    UUID                   = <time_low> "-" <time_mid> "-"
+     *                             <time_high_and_version> "-"
+     *                             <variant_and_sequence> "-"
+     *                             <node>
+     *    time_low               = 4*<hexOctet>
+     *    time_mid               = 2*<hexOctet>
+     *    time_high_and_version  = 2*<hexOctet>
+     *    variant_and_sequence   = 2*<hexOctet>
+     *    node                   = 6*<hexOctet>
+     *    hexOctet               = <hexDigit><hexDigit>
+     *    hexDigit               =
+     *          "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
+     *          | "a" | "b" | "c" | "d" | "e" | "f"
+     *          | "A" | "B" | "C" | "D" | "E" | "F"
+     * 
+ * + * @return a string representation of this UUID. + */ + @Override + public String toString() { + return (digits(mostSigBits >> 32, 8) + "-" + + digits(mostSigBits >> 16, 4) + "-" + digits(mostSigBits, 4) + + "-" + digits(leastSigBits >> 48, 4) + "-" + digits( + leastSigBits, 12)); + } + + /** Returns val represented by the specified number of hex digits. */ + private static String digits(long val, int digits) { + long hi = 1L << (digits * 4); + return Long.toHexString(hi | (val & (hi - 1))).substring(1); + } + + /** + * Returns a hash code for this UUID. + * + * @return a hash code value for this UUID. + */ + @Override + public int hashCode() { + if (hashCode == -1) { + hashCode = (int) ((mostSigBits >> 32) ^ mostSigBits + ^ (leastSigBits >> 32) ^ leastSigBits); + } + return hashCode; + } + + /** + * Compares this object to the specified object. The result is true + * if and only if the argument is not null, is a UUID + * object, has the same variant, and contains the same value, bit for bit, + * as this UUID. + * + * @param obj + * the object to compare with. + * @return true if the objects are the same; + * false otherwise. + */ + @Override + public boolean equals(Object obj) { + // 보안 취약점 점검 지적사항 반영 시작 + if (obj == null) + return false; + // 보안 취약점 점검 지적사항 반영 시작 끝 + if (!(obj instanceof EgovFormBasedUUID)) + return false; + if (((EgovFormBasedUUID) obj).variant() != this.variant()) + return false; + EgovFormBasedUUID id = (EgovFormBasedUUID) obj; + return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits); + } + + // Comparison Operations + + /** + * Compares this UUID with the specified UUID. + * + *

+ * The first of two UUIDs follows the second if the most significant field + * in which the UUIDs differ is greater for the first UUID. + * + * @param val + * UUID to which this UUID is to be + * compared. + * @return -1, 0 or 1 as this UUID is less than, equal to, or + * greater than val. + */ + public int compareTo(EgovFormBasedUUID val) { + // The ordering is intentionally set up so that the UUIDs + // can simply be numerically compared as two numbers + return (this.mostSigBits < val.mostSigBits ? -1 + : (this.mostSigBits > val.mostSigBits ? 1 + : (this.leastSigBits < val.leastSigBits ? -1 + : (this.leastSigBits > val.leastSigBits ? 1 : 0)))); + } + + /** + * Reconstitute the UUID instance from a stream (that is, + * deserialize it). This is necessary to set the transient fields to their + * correct uninitialized value so they will be recomputed on demand. + */ + private void readObject(java.io.ObjectInputStream in) + throws java.io.IOException, ClassNotFoundException { + + in.defaultReadObject(); + + // Set "cached computation" fields to their initial values + version = -1; + variant = -1; + timestamp = -1; + sequence = -1; + node = -1; + hashCode = -1; + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovFormatCheckUtil.java b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovFormatCheckUtil.java new file mode 100644 index 00000000..87d999ef --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovFormatCheckUtil.java @@ -0,0 +1,207 @@ +package egovframework.com.utl.fcc.service; + +/** + * + * 포맷유효성체크 에 대한 Util 클래스 + * @author 공통컴포넌트 개발팀 윤성록 + * @since 2009.06.23 + * @version 1.0 + * @see + * + *

+ * << 개정이력(Modification Information) >>
+ *   
+ *   수정일      수정자           수정내용
+ *  -------    --------    ---------------------------
+ *   2009.06.23  윤성록          최초 생성
+ *
+ * 
+ */ +public class EgovFormatCheckUtil { + + /** + * + * + * + * @param 전화번호 문자열( 3개 ) + * @return 유효한 전화번호 형식인지 여부 (True/False) + */ + public static boolean checkFormatTell(String tell1, String tell2, String tell3) { + + String[] check = {"02", "031", "032", "033", "041", "042", "043", "051", "052", "053", "054", "055", "061", + "062", "063", "070", "080", "0505"}; //존재하는 국번 데이터 + String temp = tell1 + tell2 + tell3; + + for(int i=0; i < temp.length(); i++){ + if (temp.charAt(i) < '0' || temp.charAt(i) > '9') + return false; + } //숫자가 아닌 값이 들어왔는지를 확인 + + for(int i = 0; i < check.length; i++){ + if(tell1.equals(check[i])) break; + if(i == check.length - 1) return false; + } //국번입력이 제대로 되었는지를 확인 + + if(tell2.charAt(0) == '0') return false; + + if(tell1.equals("02")){ + if(tell2.length() != 3 && tell2.length() !=4) return false; + if(tell3.length() != 4) return false; //서울지역(02)국번 입력때의 전화 번호 형식유효성 체크 + }else{ + if(tell2.length() != 3) return false; + if(tell3.length() != 4) return false; + } //서울을 제외한 지역(국번 입력때의 전화 번호 형식유효성 체크 + + return true; + } + + /** + *

xxx - xxx- xxxx 형식의 전화번호 하나를 입력 받아 유요한 전화번호형식인지 검사.

+ * + * + * @param 전화번호 문자열 (1개) + * @return 유효한 전화번호 형식인지 여부 (True/False) + */ + public static boolean checkFormatTell(String tellNumber) { + + String temp1; + String temp2; + String temp3; + String tell = tellNumber; + + tell = tell.replace("-", ""); + + if(tell.length() < 9 || tell.length() > 11 || tell.charAt(0) != '0') return false; //전화번호 길이에 대한 체크 + + if(tell.charAt(1) =='2'){ //서울지역 (02)국번의 경우일때 + temp1 = tell.substring(0,2); + if(tell.length() == 9){ + temp2 = tell.substring(2,5); + temp3 = tell.substring(5,9); + }else if(tell.length() == 10){ + temp2 = tell.substring(2,6); + temp3 = tell.substring(6,10); + }else + return false; + } else if(tell.substring(0,4).equals("0505")){ //평생번호(0505)국번의 경우일때 + if(tell.length() != 11) return false; + temp1 = tell.substring(0,4); + temp2 = tell.substring(4,7); + temp3 = tell.substring(7,11); + } else { // 서울지역 및 "0505" 를 제외한 일반적인 경우일때 + if(tell.length() != 10) return false; + temp1 = tell.substring(0,3); + temp2 = tell.substring(3,6); + temp3 = tell.substring(6,10); + } + + return checkFormatTell(temp1, temp2, temp3); + } + + /** + *

xxx - xxx- xxxx 형식의 휴대폰번호 앞, 중간, 뒤 문자열 3개 입력 받아 유요한 휴대폰번호형식인지 검사.

+ * + * + * @param 휴대폰번호 문자열,(3개) + * @return 유효한 휴대폰번호 형식인지 여부 (True/False) + */ + public static boolean checkFormatCell(String cell1, String cell2, String cell3) { + String[] check = {"010", "011", "016", "017", "018", "019"}; //유효한 휴대폰 첫자리 번호 데이터 + String temp = cell1 + cell2 + cell3; + + for(int i=0; i < temp.length(); i++){ + if (temp.charAt(i) < '0' || temp.charAt(i) > '9') + return false; + } //숫자가 아닌 값이 들어왔는지를 확인 + + for(int i = 0; i < check.length; i++){ + if(cell1.equals(check[i])) break; + if(i == check.length - 1) return false; + } // 휴대폰 첫자리 번호입력의 유효성 체크 + + if(cell2.charAt(0) == '0') return false; + + if(cell2.length() != 3 && cell2.length() !=4) return false; + if(cell3.length() != 4) return false; + + return true; + } + + /** + *

XXXXXXXXXX 형식의 휴대폰번호 문자열 3개 입력 받아 유요한 휴대폰번호형식인지 검사.

+ * + * + * @param 휴대폰번호 문자열(1개) + * @return 유효한 휴대폰번호 형식인지 여부 (True/False) + */ + public static boolean checkFormatCell(String cellNumber) { + + String temp1; + String temp2; + String temp3; + + String cell = cellNumber; + cell = cell.replace("-", ""); + + if(cell.length() < 10 || cell.length() > 11 || cell.charAt(0) != '0') return false; + + if(cell.length() == 10){ //전체 10자리 휴대폰 번호일 경우 + temp1 = cell.substring(0,3); + temp2 = cell.substring(3,6); + temp3 = cell.substring(6,10); + }else{ //전체 11자리 휴대폰 번호일 경우 + temp1 = cell.substring(0,3); + temp2 = cell.substring(3,7); + temp3 = cell.substring(7,11); + } + + return checkFormatCell(temp1, temp2, temp3); + } + + /** + *

이메일의 앞, 뒤 문자열 2개 입력 받아 유요한 이메일형식인지 검사.

+ * + * + * @param 이메일 문자열 (2개) + * @return 유효한 이메일 형식인지 여부 (True/False) + */ + public static boolean checkFormatMail(String mail1, String mail2) { + + int count = 0; + + for(int i = 0; i < mail1.length(); i++){ + if(mail1.charAt(i) <= 'z' && mail1.charAt(i) >= 'a') continue; + else if(mail1.charAt(i) <= 'Z' && mail1.charAt(i) >= 'A') continue; + else if(mail1.charAt(i) <= '9' && mail1.charAt(i) >= '0') continue; + else if(mail1.charAt(i) == '-' && mail1.charAt(i) == '_') continue; + else return false; + } // 유효한 문자, 숫자인지 체크 + + for(int i = 0; i < mail2.length(); i++){ + if(mail2.charAt(i) <= 'z' && mail2.charAt(i) >= 'a') continue; + else if(mail2.charAt(i) == '.'){ count++; continue;} + else return false; + } // 메일 주소의 형식 체크(xxx.xxx 형태) + + if(count == 1) return true; + else return false; + + } + + /** + *

이메일의 전체문자열 1개 입력 받아 유요한 이메일형식인지 검사.

+ * + * + * @param 이메일 문자열 (1개) + * @return 유효한 이메일 형식인지 여부 (True/False) + */ + public static boolean checkFormatMail(String mail) { + + String[] temp = mail.split("@"); // '@' 를 기점으로 앞, 뒤 문자열 구분 + + if(temp.length == 2) return checkFormatMail(temp[0], temp[1]); + else return false; + } + +} + diff --git a/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovNumberCheckUtil.java b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovNumberCheckUtil.java new file mode 100644 index 00000000..485f3c0e --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovNumberCheckUtil.java @@ -0,0 +1,246 @@ +package egovframework.com.utl.fcc.service; + +/** + * + * 번호유효성체크 에 대한 Util 클래스 + * @author 공통컴포넌트 개발팀 윤성록 + * @since 2009.06.10 + * @version 1.0 + * @see + * + *
+ * << 개정이력(Modification Information) >>
+ *
+ *   수정일      수정자           수정내용
+ *  -------    --------    ---------------------------
+ *   2009.06.10  윤성록          최초 생성
+ *   2012.02.27  이기하          법인번호 체크로직 수정
+ *
+ * 
+ */ +public class EgovNumberCheckUtil { + + /** + *

XXXXXX - XXXXXXX 형식의 주민번호 앞, 뒤 문자열 2개 입력 받아 유효한 주민번호인지 검사.

+ * + * + * @param 6자리 주민앞번호 문자열 , 7자리 주민뒷번호 문자열 + * @return 유효한 주민번호인지 여부 (True/False) + */ + @SuppressWarnings("static-access") + public static boolean checkJuminNumber(String jumin1, String jumin2) { + + EgovDateUtil egovDateUtil = new EgovDateUtil(); + String juminNumber = jumin1 + jumin2; + String IDAdd = "234567892345"; // 주민등록번호에 가산할 값 + + int count_num = 0; + int add_num = 0; + int total_id = 0; //검증을 위한 변수선언 + + if (juminNumber.length() != 13) return false; // 주민등록번호 자리수가 맞는가를 확인 + + for (int i = 0; i <12 ; i++){ + if(juminNumber.charAt(i)< '0' || juminNumber.charAt(i) > '9') return false; //숫자가 아닌 값이 들어왔는지를 확인 + count_num = Character.getNumericValue(juminNumber.charAt(i)); + add_num = Character.getNumericValue(IDAdd.charAt(i)); + total_id += count_num * add_num; //유효자리 검증식을 적용 + } + + if(Character.getNumericValue(juminNumber.charAt(0)) == 0 || Character.getNumericValue(juminNumber.charAt(0)) == 1){ + if(Character.getNumericValue(juminNumber.charAt(6)) > 4) return false; + String temp = "20" + juminNumber.substring(0,6); + if(!egovDateUtil.checkDate(temp)) return false; + }else{ + if(Character.getNumericValue(juminNumber.charAt(6)) > 2) return false; + String temp = "19" + juminNumber.substring(0,6); + if(!egovDateUtil.checkDate(temp)) return false; + } //주민번호 앞자리 날짜유효성체크 & 성별구분 숫자 체크 + + if(Character.getNumericValue(juminNumber.charAt(12)) == (11 - (total_id % 11)) % 10) //마지막 유효숫자와 검증식을 통한 값의 비교 + return true; + else + return false; + } + + /** + *

XXXXXXXXXXXXX 형식의 13자리 주민번호 1개를 입력 받아 유효한 주민번호인지 검사.

+ * + * + * @param 13자리 주민번호 문자열 + * @return 유효한 주민번호인지 여부 (True/False) + */ + public static boolean checkJuminNumber(String jumin) { + + if(jumin.length() != 13) return false; + + return checkJuminNumber(jumin.substring(0,6), jumin.substring(6,13)); //주민번호 + } + + /** + *

XXXXXX - XXXXXXX 형식의 법인번호 앞, 뒤 문자열 2개 입력 받아 유효한 법인번호인지 검사.

+ * + * + * @param 6자리 법인앞번호 문자열 , 7자리 법인뒷번호 문자열 + * @return 유효한 법인번호인지 여부 (True/False) + */ + public static boolean checkBubinNumber(String bubin1, String bubin2) { + + String bubinNumber = bubin1 + bubin2; + + int hap = 0; + int temp = 1; //유효검증식에 사용하기 위한 변수 + + if(bubinNumber.length() != 13) return false; //법인번호의 자리수가 맞는 지를 확인 + + for(int i=0; i < 13; i++){ + if (bubinNumber.charAt(i) < '0' || bubinNumber.charAt(i) > '9') //숫자가 아닌 값이 들어왔는지를 확인 + return false; + } + + + // 2012.02.27 법인번호 체크로직 수정( i<13 -> i<12 ) + // 맨끝 자리 수는 전산시스템으로 오류를 검증하기 위해 부여되는 검증번호임 + for ( int i=0; i<12; i++){ + if(temp ==3) temp = 1; + hap = hap + (Character.getNumericValue(bubinNumber.charAt(i)) * temp); + temp++; + } //검증을 위한 식의 계산 + + if ((10 - (hap%10))%10 == Character.getNumericValue(bubinNumber.charAt(12))) //마지막 유효숫자와 검증식을 통한 값의 비교 + return true; + else + return false; + } + + /** + *

XXXXXXXXXXXXX 형식의 13자리 법인번호 1개를 입력 받아 유효한 법인번호인지 검사.

+ * + * + * @param 13자리 법인번호 문자열 + * @return 유효한 법인번호인지 여부 (True/False) + */ + public static boolean checkBubinNumber(String bubin) { + + if(bubin.length() != 13) return false; + + return checkBubinNumber(bubin.substring(0,6), bubin.substring(6,13)); + } + + + /** + *

xxx - xx - xxxx 형식의 사업자번호 앞,중간, 뒤 문자열 3개 입력 받아 유효한 사업자번호인지 검사.

+ * + * + * @param 3자리 사업자앞번호 문자열 , 2자리 사업자중간번호 문자열, 5자리 사업자뒷번호 문자열 + * @return 유효한 사업자번호인지 여부 (True/False) + */ + public static boolean checkCompNumber(String comp1, String comp2, String comp3) { + + String compNumber = comp1 + comp2 + comp3; + + int hap = 0; + int temp = 0; + int check[] = {1,3,7,1,3,7,1,3,5}; //사업자번호 유효성 체크 필요한 수 + + if(compNumber.length() != 10) //사업자번호의 길이가 맞는지를 확인한다. + return false; + + for(int i=0; i < 9; i++){ + if(compNumber.charAt(i) < '0' || compNumber.charAt(i) > '9') //숫자가 아닌 값이 들어왔는지를 확인한다. + return false; + + hap = hap + (Character.getNumericValue(compNumber.charAt(i)) * check[temp]); //검증식 적용 + temp++; + } + + hap += (Character.getNumericValue(compNumber.charAt(8))*5)/10; + + if ((10 - (hap%10))%10 == Character.getNumericValue(compNumber.charAt(9))) //마지막 유효숫자와 검증식을 통한 값의 비교 + return true; + else + return false; + } + + /** + *

XXXXXXXXXX 형식의 10자리 사업자번호 3개를 입력 받아 유효한 사업자번호인지 검사.

+ * + * + * @param 10자리 사업자번호 문자열 + * @return 유효한 사업자번호인지 여부 (True/False) + */ + public static boolean checkCompNumber(String comp) { + + if(comp.length() != 10) return false; + return checkCompNumber(comp.substring(0,3), comp.substring(3,5), comp.substring(5,10)); + } + + /** + *

XXXXXX - XXXXXXX 형식의 외국인등록번호 앞, 뒤 문자열 2개 입력 받아 유효한 외국인등록번호인지 검사.

+ * + * + * @param 6자리 외국인등록앞번호 문자열 , 7자리 외국인등록뒷번호 문자열 + * @return 유효한 외국인등록번호인지 여부 (True/False) + */ + @SuppressWarnings("static-access") + public static boolean checkforeignNumber( String foreign1, String foreign2 ) { + + EgovDateUtil egovDateUtil = new EgovDateUtil(); + String foreignNumber = foreign1 + foreign2; + int check = 0; + + if( foreignNumber.length() != 13 ) //외국인등록번호의 길이가 맞는지 확인한다. + return false; + + for(int i=0; i < 13; i++){ + if (foreignNumber.charAt(i) < '0' || foreignNumber.charAt(i) > '9') //숫자가 아닌 값이 들어왔는지를 확인한다. + return false; + } + + if(Character.getNumericValue(foreignNumber.charAt(0)) == 0 || Character.getNumericValue(foreignNumber.charAt(0)) == 1){ + if(Character.getNumericValue(foreignNumber.charAt(6)) == 5 && Character.getNumericValue(foreignNumber.charAt(6)) == 6) return false; + String temp = "20" + foreignNumber.substring(0,6); + if(!egovDateUtil.checkDate(temp)) return false; + }else{ + if(Character.getNumericValue(foreignNumber.charAt(6)) == 5 && Character.getNumericValue(foreignNumber.charAt(6)) == 6) return false; + String temp = "19" + foreignNumber.substring(0,6); + if(!egovDateUtil.checkDate(temp)) return false; + } //외국인등록번호 앞자리 날짜유효성체크 & 성별구분 숫자 체크 + + for( int i = 0 ; i < 12 ; i++ ) { + check += ( ( 9 - i % 8 ) * Character.getNumericValue( foreignNumber.charAt( i ) ) ); + } + + if ( check % 11 == 0 ){ + check = 1; + }else if ( check % 11==10 ){ + check = 0; + }else + check = check % 11; + + if ( check + 2 > 9 ){ + check = check + 2- 10; + }else check = check+2; //검증식을 통합 값의 도출 + + if( check == Character.getNumericValue( foreignNumber.charAt( 12 ) ) ) //마지막 유효숫자와 검증식을 통한 값의 비교 + return true; + else + return false; + } + + + /** + *

XXXXXXXXXXXXX 형식의 13자리 외국인등록번호 1개를 입력 받아 유효한 외국인등록번호인지 검사.

+ * + * + * @param 13자리 외국인등록번호 문자열 + * @return 유효한 외국인등록번호인지 여부 (True/False) + */ + public static boolean checkforeignNumber( String foreign ) { + + if(foreign.length() != 13) return false; + return checkforeignNumber(foreign.substring(0,6), foreign.substring(6,13)); + } +} + + diff --git a/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovNumberFormat.java b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovNumberFormat.java new file mode 100644 index 00000000..701eda4e --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovNumberFormat.java @@ -0,0 +1,258 @@ +package egovframework.com.utl.fcc.service; + +import java.text.NumberFormat; +import java.util.Locale; + +/** + * 숫자, 통화, 퍼센트에 대한 형식 변환을 수행하는 클래스 + */ +public class EgovNumberFormat { + + private static final int MAX_FRACTION_DIGIT = 3; + private static final boolean GROUPING_USED = true; + + /** + * 기본 Locale에 해당하는 형식으로 숫자를 변환한다. + * + * @param number 숫자 + * @return 숫자 문자열 + */ + public static String formatNumber(Number number) { + return formatNumber(number, GROUPING_USED, MAX_FRACTION_DIGIT); + } + + /** + * Locale에 해당하는 형식으로 숫자를 변환한다. + * + * @param locale 로케일 + * @param number 숫자 + * @return 숫자 문자열 + */ + public static String formatNumber(Locale locale, Number number) { + return formatNumber(locale, number, GROUPING_USED, MAX_FRACTION_DIGIT); + } + + /** + * 기본 Locale에 해당하는 형식으로 숫자를 변환한다. + * + * @param number 숫자 + * @param groupingUsed 그룹 분리기호 포함 여부 + * @return 숫자 문자열 + */ + public static String formatNumber(Number number, boolean groupingUsed) { + return formatNumber(number, groupingUsed, MAX_FRACTION_DIGIT); + } + + /** + * Locale에 해당하는 형식으로 숫자를 변환한다. + * + * @param locale 로케일 + * @param number 숫자 + * @param groupingUsed 그룹 분리기호 포함 여부 + * @return 숫자 문자열 + */ + public static String formatNumber(Locale locale, Number number, boolean groupingUsed) { + return formatNumber(locale, number, groupingUsed, MAX_FRACTION_DIGIT); + } + + /** + * 기본 Locale에 해당하는 형식으로 숫자를 변환한다. + * + * @param number 숫자 + * @param maxFactionDigits 변환된 문자열에서 출력할 소수점 이하 최대 자리수 + * @return 숫자 문자열 + */ + public static String formatNumber(Number number, int maxFactionDigits) { + return formatNumber(number, GROUPING_USED, maxFactionDigits); + } + + /** + * Locale에 해당하는 형식으로 숫자를 변환한다. + * + * @param locale 로케일 + * @param number 숫자 + * @param maxFactionDigits 변환된 문자열에서 출력할 소수점 이하 최대 자리수 + * @return 숫자 문자열 + */ + public static String formatNumber(Locale locale, Number number, int maxFactionDigits) { + return formatNumber(locale, number, GROUPING_USED, maxFactionDigits); + } + + /** + * 기본 Locale에 해당하는 형식으로 숫자를 변환한다. + * + * @param number 숫자 + * @param groupingUsed 그룹 분리기호 포함 여부 + * @param maxFactionDigits 변환된 문자열에서 출력할 소수점 이하 최대 자리수 + * @return 숫자 문자열 + */ + public static String formatNumber(Number number, boolean groupingUsed, int maxFactionDigits) { + NumberFormat numberberFormat = NumberFormat.getNumberInstance(); + numberberFormat.setGroupingUsed(groupingUsed); + numberberFormat.setMaximumFractionDigits(maxFactionDigits); + return numberberFormat.format(number); + } + + /** + * Locale에 해당하는 형식으로 숫자를 변환한다. + * + * @param locale 로케일 + * @param number 숫자 + * @param groupingUsed 그룹 분리기호 포함 여부 + * @param maxFactionDigits 변환된 문자열에서 출력할 소수점 이하 최대 자리수 + * @return 숫자 문자열 + */ + public static String formatNumber(Locale locale, Number number, boolean groupingUsed, int maxFactionDigits) { + NumberFormat numberberFormat = NumberFormat.getNumberInstance(locale); + numberberFormat.setGroupingUsed(groupingUsed); + numberberFormat.setMaximumFractionDigits(maxFactionDigits); + return numberberFormat.format(number); + } + + /** + * 기본 Locale에 해당하는 형식으로 통화를 변환한다. + * + * @param number 숫자 + * @return 통화 문자열 + */ + public static String formatCurrency(Number number) { + return formatCurrency(number, GROUPING_USED); + } + + /** + * Locale에 해당하는 형식으로 통화를 변환한다. + * + * @param locale 로케일 + * @param number 숫자 + * @return 통화 문자열 + */ + public static String formatCurrency(Locale locale, Number number) { + return formatCurrency(locale, number, GROUPING_USED); + } + + /** + * 기본 Locale에 해당하는 형식으로 통화를 변환한다. + * + * @param number 숫자 + * @param groupingUsed 그룹 분리기호 포함 여부 + * @return 통화 문자열 + */ + public static String formatCurrency(Number number, boolean groupingUsed) { + NumberFormat numberberFormat = NumberFormat.getCurrencyInstance(); + numberberFormat.setGroupingUsed(groupingUsed); + return numberberFormat.format(number); + } + + /** + * Locale에 해당하는 형식으로 통화를 변환한다. + * + * @param locale 로케일 + * @param number 숫자 + * @param groupingUsed 그룹 분리기호 포함 여부 + * @return 통화 문자열 + */ + public static String formatCurrency(Locale locale, Number number, boolean groupingUsed) { + NumberFormat numberberFormat = NumberFormat.getCurrencyInstance(locale); + numberberFormat.setGroupingUsed(groupingUsed); + return numberberFormat.format(number); + } + + /** + * 기본 Locale에 해당하는 형식으로 퍼센트를 변환한다. + * + * @param number 숫자 + * @return 퍼센트 문자열 + */ + public static String formatPercent(Number number) { + return formatPercent(number, GROUPING_USED, MAX_FRACTION_DIGIT); + } + + /** + * Locale에 해당하는 형식으로 퍼센트를 변환한다. + * + * @param locale 로케일 + * @param number 숫자 + * @return 퍼센트 문자열 + */ + public static String formatPercent(Locale locale, Number number) { + return formatPercent(locale, number, GROUPING_USED, MAX_FRACTION_DIGIT); + } + + /** + * 기본 Locale에 해당하는 형식으로 퍼센트를 변환한다. + * + * @param number 숫자 + * @param groupingUsed 그룹 분리기호 포함 여부 + * @return 퍼센트 문자열 + */ + public static String formatPercent(Number number, boolean groupingUsed) { + return formatPercent(number, groupingUsed, MAX_FRACTION_DIGIT); + } + + /** + * Locale에 해당하는 형식으로 퍼센트를 변환한다. + * + * @param locale 로케일 + * @param number 숫자 + * @param groupingUsed 그룹 분리기호 포함 여부 + * @return 퍼센트 문자열 + */ + public static String formatPercent(Locale locale, Number number, boolean groupingUsed) { + return formatPercent(locale, number, groupingUsed, MAX_FRACTION_DIGIT); + } + + /** + * 기본 Locale에 해당하는 형식으로 퍼센트를 변환한다. + * + * @param number 숫자 + * @param maxFactionDigits 변환된 문자열에서 출력할 소수점 이하 최대 자리수 + * @return 퍼센트 문자열 + */ + public static String formatPercent(Number number, int maxFactionDigits) { + return formatPercent(number, GROUPING_USED, maxFactionDigits); + } + + /** + * Locale에 해당하는 형식으로 퍼센트를 변환한다. + * + * @param locale 로케일 + * @param number 숫자 + * @param maxFactionDigits 변환된 문자열에서 출력할 소수점 이하 최대 자리수 + * @return 퍼센트 문자열 + */ + public static String formatPercent(Locale locale, Number number, int maxFactionDigits) { + return formatPercent(locale, number, GROUPING_USED, maxFactionDigits); + } + + /** + * 기본 Locale에 해당하는 형식으로 퍼센트를 변환한다. + * + * @param number 숫자 + * @param groupingUsed 그룹 분리기호 포함 여부 + * @param maxFactionDigits 변환된 문자열에서 출력할 소수점 이하 최대 자리수 + * @return 퍼센트 문자열 + */ + public static String formatPercent(Number number, boolean groupingUsed, int maxFactionDigits) { + NumberFormat numberberFormat = NumberFormat.getPercentInstance(); + numberberFormat.setGroupingUsed(groupingUsed); + numberberFormat.setMaximumFractionDigits(maxFactionDigits); + return numberberFormat.format(number); + } + + /** + * Locale에 해당하는 형식으로 퍼센트를 변환한다. + * + * @param locale 로케일 + * @param number 숫자 + * @param groupingUsed 그룹 분리기호 포함 여부 + * @param maxFactionDigits 변환된 문자열에서 출력할 소수점 이하 최대 자리수 + * @return 퍼센트 문자열 + */ + public static String formatPercent(Locale locale, Number number, boolean groupingUsed, int maxFactionDigits) { + NumberFormat numberberFormat = NumberFormat.getPercentInstance(locale); + numberberFormat.setGroupingUsed(groupingUsed); + numberberFormat.setMaximumFractionDigits(maxFactionDigits); + return numberberFormat.format(number); + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovNumberUtil.java b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovNumberUtil.java new file mode 100644 index 00000000..2735e8bc --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovNumberUtil.java @@ -0,0 +1,216 @@ +/** + * @Class Name : EgovNumberUtil.java + * @Description : 숫자 데이터 처리 관련 유틸리티 + * @Modification Information + * + * 수정일 수정자 수정내용 + * ------- -------- --------------------------- + * 2009.02.13 이삼섭 최초 생성 + * + * @author 공통 서비스 개발팀 이삼섭 + * @since 2009. 02. 13 + * @version 1.0 + * @see + * + */ + +package egovframework.com.utl.fcc.service; + +import java.security.SecureRandom; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class EgovNumberUtil { + + /** + * 특정숫자 집합에서 랜덤 숫자를 구하는 기능 시작숫자와 종료숫자 사이에서 구한 랜덤 숫자를 반환한다 + * + * @param startNum - 시작숫자 + * @param endNum - 종료숫자 + * @return 랜덤숫자 + * @see + */ + public static int getRandomNum(int startNum, int endNum) { + int randomNum = 0; + + // 랜덤 객체 생성 + SecureRandom rnd = new SecureRandom(); + + do { + // 종료숫자내에서 랜덤 숫자를 발생시킨다. + randomNum = rnd.nextInt(endNum + 1); + } while (randomNum < startNum); // 랜덤 숫자가 시작숫자보다 작을경우 다시 랜덤숫자를 발생시킨다. + + return randomNum; + } + + /** + * 특정 숫자 집합에서 특정 숫자가 있는지 체크하는 기능 12345678에서 7이 있는지 없는지 체크하는 기능을 제공함 + * + * @param sourceInt - 특정숫자집합 + * @param searchInt - 검색숫자 + * @return 존재여부 + * @see + */ + public static Boolean getNumSearchCheck(int sourceInt, int searchInt) { + String sourceStr = String.valueOf(sourceInt); + String searchStr = String.valueOf(searchInt); + + // 특정숫자가 존재하는지 하여 위치값을 리턴한다. 없을 시 -1 + if (sourceStr.indexOf(searchStr) == -1) { + return false; + } else { + return true; + } + } + + /** + * 숫자타입을 문자열로 변환하는 기능 숫자 20081212를 문자열 '20081212'로 변환하는 기능 + * + * @param srcNumber - 숫자 + * @return 문자열 + * @see + */ + public static String getNumToStrCnvr(int srcNumber) { + String rtnStr = null; + + rtnStr = String.valueOf(srcNumber); + + return rtnStr; + } + + /** + * 숫자타입을 데이트 타입으로 변환하는 기능 + * 숫자 20081212를 데이트타입 '2008-12-12'로 변환하는 기능 + * @param srcNumber - 숫자 + * @return String + * @see + */ + public static String getNumToDateCnvr(int srcNumber) { + + String pattern = null; + String cnvrStr = null; + + String srcStr = String.valueOf(srcNumber); + + // Date 형태인 8자리 및 14자리만 정상처리 + if (srcStr.length() != 8 && srcStr.length() != 14) { + throw new IllegalArgumentException("Invalid Number: " + srcStr + " Length=" + srcStr.trim().length()); + } + + if (srcStr.length() == 8) { + pattern = "yyyyMMdd"; + } else if (srcStr.length() == 14) { + pattern = "yyyyMMddhhmmss"; + } + + SimpleDateFormat dateFormatter = new SimpleDateFormat(pattern, Locale.KOREA); + + Date cnvrDate = null; + + try { + cnvrDate = dateFormatter.parse(srcStr); + } catch (ParseException e) { + throw new RuntimeException(e); + } + + cnvrStr = String.format("%1$tY-%1$tm-%1$td", cnvrDate); + + return cnvrStr; + + } + + /** + * 체크할 숫자 중에서 숫자인지 아닌지 체크하는 기능 + * 숫자이면 True, 아니면 False를 반환한다 + * @param checkStr - 체크문자열 + * @return 숫자여부 + * @see + */ + public static Boolean getNumberValidCheck(String checkStr) { + + int i; + //String sourceStr = String.valueOf(sourceInt); + + int checkStrLt = checkStr.length(); + + for (i = 0; i < checkStrLt; i++) { + + // 아스키코드값( '0'-> 48, '9' -> 57) + if (checkStr.charAt(i) > 47 && checkStr.charAt(i) < 58) { + continue; + } else { + return false; + } + } + + return true; + } + + /** + * 특정숫자를 다른 숫자로 치환하는 기능 숫자 12345678에서 123를 999로 변환하는 기능을 제공(99945678) + * + * @param srcNumber - 숫자집합 + * @param cnvrSrcNumber - 원래숫자 + * @param cnvrTrgtNumber - 치환숫자 + * @return 치환숫자 + * @see + */ + public static int getNumberCnvr(int srcNumber, int cnvrSrcNumber, int cnvrTrgtNumber) { + + // 입력받은 숫자를 문자열로 변환 + String source = String.valueOf(srcNumber); + String subject = String.valueOf(cnvrSrcNumber); + String object = String.valueOf(cnvrTrgtNumber); + + StringBuffer rtnStr = new StringBuffer(); + String preStr = ""; + String nextStr = source; + + // 원본숫자에서 변환대상숫자의 위치를 찾는다. + while (source.indexOf(subject) >= 0) { + preStr = source.substring(0, source.indexOf(subject)); // 변환대상숫자 위치까지 숫자를 잘라낸다 + nextStr = source.substring(source.indexOf(subject) + subject.length(), source.length()); + source = nextStr; + rtnStr.append(preStr).append(object); // 변환대상위치 숫자에 변환할 숫자를 붙여준다. + } + rtnStr.append(nextStr); // 변환대상 숫자 이후 숫자를 붙여준다. + + return Integer.parseInt(rtnStr.toString()); + } + + /** + * 특정숫자가 실수인지, 정수인지, 음수인지 체크하는 기능 123이 실수인지, 정수인지, 음수인지 체크하는 기능을 제공함 + * + * @param srcNumber - 숫자집합 + * @return -1(음수), 0(정수), 1(실수) + * @see + */ + public static int checkRlnoInteger(double srcNumber) { + + // byte 1바이트 ▶소수점이 없는 숫자로, 범위 -2^7 ~ 2^7 -1 + // short 2바이트 ▶소수점이 없는 숫자로, 범위 -2^15 ~ 2^15 -1 + // int 4바이트 ▶소수점이 없는 숫자로, 범위 -2^31 ~ 2^31 - 1 + // long 8바이트 ▶소수점이 없는 숫자로, 범위 -2^63 ~ 2^63-1 + + // float 4바이트 ▶소수점이 있는 숫자로, 끝에 F 또는 f 가 붙는 숫자 (예:3.14f) + // double 8바이트 ▶소수점이 있는 숫자로, 끝에 아무것도 붙지 않는 숫자 (예:3.14) + // ▶소수점이 있는 숫자로, 끝에 D 또는 d 가 붙는 숫자(예:3.14d) + + String cnvrString = null; + + if (srcNumber < 0) { + return -1; + } else { + cnvrString = String.valueOf(srcNumber); + + if (cnvrString.indexOf(".") == -1) { + return 0; + } else { + return 1; + } + } + } +} diff --git a/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovStringUtil.java b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovStringUtil.java new file mode 100644 index 00000000..96f1324d --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/utl/fcc/service/EgovStringUtil.java @@ -0,0 +1,904 @@ +/** + * @Class Name : EgovStringUtil.java + * @Description : 문자열 데이터 처리 관련 유틸리티 + * @Modification Information + * + * 수정일 수정자 수정내용 + * ------- -------- --------------------------- + * 2009.01.13 박정규 최초 생성 + * 2009.02.13 이삼섭 내용 추가 + * + * @author 공통 서비스 개발팀 박정규 + * @since 2009. 01. 13 + * @version 1.0 + * @see + * + */ + +package egovframework.com.utl.fcc.service; + +/* + * Copyright 2001-2006 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the ";License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS"; BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.io.UnsupportedEncodingException; +import java.math.BigDecimal; +import java.security.SecureRandom; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; +import java.util.Locale; + +public class EgovStringUtil { + /** + * 빈 문자열 "". + */ + public static final String EMPTY = ""; + + /** + *

Padding을 할 수 있는 최대 수치

+ */ + // private static final int PAD_LIMIT = 8192; + + /** + *

An array of Strings used for padding.

+ *

Used for efficient space padding. The length of each String expands as needed.

+ */ + /* + private static final String[] PADDING = new String[Character.MAX_VALUE]; + + static { + // space padding is most common, start with 64 chars + PADDING[32] = " "; + } + */ + + /** + * 문자열이 지정한 길이를 초과했을때 지정한길이에다가 해당 문자열을 붙여주는 메서드. + * @param source 원본 문자열 배열 + * @param output 더할문자열 + * @param slength 지정길이 + * @return 지정길이로 잘라서 더할분자열 합친 문자열 + */ + public static String cutString(String source, String output, int slength) { + String returnVal = null; + if (source != null) { + if (source.length() > slength) { + returnVal = source.substring(0, slength) + output; + } else + returnVal = source; + } + return returnVal; + } + + /** + * 문자열이 지정한 길이를 초과했을때 해당 문자열을 삭제하는 메서드 + * @param source 원본 문자열 배열 + * @param slength 지정길이 + * @return 지정길이로 잘라서 더할분자열 합친 문자열 + */ + public static String cutString(String source, int slength) { + String result = null; + if (source != null) { + if (source.length() > slength) { + result = source.substring(0, slength); + } else + result = source; + } + return result; + } + + /** + *

+ * String이 비었거나("") 혹은 null 인지 검증한다. + *

+ * + *
+	 *  StringUtil.isEmpty(null)      = true
+	 *  StringUtil.isEmpty("")        = true
+	 *  StringUtil.isEmpty(" ")       = false
+	 *  StringUtil.isEmpty("bob")     = false
+	 *  StringUtil.isEmpty("  bob  ") = false
+	 * 
+ * + * @param str - 체크 대상 스트링오브젝트이며 null을 허용함 + * @return true - 입력받은 String 이 빈 문자열 또는 null인 경우 + */ + public static boolean isEmpty(String str) { + return str == null || str.length() == 0; + } + + /** + *

기준 문자열에 포함된 모든 대상 문자(char)를 제거한다.

+ * + *
+	 * StringUtil.remove(null, *)       = null
+	 * StringUtil.remove("", *)         = ""
+	 * StringUtil.remove("queued", 'u') = "qeed"
+	 * StringUtil.remove("queued", 'z') = "queued"
+	 * 
+ * + * @param str 입력받는 기준 문자열 + * @param remove 입력받는 문자열에서 제거할 대상 문자열 + * @return 제거대상 문자열이 제거된 입력문자열. 입력문자열이 null인 경우 출력문자열은 null + */ + public static String remove(String str, char remove) { + if (isEmpty(str) || str.indexOf(remove) == -1) { + return str; + } + char[] chars = str.toCharArray(); + int pos = 0; + for (int i = 0; i < chars.length; i++) { + if (chars[i] != remove) { + chars[pos++] = chars[i]; + } + } + return new String(chars, 0, pos); + } + + /** + *

문자열 내부의 콤마 character(,)를 모두 제거한다.

+ * + *
+	 * StringUtil.removeCommaChar(null)       = null
+	 * StringUtil.removeCommaChar("")         = ""
+	 * StringUtil.removeCommaChar("asdfg,qweqe") = "asdfgqweqe"
+	 * 
+ * + * @param str 입력받는 기준 문자열 + * @return " , "가 제거된 입력문자열 + * 입력문자열이 null인 경우 출력문자열은 null + */ + public static String removeCommaChar(String str) { + return remove(str, ','); + } + + /** + *

문자열 내부의 마이너스 character(-)를 모두 제거한다.

+ * + *
+	 * StringUtil.removeMinusChar(null)       = null
+	 * StringUtil.removeMinusChar("")         = ""
+	 * StringUtil.removeMinusChar("a-sdfg-qweqe") = "asdfgqweqe"
+	 * 
+ * + * @param str 입력받는 기준 문자열 + * @return " - "가 제거된 입력문자열 + * 입력문자열이 null인 경우 출력문자열은 null + */ + public static String removeMinusChar(String str) { + return remove(str, '-'); + } + + /** + * 원본 문자열의 포함된 특정 문자열을 새로운 문자열로 변환하는 메서드 + * @param source 원본 문자열 + * @param subject 원본 문자열에 포함된 특정 문자열 + * @param object 변환할 문자열 + * @return sb.toString() 새로운 문자열로 변환된 문자열 + */ + public static String replace(String source, String subject, String object) { + StringBuffer rtnStr = new StringBuffer(); + String preStr = ""; + String nextStr = source; + String srcStr = source; + + while (srcStr.indexOf(subject) >= 0) { + preStr = srcStr.substring(0, srcStr.indexOf(subject)); + nextStr = srcStr.substring(srcStr.indexOf(subject) + subject.length(), srcStr.length()); + srcStr = nextStr; + rtnStr.append(preStr).append(object); + } + rtnStr.append(nextStr); + + return rtnStr.toString(); + } + + /** + * 원본 문자열의 포함된 특정 문자열 첫번째 한개만 새로운 문자열로 변환하는 메서드 + * @param source 원본 문자열 + * @param subject 원본 문자열에 포함된 특정 문자열 + * @param object 변환할 문자열 + * @return sb.toString() 새로운 문자열로 변환된 문자열 / source 특정문자열이 없는 경우 원본 문자열 + */ + public static String replaceOnce(String source, String subject, String object) { + StringBuffer rtnStr = new StringBuffer(); + String preStr = ""; + String nextStr = source; + if (source.indexOf(subject) >= 0) { + preStr = source.substring(0, source.indexOf(subject)); + nextStr = source.substring(source.indexOf(subject) + subject.length(), source.length()); + rtnStr.append(preStr).append(object).append(nextStr); + + return rtnStr.toString(); + } else { + return source; + } + } + + /** + * subject에 포함된 각각의 문자를 object로 변환한다. + * + * @param source 원본 문자열 + * @param subject 원본 문자열에 포함된 특정 문자열 + * @param object 변환할 문자열 + * @return sb.toString() 새로운 문자열로 변환된 문자열 + */ + public static String replaceChar(String source, String subject, String object) { + StringBuffer rtnStr = new StringBuffer(); + String preStr = ""; + String nextStr = source; + String srcStr = source; + + char chA; + + for (int i = 0; i < subject.length(); i++) { + chA = subject.charAt(i); + + if (srcStr.indexOf(chA) >= 0) { + preStr = srcStr.substring(0, srcStr.indexOf(chA)); + nextStr = srcStr.substring(srcStr.indexOf(chA) + 1, srcStr.length()); + srcStr = rtnStr.append(preStr).append(object).append(nextStr).toString(); + } + } + + return srcStr; + } + + /** + *

strsearchStr의 시작(index) 위치를 반환.

+ * + *

입력값 중 null이 있을 경우 -1을 반환.

+ * + *
+	 * StringUtil.indexOf(null, *)          = -1
+	 * StringUtil.indexOf(*, null)          = -1
+	 * StringUtil.indexOf("", "")           = 0
+	 * StringUtil.indexOf("aabaabaa", "a")  = 0
+	 * StringUtil.indexOf("aabaabaa", "b")  = 2
+	 * StringUtil.indexOf("aabaabaa", "ab") = 1
+	 * StringUtil.indexOf("aabaabaa", "")   = 0
+	 * 
+ * + * @param str 검색 문자열 + * @param searchStr 검색 대상문자열 + * @return 검색 문자열 중 검색 대상문자열이 있는 시작 위치 검색대상 문자열이 없거나 null인 경우 -1 + */ + public static int indexOf(String str, String searchStr) { + if (str == null || searchStr == null) { + return -1; + } + + return str.indexOf(searchStr); + } + + /** + *

오라클의 decode 함수와 동일한 기능을 가진 메서드이다. + * sourStrcompareStr의 값이 같으면 + * returStr을 반환하며, 다르면 defaultStr을 반환한다. + *

+ * + *
+	 * StringUtil.decode(null, null, "foo", "bar")= "foo"
+	 * StringUtil.decode("", null, "foo", "bar") = "bar"
+	 * StringUtil.decode(null, "", "foo", "bar") = "bar"
+	 * StringUtil.decode("하이", "하이", null, "bar") = null
+	 * StringUtil.decode("하이", "하이  ", "foo", null) = null
+	 * StringUtil.decode("하이", "하이", "foo", "bar") = "foo"
+	 * StringUtil.decode("하이", "하이  ", "foo", "bar") = "bar"
+	 * 
+ * + * @param sourceStr 비교할 문자열 + * @param compareStr 비교 대상 문자열 + * @param returnStr sourceStr와 compareStr의 값이 같을 때 반환할 문자열 + * @param defaultStr sourceStr와 compareStr의 값이 다를 때 반환할 문자열 + * @return sourceStr과 compareStr의 값이 동일(equal)할 때 returnStr을 반환하며, + *
다르면 defaultStr을 반환한다. + */ + public static String decode(String sourceStr, String compareStr, String returnStr, String defaultStr) { + if (sourceStr == null && compareStr == null) { + return returnStr; + } + + if (sourceStr == null && compareStr != null) { + return defaultStr; + } + + if (sourceStr.trim().equals(compareStr)) { + return returnStr; + } + + return defaultStr; + } + + /** + *

오라클의 decode 함수와 동일한 기능을 가진 메서드이다. + * sourStrcompareStr의 값이 같으면 + * returStr을 반환하며, 다르면 sourceStr을 반환한다. + *

+ * + *
+	 * StringUtil.decode(null, null, "foo") = "foo"
+	 * StringUtil.decode("", null, "foo") = ""
+	 * StringUtil.decode(null, "", "foo") = null
+	 * StringUtil.decode("하이", "하이", "foo") = "foo"
+	 * StringUtil.decode("하이", "하이 ", "foo") = "하이"
+	 * StringUtil.decode("하이", "바이", "foo") = "하이"
+	 * 
+ * + * @param sourceStr 비교할 문자열 + * @param compareStr 비교 대상 문자열 + * @param returnStr sourceStr와 compareStr의 값이 같을 때 반환할 문자열 + * @return sourceStr과 compareStr의 값이 동일(equal)할 때 returnStr을 반환하며, + *
다르면 sourceStr을 반환한다. + */ + public static String decode(String sourceStr, String compareStr, String returnStr) { + return decode(sourceStr, compareStr, returnStr, sourceStr); + } + + /** + * 객체가 null인지 확인하고 null인 경우 "" 로 바꾸는 메서드 + * @param object 원본 객체 + * @return resultVal 문자열 + */ + public static String isNullToString(Object object) { + String string = ""; + + if (object != null) { + string = object.toString().trim(); + } + + return string; + } + + /** + *
+	 * 인자로 받은 String이 null일 경우 ""로 리턴한다.
+	 * @param src null값일 가능성이 있는 String 값.
+	 * @return 만약 String이 null 값일 경우 ""로 바꾼 String 값.
+	 *
+ */ + public static String nullConvert(Object src) { + //if (src != null && src.getClass().getName().equals("java.math.BigDecimal")) { + if (src != null && src instanceof java.math.BigDecimal) { + return ((BigDecimal) src).toString(); + } + + if (src == null || src.equals("null")) { + return ""; + } else { + return ((String) src).trim(); + } + } + + /** + *
+	 * 인자로 받은 String이 null일 경우 ""로 리턴한다.
+	 * @param src null값일 가능성이 있는 String 값.
+	 * @return 만약 String이 null 값일 경우 ""로 바꾼 String 값.
+	 *
+ */ + public static String nullConvertInt(Object src) { + //if (src != null && src.getClass().getName().equals("java.math.BigDecimal")) { + if (src != null && src instanceof java.math.BigDecimal) { + return ((BigDecimal) src).toString(); + } + + if (src == null || src.equals("null")) { + return "0"; + } else { + return ((String) src).trim(); + } + } + + /** + *
+	 * 인자로 받은 String이 null일 경우 ""로 리턴한다.
+	 * @param src null값일 가능성이 있는 String 값.
+	 * @return 만약 String이 null 값일 경우 ""로 바꾼 String 값.
+	 *
+ */ + public static String nullConvert(String src) { + + if (src == null || src.equals("null") || "".equals(src) || " ".equals(src)) { + return ""; + } else { + return src.trim(); + } + } + + /** + *
+	 * 인자로 받은 String이 null일 경우 "0"로 리턴한다.
+	 * @param src null값일 가능성이 있는 String 값.
+	 * @return 만약 String이 null 값일 경우 "0"로 바꾼 String 값.
+	 *
+ */ + public static int zeroConvert(Object src) { + + if (src == null || src.equals("null")) { + return 0; + } else { + return Integer.parseInt(((String) src).trim()); + } + } + + /** + *
+	 * 인자로 받은 String이 null일 경우 ""로 리턴한다.
+	 * @param src null값일 가능성이 있는 String 값.
+	 * @return 만약 String이 null 값일 경우 ""로 바꾼 String 값.
+	 *
+ */ + public static int zeroConvert(String src) { + + if (src == null || src.equals("null") || "".equals(src) || " ".equals(src)) { + return 0; + } else { + return Integer.parseInt(src.trim()); + } + } + + /** + *

문자열에서 {@link Character#isWhitespace(char)}에 정의된 + * 모든 공백문자를 제거한다.

+ * + *
+	 * StringUtil.removeWhitespace(null)         = null
+	 * StringUtil.removeWhitespace("")           = ""
+	 * StringUtil.removeWhitespace("abc")        = "abc"
+	 * StringUtil.removeWhitespace("   ab  c  ") = "abc"
+	 * 
+ * + * @param str 공백문자가 제거도어야 할 문자열 + * @return the 공백문자가 제거된 문자열, null이 입력되면 null이 리턴 + */ + public static String removeWhitespace(String str) { + if (isEmpty(str)) { + return str; + } + int sz = str.length(); + char[] chs = new char[sz]; + int count = 0; + for (int i = 0; i < sz; i++) { + if (!Character.isWhitespace(str.charAt(i))) { + chs[count++] = str.charAt(i); + } + } + if (count == sz) { + return str; + } + + return new String(chs, 0, count); + } + + /** + * Html 코드가 들어간 문서를 표시할때 태그에 손상없이 보이기 위한 메서드 + * + * @param strString + * @return HTML 태그를 치환한 문자열 + */ + public static String checkHtmlView(String strString) { + String strNew = ""; + + StringBuffer strTxt = new StringBuffer(""); + + char chrBuff; + int len = strString.length(); + + for (int i = 0; i < len; i++) { + chrBuff = (char) strString.charAt(i); + + switch (chrBuff) { + case '<': + strTxt.append("<"); + break; + case '>': + strTxt.append(">"); + break; + case '"': + strTxt.append("""); + break; + case 10: + strTxt.append("
"); + break; + case ' ': + strTxt.append(" "); + break; + //case '&' : + //strTxt.append("&"); + //break; + default: + strTxt.append(chrBuff); + } + } + + strNew = strTxt.toString(); + + return strNew; + } + + /** + * 문자열을 지정한 분리자에 의해 배열로 리턴하는 메서드. + * @param source 원본 문자열 + * @param separator 분리자 + * @return result 분리자로 나뉘어진 문자열 배열 + */ + public static String[] split(String source, String separator) throws NullPointerException { + String[] returnVal = null; + int cnt = 1; + + int index = source.indexOf(separator); + int index0 = 0; + while (index >= 0) { + cnt++; + index = source.indexOf(separator, index + 1); + } + returnVal = new String[cnt]; + cnt = 0; + index = source.indexOf(separator); + while (index >= 0) { + returnVal[cnt] = source.substring(index0, index); + index0 = index + 1; + index = source.indexOf(separator, index + 1); + cnt++; + } + returnVal[cnt] = source.substring(index0); + + return returnVal; + } + + /** + *

{@link String#toLowerCase()}를 이용하여 소문자로 변환한다.

+ * + *
+	 * StringUtil.lowerCase(null)  = null
+	 * StringUtil.lowerCase("")    = ""
+	 * StringUtil.lowerCase("aBc") = "abc"
+	 * 
+ * + * @param str 소문자로 변환되어야 할 문자열 + * @return 소문자로 변환된 문자열, null이 입력되면 null 리턴 + */ + public static String lowerCase(String str) { + if (str == null) { + return null; + } + + return str.toLowerCase(); + } + + /** + *

{@link String#toUpperCase()}를 이용하여 대문자로 변환한다.

+ * + *
+	 * StringUtil.upperCase(null)  = null
+	 * StringUtil.upperCase("")    = ""
+	 * StringUtil.upperCase("aBc") = "ABC"
+	 * 
+ * + * @param str 대문자로 변환되어야 할 문자열 + * @return 대문자로 변환된 문자열, null이 입력되면 null 리턴 + */ + public static String upperCase(String str) { + if (str == null) { + return null; + } + + return str.toUpperCase(); + } + + /** + *

입력된 String의 앞쪽에서 두번째 인자로 전달된 문자(stripChars)를 모두 제거한다.

+ * + *
+	 * StringUtil.stripStart(null, *)          = null
+	 * StringUtil.stripStart("", *)            = ""
+	 * StringUtil.stripStart("abc", "")        = "abc"
+	 * StringUtil.stripStart("abc", null)      = "abc"
+	 * StringUtil.stripStart("  abc", null)    = "abc"
+	 * StringUtil.stripStart("abc  ", null)    = "abc  "
+	 * StringUtil.stripStart(" abc ", null)    = "abc "
+	 * StringUtil.stripStart("yxabc  ", "xyz") = "abc  "
+	 * 
+ * + * @param str 지정된 문자가 제거되어야 할 문자열 + * @param stripChars 제거대상 문자열 + * @return 지정된 문자가 제거된 문자열, null이 입력되면 null 리턴 + */ + public static String stripStart(String str, String stripChars) { + int strLen; + if (str == null || (strLen = str.length()) == 0) { + return str; + } + int start = 0; + if (stripChars == null) { + while ((start != strLen) && Character.isWhitespace(str.charAt(start))) { + start++; + } + } else if (stripChars.length() == 0) { + return str; + } else { + while ((start != strLen) && (stripChars.indexOf(str.charAt(start)) != -1)) { + start++; + } + } + + return str.substring(start); + } + + /** + *

입력된 String의 뒤쪽에서 두번째 인자로 전달된 문자(stripChars)를 모두 제거한다.

+ * + *
+	 * StringUtil.stripEnd(null, *)          = null
+	 * StringUtil.stripEnd("", *)            = ""
+	 * StringUtil.stripEnd("abc", "")        = "abc"
+	 * StringUtil.stripEnd("abc", null)      = "abc"
+	 * StringUtil.stripEnd("  abc", null)    = "  abc"
+	 * StringUtil.stripEnd("abc  ", null)    = "abc"
+	 * StringUtil.stripEnd(" abc ", null)    = " abc"
+	 * StringUtil.stripEnd("  abcyx", "xyz") = "  abc"
+	 * 
+ * + * @param str 지정된 문자가 제거되어야 할 문자열 + * @param stripChars 제거대상 문자열 + * @return 지정된 문자가 제거된 문자열, null이 입력되면 null 리턴 + */ + public static String stripEnd(String str, String stripChars) { + int end; + if (str == null || (end = str.length()) == 0) { + return str; + } + + if (stripChars == null) { + while ((end != 0) && Character.isWhitespace(str.charAt(end - 1))) { + end--; + } + } else if (stripChars.length() == 0) { + return str; + } else { + while ((end != 0) && (stripChars.indexOf(str.charAt(end - 1)) != -1)) { + end--; + } + } + + return str.substring(0, end); + } + + /** + *

입력된 String의 앞, 뒤에서 두번째 인자로 전달된 문자(stripChars)를 모두 제거한다.

+ * + *
+	 * StringUtil.strip(null, *)          = null
+	 * StringUtil.strip("", *)            = ""
+	 * StringUtil.strip("abc", null)      = "abc"
+	 * StringUtil.strip("  abc", null)    = "abc"
+	 * StringUtil.strip("abc  ", null)    = "abc"
+	 * StringUtil.strip(" abc ", null)    = "abc"
+	 * StringUtil.strip("  abcyx", "xyz") = "  abc"
+	 * 
+ * + * @param str 지정된 문자가 제거되어야 할 문자열 + * @param stripChars 제거대상 문자열 + * @return 지정된 문자가 제거된 문자열, null이 입력되면 null 리턴 + */ + public static String strip(String str, String stripChars) { + if (isEmpty(str)) { + return str; + } + + String srcStr = str; + srcStr = stripStart(srcStr, stripChars); + + return stripEnd(srcStr, stripChars); + } + + /** + * 문자열을 지정한 분리자에 의해 지정된 길이의 배열로 리턴하는 메서드. + * @param source 원본 문자열 + * @param separator 분리자 + * @param arraylength 배열 길이 + * @return 분리자로 나뉘어진 문자열 배열 + */ + public static String[] split(String source, String separator, int arraylength) throws NullPointerException { + String[] returnVal = new String[arraylength]; + int cnt = 0; + int index0 = 0; + int index = source.indexOf(separator); + while (index >= 0 && cnt < (arraylength - 1)) { + returnVal[cnt] = source.substring(index0, index); + index0 = index + 1; + index = source.indexOf(separator, index + 1); + cnt++; + } + returnVal[cnt] = source.substring(index0); + if (cnt < (arraylength - 1)) { + for (int i = cnt + 1; i < arraylength; i++) { + returnVal[i] = ""; + } + } + + return returnVal; + } + + /** + * 문자열 A에서 Z사이의 랜덤 문자열을 구하는 기능을 제공 시작문자열과 종료문자열 사이의 랜덤 문자열을 구하는 기능 + * + * @param startChr - 첫 문자 + * @param endChr - 마지막문자 + * @return 랜덤문자 + * @exception MyException + * @see + */ + public static String getRandomStr(char startChr, char endChr) { + + int randomInt; + String randomStr = null; + + // 시작문자 및 종료문자를 아스키숫자로 변환한다. + int startInt = Integer.valueOf(startChr); + int endInt = Integer.valueOf(endChr); + + // 시작문자열이 종료문자열보가 클경우 + if (startInt > endInt) { + throw new IllegalArgumentException("Start String: " + startChr + " End String: " + endChr); + } + + // 랜덤 객체 생성 + SecureRandom rnd = new SecureRandom(); + + do { + // 시작문자 및 종료문자 중에서 랜덤 숫자를 발생시킨다. + randomInt = rnd.nextInt(endInt + 1); + } while (randomInt < startInt); // 입력받은 문자 'A'(65)보다 작으면 다시 랜덤 숫자 발생. + + // 랜덤 숫자를 문자로 변환 후 스트링으로 다시 변환 + randomStr = (char) randomInt + ""; + + // 랜덤문자열를 리턴 + return randomStr; + } + + /** + * 문자열을 다양한 문자셋(EUC-KR[KSC5601],UTF-8..)을 사용하여 인코딩하는 기능 역으로 디코딩하여 원래의 문자열을 + * 복원하는 기능을 제공함 String temp = new String(문자열.getBytes("바꾸기전 인코딩"),"바꿀 인코딩"); + * String temp = new String(문자열.getBytes("8859_1"),"KSC5601"); => UTF-8 에서 + * EUC-KR + * + * @param srcString - 문자열 + * @param srcCharsetNm - 원래 CharsetNm + * @param charsetNm - CharsetNm + * @return 인(디)코딩 문자열 + * @exception MyException + * @see + */ + public static String getEncdDcd(String srcString, String srcCharsetNm, String cnvrCharsetNm) { + + String rtnStr = null; + + if (srcString == null) + return null; + + try { + rtnStr = new String(srcString.getBytes(srcCharsetNm), cnvrCharsetNm); + } catch (UnsupportedEncodingException e) { + rtnStr = null; + } + + return rtnStr; + } + + /** + * 특수문자를 웹 브라우저에서 정상적으로 보이기 위해 특수문자를 처리('<' -> & lT)하는 기능이다 + * @param srcString - '<' + * @return 변환문자열('<' -> "<" + * @exception MyException + * @see + */ + public static String getSpclStrCnvr(String srcString) { + + String rtnStr = null; + + StringBuffer strTxt = new StringBuffer(""); + + char chrBuff; + int len = srcString.length(); + + for (int i = 0; i < len; i++) { + chrBuff = (char) srcString.charAt(i); + + switch (chrBuff) { + case '<': + strTxt.append("<"); + break; + case '>': + strTxt.append(">"); + break; + case '&': + strTxt.append("&"); + break; + default: + strTxt.append(chrBuff); + } + } + + rtnStr = strTxt.toString(); + + return rtnStr; + } + + /** + * 응용어플리케이션에서 고유값을 사용하기 위해 시스템에서17자리의TIMESTAMP값을 구하는 기능 + * + * @param + * @return Timestamp 값 + * @exception MyException + * @see + */ + public static String getTimeStamp() { + + String rtnStr = null; + + // 문자열로 변환하기 위한 패턴 설정(년도-월-일 시:분:초:초(자정이후 초)) + String pattern = "yyyyMMddhhmmssSSS"; + + SimpleDateFormat sdfCurrent = new SimpleDateFormat(pattern, Locale.KOREA); + Timestamp ts = new Timestamp(System.currentTimeMillis()); + + rtnStr = sdfCurrent.format(ts.getTime()); + + return rtnStr; + } + + /** + * html의 특수문자를 표현하기 위해 + * + * @param srcString + * @return String + * @exception Exception + * @see + */ + public static String getHtmlStrCnvr(String srcString) { + + String tmpString = srcString; + + tmpString = tmpString.replaceAll("<", "<"); + tmpString = tmpString.replaceAll(">", ">"); + tmpString = tmpString.replaceAll("&", "&"); + tmpString = tmpString.replaceAll(" ", " "); + tmpString = tmpString.replaceAll("'", "\'"); + tmpString = tmpString.replaceAll(""", "\""); + + return tmpString; + + } + + /** + *

날짜 형식의 문자열 내부에 마이너스 character(-)를 추가한다.

+ * + *
+	 *   StringUtil.addMinusChar("20100901") = "2010-09-01"
+	 * 
+ * + * @param date 입력받는 문자열 + * @return " - "가 추가된 입력문자열 + */ + public static String addMinusChar(String date) { + if (date.length() == 8) { + return date.substring(0, 4).concat("-").concat(date.substring(4, 6)).concat("-").concat(date.substring(6, 8)); + } else { + return ""; + } + } +} diff --git a/legacy/nlib/src/main/java/egovframework/com/utl/sim/service/EgovFileScrty.java b/legacy/nlib/src/main/java/egovframework/com/utl/sim/service/EgovFileScrty.java new file mode 100644 index 00000000..56d9a0b1 --- /dev/null +++ b/legacy/nlib/src/main/java/egovframework/com/utl/sim/service/EgovFileScrty.java @@ -0,0 +1,288 @@ +/** + * Class Name : EgovFileScrty.java + * Description : Base64인코딩/디코딩 방식을 이용한 데이터를 암호화/복호화하는 Business Interface class + * Modification Information + * + * 수정일 수정자 수정내용 + * ------- -------- --------------------------- + * 2009.02.04 박지욱 최초 생성 + * + * @author 공통 서비스 개발팀 박지욱 + * @since 2009. 02. 04 + * @version 1.0 + * @see + * + * Copyright (C) 2009 by MOPAS All right reserved. + */ +package egovframework.com.utl.sim.service; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStreamReader; +import java.security.MessageDigest; + +import egovframework.com.cmm.util.EgovResourceCloseHelper; + +import org.apache.commons.codec.binary.Base64; + +public class EgovFileScrty { + + // 파일구분자 + static final char FILE_SEPARATOR = File.separatorChar; + + static final int BUFFER_SIZE = 1024; + + /** + * 파일을 암호화하는 기능 + * + * @param String source 암호화할 파일 + * @param String target 암호화된 파일 + * @return boolean result 암호화여부 True/False + * @exception Exception + */ + public static boolean encryptFile(String source, String target) throws Exception { + + // 암호화 여부 + boolean result = false; + + String sourceFile = source.replace('\\', FILE_SEPARATOR).replace('/', FILE_SEPARATOR); + String targetFile = target.replace('\\', FILE_SEPARATOR).replace('/', FILE_SEPARATOR); + File srcFile = new File(sourceFile); + + BufferedInputStream input = null; + BufferedOutputStream output = null; + + byte[] buffer = new byte[BUFFER_SIZE]; + + try { + if (srcFile.exists() && srcFile.isFile()) { + + input = new BufferedInputStream(new FileInputStream(srcFile)); + output = new BufferedOutputStream(new FileOutputStream(targetFile)); + + int length = 0; + while ((length = input.read(buffer)) >= 0) { + byte[] data = new byte[length]; + System.arraycopy(buffer, 0, data, 0, length); + output.write(encodeBinary(data).getBytes()); + output.write(System.getProperty("line.separator").getBytes()); + } + result = true; + } + } finally { + EgovResourceCloseHelper.close(input, output); + } + + return result; + } + + /** + * 파일을 복호화하는 기능 + * + * @param String source 복호화할 파일 + * @param String target 복호화된 파일 + * @return boolean result 복호화여부 True/False + * @exception Exception + */ + public static boolean decryptFile(String source, String target) throws Exception { + + // 복호화 여부 + boolean result = false; + + String sourceFile = source.replace('\\', FILE_SEPARATOR).replace('/', FILE_SEPARATOR); + String targetFile = target.replace('\\', FILE_SEPARATOR).replace('/', FILE_SEPARATOR); + File srcFile = new File(sourceFile); + + BufferedReader input = null; + BufferedOutputStream output = null; + + //byte[] buffer = new byte[BUFFER_SIZE]; + String line = null; + + try { + if (srcFile.exists() && srcFile.isFile()) { + + input = new BufferedReader(new InputStreamReader(new FileInputStream(srcFile))); + output = new BufferedOutputStream(new FileOutputStream(targetFile)); + + while ((line = input.readLine()) != null) { + byte[] data = line.getBytes(); + output.write(decodeBinary(new String(data))); + } + + result = true; + } + } finally { + EgovResourceCloseHelper.close(input, output); + } + + return result; + } + + /** + * 데이터를 암호화하는 기능 + * + * @param byte[] data 암호화할 데이터 + * @return String result 암호화된 데이터 + * @exception Exception + */ + public static String encodeBinary(byte[] data) throws Exception { + if (data == null) { + return ""; + } + + return new String(Base64.encodeBase64(data)); + } + + /** + * 데이터를 암호화하는 기능 + * + * @param String data 암호화할 데이터 + * @return String result 암호화된 데이터 + * @exception Exception + */ + @Deprecated + public static String encode(String data) throws Exception { + return encodeBinary(data.getBytes()); + } + + /** + * 데이터를 복호화하는 기능 + * + * @param String data 복호화할 데이터 + * @return String result 복호화된 데이터 + * @exception Exception + */ + public static byte[] decodeBinary(String data) throws Exception { + return Base64.decodeBase64(data.getBytes()); + } + + /** + * 데이터를 복호화하는 기능 + * + * @param String data 복호화할 데이터 + * @return String result 복호화된 데이터 + * @exception Exception + */ + @Deprecated + public static String decode(String data) throws Exception { + return new String(decodeBinary(data)); + } + + /** + * 비밀번호를 암호화하는 기능(복호화가 되면 안되므로 SHA-256 인코딩 방식 적용). + * + * deprecated : 보안 강화를 위하여 salt로 ID를 지정하는 encryptPassword(password, id) 사용 + * + * @param String data 암호화할 비밀번호 + * @return String result 암호화된 비밀번호 + * @exception Exception + */ + @Deprecated + public static String encryptPassword(String data) throws Exception { + + if (data == null) { + return ""; + } + + byte[] plainText = null; // 평문 + byte[] hashValue = null; // 해쉬값 + plainText = data.getBytes(); + + MessageDigest md = MessageDigest.getInstance("SHA-256"); + + // 변경 시 기존 hash 값에 검증 불가.. => deprecated 시키고 유지 + /* + // Random 방식의 salt 추가 + SecureRandom ng = new SecureRandom(); + byte[] randomBytes = new byte[16]; + ng.nextBytes(randomBytes); + + md.reset(); + md.update(randomBytes); + + */ + hashValue = md.digest(plainText); + + /* + BASE64Encoder encoder = new BASE64Encoder(); + return encoder.encode(hashValue); + */ + return new String(Base64.encodeBase64(hashValue)); + } + + /** + * 비밀번호를 암호화하는 기능(복호화가 되면 안되므로 SHA-256 인코딩 방식 적용) + * + * @param password 암호화될 패스워드 + * @param id salt로 사용될 사용자 ID 지정 + * @return + * @throws Exception + */ + public static String encryptPassword(String password, String id) throws Exception { + + if (password == null) return ""; + if (id == null) return ""; // KISA 보안약점 조치 (2018-12-11, 신용호) + + byte[] hashValue = null; // 해쉬값 + + MessageDigest md = MessageDigest.getInstance("SHA-256"); + + md.reset(); + md.update(id.getBytes()); + + hashValue = md.digest(password.getBytes()); + + return new String(Base64.encodeBase64(hashValue)); + } + + /** + * 비밀번호를 암호화하는 기능(복호화가 되면 안되므로 SHA-256 인코딩 방식 적용) + * @param data 암호화할 비밀번호 + * @param salt Salt + * @return 암호화된 비밀번호 + * @throws Exception + */ + public static String encryptPassword(String data, byte[] salt) throws Exception { + + if (data == null) { + return ""; + } + + byte[] hashValue = null; // 해쉬값 + + MessageDigest md = MessageDigest.getInstance("SHA-256"); + + md.reset(); + md.update(salt); + + hashValue = md.digest(data.getBytes()); + + return new String(Base64.encodeBase64(hashValue)); + } + + /** + * 비밀번호를 암호화된 패스워드 검증(salt가 사용된 경우만 적용). + * + * @param data 원 패스워드 + * @param encoded 해쉬처리된 패스워드(Base64 인코딩) + * @return + * @throws Exception + */ + public static boolean checkPassword(String data, String encoded, byte[] salt) throws Exception { + byte[] hashValue = null; // 해쉬값 + + MessageDigest md = MessageDigest.getInstance("SHA-256"); + + md.reset(); + md.update(salt); + hashValue = md.digest(data.getBytes()); + + return MessageDigest.isEqual(hashValue, Base64.decodeBase64(encoded.getBytes())); + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/bbs/service/ArticleVO.java b/legacy/nlib/src/main/java/nlib/bbs/service/ArticleVO.java new file mode 100644 index 00000000..dd82b9f7 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/service/ArticleVO.java @@ -0,0 +1,395 @@ +package nlib.bbs.service; + +import java.util.List; +import org.apache.commons.lang.StringEscapeUtils; +import com.fasterxml.jackson.annotation.JsonIgnore; +import nlib.cmm.service.PagingVO; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : ArticleVO.java
+ * 
+ * @Description : 게시물 공통 VO
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 09. 13. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 09. 13. + * @version 1.0 + * + */ +public class ArticleVO extends PagingVO { + + private String articleId; /* 게시글ID */ + private String mngOrgCd; /* 관리문화원코드 */ + private String mngOrgNm; /* 관리문화원명 */ + @JsonIgnore + private String bdType; /* 게시판유형 */ + @JsonIgnore + private String bdTypeName; /* 게시판유형명 */ + private String title; /* 제목 */ + private String content; /* 내용 */ + + // 공지사항관련 + private String notiYn; /* 공지여부 */ + private String openYn; /* 공개여부 */ + @JsonIgnore + private String postStartDate; /* 게시시작일자 */ + @JsonIgnore + private String postEndDate; /* 게시종료일자 */ + + // FAQ, QNA관련 + private String answer; /* 답변 */ + private String answerYn; /* 답변여부 */ + @JsonIgnore + private String useYn; /* 사용여부 */ + private String questionType; /* 질문유형 */ + private String questionTypeName; /* 질문유형명 */ + private String secretYn; /* 비밀글여부 */ + private String emailRecvYn; /* 답변이미엘수신여부 */ + private String email; /* 이메일 */ + private int viewCnt; /* 조회수 */ + private String bdAttachFileId; /* 첨부파일아이디 */ + private String attachYn; /* 첨부파일존재여부 */ + private List attachFiles; /* 첨부파일목록 */ + private List removedAttachFiles; /* 삭제첨부파일목록 */ + + @JsonIgnore + private String regId; /* 등록자아이디 */ + private String regNm; /* 등록자명 */ + private String regDd; /* 등록일자 */ + @JsonIgnore + private String modId; /* 등록자아이디 */ + private String modDd; /* 등록일자 */ + private int rno; /* 글번호 */ + @JsonIgnore + private String loginedMbInfoId; /* 로그인 사용자 ID */ + private String loginedName; /* 로그인 사용자명 */ + private String myQnaYn; /* 내가한 질문인지 여부 */ + + // 검색관련 + private String searchType; /* 검색대상구분 */ + private String searchKeyword; /* 검색어 */ + private String searchQuestionType; /* 검색FAQ유형 */ + @JsonIgnore + private String searchMbInfoId; /* 로그인한 사용자ID */ + + // 처리결과 관련 + private String resultMessage = null; /* 처리결과메시지 */ + private String resultCode = null; /* 처리결과코드 */ + + public int getAttachFileCnt() { + if(attachFiles == null) return 0; + return attachFiles.size(); + } + + public String getSanitizedContent() { + return StringUtil.sanitizeHtml(content); + } + + // SETTER & GETTER + public String getArticleId() { + return articleId; + } + public void setArticleId(String articleId) { + // 쿼리 조건으로 사용되는 항목에 대하여 SQL 인젝션으로 처리될만한 문자 강체 치환 처리 + this.articleId = StringUtil.getValidCodeString(articleId); + } + public String getMngOrgCd() { + return mngOrgCd; + } + public void setMngOrgCd(String mngOrgCd) { + // 쿼리 조건으로 사용되는 항목에 대하여 SQL 인젝션으로 처리될만한 문자 강체 치환 처리 + this.mngOrgCd = StringUtil.getValidCodeString(mngOrgCd); + } + public String getBdType() { + return bdType; + } + public void setBdType(String bdType) { + this.bdType = bdType; + } + public String getUnescapeTitle() { + return StringEscapeUtils.unescapeHtml(title); + } + public String getTitle() { + return title; + } + + public void setTitle(String title) { + + /* + * 통합자료관관리시스템과 동일하게 게시글 저장 처리를 수행하며, + * 제목의 경우, DB에 일부 특수문자에 대하여 치환되어 저장되고, + * 내용의 경우, HTML 요청된 그대로 저장하되 표출할 때 HTML Sanitizing하여 표출토록 처리하기로 협의됨에 따라 + * 제목 설정시 치환되어 저장토록 함 (2021.12.21, 이규모차장님) + */ + this.title = StringUtil.getRemovedQuotesStr(title); + } + public String getContent() { + return content; + } + public void setContent(String content) { + this.content = content; + } + public String getNotiYn() { + return notiYn; + } + public void setNotiYn(String notiYn) { + this.notiYn = notiYn; + } + public String getOpenYn() { + return openYn; + } + public void setOpenYn(String openYn) { + this.openYn = openYn; + } + public String getPostStartDate() { + return postStartDate; + } + public void setPostStartDate(String postStartDate) { + this.postStartDate = postStartDate; + } + public String getPostEndDate() { + return postEndDate; + } + public void setPostEndDate(String postEndDate) { + this.postEndDate = postEndDate; + } + public int getViewCnt() { + return viewCnt; + } + public void setViewCnt(int viewCnt) { + this.viewCnt = viewCnt; + } + public String getBdAttachFileId() { + return bdAttachFileId; + } + public void setBdAttachFileId(String bdAttachFileId) { + this.bdAttachFileId = bdAttachFileId; + } + public String getRegId() { + return regId; + } + public void setRegId(String regId) { + this.regId = regId; + } + public String getRegDd() { + return regDd; + } + public void setRegDd(String regDd) { + this.regDd = regDd; + } + public String getModId() { + return modId; + } + public void setModId(String modId) { + this.modId = modId; + } + public String getModDd() { + return modDd; + } + public void setModDd(String modDd) { + this.modDd = modDd; + } + public String getRegNm() { + return regNm; + } + public String getRegNmSec() { + if(StringUtil.isEmpty(regNm)) return null; + return StringUtil.maskName(regNm); + } + public void setRegNm(String regNm) { + this.regNm = regNm; + } + public int getRno() { + return rno; + } + public void setRno(int rno) { + this.rno = rno; + } + public String getSearchType() { + return searchType; + } + public void setSearchType(String searchType) { + this.searchType = searchType; + } + public String getSearchKeyword() { + return searchKeyword; + } + public String getEscapeSearchKeyword() { + return StringUtil.getSqlSearchKeyword(searchKeyword); + } + public void setSearchKeyword(String searchKeyword) { + this.searchKeyword = searchKeyword; + } + public String getAttachYn() { + return attachYn; + } + public void setAttachYn(String attachYn) { + this.attachYn = attachYn; + } + public String getMngOrgNm() { + return mngOrgNm; + } + public void setMngOrgNm(String mngOrgNm) { + this.mngOrgNm = mngOrgNm; + } + public String getBdTypeName() { + return bdTypeName; + } + public void setBdTypeName(String bdTypeName) { + this.bdTypeName = bdTypeName; + } + public List getAttachFiles() { + return attachFiles; + } + public void setAttachFiles(List attachFiles) { + if(attachFiles == null || attachFiles.size() < 1) this.attachFiles = null; + this.attachFiles = attachFiles; + } + + public String getAnswerYn() { + return StringUtil.isEmpty(answerYn) ? "N" : answerYn; + } + + public void setAnswerYn(String answerYn) { + this.answerYn = answerYn; + } + + public String getUseYn() { + return useYn; + } + + public void setUseYn(String useYn) { + this.useYn = useYn; + } + + public String getQuestionType() { + return questionType; + } + + public void setQuestionType(String questionType) { + this.questionType = questionType; + } + + public String getQuestionTypeName() { + return questionTypeName; + } + + public void setQuestionTypeName(String questionTypeName) { + this.questionTypeName = questionTypeName; + } + + public String getAnswer() { + return answer; + } + + public String getSanitizedAnswer() { + return StringUtil.sanitizeHtml(answer); + } + + public void setAnswer(String answer) { + this.answer = answer; + } + + public String getSearchQuestionType() { + return searchQuestionType; + } + + public void setSearchQuestionType(String searchQuestionType) { + this.searchQuestionType = searchQuestionType; + } + + public String getSearchMbInfoId() { + return searchMbInfoId; + } + + public void setSearchMbInfoId(String searchMbInfoId) { + // 쿼리 조건으로 사용되는 항목에 대하여 SQL 인젝션으로 처리될만한 문자 강체 치환 처리 + this.searchMbInfoId = StringUtil.getValidCodeString(searchMbInfoId); + } + + public String getSecretYn() { + return secretYn; + } + + public void setSecretYn(String secretYn) { + this.secretYn = secretYn; + } + + public String getLoginedMbInfoId() { + return loginedMbInfoId; + } + + public void setLoginedMbInfoId(String loginedMbInfoId) { + // 쿼리 조건으로 사용되는 항목에 대하여 SQL 인젝션으로 처리될만한 문자 강체 치환 처리 + this.loginedMbInfoId = StringUtil.getValidCodeString(loginedMbInfoId); + } + + public String getMyQnaYn() { + return StringUtil.isEmpty(myQnaYn) ? "N" : myQnaYn; + } + + public void setMyQnaYn(String myQnaYn) { + this.myQnaYn = myQnaYn; + } + + public String getLoginedName() { + return loginedName; + } + + public void setLoginedName(String loginedName) { + this.loginedName = loginedName; + } + + public String getEmailRecvYn() { + return StringUtil.isEmpty(emailRecvYn) ? "N" : emailRecvYn; + } + + public void setEmailRecvYn(String emailRecvYn) { + this.emailRecvYn = emailRecvYn; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getResultMessage() { + return resultMessage; + } + + public void setResultMessage(String resultMessage) { + this.resultMessage = resultMessage; + } + + public String getResultCode() { + return resultCode; + } + + public void setResultCode(String resultCode) { + this.resultCode = resultCode; + } + + public List getRemovedAttachFiles() { + return removedAttachFiles; + } + + public void setRemovedAttachFiles(List removedAttachFiles) { + this.removedAttachFiles = removedAttachFiles; + } + +} diff --git a/legacy/nlib/src/main/java/nlib/bbs/service/AttachFileService.java b/legacy/nlib/src/main/java/nlib/bbs/service/AttachFileService.java new file mode 100644 index 00000000..643a5501 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/service/AttachFileService.java @@ -0,0 +1,109 @@ + +package nlib.bbs.service; + +import java.util.List; + +/** + *
+ * @Class Name : AttachFileService.java
+ * 
+ * @Description : 첨부파일을 관리하는 서비스 인터페이스
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 16. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 9. 16. + * @version 1.0 + * + */ +public interface AttachFileService +{ + + /** + * 첨부파일 개수를 조회한다. + * + * @param attachFileId + * @return + * @throws Exception + */ + public int countAttachFiles(String attachFileId) throws Exception; + + /** + * 첨부파일 목록을 조회한다. + * + * @param attachFileId + * @return + * @throws Exception + */ + public List listAttachFiles(String attachFileId) throws Exception; + + + /** + * 첨부파일그룹 등록한다. + * + * @param attachFileVO + * @return + * @throws Exception + */ + public int insertAttachFileGroup(AttachFileVO attachFileVO) throws Exception; + + + /** + * 첨부파일 등록한다. + * + * @param attachFileVO + * @return + * @throws Exception + */ + public int insertAttachFile(AttachFileVO attachFileVO) throws Exception; + + + /** + * 첨부파일그룹을 삭제한다. + * + * @param attachFileVO + * @return + * @throws Exception + */ + public int deleteAttachFileGroup(String attachFileId) throws Exception; + + /** + * 첨부파일 삭제한다. + * + * @param attachFileVO + * @return + * @throws Exception + */ + public int deleteAttachFile(AttachFileVO attachFileVO) throws Exception; + + + /** + * 첨부파일 정보를 조회한다. + * + * @param attachFileVO + * @return + * @throws Exception + */ + public AttachFileVO selectAttachFile(AttachFileVO attachFileVO) throws Exception; + + + /** + * 다운로드 가능 여부를 확인하다. + * + * @param attachFileVO + * @return + * @throws Exception + */ + public boolean checkAttachFileDownload(AttachFileVO attachFileVO) throws Exception; + +} + diff --git a/legacy/nlib/src/main/java/nlib/bbs/service/AttachFileVO.java b/legacy/nlib/src/main/java/nlib/bbs/service/AttachFileVO.java new file mode 100644 index 00000000..4c662d23 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/service/AttachFileVO.java @@ -0,0 +1,111 @@ +package nlib.bbs.service; + +/** + *
+ * @Class Name : AttachFileVO.java
+ * 
+ * @Description : 첨부파일 정보 VO 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 14. KNKIM 최초 생성 + * @ 2021.11. 24. KNKIM DB컬럼명 수정에 따른 변경 처리 (FILE_STRE_COURS -> FILE_STRE_PATH, FILE_EXTSN -> FILE_EXT) + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 9. 14. + * @version 1.0 + * + */ +public class AttachFileVO { + + private String bdType; /* 첨부된 게시판 유형 : ancmnt, faq, qna */ + private String mbInfoId; /* 사용자ID (권한체크 등에 사용) */ + + private String subPathKey; /* 첨부파일서브경로 */ + + private String attachFileId; /* 첨부파일아이디 */ + private int fileSn; /* 파일 순번 */ + private String fileStrePath; /* 파일 저장결올 */ + private String streFileNm; /* 저장파일명 */ + private String orignlFileNm; /* 원본파일명 */ + private String fileExt; /* 파일확장자 */ + private int fileSize; /* 파일 사이즈 */ + private String useAt; /* 사용영부 */ + + + // GET/SET + public String getSubPathKey() { + return subPathKey; + } + public void setSubPathKey(String subPathKey) { + this.subPathKey = subPathKey; + } + public String getAttachFileId() { + return attachFileId; + } + public void setAttachFileId(String attachFileId) { + this.attachFileId = attachFileId; + } + public int getFileSn() { + return fileSn; + } + public void setFileSn(int fileSn) { + this.fileSn = fileSn; + } + public String getFileStrePath() { + return fileStrePath; + } + public void setFileStrePath(String fileStrePath) { + this.fileStrePath = fileStrePath; + } + public String getStreFileNm() { + return streFileNm; + } + public void setStreFileNm(String streFileNm) { + this.streFileNm = streFileNm; + } + public String getOrignlFileNm() { + return orignlFileNm; + } + public void setOrignlFileNm(String orignlFileNm) { + this.orignlFileNm = orignlFileNm; + } + public String getFileExt() { + return fileExt; + } + public void setFileExt(String fileExt) { + this.fileExt = (fileExt == null ? null : fileExt.toLowerCase()); + } + public int getFileSize() { + return fileSize; + } + public void setFileSize(int fileSize) { + this.fileSize = fileSize; + } + public String getUseAt() { + return useAt; + } + public void setUseAt(String useAt) { + this.useAt = useAt; + } + public String getMbInfoId() { + return mbInfoId; + } + public void setMbInfoId(String mbInfoId) { + this.mbInfoId = mbInfoId; + } + public String getBdType() { + return bdType; + } + public void setBdType(String bdType) { + this.bdType = bdType; + } + +} diff --git a/legacy/nlib/src/main/java/nlib/bbs/service/BoardService.java b/legacy/nlib/src/main/java/nlib/bbs/service/BoardService.java new file mode 100644 index 00000000..837bb604 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/service/BoardService.java @@ -0,0 +1,61 @@ + +package nlib.bbs.service; + +import java.util.List; + +/** + *
+ * @Class Name : BoardService.java
+ * 
+ * @Description : 게시물 관련 공통 서비스 인터페이스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 07. 1. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 07. 1. + * @version 1.0 + * + */ +public interface BoardService +{ + + /** + * 게시글 목록을 조회한다. + */ + public List listArticles(ArticleVO ArticleVO) throws Exception; + + + /** + * 게시글 건수를 조회한다. + */ + public int countArticles(ArticleVO articleVO) throws Exception; + + /** + * 조회수를 증가시킨다. + * + * @param + * @return + * @throws Exception + */ + public int updateRead(ArticleVO articleVO) throws Exception; + + /** + * 게시글 상세 내용을 조회한다. + * + * @param + * @return + * @throws Exception + */ + public ArticleVO selectArticle(ArticleVO articleVO) throws Exception; + +} + diff --git a/legacy/nlib/src/main/java/nlib/bbs/service/QnaService.java b/legacy/nlib/src/main/java/nlib/bbs/service/QnaService.java new file mode 100644 index 00000000..e1c2d2ec --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/service/QnaService.java @@ -0,0 +1,91 @@ + +package nlib.bbs.service; + +/** + *
+ * @Class Name : QnaService.java
+ * 
+ * @Description : 공통 게시물관리 서비스를 상속받아 Q&A 추가 기능을 명시한 서비스 인터페이스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 09. 29. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 09. 29. + * @version 1.0 + * + */ +public interface QnaService extends BoardService +{ + + /** + * 공통적인 게시판 목록, 조회관련한 맴버함수는 BoardService 에서 상속하고, + * QnaService에 추가된 멤버함순만 추가 정의 한다. + * + */ + + /** + * 게시글을 등록한다. + * + * @param + * @return + * @throws Exception + */ + public ArticleVO insertArticle(ArticleVO articleVO) throws Exception; + + /** + * 게시글을 수정한다. + * + * @param + * @return + * @throws Exception + */ + public int updateArticle(ArticleVO articleVO) throws Exception; + + /** + * 게시글을 삭제한다. + * + * @param + * @return + * @throws Exception + */ + public int deleteArticle(ArticleVO articleVO) throws Exception; + + + /** + * 해당 QNA 글을 변경할 수 있는지 여부를 확인한다. + * + * @param articleVO + * @return + * @throws Exception + */ + public String canModify(ArticleVO articleVO) throws Exception; + + /** + * 해당 QNA 글을 변경할 수 있는지 여부를 확인한다. + * + * @param articleVO + * @return + * @throws Exception + */ + public String canModify(ArticleVO articleVO, String mbInfoId) throws Exception; + + /** + * 해당 QNA 글을 읽을 수 있는지 여부를 확인한다. + * + * @param articleVO + * @return + * @throws Exception + */ + public String canRead(ArticleVO articleVO) throws Exception; + +} + diff --git a/legacy/nlib/src/main/java/nlib/bbs/service/impl/AncmntDAO.java b/legacy/nlib/src/main/java/nlib/bbs/service/impl/AncmntDAO.java new file mode 100644 index 00000000..38dc7468 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/service/impl/AncmntDAO.java @@ -0,0 +1,34 @@ +package nlib.bbs.service.impl; + +import egovframework.rte.psl.dataaccess.mapper.Mapper; + +/** + *
+ * @Class Name : AncmntDAO.java
+ * 
+ * @Description : 공지사항 정보 제공 DAO 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 13. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 9. 13. + * @version 1.0 + * + */ +@Mapper("ancmntDAO") +public interface AncmntDAO extends BoardDAO { + + /* + * BoardDAO 상속 내용과 동일 + */ + +} diff --git a/legacy/nlib/src/main/java/nlib/bbs/service/impl/AncmntServiceImpl.java b/legacy/nlib/src/main/java/nlib/bbs/service/impl/AncmntServiceImpl.java new file mode 100644 index 00000000..3382f97c --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/service/impl/AncmntServiceImpl.java @@ -0,0 +1,43 @@ +package nlib.bbs.service.impl; + +import javax.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +/** + *
+ * @Class Name : AncmntServiceImpl.java
+ * 
+ * @Description : 공지사항 서비스 구현 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 09. 13. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 09. 13. + * @version 1.0 + * + */ +@Service("ancmntService") +public class AncmntServiceImpl extends BoardServiceImpl +{ + static Logger log = LoggerFactory.getLogger(AncmntServiceImpl.class); + + @Resource(name="ancmntDAO") + AncmntDAO ancmntDAO; + + @Override + public BoardDAO getBoardDAO() { + return ancmntDAO; + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/bbs/service/impl/AttachFileDAO.java b/legacy/nlib/src/main/java/nlib/bbs/service/impl/AttachFileDAO.java new file mode 100644 index 00000000..6d6271c8 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/service/impl/AttachFileDAO.java @@ -0,0 +1,115 @@ +package nlib.bbs.service.impl; + +import java.util.List; +import egovframework.rte.psl.dataaccess.mapper.Mapper; +import nlib.bbs.service.AttachFileVO; + +/** + *
+ * @Class Name : AttachFileDAO.java
+ * 
+ * @Description : 게시판 첨부파일 관리 DAO  
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 16. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 9. 16. + * @version 1.0 + * + */ +@Mapper("attachFileDAO") +public interface AttachFileDAO { + + + /** + * 첨부파일 개수를 조회한다. + * + * @param attachFileId + * @return + * @throws Exception + */ + public int countAttachFiles(String attachFileId) throws Exception; + + /** + * 첨부파일 목록을 조회한다. + * + * @param + * @return + * @throws Exception + */ + public List listAttachFiles(String attachFileId) throws Exception; + + + /** + * 첨부파일그룹을 등록한다. + * + * @param + * @return + * @throws Exception + */ + public int insertAttachFileGroup(AttachFileVO attachFileVO) throws Exception; + + + /** + * 첨부파일 등록한다. + * + * @param + * @return + * @throws Exception + */ + public int insertAttachFile(AttachFileVO attachFileVO) throws Exception; + + /** + * 첨부파일그룹을 삭제한다. + * + * @param + * @return + * @throws Exception + */ + public int deleteAttachFileGroup(String attachFileId) throws Exception; + + /** + * 첨부파일그룹에 속한 모든 파일을 삭제한다. + * + * @param attachFileVO + * @return + * @throws Exception + */ + public int deleteAllFilesOfAttachFileGroup(String attachFileId) throws Exception; + + /** + * 첨부파일 삭제한다. + * + * @param + * @return + * @throws Exception + */ + public int deleteAttachFile(AttachFileVO attachFileVO) throws Exception; + + /** + * 첨부파일 정보를 조회한다. + * + * @param attachFileVO + * @return + * @throws Exception + */ + public AttachFileVO selectAttachFile(AttachFileVO attachFileVO) throws Exception; + + /** + * 다운로드 가능 여부를 확인하다. + * + * @param attachFileVO + * @return + * @throws Exception + */ + public String checkAttachFileDownload(AttachFileVO attachFileVO) throws Exception; +} diff --git a/legacy/nlib/src/main/java/nlib/bbs/service/impl/AttachFileServiceImpl.java b/legacy/nlib/src/main/java/nlib/bbs/service/impl/AttachFileServiceImpl.java new file mode 100644 index 00000000..ac3ca0d8 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/service/impl/AttachFileServiceImpl.java @@ -0,0 +1,158 @@ +package nlib.bbs.service.impl; + +import java.util.List; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import nlib.bbs.service.AttachFileService; +import nlib.bbs.service.AttachFileVO; +import nlib.bbs.service.QnaService; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : AttachFileServiceImpl.java
+ * 
+ * @Description : 첨부파일을 관리하는 서비스 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 16. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 9. 16. + * @version 1.0 + * + */ +@Service("attachFileService") +public class AttachFileServiceImpl implements AttachFileService +{ + static Logger log = LoggerFactory.getLogger(AttachFileServiceImpl.class); + + @Resource(name="attachFileDAO") + AttachFileDAO attachFileDAO; + + @Resource(name = "qnaService") + private QnaService qnaService; + + + /** + * 첨부파일 개수를 조회한다. + * + * @param attachFileId + * @return + * @throws Exception + */ + public int countAttachFiles(String attachFileId) throws Exception { + return attachFileDAO.countAttachFiles(attachFileId); + } + + /** + * 첨부파일 목록을 조회한다. + * + * @param + * @return + * @throws Exception + */ + @Override + public List listAttachFiles(String attachFileId) throws Exception { + return attachFileDAO.listAttachFiles(attachFileId); + } + + /** + * 첨부파일그룹 등록한다. + * + * @param + * @return + * @throws Exception + */ + @Override + public int insertAttachFileGroup(AttachFileVO attachFileVO) throws Exception { + return attachFileDAO.insertAttachFileGroup(attachFileVO); + } + + /** + * 첨부파일 등록한다. + * + * @param + * @return + * @throws Exception + */ + @Override + public int insertAttachFile(AttachFileVO attachFileVO) throws Exception { + return attachFileDAO.insertAttachFile(attachFileVO); + } + + /** + * 첨부파일그룹을 삭제한다. + * + * @param + * @return + * @throws Exception + */ + @Override + public int deleteAttachFileGroup(String attachFileId) throws Exception { + int ret = attachFileDAO.deleteAttachFileGroup(attachFileId); + attachFileDAO.deleteAllFilesOfAttachFileGroup(attachFileId); + return ret; + } + + /** + * 첨부파일 삭제한다. + * + * @param + * @return + * @throws Exception + */ + @Override + public int deleteAttachFile(AttachFileVO attachFileVO) throws Exception { + return attachFileDAO.deleteAttachFile(attachFileVO); + } + + + + /** + * 첨부파일 정보를 조회한다. + * + * @param attachFileVO + * @return + * @throws Exception + */ + public AttachFileVO selectAttachFile(AttachFileVO attachFileVO) throws Exception { + + if(attachFileVO == null) return null; + if(StringUtil.isEmpty(attachFileVO.getAttachFileId())) return null; + if(attachFileVO.getFileSn() < 0) return null; + + return attachFileDAO.selectAttachFile(attachFileVO); + } + + /** + * 다운로드 가능 여부를 확인하다. + * + * @param attachFileVO + * @return + * @throws Exception + */ + public boolean checkAttachFileDownload(AttachFileVO attachFileVO) throws Exception { + + String bdType = attachFileVO.getBdType(); + if(StringUtil.isEmpty(bdType)) return false; + + String ret = "Y"; + ret = attachFileDAO.checkAttachFileDownload(attachFileVO); + + return StringUtil.isEmpty(ret) ? false : (ret.charAt(0) == 'Y'); + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/bbs/service/impl/BoardDAO.java b/legacy/nlib/src/main/java/nlib/bbs/service/impl/BoardDAO.java new file mode 100644 index 00000000..159e12b9 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/service/impl/BoardDAO.java @@ -0,0 +1,59 @@ +package nlib.bbs.service.impl; + +import java.util.List; +import nlib.bbs.service.ArticleVO; + +/** + *
+ * @Class Name : BoardDAO.java
+ * 
+ * @Description : 공지사항 정보 제공 DAO 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 13. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 9. 13. + * @version 1.0 + * + */ + +public interface BoardDAO { + + /* + * 게시글 목록을 조회한다. + */ + public abstract List listArticles(ArticleVO ArticleVO) throws Exception; + + /** + * 게시글 건수를 조회한다. + */ + public abstract int countArticles(ArticleVO ArticleVO) throws Exception; + + /** + * 조회수를 증가시킨다. + * + * @param + * @return + * @throws Exception + */ + public abstract int updateRead(ArticleVO notiVO) throws Exception; + + /** + * 게시글 상세 내용을 조회한다. + * + * @param + * @return + * @throws Exception + */ + public abstract ArticleVO selectArticle(ArticleVO notiVO) throws Exception; + +} diff --git a/legacy/nlib/src/main/java/nlib/bbs/service/impl/BoardServiceImpl.java b/legacy/nlib/src/main/java/nlib/bbs/service/impl/BoardServiceImpl.java new file mode 100644 index 00000000..a12b8f56 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/service/impl/BoardServiceImpl.java @@ -0,0 +1,100 @@ +package nlib.bbs.service.impl; + +import java.util.List; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import nlib.bbs.service.ArticleVO; +import nlib.bbs.service.AttachFileService; +import nlib.bbs.service.AttachFileVO; +import nlib.bbs.service.BoardService; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : BoardServiceImpl.java
+ * 
+ * @Description : 게시판 서비스 추상 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 07. 01. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 07. 01. + * @version 1.0 + * + */ +public abstract class BoardServiceImpl implements BoardService +{ + static Logger log = LoggerFactory.getLogger(BoardServiceImpl.class); + + @Resource(name="attachFileService") + AttachFileService attachFileService; + + public abstract BoardDAO getBoardDAO(); + + /* + * 게시글 목록을 조회한다. + */ + public List listArticles(ArticleVO articleVO) throws Exception { + + return getBoardDAO().listArticles(articleVO); + } + + /** + * 게시글 건수를 조회한다. + */ + public int countArticles(ArticleVO articleVO) throws Exception { + + return getBoardDAO().countArticles(articleVO); + } + + + /** + * 조회수를 증가시킨다. + * + * @param + * @return + * @throws Exception + */ + public int updateRead(ArticleVO articleVO) throws Exception { + return getBoardDAO().updateRead(articleVO); + } + + /** + * 게시글 상세 내용을 조회한다. + * + * @param + * @return + * @throws Exception + */ + public ArticleVO selectArticle(ArticleVO articleVO) throws Exception { + + if(StringUtil.isEmpty(articleVO.getArticleId())) return null; + + // 게시글 조회 + ArticleVO retVO = getBoardDAO().selectArticle(articleVO); + // 첨부파일 조회 + if(StringUtil.isNotEmpty(retVO.getBdAttachFileId())) { + String attachFileId = retVO.getBdAttachFileId(); + List listFile = attachFileService.listAttachFiles(attachFileId); + retVO.setAttachFiles(listFile); + } + // 조회수 증가 + updateRead(articleVO); + + return retVO; + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/bbs/service/impl/FaqDAO.java b/legacy/nlib/src/main/java/nlib/bbs/service/impl/FaqDAO.java new file mode 100644 index 00000000..4b3ce7ad --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/service/impl/FaqDAO.java @@ -0,0 +1,34 @@ +package nlib.bbs.service.impl; + +import egovframework.rte.psl.dataaccess.mapper.Mapper; + +/** + *
+ * @Class Name : FaqDAO.java
+ * 
+ * @Description : FAQ DAO 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 09. 15. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 09. 15. + * @version 1.0 + * + */ +@Mapper("faqDAO") +public interface FaqDAO extends BoardDAO { + + /* + * BoardDAO 상속 내용과 동일 + */ + +} diff --git a/legacy/nlib/src/main/java/nlib/bbs/service/impl/FaqServiceImpl.java b/legacy/nlib/src/main/java/nlib/bbs/service/impl/FaqServiceImpl.java new file mode 100644 index 00000000..7fe1a5e7 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/service/impl/FaqServiceImpl.java @@ -0,0 +1,44 @@ +package nlib.bbs.service.impl; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +/** + *
+ * @Class Name : FaqServiceImpl.java
+ * 
+ * @Description : FAQ 서비스 구현 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 09. 15. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 09. 15. + * @version 1.0 + * + */ +@Service("faqService") +public class FaqServiceImpl extends BoardServiceImpl +{ + static Logger log = LoggerFactory.getLogger(FaqServiceImpl.class); + + @Resource(name="faqDAO") + FaqDAO faqDAO; + + @Override + public BoardDAO getBoardDAO() { + return faqDAO; + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/bbs/service/impl/QnaDAO.java b/legacy/nlib/src/main/java/nlib/bbs/service/impl/QnaDAO.java new file mode 100644 index 00000000..a5e1ffbe --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/service/impl/QnaDAO.java @@ -0,0 +1,60 @@ +package nlib.bbs.service.impl; + +import egovframework.rte.psl.dataaccess.mapper.Mapper; +import nlib.bbs.service.ArticleVO; + + +/** + *
+ * @Class Name : QnaDAO.java
+ * 
+ * @Description : Q&A DAO 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 09. 15. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 09. 15. + * @version 1.0 + * + */ +@Mapper("qnaDAO") +public interface QnaDAO extends BoardDAO { + + /* + * BoardDAO 상속 내용과 동일 + */ + + /** + * Q&A 게시글을 등록한다. + * + * @param reqVO + * @return + */ + public int insertArticle(ArticleVO articleVO); + + /** + * Q&A 게시글을 수정한다. + * + * @param reqVO + * @return + */ + public int updateArticle(ArticleVO articleVO); + + /** + * Q&A 게시글을 삭제한다. + * + * @param reqVO + * @return + */ + public int deleteArticle(ArticleVO articleVO); + +} diff --git a/legacy/nlib/src/main/java/nlib/bbs/service/impl/QnaServiceImpl.java b/legacy/nlib/src/main/java/nlib/bbs/service/impl/QnaServiceImpl.java new file mode 100644 index 00000000..170705bb --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/service/impl/QnaServiceImpl.java @@ -0,0 +1,270 @@ +package nlib.bbs.service.impl; + +import java.util.List; +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import nlib.bbs.service.ArticleVO; +import nlib.bbs.service.AttachFileService; +import nlib.bbs.service.AttachFileVO; +import nlib.bbs.service.QnaService; +import nlib.cmm.service.NlibProperty; +import nlib.util.StringUtil; +import nlib.util.UUID; + +/** + *
+ * @Class Name : QnaServiceImpl.java
+ * 
+ * @Description : Q&A 서비스 구현 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 09. 15. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 09. 15. + * @version 1.0 + * + */ +@Service("qnaService") +public class QnaServiceImpl extends BoardServiceImpl implements QnaService +{ + static Logger log = LoggerFactory.getLogger(QnaServiceImpl.class); + + @Resource(name="qnaDAO") + QnaDAO qnaDAO; + + @Resource(name="attachFileService") + AttachFileService attachFileService; + + @Override + public BoardDAO getBoardDAO() { + return qnaDAO; + } + + + /** + * Q&A 게시글을 등록한다. + * + * @param reqVO + * @return + */ + public ArticleVO insertArticle(ArticleVO articleVO) throws Exception { + articleVO.setArticleId(UUID.getNlibCommonID("NQ", 35)); + int ret = qnaDAO.insertArticle(articleVO); + + if(ret < 1) { + throw new Exception("등록에 실패하였습니다."); + } + + articleVO.setResultCode("S001"); + + if(articleVO.getAttachFileCnt() > 0) { + addAttachFiles(articleVO); + } + + articleVO.setResultMessage("정상적으로 등록되었습니다." + (StringUtil.isNotEmpty(articleVO.getResultMessage())? "\\\\n " + articleVO.getResultMessage() : "")); + + return articleVO; + } + + /** + * 첨부파일을 추가한다. + * + * @param articleVO + * @throws Exception + */ + public void addAttachFiles(ArticleVO articleVO) throws Exception { + int savedCnt = 0; + List attachFileList = articleVO.getAttachFiles(); + + // 최대 개수 + int maxFileCount = NlibProperty.getInt("fileupload.max.files", 5); + + // 첨부파일그룹 등록 + int groupCnt = attachFileService.insertAttachFileGroup(attachFileList.get(0)); + + if(groupCnt > 0) { + + int curFileCount = attachFileService.countAttachFiles(articleVO.getBdAttachFileId()); + int addingCount = maxFileCount - curFileCount; + + // 첨부파일 등록 + if(addingCount > 0) { + for(int i=0; i= addingCount) { + String message = "최대 허용 개수가 도달하여 등록을 중단합니다."; + log.error(message); + articleVO.setResultMessage(message); + break; + } + + AttachFileVO attachFileVO = attachFileList.get(i); + int retAttFile = attachFileService.insertAttachFile(attachFileVO); + savedCnt += retAttFile; + if(retAttFile < 1) { + log.error("insertArticle > 첨부파일 등록에 실패하였습니다 : " + attachFileVO.getOrignlFileNm()); + } + } + } + + if(savedCnt != articleVO.getAttachFileCnt()) { + articleVO.setResultMessage("총 " + articleVO.getAttachFileCnt() + "개 파일 중 " + savedCnt + "개 파일만 정상등록되었습니다."); + } + + } else { + articleVO.setResultMessage("게시글은 등록되었으나, 첨부파일그룹 등록에 실패하여 첨부파일 등록처리가 수행되지 않았습니다."); + } + } + + + /** + * 첨부파일을 삭제한다. + * + * @param articleVO + * @throws Exception + */ + public void removeAttachFiles(ArticleVO articleVO) throws Exception { + int savedCnt = 0; + List attachFileList = articleVO.getRemovedAttachFiles(); + + if(attachFileList == null || attachFileList.size() < 1) return; + + String attachFileId = attachFileList.get(0).getAttachFileId(); + + if(StringUtil.isNotEmpty(attachFileId)) { + + // 첨부파일 삭제 + for(int i=0; i 첨부파일 삭제에 실패하였습니다 : " + attachFileVO.getOrignlFileNm()); + } + } + + if(savedCnt != attachFileList.size()) { + articleVO.setResultMessage(String.format("총 %d개 파일 중 %개 파일만 정상 삭제되었습니다.", attachFileList.size(), savedCnt)); + } + + } else { + articleVO.setResultMessage("첨부파일그룹ID 정보가 누락되어 첨부파일 삭제가 불가합니다."); + } + + return; + } + + /** + * Q&A 게시글을 수정한다. + * + * @param reqVO + * @return + */ + public int updateArticle(ArticleVO articleVO) throws Exception { + + int updateRet = qnaDAO.updateArticle(articleVO); + + // 첨부파일 삭제 + List removedAttachFiles = articleVO.getRemovedAttachFiles(); + if(removedAttachFiles != null && removedAttachFiles.size() > 0) { + removeAttachFiles(articleVO); + } + + // 첨부파일 추가 + List addedFiles = articleVO.getAttachFiles(); + if(addedFiles != null && addedFiles.size() > 0) { + addAttachFiles(articleVO); + } + + return updateRet; + } + + /** + * Q&A 게시글을 삭제한다. + * + * @param reqVO + * @return + */ + public int deleteArticle(ArticleVO articleVO) throws Exception { + int ret = qnaDAO.deleteArticle(articleVO); + attachFileService.deleteAttachFileGroup(articleVO.getBdAttachFileId()); + return ret; + } + + /** + * 해당 QNA 글을 변경할 수 있는지 여부를 확인한다. + * (articleVO.getLoginedMbInfoId() 값을 확인하여 DB에 저장된 게시글을 조회하여 검사하므로 호출 전 설정 필요) + * + * @param articleVO + * @return + * @throws Exception + */ + public String canModify(ArticleVO articleVO) throws Exception { + + if(StringUtil.isEmpty(articleVO.getLoginedMbInfoId())) { + return "로그인 후, 이용하실 수 있습니다."; + } + + return canModify(selectArticle(articleVO), articleVO.getLoginedMbInfoId()); + } + + /** + * 해당 QNA 글을 변경할 수 있는지 여부를 확인한다. + * + * @param articleVO + * @return + * @throws Exception + */ + public String canModify(ArticleVO articleVO, String mbInfoId) throws Exception { + if(StringUtil.isEmpty(mbInfoId)) { + return "로그인 후, 이용하실 수 있습니다."; + } + + if(articleVO == null) { + return "대상 게시글 정보가 없습니다."; + } + + if(!"Y".equals(articleVO.getMyQnaYn())) { + return "본인의 글만 변경할 수 있습니다."; + } + + if("Y".equals(articleVO.getAnswerYn())) { + return "이미 답변완료된 글은 변경할 수 없습니다."; + } + + return null; + } + + /** + * 해당 QNA 글을 읽을 수 있는지 여부를 확인한다. + * + * @param articleVO + * @return + * @throws Exception + */ + public String canRead(ArticleVO articleVO) throws Exception { + + ArticleVO savedArticleVO = selectArticle(articleVO); + + if("Y".equals(savedArticleVO.getMyQnaYn())) return null; + + if("Y".equals(savedArticleVO.getSecretYn())) { + return "다른 사용자의 비밀글은 조회할 수 없습니다."; + } + + return null; + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/bbs/web/AncmntController.java b/legacy/nlib/src/main/java/nlib/bbs/web/AncmntController.java new file mode 100644 index 00000000..828ac8be --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/web/AncmntController.java @@ -0,0 +1,159 @@ + +package nlib.bbs.web; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.InitBinder; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import nlib.bbs.service.ArticleVO; +import nlib.bbs.service.BoardService; +import nlib.cmm.NlibCommonController; +import nlib.cmm.service.NlibProperty; +import nlib.cmm.service.PagingVO; + +/** + *
+ * @Class Name : AncmntController.java
+ * 
+ * @Description : 공지사항 컨트롤러 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 09. 13. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 09. 13. + * @version 1.0 + * + */ +@Controller +public class AncmntController extends NlibCommonController +{ + private static final Logger log = LoggerFactory.getLogger(AncmntController.class); + + static final int DEFUALT_PAGE_SIZE = NlibProperty.getInt("list.paging.page.size", 10); + + @Resource(name = "ancmntService") + private BoardService ancmntService; + + final String[] DISALLOWED_FIELDS = new String[] { + "mngOrgCd", + "mngOrgNm", + "bdType", + "title", + "content", + "notiYn", + "bdAttachFileId", + "attachYn", + "resultMessage", + "resultCode" + }; + + @InitBinder + public void initBinder(WebDataBinder binder) { + binder.setDisallowedFields(DISALLOWED_FIELDS); + } + + /** + * 목록 화면을 표시한다. + * + * @param req + * @return + */ + @RequestMapping("/bbs/listAncmnts.do") + public String listAncmnts( + HttpServletRequest req, + @RequestParam Map paramMap, + ArticleVO searchArticleVO, + ModelMap model + ) throws Exception { + + model.addAttribute("searchArticle", searchArticleVO); + + return "nlib/bbs/listAncmnts"; + } + + /** + * 목록 조회한다. + * + * @param request + * @return + */ + @RequestMapping(value="/bbs/listAncmntsAjax.do") + public ResponseEntity listAncmntsAjax( + HttpServletRequest request, + Authentication authentication, + @RequestBody ArticleVO searchArticleVO) throws Exception { + + if(searchArticleVO.getPageIndex() < 1) searchArticleVO.setPageIndex(1); + if(searchArticleVO.getPageSize() < 1) searchArticleVO.setPageSize(DEFUALT_PAGE_SIZE); + searchArticleVO.setMngOrgCd(getCurCouncilCd(request)); + + List list = ancmntService.listArticles(searchArticleVO); + + int totRecordCount = ancmntService.countArticles(searchArticleVO); + + //------------------------------- + // JSON변환 응답 처리 + //------------------------------- + // JS-GRID 페이징 처리를 포함한 응답값 처리 + // {data: [{...}], + // itemsCount: 255 + // } + HashMap retMap = new HashMap(); + retMap.put("data", list); + retMap.put("itemsCount", totRecordCount); + + PagingVO pageVO = new PagingVO(); + pageVO.setPagingVO(totRecordCount, searchArticleVO.getPageIndex(), searchArticleVO.getPageSize()); + retMap.put("pagingPageIndex" , pageVO.getPageIndex()); + retMap.put("pagingTotRecordCount", pageVO.getTotRecordCount()); + retMap.put("pagingStartPage" , pageVO.getStartPage()); + retMap.put("pagingEndPage" , pageVO.getEndPage()); + retMap.put("pagingLastPage" , pageVO.getLastPage()); + + return makeResponseEntityJson(retMap); + } + + + /** + * 알림 상세 내용 조회한다. + * + * @param req + * @return + */ + @RequestMapping("/bbs/selectAncmntArticle.do") + public String selectAncmntArticle(HttpServletRequest req, Authentication authentication, ArticleVO searchArticleVO, ModelMap model) throws Exception { + + // 읽음처리 및 상세내용 조회 + ArticleVO articleVO = ancmntService.selectArticle(searchArticleVO); + + model.addAttribute("searchArticle", searchArticleVO); + model.addAttribute("article", articleVO); + + return "nlib/bbs/selectAncmntArticle"; + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/bbs/web/FaqController.java b/legacy/nlib/src/main/java/nlib/bbs/web/FaqController.java new file mode 100644 index 00000000..81658842 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/web/FaqController.java @@ -0,0 +1,158 @@ + +package nlib.bbs.web; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import nlib.bbs.service.ArticleVO; +import nlib.bbs.service.BoardService; +import nlib.cmm.NlibCommonController; +import nlib.cmm.service.CodeService; +import nlib.cmm.service.NlibProperty; +import nlib.cmm.service.PagingVO; + +/** + *
+ * @Class Name : FaqController.java
+ * 
+ * @Description : FAQ 컨트롤러 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 09. 13. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 09. 13. + * @version 1.0 + * + */ +@Controller +public class FaqController extends NlibCommonController { + + private static final Logger log = LoggerFactory.getLogger(FaqController.class); + + static final int DEFUALT_PAGE_SIZE = NlibProperty.getInt("list.paging.page.size", 10); + + @Resource(name = "faqService") + private BoardService faqService; + + @Resource(name="codeService") + private CodeService codeService; + + /** + * 목록 화면을 표시한다. + * + * @param req + * @return + */ + @RequestMapping("/bbs/listFaqs.do") + public String listFaqs( + HttpServletRequest req, + @RequestParam Map paramMap, + ArticleVO searchArticleVO, + ModelMap model + ) throws Exception { + + + List> questionTypeList = codeService.listCodes("NLIB_FAQ_TYPE_CD"); + model.addAttribute("questionTypeList", questionTypeList); + model.addAttribute("searchArticle", searchArticleVO); + + return "nlib/bbs/listFaqs"; + } + + /** + * 목록 조회한다. + * + * @param req + * @return + */ + @RequestMapping(value="/bbs/listFaqsAjax.do") + public ResponseEntity listFaqsAjax( + HttpServletRequest req, + Authentication authentication, + @RequestBody ArticleVO searchArticleVO) throws Exception { + + if(searchArticleVO.getPageIndex() < 1) searchArticleVO.setPageIndex(1); + if(searchArticleVO.getPageSize() < 1) searchArticleVO.setPageSize(DEFUALT_PAGE_SIZE); + searchArticleVO.setMngOrgCd(getCurCouncilCd(req)); + + List list = faqService.listArticles(searchArticleVO); + + int totRecordCount = faqService.countArticles(searchArticleVO); + + //------------------------------- + // JSON변환 응답 처리 + //------------------------------- + // JS-GRID 페이징 처리를 포함한 응답값 처리 + // {data: [{...}], + // itemsCount: 255 + // } + HashMap retMap = new HashMap(); + retMap.put("data", list); + retMap.put("itemsCount", totRecordCount); + + PagingVO pageVO = new PagingVO(); + pageVO.setPagingVO(totRecordCount, searchArticleVO.getPageIndex(), searchArticleVO.getPageSize()); + retMap.put("pagingPageIndex" , pageVO.getPageIndex()); + retMap.put("pagingTotRecordCount", pageVO.getTotRecordCount()); + retMap.put("pagingStartPage" , pageVO.getStartPage()); + retMap.put("pagingEndPage" , pageVO.getEndPage()); + retMap.put("pagingLastPage" , pageVO.getLastPage()); + + return makeResponseEntityJson(retMap); + } + + + /** + * 알림 상세 내용 조회한다. + * + * @param req + * @return + */ + @RequestMapping("/bbs/selectFaqArticleAjax.do") + public ResponseEntity selectFaqArticleAjax(HttpServletRequest req, Authentication authentication, @RequestBody ArticleVO searchArticleVO) throws Exception { + + // 읽음처리 및 상세내용 조회 + ArticleVO articleVO = faqService.selectArticle(searchArticleVO); + + // AJAX OUT에 XSS처리되지 않은 HTML 전송 차단위한 변경 처리 + if(articleVO != null) { + articleVO.setAnswer(articleVO.getSanitizedAnswer()); + articleVO.setContent(articleVO.getSanitizedContent()); + } + + //------------------------------- + // JSON변환 응답 처리 + //------------------------------- + // JS-GRID 페이징 처리를 포함한 응답값 처리 + // {data: [{...}], + // itemsCount: 255 + // } + HashMap retMap = new HashMap(); + retMap.put("data", articleVO); + + return makeResponseEntityJson(retMap); + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/bbs/web/QnaController.java b/legacy/nlib/src/main/java/nlib/bbs/web/QnaController.java new file mode 100644 index 00000000..3d25bf13 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/bbs/web/QnaController.java @@ -0,0 +1,602 @@ + +package nlib.bbs.web; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import nlib.bbs.service.ArticleVO; +import nlib.bbs.service.AttachFileVO; +import nlib.bbs.service.QnaService; +import nlib.cmm.NlibCommonController; +import nlib.cmm.service.CodeService; +import nlib.cmm.service.NlibProperty; +import nlib.cmm.service.PagingVO; +import nlib.user.service.NlibLoginVO; +import nlib.util.StringUtil; +import nlib.util.UUID; + +/** + *
+ * @Class Name : QnaController.java
+ * 
+ * @Description : Q&A 컨트롤러 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 09. 13. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 09. 13. + * @version 1.0 + * + */ +@Controller +public class QnaController extends NlibCommonController { + + private static final Logger log = LoggerFactory.getLogger(QnaController.class); + + static final int DEFUALT_PAGE_SIZE = NlibProperty.getInt("list.paging.page.size", 10); + + static final String BD_TYPE_QNA = "QNA"; + + @Resource(name = "qnaService") + private QnaService qnaService; + + @Resource(name="codeService") + private CodeService codeService; + + + /** + * 전체 목록 화면을 표시한다. + * + * @param req + * @return + */ + @RequestMapping("/bbs/listQnas.do") + public String listQnas( + HttpServletRequest req, + @RequestParam Map paramMap, + ArticleVO searchArticleVO, + ModelMap model + ) throws Exception { + + model.addAttribute("searchArticle", searchArticleVO); + + return "nlib/bbs/listQnas"; + } + + /** + * 내질문 목록 화면을 표시한다. (권한 적용을 위해 분리함) + * + * @param req + * @return + */ + @Secured("ROLE_USER") + @RequestMapping("/bbs/listMyQnas.do") + public String listMyQnas( + HttpServletRequest req, + @RequestParam Map paramMap, + ArticleVO searchArticleVO, + ModelMap model + ) throws Exception { + + searchArticleVO.setSearchQuestionType("USER"); + model.addAttribute("searchArticle", searchArticleVO); + + return "nlib/bbs/listQnas"; + } + + /** + * 목록 조회한다. + * + * @param request + * @return + */ + @RequestMapping(value="/bbs/listQnasAjax.do") + public ResponseEntity listQnasAjax( + HttpServletRequest request, + Authentication authentication, + @RequestBody ArticleVO searchArticleVO) throws Exception { + + String message = null; + boolean needToQeury = true; + + if(searchArticleVO.getPageIndex() < 1) searchArticleVO.setPageIndex(1); + if(searchArticleVO.getPageSize() < 1) searchArticleVO.setPageSize(DEFUALT_PAGE_SIZE); + searchArticleVO.setMngOrgCd(getCurCouncilCd(request)); + + String mbInfoId = getMbInfoId(request); + searchArticleVO.setLoginedMbInfoId(mbInfoId); + if(StringUtil.equalsIgnoreCase(searchArticleVO.getSearchQuestionType(), "USER")) { + searchArticleVO.setSearchMbInfoId(mbInfoId); + if(StringUtil.isEmpty(mbInfoId)) needToQeury = false; + } else { + searchArticleVO.setSearchMbInfoId(null); + } + + List list = null; + int totRecordCount = 0; + + if(needToQeury) { + list = qnaService.listArticles(searchArticleVO); + totRecordCount = qnaService.countArticles(searchArticleVO); + } else { + list = new ArrayList(); + message = "로그인 후, 이용하여 주시기 바랍니다"; + } + + //------------------------------- + // JSON변환 응답 처리 + //------------------------------- + // JS-GRID 페이징 처리를 포함한 응답값 처리 + // {data: [{...}], + // itemsCount: 255 + // } + HashMap retMap = new HashMap(); + retMap.put("data", list); + retMap.put("itemsCount", totRecordCount); + retMap.put("message", message); + + PagingVO pageVO = new PagingVO(); + pageVO.setPagingVO(totRecordCount, searchArticleVO.getPageIndex(), searchArticleVO.getPageSize()); + retMap.put("pagingPageIndex" , pageVO.getPageIndex()); + retMap.put("pagingTotRecordCount", pageVO.getTotRecordCount()); + retMap.put("pagingStartPage" , pageVO.getStartPage()); + retMap.put("pagingEndPage" , pageVO.getEndPage()); + retMap.put("pagingLastPage" , pageVO.getLastPage()); + + return makeResponseEntityJson(retMap); + } + + /** + * 알림 상세 내용 조회한다. + * + * @param req + * @return + */ + @RequestMapping("/bbs/selectQnaArticle.do") + public String selectQnaArticle(HttpServletRequest request, Authentication authentication, ArticleVO searchArticleVO, ModelMap model) throws Exception { + + // 읽음처리 및 상세내용 조회 + searchArticleVO.setLoginedMbInfoId(getMbInfoId(request)); + ArticleVO articleVO = null; + + String canRead = qnaService.canRead(searchArticleVO); + if(canRead != null) { + model.addAttribute("message", canRead); + articleVO = searchArticleVO; + } else { + articleVO = qnaService.selectArticle(searchArticleVO); + } + + model.addAttribute("searchArticle", searchArticleVO); + model.addAttribute("article", articleVO); + + return "nlib/bbs/selectQnaArticle"; + } + + /** + * 묻고답하기 글작성화면을 표출한다. + * + * @param req + * @return + */ + @Secured("ROLE_USER") + @RequestMapping({"/bbs/insertQnaForm.do", "/bbs/updateQnaForm.do"}) + public String insertQnaForm( + HttpServletRequest request + , ArticleVO searchArticleVO + , RedirectAttributes redirectAttrs + , ModelMap model) throws Exception { + + NlibLoginVO nlibLoginVO = getNlibLoginVO(request); + + searchArticleVO.setLoginedMbInfoId(getMbInfoId(request)); + Map rAttrs = redirectAttrs.getFlashAttributes(); + ArticleVO redirectSearchArticleVO = (ArticleVO)rAttrs.get("searchArticle"); + + if(redirectSearchArticleVO != null && StringUtil.isNotEmpty(redirectSearchArticleVO.getTitle())) { + searchArticleVO = redirectSearchArticleVO; + } else { + ArticleVO articleVO = qnaService.selectArticle(searchArticleVO); + if(articleVO != null && !StringUtil.isEmpty(articleVO.getTitle())) { + articleVO.setSearchKeyword(searchArticleVO.getSearchKeyword()); + articleVO.setPageIndex(searchArticleVO.getPageIndex()); + articleVO.setPageSize(searchArticleVO.getPageSize()); + + searchArticleVO = articleVO; + } + } + + searchArticleVO.setLoginedMbInfoId(nlibLoginVO.getMbInfoId()); + searchArticleVO.setLoginedName(nlibLoginVO.getName()); + searchArticleVO.setEmail(nlibLoginVO.getEmail()); + + model.addAttribute("searchArticle", searchArticleVO); + + // 첨부파일 업로드 설정값 + model.addAttribute("maxFilesize" , NlibProperty.getString("fileupload.max.mbsize")); + model.addAttribute("maxFiles" , NlibProperty.getString("fileupload.max.files")); + model.addAttribute("acceptedFiles", NlibProperty.getString("fileupload.acceptable.ext")); + + return "nlib/bbs/insertQnaForm"; + } + + + /** + * 묻고답하기 등록 처리한다. + * + * @param req + * @param authentication + * @param paramMap + * @param model + * @return + */ + @Secured("ROLE_USER") + @RequestMapping("/bbs/insertQnaArticle.do") + public String insertQna(HttpServletRequest request + , Authentication authentication + , ArticleVO articleVO + , String fileList + , RedirectAttributes redirectAttrs + , ModelMap model) throws Exception { + + NlibLoginVO loginVO = getNlibLoginVO(authentication); + + String message = null; + if(loginVO == null || StringUtil.isEmpty(loginVO.getMbInfoId())) { + message = "로그인하신 후, 이용하여 주시기 바랍니다."; + log.error("inserQna > " + message); + redirectAttrs.addFlashAttribute("searchArticle", articleVO); + redirectAttrs.addFlashAttribute("message", message); + redirectAttrs.addFlashAttribute("title", articleVO.getTitle()); + return "redirect:/bbs/insertQnaForm.do"; + } + + //--------------------------- + // 기본 정보 설정 + //--------------------------- + articleVO.setRegId(loginVO.getMbInfoId()); + articleVO.setMngOrgCd(getCurCouncilCd(request)); // 문화원코드 + articleVO.setBdType(BD_TYPE_QNA); + articleVO.setAnswerYn("N"); + articleVO.setAnswer(null); + if(StringUtil.isEmpty(articleVO.getEmailRecvYn())) articleVO.setEmailRecvYn("N"); + if(StringUtil.isEmpty(articleVO.getSecretYn())) articleVO.setSecretYn("N"); + + + //--------------------------- + // 첨부파일 정보 설정 + //--------------------------- + if(StringUtil.isNotEmpty(fileList)) { + + String fileListJsonStr = fileList; + if(fileListJsonStr.startsWith("&")) fileListJsonStr = StringEscapeUtils.unescapeHtml(fileListJsonStr); + if(fileListJsonStr.startsWith("\"")) fileListJsonStr = fileListJsonStr.substring(1); + if(fileListJsonStr.endsWith("\"")) fileListJsonStr = fileListJsonStr.substring(0, fileListJsonStr.length()-1); + fileListJsonStr = fileListJsonStr.replaceAll("\\\\", ""); + + log.debug("fileListJsonStr : " + fileListJsonStr); + + ObjectMapper mapper = new ObjectMapper(); + List> fileListObj = null; + try { + fileListObj = mapper.readValue(fileListJsonStr, new TypeReference>>() { + }); + + } catch (JsonMappingException e) { + log.error("insertQna Json 변환 처리 오류 JsonMappingException : " + e.toString()); + + } catch (JsonProcessingException e) { + log.error("insertQna Json 변환 처리 오류 JsonProcessingException : " + e.toString()); + + } + + if(fileListObj != null && fileListObj.size() > 0) { + + String attachFileId = (String)(fileListObj.get(0).get("attachFileId")); + if(StringUtil.isEmpty(attachFileId)) { + attachFileId = UUID.getNewAttachFileId(); + } + + if(StringUtil.isNotEmpty(attachFileId)) { + articleVO.setBdAttachFileId(attachFileId); + + String fileSStreCours = NlibProperty.getProperty("fileupload.base.path") + NlibProperty.getProperty("fileupload.bbs.qna.subpath") + "/"; + List attachFiles = new ArrayList(); + + // 최대 개수 + int maxFileCount = NlibProperty.getInt("fileupload.max.files", 5); + + for(int i=0; i> fileListObj = null; + try { + fileListObj = mapper.readValue(fileListJsonStr, new TypeReference>>() { + }); + + } catch (JsonMappingException e) { + log.error("updateQnaArticle Json 변환 처리 오류 JsonMappingException : " + e.toString()); + + } catch (JsonProcessingException e) { + log.error("updateQnaArticle Json 변환 처리 오류 JsonProcessingException : " + e.toString()); + + } + + if(fileListObj != null && fileListObj.size() > 0) { + + String attachFileId = articleOrg.getBdAttachFileId(); + if(StringUtil.isEmpty(attachFileId)) { + attachFileId = UUID.getNewAttachFileId(); + articleVO.setBdAttachFileId(attachFileId); + } + + if(StringUtil.isNotEmpty(articleVO.getBdAttachFileId())) articleVO.setBdAttachFileId(attachFileId); + + String fileSStreCours = NlibProperty.getProperty("fileupload.base.path") + NlibProperty.getProperty("fileupload.bbs.qna.subpath") + "/"; + List attachFiles = new ArrayList(); + + for(int i=0; i> removedFileListObj = null; + try { + removedFileListObj = mapper.readValue(removedFileListJsonStr, new TypeReference>>() { + }); + + } catch (JsonMappingException e) { + log.error("updateQnaArticle Json 변환 처리 오류 JsonMappingException : " + e.toString()); + + } catch (JsonProcessingException e) { + log.error("updateQnaArticle Json 변환 처리 오류 JsonProcessingException : " + e.toString()); + + } + + if(removedFileListObj != null && removedFileListObj.size() > 0) { + + String attachFileId = (String)(removedFileListObj.get(0).get("attachFileId")); + if(StringUtil.isEmpty(attachFileId)) attachFileId = articleOrg.getBdAttachFileId(); + + if(StringUtil.isEmpty(attachFileId)) { + log.error("첨부파일 아이디(attachFileId) 값은 필수 항목입니다. 첨부파일 삭제에 실패하였습니다. 그러나, 게시물 변경은 계속 진행됩니다."); + } + + if(StringUtil.isNotEmpty(attachFileId) && attachFileId.equals(articleOrg.getBdAttachFileId())) { + + List removedAttachFiles = new ArrayList(); + + for(int i=0; i + * @Class Name : NlibCommonController.java + * + * @Description : 컨트롤러의 공통적인 기능을 제공하는 컨트롤러 상위 클래스 + * + * + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021) + * + * + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 23. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 23. + * @version 1.0 + * + */ +public class NlibCommonController { + + private static final Logger log = LoggerFactory.getLogger(NlibCommonController.class); + + @Resource(name = "loginService") + private LoginService _loginService; + + private static final int INFO_ID_COUNCIL_CD = 1; /* 현재 지방문화원 코드를 지칭하는 식별자 */ + private static final int INFO_ID_COUNCIL_NM = 2; /* 현재 지방문화원 명칭을 지칭하는 식별자 */ + + /** + * 스프링 시큐리티 Authentication를 통해서 사용자로그인정보 NlibLoginVO를 리턴한다. + * + * @param authentication + * @return + */ + public NlibLoginVO getNlibLoginVO(Authentication authentication) { + if(authentication == null) return new NlibLoginVO(); + + return (NlibLoginVO)authentication.getPrincipal(); + } + + public NlibLoginVO getNlibLoginVO(HttpServletRequest request) { + + Authentication auth = (Authentication)request.getUserPrincipal(); + if(auth == null || !auth.isAuthenticated()) return new NlibLoginVO(); + + NlibLoginVO loginVO = (NlibLoginVO)auth.getPrincipal(); + if(loginVO == null || StringUtil.isEmpty(loginVO.getMbInfoId())) return new NlibLoginVO(); + + return loginVO; + } + + + /** + * 인증에 저장된 사용자 로그인 정보 VO의 값을 매개변수값으로 대체하여 저장하고 돌려 준다. + * + * @param request + * @param newLoginVO + * @return + */ + public NlibLoginVO replaceNlibLoginVO(HttpServletRequest request, NlibLoginVO newLoginVO) { + + if(newLoginVO == null) return null; + + Authentication auth = (Authentication)request.getUserPrincipal(); + if(auth == null || !auth.isAuthenticated()) return new NlibLoginVO(); + + NlibLoginVO loginVO = getNlibLoginVO(request); + if(loginVO == null) return null; + + if(!loginVO.getMbInfoId().equals(newLoginVO.getMbInfoId())) { + log.error("replaceNlibLoginVO > 서로 다른 사용자 정보이므로 인증 LoginVO 정보를 변경할 수 없습니다."); + return null; + } + + // 값 복사작업 + Method[] methods = NlibLoginVO.class.getMethods(); + String mName; + HashMap setterNames = new HashMap(); + HashMap getterNames = new HashMap(); + final String skipSetterList = "|setIp|setAlerted|setAuthorityList|"; + for(Method m : methods) { + mName = m.getName(); + if(skipSetterList.contains(mName)) continue; + + //log.debug("NlibLoginVO : methods > " + m.getName()); + + if(mName.toUpperCase().startsWith("SET")) setterNames.put(mName, m); + else if(mName.toUpperCase().startsWith("GET")) getterNames.put(mName, m); + else if(mName.toUpperCase().startsWith("IS")) getterNames.put(mName, m); + } + + String getterName; + for(String setterName : setterNames.keySet()) { + getterName = "get" + setterName.substring(3); + Method setter = setterNames.get(setterName); + Method getter = getterNames.get(getterName); + + if(setter != null && getter != null) { + try { + String oldValue = (String)getter.invoke(loginVO); + String newValue = (String)getter.invoke(newLoginVO); + + setter.invoke(loginVO, getter.invoke(newLoginVO)); + //log.debug("replaceNlibLoginVO > Method invoke : " + setterName + " : " + oldValue + " -> " + newValue); + + } catch(IllegalAccessException e) { + log.error("replaceNlibLoginVO > Method invoke IllegalAccessException : " + setterName + ", " + getterName); + } catch(IllegalArgumentException e) { + log.error("replaceNlibLoginVO > Method invoke IllegalArgumentException : " + setterName + ", " + getterName); + } catch(InvocationTargetException e) { + log.error("replaceNlibLoginVO > Method invoke InvocationTargetException : " + setterName + ", " + getterName); + } + } + + } + + return loginVO; + } + + + /** + * 사용자로그인정보 ID를 리턴한다. + * 로그인하지 않은 경우, null을 리턴한다. + * + * @param request + * @return + */ + public String getMbInfoId(HttpServletRequest request) { + + Authentication auth = (Authentication)request.getUserPrincipal(); + if(auth == null || !auth.isAuthenticated()) return null; + + NlibLoginVO loginVO = (NlibLoginVO)auth.getPrincipal(); + if(loginVO == null || StringUtil.isEmpty(loginVO.getMbInfoId())) return null; + + return loginVO.getMbInfoId(); + } + + /** + * 스프링 시큐리티 Authentication를 통해서 사용자로그인정보 SecUserVO를 리턴한다. + * + * @param authentication + * @return + */ + public SecUserVO getSecLoginVO(Authentication authentication) { + + if(authentication == null) return null; + + return (SecUserVO)authentication.getPrincipal(); + } + + public ResponseEntity makeResponseEntityJson(DataApiResVO resVO) { + + // Convert Json + ObjectMapper mapper = new ObjectMapper(); + String jsonStr = null; + + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8"); + + try { + jsonStr = mapper.writeValueAsString(resVO); + log.debug("RETURN DATA > json:" + jsonStr); + } catch (JsonProcessingException e) { + ErrorMessage eMsg = new ErrorMessage("ERR_JSON_CONVERT", "응답객체를 JSON으로 변환 처리 중 오류가 발생하였습니다. : " + e.toString()); + try { jsonStr = mapper.writeValueAsString(eMsg); } catch (JsonProcessingException ee) { + log.error("makeResponseEntityJson > JsonProcessingException내부 JsonProcessingException : " + ee.toString()); + } + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(headers).body(jsonStr); + } + + return ResponseEntity.ok().headers(headers).body(jsonStr); + } + + + public ResponseEntity makeResponseEntityJson(List> list) { + + // Convert Json + ObjectMapper mapper = new ObjectMapper(); + String jsonStr = null; + + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8"); + + try { + jsonStr = mapper.writeValueAsString(list); + log.debug("RETURN DATA > json:" + jsonStr); + } catch (JsonProcessingException e) { + ErrorMessage eMsg = new ErrorMessage("ERR_JSON_CONVERT", "응답객체를 JSON으로 변환 처리 중 오류가 발생하였습니다. : " + e.toString()); + try { jsonStr = mapper.writeValueAsString(eMsg); } catch (JsonProcessingException ee) { + log.error("makeResponseEntityJson > JsonProcessingException내부 JsonProcessingException : " + ee.toString()); + } + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(headers).body(jsonStr); + } + + return ResponseEntity.ok().headers(headers).body(jsonStr); + } + + public ResponseEntity makeResponseEntityJson(HashMap retMap) { + + // Convert Json + ObjectMapper mapper = new ObjectMapper(); + String jsonStr = null; + + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8"); + + try { + jsonStr = mapper.writeValueAsString(retMap); + log.debug("RETURN DATA > json:" + jsonStr); + } catch (JsonProcessingException e) { + ErrorMessage eMsg = new ErrorMessage("ERR_JSON_CONVERT", "응답객체를 JSON으로 변환 처리 중 오류가 발생하였습니다. : " + e.toString()); + try { jsonStr = mapper.writeValueAsString(eMsg); } catch (JsonProcessingException ee) { + log.error("makeResponseEntityJson > JsonProcessingException내부 JsonProcessingException : " + ee.toString()); + } + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(headers).body(jsonStr); + } + + return ResponseEntity.ok().headers(headers).body(jsonStr); + } + + public ModelMap addParamsToModel(Map paramMap, ModelMap model) { + return addParamsToModel(paramMap, model, null, null); + } + public ModelMap addParamsToModel(Map paramMap, ModelMap model, String upperMapName, String itemNames) { + + + if(paramMap == null || paramMap.size() < 1) return model; + if(model == null) return model; + + String filter = null; + if(StringUtil.isNotEmpty(itemNames)) { + filter = "," + itemNames + ","; + filter = filter.replaceAll(" ", ""); + } + + boolean existUpperMap = StringUtil.isNotEmpty(upperMapName); + Map uppperMap = null; + if(existUpperMap) uppperMap = new HashMap(); + + for(String key : paramMap.keySet()) { + + if(filter != null && !filter.contains("," + key + ",")) { + continue; + } + if(existUpperMap) { + uppperMap.put(key, paramMap.get(key)); + } else { + model.addAttribute(key, paramMap.get(key)); + } + + } + + if(existUpperMap) model.addAttribute(upperMapName, uppperMap); + + return model; + } + + + public RedirectAttributes addParamsToRedirect(Map paramMap, RedirectAttributes redirectAttrs) { + return addParamsToRedirect(paramMap, redirectAttrs, null, null); + } + public RedirectAttributes addParamsToRedirect(Map paramMap + , RedirectAttributes redirectAttrs + , String upperMapName + , String itemNames) { + + + if(paramMap == null || paramMap.size() < 1) return redirectAttrs; + if(redirectAttrs == null) return redirectAttrs; + + String filter = null; + if(StringUtil.isNotEmpty(itemNames)) { + filter = "," + itemNames + ","; + filter = filter.replaceAll(" ", ""); + } + + boolean existUpperMap = StringUtil.isNotEmpty(upperMapName); + Map uppperMap = null; + if(existUpperMap) uppperMap = new HashMap(); + + for(String key : paramMap.keySet()) { + + if(filter != null && !filter.contains("," + key + ",")) { + continue; + } + if(existUpperMap) { + uppperMap.put(key, paramMap.get(key)); + } else { + redirectAttrs.addFlashAttribute(key, paramMap.get(key)); + } + + } + + if(existUpperMap) redirectAttrs.addFlashAttribute(upperMapName, uppperMap); + + return redirectAttrs; + } + + + public String addParamsToUrl(String url, String paramName, String paramValue) { + + if(StringUtil.isEmpty(url)) return null; + if(StringUtil.isEmpty(paramName)) return url; + + String newUrl = url; + + if(url.contains("?")) newUrl += "&"; + else newUrl += "?"; + + newUrl += paramName + "=" + StringUtil.getString(paramValue, "").trim(); + + return newUrl; + } + + /** + * paramMap에 이전 요청에서 전달할 때 추가한 POST방식의 매개변수값을 paramMap에 추가한다. + * + * @param paramMap + * @param req + */ + public void addParamFromInputFlash(Map paramMap, HttpServletRequest req) { + if(req == null) return; + + Map inFlashMap = (Map)RequestContextUtils.getInputFlashMap(req); + if(inFlashMap == null || inFlashMap.size() < 1) return; + + if(paramMap == null) paramMap = new HashMap(); + + for(String key : inFlashMap.keySet()) { + String value = inFlashMap.get(key); + if(StringUtil.isNotEmpty(value)) { + paramMap.put(key, value); + } + } + + return; + } + + /** + * 현재 요청(또는 세션)하고 있는 지방문화원 코드를 리턴한다. + * + * @param request + * @return + */ + private String getCurCouncilInfo(HttpServletRequest request, int which) { + + HttpSession session = request.getSession(); + return (String)session.getAttribute( (which == INFO_ID_COUNCIL_CD ? "councilCd" : "councilNm")); + } + + public String getCurCouncilCd(HttpServletRequest request) { + return getCurCouncilInfo(request, INFO_ID_COUNCIL_CD); + } + + public String getCurCouncilNm(HttpServletRequest request) { + return getCurCouncilInfo(request, INFO_ID_COUNCIL_NM); + } + + public void setAlerted(HttpServletRequest request, boolean alerted) { + NlibLoginVO nlibLoginVO = getNlibLoginVO(request); + if(nlibLoginVO == null) return; + + nlibLoginVO.setAlerted(alerted); + return; + } + + public boolean isAlerted(HttpServletRequest request) { + NlibLoginVO nlibLoginVO = getNlibLoginVO(request); + if(nlibLoginVO == null) return false; + + return nlibLoginVO.isAlerted(); + } + + public String getParamStr(Map paramMap, String paramName) { + return getParamStr(paramMap, paramName, null); + } + + public String getParamStr(Map paramMap, String paramName, String defValue) { + if(paramMap == null) return null; + if(StringUtil.isEmpty(paramName)) return null; + String value = (String)paramMap.get(paramName); + + return StringUtil.isEmpty(value) ? defValue : value; + } + + /** + * 세션에 CSRF 방지를 위한 토큰을 생성한다. + * + * @param request + */ + public final static String SESSION_CSRF_TOKEN_NAME = "SESSION_CSRF_TOKEN"; + + public String generateCsrfToken(HttpServletRequest request) { + HttpSession session = request.getSession(); + String token = UUID.getNewUUID(); + session.setAttribute(SESSION_CSRF_TOKEN_NAME, token); + log.debug("generateCsrfToken > " + session.getAttribute(SESSION_CSRF_TOKEN_NAME)); + + return token; + } + + /** + * 입력받은 CSRF 토큰이 유효한지 확인한다. + * + * @param request + * @param pToken + * @return + */ + public boolean isValidCsrfToken(HttpServletRequest request, String pToken) { + + HttpSession session = request.getSession(); + String sToken = (String)session.getAttribute(SESSION_CSRF_TOKEN_NAME); + + if(request == null || StringUtil.isEmpty(pToken) || StringUtil.isEmpty(sToken)) return false; + + if(sToken.equals(pToken)) return true; + + return false; + } + +} diff --git a/legacy/nlib/src/main/java/nlib/cmm/crypto/AriaCrypto.java b/legacy/nlib/src/main/java/nlib/cmm/crypto/AriaCrypto.java new file mode 100644 index 00000000..11d07982 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/crypto/AriaCrypto.java @@ -0,0 +1,166 @@ +package nlib.cmm.crypto; + +import java.io.UnsupportedEncodingException; +import java.security.InvalidKeyException; + +import org.apache.commons.codec.binary.Base64; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import egovframework.rte.fdl.cryptography.EgovPasswordEncoder; +import egovframework.rte.fdl.cryptography.impl.EgovARIACryptoServiceImpl; +import nlib.cmm.service.NlibProperty; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : AriaCrypto.java
+ * 
+ * @Description : 양방향 Aria 알고리즘 암복호화 처리 클래스 (egov Aria 알고리즘 구현체 사용) 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 8. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 8. + * @version 1.0 + * + */ +@Component("ariaCrypto") +public class AriaCrypto { + + private static final Logger log = LoggerFactory.getLogger(AriaCrypto.class); + + /** + * 기본키를 가지고 암호화한다. + * + * @param value + * @return + * @throws InvalidKeyException + */ + public static String encode(String value){ + + String ret = null; + + try { + ret = AriaUtil.ariaEncrypt(value); + } catch(UnsupportedEncodingException | InvalidKeyException e) { + log.error("ERROR at AriaCrypto.encode : " + e.toString()); + ret = null; + } + + return ret; + } + + /** + * 기본키를 가지고 Egov 모듈을 사용하여 암호화한다. + * + * @param value + * @return + */ + public static String encodeEgov(String value) { + return encodeEgov(value, NlibProperty.getProperty("crypto.aria.defaultKey")); + } + + /** + * 전달받은 key(사용자고유번호 혹은 메일주소 등 salt값)로 Egov 모듈을 사용하여 암호화한다. + * + * @param value + * @param key + * @return + */ + public static String encodeEgov(String value, String key) { + + if(StringUtil.isEmpty(value)) { + log.error("encode : 암호화할 문자열 정보가 없습니다."); + return null; + } + + if(StringUtil.isEmpty(key)) { + log.error("encode : 암호화에 사용할 키 정보가 없습니다."); + return null; + } + + EgovPasswordEncoder egovPasswordEncoder = new EgovPasswordEncoder(); + + String hashedPassword = egovPasswordEncoder.encryptPassword(key); + egovPasswordEncoder.setHashedPassword(hashedPassword); + egovPasswordEncoder.setAlgorithm("SHA-256"); + + EgovARIACryptoServiceImpl egovARIACryptoServiceImpl = new EgovARIACryptoServiceImpl(); + egovARIACryptoServiceImpl.setPasswordEncoder(egovPasswordEncoder); + egovARIACryptoServiceImpl.setBlockSize(1025); + + return Base64.encodeBase64String(egovARIACryptoServiceImpl.encrypt(value.getBytes(), key)); + } + + /** + * 기본키를 가지고 복호화한다. + * + * @param value + * @return + */ + public static String decode(String value) { + + String ret = null; + + try { + ret = AriaUtil.ariaDecrypt(value); + } catch(UnsupportedEncodingException | InvalidKeyException e) { + log.error("ERROR at AriaCrypto.decode : " + e.toString()); + ret = null; + } + + return ret; + } + + /** + * 기본키를 가지고 Egov 모듈을 사용하여 복호화한다. + * + * @param value + * @return + */ + public static String decodeEgov(String value) { + return decodeEgov(value, NlibProperty.getProperty("crypto.aria.defaultKey")); + } + + /** + * 전달받은 key(사용자고유번호 혹은 메일주소 등 salt값)로 Egov 모듈을 사용하여 복호화한다. + * @param value + * @param key + * @return + */ + public static String decodeEgov(String value, String key) { + + if(StringUtil.isEmpty(value)) { + log.error("decode : 복호화할 암호문자열 정보가 없습니다."); + return null; + } + + if(StringUtil.isEmpty(key)) { + log.error("decode : 복호화에 사용할 키 정보가 없습니다."); + return null; + } + + EgovPasswordEncoder egovPasswordEncoder = new EgovPasswordEncoder(); + + String hashedPassword = egovPasswordEncoder.encryptPassword(key); + egovPasswordEncoder.setHashedPassword(hashedPassword); + egovPasswordEncoder.setAlgorithm("SHA-256"); + + EgovARIACryptoServiceImpl egovARIACryptoServiceImpl = new EgovARIACryptoServiceImpl(); + egovARIACryptoServiceImpl.setPasswordEncoder(egovPasswordEncoder); + egovARIACryptoServiceImpl.setBlockSize(1025); + + return new String(egovARIACryptoServiceImpl.decrypt(Base64.decodeBase64(value), key)); + } +} diff --git a/legacy/nlib/src/main/java/nlib/cmm/crypto/AriaEngine.java b/legacy/nlib/src/main/java/nlib/cmm/crypto/AriaEngine.java new file mode 100644 index 00000000..78bff06f --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/crypto/AriaEngine.java @@ -0,0 +1,590 @@ +// +// ARIA.java +// +// A pure Java implementation of ARIA +// following the official ARIA specification at +// + +package nlib.cmm.crypto; + +import java.io.PrintStream; +import java.security.InvalidKeyException; + +public class AriaEngine { + + private static final char[] HEX_DIGITS = { + '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' + }; + + private static final int[][] KRK = { + {0x517cc1b7, 0x27220a94, 0xfe13abe8, 0xfa9a6ee0}, + {0x6db14acc, 0x9e21c820, 0xff28b1d5, 0xef5de2b0}, + {0xdb92371d, 0x2126e970, 0x03249775, 0x04e8c90e} + }; + + private static final byte[] S1 = new byte[256]; + private static final byte[] S2 = new byte[256]; + private static final byte[] X1 = new byte[256]; + private static final byte[] X2 = new byte[256]; + + private static final int[] TS1 = new int[256]; + private static final int[] TS2 = new int[256]; + private static final int[] TX1 = new int[256]; + private static final int[] TX2 = new int[256]; + + private String publicKey = "CREDIF_MASTERKEY"; + + private String privateKey = ""; + + + // Static initializer. For setting up the tables + static { + int[] exp = new int[256]; + int[] log = new int[256]; + exp[0] = 1; + for (int i=1; i < 256; i++) { + int j = (exp[i-1] << 1) ^ exp[i-1]; + if ((j & 0x100) != 0) j ^= 0x11b; + exp[i] = j; + } + for (int i=1; i < 255; i++) + log[exp[i]] = i; + + int[][] A = { + {1, 0, 0, 0, 1, 1, 1, 1}, + {1, 1, 0, 0, 0, 1, 1, 1}, + {1, 1, 1, 0, 0, 0, 1, 1}, + {1, 1, 1, 1, 0, 0, 0, 1}, + {1, 1, 1, 1, 1, 0, 0, 0}, + {0, 1, 1, 1, 1, 1, 0, 0}, + {0, 0, 1, 1, 1, 1, 1, 0}, + {0, 0, 0, 1, 1, 1, 1, 1} + }; + int[][] B = { + {0, 1, 0, 1, 1, 1, 1, 0}, + {0, 0, 1, 1, 1, 1, 0, 1}, + {1, 1, 0, 1, 0, 1, 1, 1}, + {1, 0, 0, 1, 1, 1, 0, 1}, + {0, 0, 1, 0, 1, 1, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 1}, + {0, 1, 0, 1, 1, 1, 0, 1}, + {1, 1, 0, 1, 0, 0, 1, 1} + }; + + for (int i=0; i<256; i++) { + int t=0, p; + if (i==0) + p=0; + else + p=exp[255-log[i]]; + for (int j=0; j<8; j++) { + int s=0; + for (int k=0; k<8; k++) { + if (((p>>>(7-k))&0x01)!=0) + s^=A[k][j]; + } + t=(t<<1)^s; + } + t^=0x63; + S1[i]=(byte)t; + X1[t]=(byte)i; + } + for (int i = 0; i < 256; i++) { + int t = 0, p; + if (i==0) + p=0; + else + p=exp[(247*log[i])%255]; + for (int j = 0; j < 8; j++) { + int s = 0; + for (int k = 0; k < 8; k++) { + if (((p >>> k) & 0x01) != 0) + s ^= B[7-j][k]; + } + t = (t << 1) ^ s; + } + t^=0xe2; + S2[i] = (byte) t; + X2[t] = (byte) i; + } + + for (int i = 0; i < 256; i++) { + TS1[i]=0x00010101*(S1[i]&0xff); + TS2[i]=0x01000101*(S2[i]&0xff); + TX1[i]=0x01010001*(X1[i]&0xff); + TX2[i]=0x01010100*(X2[i]&0xff); + } + } + + private int keySize=0; + private int numberOfRounds=0; + private byte[] masterKey=null; + private int[] encRoundKeys=null, decRoundKeys=null; + + public AriaEngine(int keySize) throws InvalidKeyException { + setKeySize(keySize); + } + + /** + * Resets the class so that it can be reused for another master key. + */ + void reset() { + this.keySize=0; + this.numberOfRounds=0; + this.masterKey=null; + this.encRoundKeys=null; + this.decRoundKeys=null; + } + + int getKeySize() { + return this.keySize; + } + + void setKeySize(int keySize) throws InvalidKeyException { + this.reset(); + if (keySize!=128 && keySize!=192 && keySize!=256) + throw new InvalidKeyException("keySize="+keySize); + this.keySize = keySize; + switch (keySize) { + case 128: + this.numberOfRounds = 12; + break; + case 192: + this.numberOfRounds = 14; + break; + case 256: + this.numberOfRounds = 16; + } + } + + void setKey(byte[] masterKey) throws InvalidKeyException { + if (masterKey.length*8>>24)&0xff]^TS2[(t0>>>16)&0xff]^TX1[(t0>>>8)&0xff]^TX2[t0&0xff]; + t1=TS1[(t1>>>24)&0xff]^TS2[(t1>>>16)&0xff]^TX1[(t1>>>8)&0xff]^TX2[t1&0xff]; + t2=TS1[(t2>>>24)&0xff]^TS2[(t2>>>16)&0xff]^TX1[(t2>>>8)&0xff]^TX2[t2&0xff]; + t3=TS1[(t3>>>24)&0xff]^TS2[(t3>>>16)&0xff]^TX1[(t3>>>8)&0xff]^TX2[t3&0xff]; + t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; + t1=badc(t1); t2=cdab(t2); t3=dcba(t3); + t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; + + t0^=rk[j++]; t1^=rk[j++]; t2^=rk[j++]; t3^=rk[j++]; + t0=TX1[(t0>>>24)&0xff]^TX2[(t0>>>16)&0xff]^TS1[(t0>>>8)&0xff]^TS2[t0&0xff]; + t1=TX1[(t1>>>24)&0xff]^TX2[(t1>>>16)&0xff]^TS1[(t1>>>8)&0xff]^TS2[t1&0xff]; + t2=TX1[(t2>>>24)&0xff]^TX2[(t2>>>16)&0xff]^TS1[(t2>>>8)&0xff]^TS2[t2&0xff]; + t3=TX1[(t3>>>24)&0xff]^TX2[(t3>>>16)&0xff]^TS1[(t3>>>8)&0xff]^TS2[t3&0xff]; + t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; + t3=badc(t3); t0=cdab(t0); t1=dcba(t1); + t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; + } + t0^=rk[j++]; t1^=rk[j++]; t2^=rk[j++]; t3^=rk[j++]; + t0=TS1[(t0>>>24)&0xff]^TS2[(t0>>>16)&0xff]^TX1[(t0>>>8)&0xff]^TX2[t0&0xff]; + t1=TS1[(t1>>>24)&0xff]^TS2[(t1>>>16)&0xff]^TX1[(t1>>>8)&0xff]^TX2[t1&0xff]; + t2=TS1[(t2>>>24)&0xff]^TS2[(t2>>>16)&0xff]^TX1[(t2>>>8)&0xff]^TX2[t2&0xff]; + t3=TS1[(t3>>>24)&0xff]^TS2[(t3>>>16)&0xff]^TX1[(t3>>>8)&0xff]^TX2[t3&0xff]; + t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; + t1=badc(t1); t2=cdab(t2); t3=dcba(t3); + t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; + + t0^=rk[j++]; t1^=rk[j++]; t2^=rk[j++]; t3^=rk[j++]; + o[ 0+ooffset] = (byte)(X1[0xff&(t0>>>24)] ^ (rk[j ]>>>24)); + o[ 1+ooffset] = (byte)(X2[0xff&(t0>>>16)] ^ (rk[j ]>>>16)); + o[ 2+ooffset] = (byte)(S1[0xff&(t0>>> 8)] ^ (rk[j ]>>> 8)); + o[ 3+ooffset] = (byte)(S2[0xff&(t0 )] ^ (rk[j ] )); + o[ 4+ooffset] = (byte)(X1[0xff&(t1>>>24)] ^ (rk[j+1]>>>24)); + o[ 5+ooffset] = (byte)(X2[0xff&(t1>>>16)] ^ (rk[j+1]>>>16)); + o[ 6+ooffset] = (byte)(S1[0xff&(t1>>> 8)] ^ (rk[j+1]>>> 8)); + o[ 7+ooffset] = (byte)(S2[0xff&(t1 )] ^ (rk[j+1] )); + o[ 8+ooffset] = (byte)(X1[0xff&(t2>>>24)] ^ (rk[j+2]>>>24)); + o[ 9+ooffset] = (byte)(X2[0xff&(t2>>>16)] ^ (rk[j+2]>>>16)); + o[10+ooffset] = (byte)(S1[0xff&(t2>>> 8)] ^ (rk[j+2]>>> 8)); + o[11+ooffset] = (byte)(S2[0xff&(t2 )] ^ (rk[j+2] )); + o[12+ooffset] = (byte)(X1[0xff&(t3>>>24)] ^ (rk[j+3]>>>24)); + o[13+ooffset] = (byte)(X2[0xff&(t3>>>16)] ^ (rk[j+3]>>>16)); + o[14+ooffset] = (byte)(S1[0xff&(t3>>> 8)] ^ (rk[j+3]>>> 8)); + o[15+ooffset] = (byte)(S2[0xff&(t3 )] ^ (rk[j+3] )); + } + + void encrypt(byte[] i, int ioffset, byte[] o, int ooffset) throws InvalidKeyException { + if (this.keySize==0) + throw new InvalidKeyException("keySize"); + if (this.encRoundKeys==null) + if (this.masterKey==null) + throw new InvalidKeyException("masterKey"); + else + setupEncRoundKeys(); + doCrypt(i, ioffset, this.encRoundKeys, this.numberOfRounds, o, ooffset); + } + + byte[] encrypt(byte[] i, int ioffset) throws InvalidKeyException { + byte[] o = new byte[16]; + this.encrypt(i, ioffset, o, 0); + return o; + } + + + public void decrypt(byte cipher[], byte plain[], int size) + throws InvalidKeyException { + int iLoop = size / 16; + int offset = 0; + for (int i = 0; i < iLoop; i++) { + decrypt(cipher, offset, plain, offset); + offset += 16; + } + + } + + void decrypt(byte[] i, int ioffset, byte[] o, int ooffset) throws InvalidKeyException { + if (this.keySize==0) + throw new InvalidKeyException("keySize"); + if (this.decRoundKeys==null) + if (this.masterKey==null) + throw new InvalidKeyException("masterKey"); + else + setupDecRoundKeys(); + doCrypt(i, ioffset, this.decRoundKeys, this.numberOfRounds, o, ooffset); + } + + byte[] decrypt(byte[] i, int ioffset) throws InvalidKeyException { + byte[] o = new byte[16]; + this.decrypt(i, ioffset, o, 0); + return o; + } + + private static void doEncKeySetup(byte[] mk, int[] rk, int keyBits) { + int t0, t1, t2, t3, q, j=0; + int[] w0 = new int[4]; + int[] w1 = new int[4]; + int[] w2 = new int[4]; + int[] w3 = new int[4]; + + w0[0] = toInt(mk[ 0], mk[ 1], mk[ 2], mk[ 3]); + w0[1] = toInt(mk[ 4], mk[ 5], mk[ 6], mk[ 7]); + w0[2] = toInt(mk[ 8], mk[ 9], mk[10], mk[11]); + w0[3] = toInt(mk[12], mk[13], mk[14], mk[15]); + + q = (keyBits - 128) / 64; + t0=w0[0]^KRK[q][0]; t1=w0[1]^KRK[q][1]; + t2=w0[2]^KRK[q][2]; t3=w0[3]^KRK[q][3]; + t0=TS1[(t0>>>24)&0xff]^TS2[(t0>>>16)&0xff]^TX1[(t0>>>8)&0xff]^TX2[t0&0xff]; + t1=TS1[(t1>>>24)&0xff]^TS2[(t1>>>16)&0xff]^TX1[(t1>>>8)&0xff]^TX2[t1&0xff]; + t2=TS1[(t2>>>24)&0xff]^TS2[(t2>>>16)&0xff]^TX1[(t2>>>8)&0xff]^TX2[t2&0xff]; + t3=TS1[(t3>>>24)&0xff]^TS2[(t3>>>16)&0xff]^TX1[(t3>>>8)&0xff]^TX2[t3&0xff]; + t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; + t1=badc(t1); t2=cdab(t2); t3=dcba(t3); + t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; + + if (keyBits > 128) { + w1[0] = toInt(mk[16], mk[17], mk[18], mk[19]); + w1[1] = toInt(mk[20], mk[21], mk[22], mk[23]); + if (keyBits > 192) { + w1[2] = toInt(mk[24], mk[25], mk[26], mk[27]); + w1[3] = toInt(mk[28], mk[29], mk[30], mk[31]); + } else { + w1[2]=w1[3]=0; + } + } else { + w1[0]=w1[1]=w1[2]=w1[3]=0; + } + w1[0]^=t0; w1[1]^=t1; w1[2]^=t2; w1[3]^=t3; + t0=w1[0]; t1=w1[1]; t2=w1[2]; t3=w1[3]; + + q = (q==2)? 0 : (q+1); + t0^=KRK[q][0]; t1^=KRK[q][1]; t2^=KRK[q][2]; t3^=KRK[q][3]; + t0=TX1[(t0>>>24)&0xff]^TX2[(t0>>>16)&0xff]^TS1[(t0>>>8)&0xff]^TS2[t0&0xff]; + t1=TX1[(t1>>>24)&0xff]^TX2[(t1>>>16)&0xff]^TS1[(t1>>>8)&0xff]^TS2[t1&0xff]; + t2=TX1[(t2>>>24)&0xff]^TX2[(t2>>>16)&0xff]^TS1[(t2>>>8)&0xff]^TS2[t2&0xff]; + t3=TX1[(t3>>>24)&0xff]^TX2[(t3>>>16)&0xff]^TS1[(t3>>>8)&0xff]^TS2[t3&0xff]; + t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; + t3=badc(t3); t0=cdab(t0); t1=dcba(t1); + t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; + t0^=w0[0]; t1^=w0[1]; t2^=w0[2]; t3^=w0[3]; + w2[0]=t0; w2[1]=t1; w2[2]=t2; w2[3]=t3; + + q = (q==2)? 0 : (q+1); + t0^=KRK[q][0]; t1^=KRK[q][1]; t2^=KRK[q][2]; t3^=KRK[q][3]; + t0=TS1[(t0>>>24)&0xff]^TS2[(t0>>>16)&0xff]^TX1[(t0>>>8)&0xff]^TX2[t0&0xff]; + t1=TS1[(t1>>>24)&0xff]^TS2[(t1>>>16)&0xff]^TX1[(t1>>>8)&0xff]^TX2[t1&0xff]; + t2=TS1[(t2>>>24)&0xff]^TS2[(t2>>>16)&0xff]^TX1[(t2>>>8)&0xff]^TX2[t2&0xff]; + t3=TS1[(t3>>>24)&0xff]^TS2[(t3>>>16)&0xff]^TX1[(t3>>>8)&0xff]^TX2[t3&0xff]; + t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; + t1=badc(t1); t2=cdab(t2); t3=dcba(t3); + t1^=t2; t2^=t3; t0^=t1; t3^=t1; t2^=t0; t1^=t2; + w3[0]=t0^w1[0]; w3[1]=t1^w1[1]; w3[2]=t2^w1[2]; w3[3]=t3^w1[3]; + + gsrk(w0, w1, 19, rk, j); j+=4; + gsrk(w1, w2, 19, rk, j); j+=4; + gsrk(w2, w3, 19, rk, j); j+=4; + gsrk(w3, w0, 19, rk, j); j+=4; + gsrk(w0, w1, 31, rk, j); j+=4; + gsrk(w1, w2, 31, rk, j); j+=4; + gsrk(w2, w3, 31, rk, j); j+=4; + gsrk(w3, w0, 31, rk, j); j+=4; + gsrk(w0, w1, 67, rk, j); j+=4; + gsrk(w1, w2, 67, rk, j); j+=4; + gsrk(w2, w3, 67, rk, j); j+=4; + gsrk(w3, w0, 67, rk, j); j+=4; + gsrk(w0, w1, 97, rk, j); j+=4; + if (keyBits > 128) { + gsrk(w1, w2, 97, rk, j); j+=4; + gsrk(w2, w3, 97, rk, j); j+=4; + } + if (keyBits > 192) { + gsrk(w3, w0, 97, rk, j); j+=4; + gsrk(w0, w1, 109, rk, j); + } + } + + /** + * Main bulk of the decryption key setup method. Here we assume that + * the int array rk already contains the encryption round keys. + * @param mk the master key + * @param rk the array which contains the encryption round keys at the + * beginning of the method execution. At the end of method execution + * this will hold the decryption round keys. + * @param keyBits the length of the master key + * @return + */ + private static void doDecKeySetup(byte[] mk, int[] rk, int keyBits) { + int a=0, z; + int[] t = new int[4]; + + z=32+keyBits/8; + swapBlocks(rk, 0, z); + a+=4; z-=4; + + for (; a>>24); + b[offset+1] = (byte)(i>>>16); + b[offset+2] = (byte)(i>>> 8); + b[offset+3] = (byte)(i ); + } + + private static int m(int t) { + return 0x00010101*((t>>>24)&0xff) ^ 0x01000101*((t>>>16)&0xff) ^ + 0x01010001*((t>>>8)&0xff) ^ 0x01010100*(t&0xff); + } + + private static final int badc(int t) { + return ((t<<8)&0xff00ff00) ^ ((t>>>8)&0x00ff00ff); + } + + private static final int cdab(int t) { + return ((t<<16)&0xffff0000) ^ ((t>>>16)&0x0000ffff); + } + + private static final int dcba(int t) { + return (t&0x000000ff)<<24 ^ (t&0x0000ff00)<<8 ^ (t&0x00ff0000)>>>8 ^ (t&0xff000000)>>>24; + } + + private static final void gsrk(int[] x, int[] y, int rot, int[] rk, int offset) { + int q=4-(rot/32), r=rot%32, s=32-r; + + rk[offset] = x[0] ^ y[(q )%4]>>>r ^ y[(q+3)%4]<>>r ^ y[(q )%4]<>>r ^ y[(q+1)%4]<>>r ^ y[(q+2)%4]<>> 4) & 0x0F], + HEX_DIGITS[ b & 0x0F] + }; + out.print(new String(buf)); + } + + private static void intToHex(PrintStream out, int i) { + byte[] b = new byte[4]; + toByteArray(i, b, 0); + byteToHex(out, b[0]); + byteToHex(out, b[1]); + byteToHex(out, b[2]); + byteToHex(out, b[3]); + } + + private static void printRoundKeys(PrintStream out, int[] roundKeys) { + for (int i=0; i= iLoop - 1) + if (iMod == 0) + iCopySize = 16; + else + iCopySize = iMod; + for (int j = 0; j < 16; j++) + in[j] = 0; + + System.arraycopy(plain, offset, in, 0, iCopySize); + encrypt(in, 0, cipher, offset); + offset += iCopySize; + } + + } + /* hex to byte[] convert */ + public static byte[] hexToByteArray(String hex) { + if (hex == null || hex.length() == 0) { + return null; + } + + byte[] ba = new byte[hex.length() / 2]; + for (int i = 0; i < ba.length; i++) { + ba[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16); + } + return ba; + } + + + + /* byte to hexa convert */ + public static String byteArrayToHex(byte[] ba) { + if (ba == null || ba.length == 0) { + return null; + } + + StringBuffer sb = new StringBuffer(ba.length * 2); + String hexNumber; + for (int x = 0; x < ba.length; x++) { + hexNumber = "0" + Integer.toHexString(0xff & ba[x]); + + sb.append(hexNumber.substring(hexNumber.length() - 2)); + } + return sb.toString(); + } + + public AriaEngine(int keySize, String privateKey)throws InvalidKeyException { + + this.keySize = 0; + numberOfRounds = 0; + masterKey = null; + encRoundKeys = null; + decRoundKeys = null; + setKeySize(keySize); + + byte[] mk = new byte[32]; + this.privateKey = privateKey; + byte[] p1Key = this.publicKey.getBytes(); + System.arraycopy(p1Key, 0, mk, 0, p1Key.length); + this.setKey(mk); + this.setupRoundKeys(); + + byte[] p2Key = new byte[32]; + byte[] mk2 = new byte[32]; + byte[] privateKeyByte = privateKey.getBytes(); + if (privateKeyByte.length > 32) { + System.arraycopy(privateKeyByte, 0, mk2, 0, 32); + } else { + System.arraycopy(privateKeyByte, 0, mk2, 0, privateKeyByte.length); + } + byte[] makeKey = new byte[32]; + this.encrypt(mk2, makeKey, mk2.length); + this.setKey(makeKey); + this.setupRoundKeys(); + + + } + public static void main(String[] args) throws InvalidKeyException { + + } +} diff --git a/legacy/nlib/src/main/java/nlib/cmm/crypto/AriaUtil.java b/legacy/nlib/src/main/java/nlib/cmm/crypto/AriaUtil.java new file mode 100644 index 00000000..5d79863f --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/crypto/AriaUtil.java @@ -0,0 +1,380 @@ +/** + * 전자정부 제공 ARIAUTIL + * ARIAUtil + */ + +package nlib.cmm.crypto; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.InvalidKeyException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import nlib.cmm.service.NlibProperty; + +public class AriaUtil { + + private static final Logger log = LoggerFactory.getLogger(AriaUtil.class); + + public static String ariaEncrypt(String str, String privateKey) + throws InvalidKeyException, UnsupportedEncodingException { + if (str==null || str.equals("")) return ""; + + byte[] p; + byte[] c; + AriaEngine instance = new AriaEngine(256, privateKey); + p = new byte[str.getBytes().length]; + p = str.getBytes(); + + int len = str.getBytes().length; + if ((len % 16) != 0) { + len = (len / 16 + 1) * 16; + } + c = new byte[len]; + System.arraycopy(p, 0, c, 0, p.length); + instance.encrypt(p, c, p.length); + + return AriaEngine.byteArrayToHex(c).toUpperCase(); + } + + /** + * @param privateKey + * @param src + * @param dest + * @throws IOException + * @throws InvalidKeyException + * @throws UnsupportedEncodingException + */ + public static void ariaFileEncrypt(String privateKey, String src, String dest) + throws IOException, InvalidKeyException, UnsupportedEncodingException { + File f = new File(src); + FileInputStream fis = new FileInputStream(src); + + long length = f.length(); + byte[] b = new byte[(int)length]; + + try { + int offset = 0; + int numRead = 0; + while (offset < b.length && (numRead=fis.read(b, offset, b.length-offset)) >= 0 ) { + if( (offset + numRead) <= Integer.MAX_VALUE) { + offset += numRead; + } else { + throw new IOException(f.getName() + " too long."); + } + } + if (offset < b.length) { + throw new IOException(f.getName()); + } + } finally{ + fis.close(); + } + + AriaEngine instance = new AriaEngine(256, privateKey); + int len = b.length; + if ((len % 16) != 0) { + len = (len / 16 + 1) * 16; + } + byte[] c = new byte[len]; + System.arraycopy(b, 0, c, 0, b.length); + instance.encrypt(b, c, b.length); + FileOutputStream fos = new FileOutputStream(dest); + try { + fos.write(c); + } catch (IOException e) { + log.error(e.toString()); + } finally { + try { + fos.close(); + } catch (IOException e) { + log.error(e.toString()); + } + } + } + + /* + *Aria 복호화 + */ + public static String ariaDecrypt(String strHex, String privateKey) + throws InvalidKeyException, UnsupportedEncodingException { + if (strHex==null || strHex.equals("")) return ""; + + byte[] p; + byte[] c; + AriaEngine instance = new AriaEngine(256, privateKey); + + c = AriaEngine.hexToByteArray(strHex); + if(c == null) return null; + + p = new byte[c.length]; + instance.decrypt(c, p, p.length); + + StringBuffer buf = new StringBuffer(); + buf.append(new String(p)); + + return buf.toString().trim(); + } + + + public static void ariaFileDecrypt(String privateKey, String src, String dest) + throws IOException, InvalidKeyException, UnsupportedEncodingException { + File f = new File(src); + FileInputStream fis = new FileInputStream(src); + + long length = f.length(); + byte[] b = new byte[(int)length]; + + try { + int offset = 0; + int numRead = 0; + while (offset < b.length && (numRead=fis.read(b, offset, b.length-offset)) >= 0) { + if( (offset + numRead) <= Integer.MAX_VALUE) { + offset += numRead; + } else { + throw new IOException(f.getName() + " too long."); + } + } + if (offset < b.length) { + throw new IOException(f.getName()); + } + } finally{ + fis.close(); + } + + AriaEngine instance = new AriaEngine(256, privateKey); + int len = b.length; + if ((len % 16) != 0) { + len = (len / 16 + 1) * 16; + } + byte[] c = new byte[len]; + System.arraycopy(b, 0, c, 0, b.length); + instance.decrypt(b, c, b.length); + + FileOutputStream fos = new FileOutputStream(dest); + try { + fos.write(c); + } catch (IOException e) { + log.error(e.toString()); + } finally { + try { + fos.close(); + } catch (IOException e) { + log.error(e.toString()); + } + } + } + + private static String makeMasterKey(String str) { + String appendStr = "Naravision KebiPortal Solution"; + StringBuffer buf = new StringBuffer(); + buf.append(str).append(appendStr); + + return buf.substring(0,32); + } + + + /* + *Aria 기본 복호화 + */ + public static String ariaDecrypt(String strHex) + throws InvalidKeyException, UnsupportedEncodingException { + String originalData = strHex; + if (strHex==null || strHex.equals("")) return ""; + StringBuffer buf = null; + try { + String privateKey = NlibProperty.getProperty("crypto.aria.defaultKey"); + + byte[] p; + byte[] c; + AriaEngine instance = new AriaEngine(256, privateKey); + + c = hexToByteArray(strHex); + + if(c == null) + { + return null; + } + p = new byte[c.length]; + instance.decrypt(c, p, p.length); + + buf = new StringBuffer(); + buf.append(new String(p)); + return buf.toString().trim(); + } catch (Exception e) { + log.error("ERROR at AriaCrypto.hexToByteArray : " + e.toString()); + return originalData; + } + } + /* + *aria 기본 암호화 + */ + public static String ariaEncrypt(String str) + throws InvalidKeyException, UnsupportedEncodingException { + if (str==null || str.equals("")) return ""; + String privateKey = NlibProperty.getProperty("crypto.aria.defaultKey"); + + byte[] p; + byte[] c; + AriaEngine instance = new AriaEngine(256, privateKey); + p = new byte[str.getBytes().length]; + p = str.getBytes(); + + int len = str.getBytes().length; + if ((len % 16) != 0) { + len = (len / 16 + 1) * 16; + } + c = new byte[len]; + System.arraycopy(p, 0, c, 0, p.length); + instance.encrypt(p, c, p.length); + + return byteArrayToHex(c).toUpperCase(); + } + + /* + *캐릭터셋 변경 암호화 + */ + public static String ariaCharEncrypt(String str, String charset) + throws InvalidKeyException, UnsupportedEncodingException { + if (str==null || str.equals("")) return ""; + String privateKey = NlibProperty.getProperty("crypto.aria.defaultKey"); + byte[] p; + byte[] c; + AriaEngine instance = new AriaEngine(256, privateKey); + p = new byte[str.getBytes(charset).length]; + p = str.getBytes(charset); + int len = str.getBytes(charset).length; + if ((len % 16) != 0) { + len = (len / 16 + 1) * 16; + } + c = new byte[len]; + System.arraycopy(p, 0, c, 0, p.length); + instance.encrypt(p, c, p.length); + + return byteArrayToHex(c).toUpperCase(); + } + + /* + *캐릭터셋 변경 암호화 + *(서버타입설정 열람서버 : read, 등록관리서버 : regi) + */ + public static String ariaCharEncrypt(String str, String charset, String server) + throws InvalidKeyException, UnsupportedEncodingException { + if (str==null || str.equals("")) return ""; + String privateKey = ""; + if(server.equals("regi")) privateKey = NlibProperty.getProperty("crypto.aria.defaultKey"); + else privateKey = NlibProperty.getProperty("crypto.aria.defaultKey"); + + byte[] p; + byte[] c; + AriaEngine instance = new AriaEngine(256, privateKey); + p = new byte[str.getBytes(charset).length]; + p = str.getBytes(charset); + int len = str.getBytes(charset).length; + if ((len % 16) != 0) { + len = (len / 16 + 1) * 16; + } + c = new byte[len]; + System.arraycopy(p, 0, c, 0, p.length); + instance.encrypt(p, c, p.length); + + return byteArrayToHex(c).toUpperCase(); + } + + + + /* + *Aria 캐릭터셋 변경 복호화 + */ + public static String ariaCharDecrypt(String strHex, String charset) + throws InvalidKeyException, UnsupportedEncodingException { + if (strHex==null || strHex.equals("")) return ""; + String privateKey = NlibProperty.getProperty("crypto.aria.defaultKey"); + + byte[] p; + byte[] c; + AriaEngine instance = new AriaEngine(256, privateKey); + + c = hexToByteArray(strHex); + + if(c == null) return null; + p = new byte[c.length]; + instance.decrypt(c, p, p.length); + + StringBuffer buf = new StringBuffer(); + buf.append(new String(p,charset)); + + return buf.toString().trim(); + } + + /* + *Aria 캐릭터셋 변경 복호화 + *(서버타입설정 열람서버 : read, 등록관리서버 : regi) + */ + public static String ariaCharDecrypt(String strHex, String charset, String server) + throws InvalidKeyException, UnsupportedEncodingException { + if (strHex==null || strHex.equals("")) return ""; + String privateKey = ""; + if(server.equals("regi")) privateKey = NlibProperty.getProperty("crypto.aria.defaultKey"); + else privateKey = NlibProperty.getProperty("crypto.aria.defaultKey"); + + byte[] p; + byte[] c; + AriaEngine instance = new AriaEngine(256, privateKey); + + c = hexToByteArray(strHex); + if(c == null) return null; + p = new byte[c.length]; + instance.decrypt(c, p, p.length); + + StringBuffer buf = new StringBuffer(); + buf.append(new String(p,charset)); + + return buf.toString().trim(); + } + + // hex to byte[] + public static byte[] hexToByteArray(String hex) { + if (hex == null || hex.length() == 0) { + return null; + } + + byte[] ba = new byte[hex.length() / 2]; + + try { + + for (int i = 0; i < ba.length; i++) { + ba[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16); + } + + }catch(NumberFormatException e){ + log.error("ERROR at AriaCrypto.hexToByteArray : " + e.toString()); + }catch(Exception e) { + log.error("ERROR at AriaCrypto.hexToByteArray : " + e.toString()); + } + + + return ba; + } + + // byte[] to hex + public static String byteArrayToHex(byte[] ba) { + if (ba == null || ba.length == 0) { + return null; + } + + StringBuffer sb = new StringBuffer(ba.length * 2); + String hexNumber; + for (int x = 0; x < ba.length; x++) { + hexNumber = "0" + Integer.toHexString(0xff & ba[x]); + + sb.append(hexNumber.substring(hexNumber.length() - 2)); + } + return sb.toString(); + + } +} diff --git a/legacy/nlib/src/main/java/nlib/cmm/crypto/NlibPasswordEncoder.java b/legacy/nlib/src/main/java/nlib/cmm/crypto/NlibPasswordEncoder.java new file mode 100644 index 00000000..75446a37 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/crypto/NlibPasswordEncoder.java @@ -0,0 +1,62 @@ +package nlib.cmm.crypto; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; + +import egovframework.rte.fdl.cryptography.EgovPasswordEncoder; + +/** + *
+ * @Class Name : NlibPasswordEncoder.java
+ * 
+ * @Description : 스프링 시큐리티 비밀번호 암호화 처리를 위하여 전자정부 프레임워크의 SHA256 알고리즘 구현체를 사용한 비밀번호 인코더 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 9. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 9. + * @version 1.0 + * + */ +@Component("nlibPasswordEncoder") +public class NlibPasswordEncoder implements PasswordEncoder { /* extends EgovPasswordEncoder */ + + private static final Logger log = LoggerFactory.getLogger(NlibPasswordEncoder.class); + + @Resource(name = "egovEnvPasswordEncoderService") + EgovPasswordEncoder egovPasswordEncoder; + + + /* + * 비밀번호를 SHA-256 알고리즘을 사용하여 암호화한다. + */ + @Override + public String encode(CharSequence rawPassword) { + log.debug("encode > rawPassword = " + rawPassword); + return egovPasswordEncoder.encryptPassword(rawPassword.toString()); + } + + /* + * 두 입력된 비밀번호가 일치하는 지 확인한다. + */ + @Override + public boolean matches(CharSequence rawPassword, String encodedPassword) { + log.debug("matches > rawPassword = " + rawPassword); + log.debug("matches > encodedPassword = " + encodedPassword); + return egovPasswordEncoder.checkPassword(rawPassword.toString(), encodedPassword); + } + +} diff --git a/legacy/nlib/src/main/java/nlib/cmm/exception/ErrorMessage.java b/legacy/nlib/src/main/java/nlib/cmm/exception/ErrorMessage.java new file mode 100644 index 00000000..193775fa --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/exception/ErrorMessage.java @@ -0,0 +1,55 @@ +package nlib.cmm.exception; + +/** + *
+ * @Class Name : ErrorMessage.java
+ * 
+ * @Description : AJAX 응답값 오류 정보 VO 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 07. 16. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 07. 16. + * @version 1.0 + * + */ +public class ErrorMessage { + + String code = null; + String message = null; + + public ErrorMessage() { + super(); + } + + public ErrorMessage(String code, String message) { + this.code = code; + this.message = message; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + +} diff --git a/legacy/nlib/src/main/java/nlib/cmm/fileupload/DownloadView.java b/legacy/nlib/src/main/java/nlib/cmm/fileupload/DownloadView.java new file mode 100644 index 00000000..a5697c37 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/fileupload/DownloadView.java @@ -0,0 +1,91 @@ +package nlib.cmm.fileupload; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.OutputStream; +import java.net.URLEncoder; +import java.util.Map; + +import javax.activation.MimetypesFileTypeMap; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.FileCopyUtils; +import org.springframework.web.servlet.view.AbstractView; + +/** + *
+ * @Class Name : DownloadView.java
+ * 
+ * @Description : 파일 다운로드 VIEW 처리 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 8. 3. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 8. 3. + * @version 1.0 + * + */ +public class DownloadView extends AbstractView { + + private static final Logger log = LoggerFactory.getLogger(DownloadView.class); + + @Override + protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception { + + File file = (File) model.get("downloadFile"); + + if(file == null) return; + + String fileName = (String) model.get("fname"); + String encfileName = null; + String userAgent = request.getHeader("User-Agent"); + + if (userAgent.indexOf("MSIE") > -1 || userAgent.indexOf("Trident") > -1) { + encfileName = URLEncoder.encode(fileName, "utf-8").replaceAll("\\+", "%20"); + } else if (userAgent.indexOf("Chrome") > -1) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < fileName.length(); i++) { + char c = fileName.charAt(i); + if (c > '~') { + sb.append(URLEncoder.encode("" + c, "UTF-8")); + } else { + sb.append(c); + } + } + encfileName = sb.toString(); + } else { + encfileName = new String(fileName.getBytes("utf-8")); + } + + response.setContentType(getContentType()); + + MimetypesFileTypeMap mimetypesFileTypeMap = new MimetypesFileTypeMap(); + response.setContentType(mimetypesFileTypeMap.getContentType(fileName)); + + response.setContentLength((int) file.length()); + response.setHeader("Content-Disposition", "attachment; filename=\"" + encfileName + "\";"); + response.setHeader("Content-Transfer-Encoding", "binary"); + + try( FileInputStream fis = new FileInputStream(file); + OutputStream out = response.getOutputStream()) + { + FileCopyUtils.copy(fis, out); + out.flush(); + } catch (FileNotFoundException e) { + log.error("renderMergedOutputModel FileNotFoundException ERROR : " + e.toString()); + } + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/cmm/fileupload/FileUploadController.java b/legacy/nlib/src/main/java/nlib/cmm/fileupload/FileUploadController.java new file mode 100644 index 00000000..af2d3b6a --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/fileupload/FileUploadController.java @@ -0,0 +1,322 @@ +package nlib.cmm.fileupload; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.servlet.ModelAndView; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import nlib.bbs.service.AttachFileService; +import nlib.bbs.service.AttachFileVO; +import nlib.cmm.NlibCommonController; +import nlib.cmm.exception.ErrorMessage; +import nlib.cmm.service.NlibProperty; +import nlib.util.FileUtil; +import nlib.util.StringUtil; +import nlib.util.UUID; + +/** + *
+ * @Class Name : FileUploadController.java
+ * 
+ * @Description : 파일 업로드를 처리하는 컨트롤러  
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 15. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 15. + * @version 1.0 + * + */ +@Controller +public class FileUploadController extends NlibCommonController { + + private static final Logger log = LoggerFactory.getLogger(FileUploadController.class); + + + /** + * 첨부파일이 저장되는 최상위 위치 + */ + private String FILEUPLOAD_BASE_PATH = NlibProperty.getProperty("fileupload.base.path"); + + /** + * 경로 부적합 오류 메시지 + */ + private static final String MSG_NOT_VALID_FILE_PATH = "파일 경로가 부적합합니다. 관리자에게 문의하여 주시기 바랍니다."; + + + @Resource(name="attachFileService") + private AttachFileService attachFileService; + + /** + * 파일업로드(Ajax) 처리 + * - 화면 : Javascript Free Open Framework DropZone 사용 + * + * @param multiRequest + * @param subPathKey + * @param response : 파일정보를 담은 JSON String + * @return + */ + @Secured("ROLE_USER") + @ResponseBody + @RequestMapping(value="/fileupload/uploadFilesAjax.do", produces="application/json") + public ResponseEntity uploadFilesAjax( + final MultipartHttpServletRequest multiRequest + , @RequestParam(name="subPathKey") String subPathKey + , HttpServletResponse response) { + + String message = null; + + // TODO : 권한 체크 추가할 것 + List result = new ArrayList(); + + try { + + // 최상위 위치 + if(FileUtil.isEmpty(FILEUPLOAD_BASE_PATH)) { + message = "첨부파일이 저장되는 최상위 위치정보값이 정확하지 않습니다."; + log.error(message + " : FILEUPLOAD_BASE_PATH 값 부재"); + ErrorMessage errorMessage = new ErrorMessage("ERROR", message); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorMessage); + } + + // 서브 위치 + if(StringUtil.isEmpty(subPathKey)) { + message = "첨부파일이 저장되는 하위 위치정보값이 정확하지 않습니다."; + log.error(message + " : 매개변수 subPathKey 값 부재"); + ErrorMessage errorMessage = new ErrorMessage("ERROR", message); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorMessage); + } + String subPath = NlibProperty.getProperty(subPathKey); + if(StringUtil.isEmpty(subPath)) { + message = "첨부파일이 저장되는 하위 위치정보값을 찾을 수 없습니다."; + log.error(message + " : 매개변수 subPathKey의 속성값 부재"); + ErrorMessage errorMessage = new ErrorMessage("ERROR", message); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorMessage); + } + + // 위치정보 적합 확인 + if(FileUtil.isNotValid(FILEUPLOAD_BASE_PATH + subPath)) { + message = MSG_NOT_VALID_FILE_PATH; + log.error(message + " : " + (FILEUPLOAD_BASE_PATH + subPath)); + ErrorMessage errorMessage = new ErrorMessage("ERROR", message); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorMessage); + } + + // 파일 업로드 처리 + final Map files = multiRequest.getFileMap(); + log.debug("uploadFilesAjax : 진입 > 파일수 = " + (files == null ? " files null " : files.size())); + + File dir = new File(FILEUPLOAD_BASE_PATH + subPath); + if(!dir.exists() || !dir.isDirectory()) dir.mkdirs(); + + if(!files.isEmpty()) { + + Iterator> itr = files.entrySet().iterator(); + MultipartFile file; + String filePath = ""; + AttachFileVO atvo; + + // 허용 파일 확장자 + String acceptableExtList = StringUtil.getString(NlibProperty.getString("fileupload.acceptable.ext"), null); + if(acceptableExtList != null) acceptableExtList = "," + acceptableExtList.trim().toLowerCase(); + boolean acceptableExt = false; + + // 최대 파일크기 + int maxFileSize = NlibProperty.getInt("fileupload.max.mbsize", 10) * 1024 * 1024; + + // 최대 개수 + int maxFileCount = NlibProperty.getInt("fileupload.max.files", 5); + + while (itr.hasNext()) { + + if(result.size() >= maxFileCount) { + log.error("최대 개수를 초과하여 이후 파일은 처리되지 않습니다."); + break; + } + + acceptableExt = false; + + Entry entry = itr.next(); + + file = entry.getValue(); + String orignlFileNm = file.getOriginalFilename(); + + //-------------------------------------- + // 원 파일명이 없는 경우 처리 SKIP + // (첨부가 되지 않은 input file type) + //-------------------------------------- + if (orignlFileNm == null || "".equals(orignlFileNm)) { + continue; + } + + // 파일 확장자 + int index = orignlFileNm.lastIndexOf("."); + String fileExt = (index < 1 ? "" : orignlFileNm.substring(index + 1)).toLowerCase(); + + if(acceptableExtList != null) { + + if(acceptableExtList.contains("." + fileExt)) { + acceptableExt = true; + } else if(acceptableExtList.contains("image/*")) { + acceptableExt = ".jpg,.jpe,.jpge,.bmp,.gif,.png".contains("." + fileExt); + } + } + if(!acceptableExt) { + log.error("허용되지 않는 파일 확장자 입니다. : " + orignlFileNm); + continue; + } + + int size = (int)file.getSize(); + if(size > maxFileSize) { + log.error("첨부파일이 허용 크기를 초과합니다. : " + orignlFileNm); + continue; + } + + String streFileNm = UUID.getNewStreFileNm(); + + filePath = FILEUPLOAD_BASE_PATH + subPath + "/" + streFileNm; + log.debug("FILE UPLOAD : filePath=" + filePath); + + file.transferTo(new File(FileUtil.filePathBlackList(filePath))); + + atvo = new AttachFileVO(); + atvo.setSubPathKey(subPathKey); + //atvo.setAttachFileId(attachFileId); // 실제 DB 저장 처리될때 설정함 + atvo.setStreFileNm(streFileNm); + atvo.setOrignlFileNm(orignlFileNm); + atvo.setFileExt(fileExt); + atvo.setFileSize(size); + + result.add(atvo); + } + } + } catch(SecurityException e) { + log.error("uploadFilesAjax SecurityException : " + e.toString()); + ErrorMessage errorMessage = new ErrorMessage("ERROR", "처리에 실패하였습니다(1)"); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorMessage); + } catch(IllegalStateException e) { + log.error("uploadFilesAjax IllegalStateException : " + e.toString()); + ErrorMessage errorMessage = new ErrorMessage("ERROR", "처리에 실패하였습니다(1)"); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorMessage); + } catch(IOException e) { + log.error("uploadFilesAjax IOException : " + e.toString()); + ErrorMessage errorMessage = new ErrorMessage("ERROR", "처리에 실패하였습니다(1)"); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorMessage); + } + + // Convert Json + ObjectMapper mapper = new ObjectMapper(); + String json; + try { + json = mapper.writeValueAsString(result); + log.debug("RETURN DATA > json:" + json); + } catch (JsonProcessingException e) { + json = null; + log.error("uploadFilesAjax Error : " + e.toString()); + ErrorMessage errorMessage = new ErrorMessage("ERROR", "JSON 변환 처리에 실패하였습니다 : " + e.toString()); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorMessage); + } + + HttpHeaders responseHeaders = new HttpHeaders(); + ResponseEntity ret = ResponseEntity.ok().headers(responseHeaders).body(json); + return ret; + } + + /** + * 파일 다운로드를 처리한다. + * + * @param params + * @param mv + * @return + * @throws Exception + */ + @RequestMapping(value="/fileupload/downloadAttachFile.do") + public ModelAndView downloadAttachFile(HttpServletRequest request, AttachFileVO attachFileVO, ModelAndView mv) throws Exception { + + //--------------------------------- + // 권한체크 + //--------------------------------- + // 공지사항, FAQ : 모두 공개 + // QnA : 공개된 글인 경우, 모두 공개 + // QnA : 비밀글 (본인에 한정) + + attachFileVO.setMbInfoId(getMbInfoId(request)); + boolean hasAuth = attachFileService.checkAttachFileDownload(attachFileVO); + + if(!hasAuth) { + throw new Exception("잘못된 접근입니다. 파일다운로드를 할 수 있는 권한이 없습니다."); + } + + AttachFileVO retAttachFileVO = attachFileService.selectAttachFile(attachFileVO); + + if(retAttachFileVO == null || StringUtil.isEmpty(retAttachFileVO.getAttachFileId())) { + throw new Exception("잘못된 접근이므로 파일다운로드를 할 수 없습니다."); + } + + if(StringUtil.isEmpty(retAttachFileVO.getFileStrePath()) || StringUtil.isEmpty(retAttachFileVO.getStreFileNm())) { + throw new Exception("파일정보가 올바르지 않습니다."); + } + + if(StringUtil.isEmpty(retAttachFileVO.getOrignlFileNm())) { + retAttachFileVO.setOrignlFileNm("첨부파일." + retAttachFileVO.getFileExt()); + } + + if(StringUtil.isEmpty(retAttachFileVO.getOrignlFileNm())) { + retAttachFileVO.setOrignlFileNm("첨부파일." + retAttachFileVO.getFileExt()); + } + + String fullPath = retAttachFileVO.getFileStrePath() + retAttachFileVO.getStreFileNm(); + + log.debug("downloadAttachFile > fullPath = " + fullPath); + + if(FileUtil.isNotValid(fullPath)) { + throw new Exception(MSG_NOT_VALID_FILE_PATH); + } + + File file = new File(FileUtil.filePathBlackList(fullPath)); + if(!file.isFile()) { + throw new Exception("해당 파일이 존재하지 않습니다. 관리자에게 문의하여 주시기 바랍니다."); + } + + mv.setViewName("downloadView"); // dispatcher-servlet.xml내 BeanNameViewResolver 정의 + mv.addObject("downloadFile", file); + mv.addObject("fname", retAttachFileVO.getOrignlFileNm()); + + return mv; + } + +} + diff --git a/legacy/nlib/src/main/java/nlib/cmm/interceptor/NlibInterceptor.java b/legacy/nlib/src/main/java/nlib/cmm/interceptor/NlibInterceptor.java new file mode 100644 index 00000000..0ac6495a --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/interceptor/NlibInterceptor.java @@ -0,0 +1,84 @@ +package nlib.cmm.interceptor; + +import java.util.HashMap; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import nlib.cmm.service.NlibProperty; +import nlib.user.service.LoginService; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : NlibInterceptor.java
+ * 
+ * @Description : 소장자료관 인터셉터로써 지방문화원 접속 정보를 세션에 저장 처리  
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 8. 31. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 8. 31. + * @version 1.0 + * + */ +public class NlibInterceptor extends HandlerInterceptorAdapter { + + private static final Logger log = LoggerFactory.getLogger(NlibInterceptor.class); + + @Resource(name = "loginService") + private LoginService loginService; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + + //--------------------------------------- + // 지방문화원 접속 정보를 세션에 담기 + //--------------------------------------- + HttpSession session = request.getSession(); + log.debug("preHandle > sessionid=" + session.getId()); + String councilCd = (String)session.getAttribute("councilCd"); + String councilNm = (String)session.getAttribute("councilNm"); + if(StringUtil.isEmpty(councilCd)) { + + // 지방문화원 코드 확인 + String councilDnsHost = StringUtil.getHostName(request.getRequestURL().toString()); + HashMap councilInfoMap = loginService.selectCouncilInfoByDnsHost(councilDnsHost); + if(councilInfoMap == null || councilInfoMap.size() < 1) { + log.error("preHandle > [오류] 등록되지 않은 도메인입니다. 지방문화원 정보에 도메인 호스트명을 등록해 주시기 바랍니다. : " + councilDnsHost); + log.error("preHandle > [오류] 도메인이 등록되지 않음에 따라 Default 도메인으로 등록되나, 로그인/회원가입 및 기타 서비스 이용시 문제 발생할 수 있습니다. " + NlibProperty.getString("nlib.council.cd") + ", " + NlibProperty.getString("nlib.council.nm")); + councilCd = null; + councilNm = null; + } else { + councilCd = councilInfoMap.get("councilCd"); + councilNm = councilInfoMap.get("councilNm"); + } + + if(StringUtil.isEmpty(councilCd)) councilCd = NlibProperty.getString("nlib.council.cd"); + if(StringUtil.isEmpty(councilNm)) councilNm = NlibProperty.getString("nlib.council.nm"); + if(StringUtil.isEmpty(councilDnsHost)) councilDnsHost = NlibProperty.getString("nlib.council.dns.host"); + + session.setAttribute("councilCd" , councilCd); + session.setAttribute("councilNm" , councilNm); + session.setAttribute("councilDnsHost", councilDnsHost); + } + + return true; + } +} + diff --git a/legacy/nlib/src/main/java/nlib/cmm/qrcode/QRCodeUtil.java b/legacy/nlib/src/main/java/nlib/cmm/qrcode/QRCodeUtil.java new file mode 100644 index 00000000..21f21bce --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/qrcode/QRCodeUtil.java @@ -0,0 +1,169 @@ +package nlib.cmm.qrcode; + +import java.awt.image.BufferedImage; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.client.j2se.MatrixToImageWriter; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.QRCodeWriter; + +import egovframework.com.utl.sim.service.EgovFileScrty; +import nlib.user.service.NlibLoginVO; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : QRCodeUtil.java
+ * 
+ * @Description : QR 코드 생성 처리 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * -------------------------------------------------------- + * ※ 참고 : 바코드 정보 + * -------------------------------------------------------- + * [Universal Product Code : UPC] : 1D 바코드 + * - UPC-A : 12자리 (6자리 제조사ID번호 + 5자리품목번호 + 1자리 체크 숫자) + * - UPC-E : 8자리 (주로 작은 패키지용으로 사용) + * + * [European Article Number : EAN Codes] + * - EAN-13(Most commonly), EAN-8, JAN-13, ISBN + * - EAN-13 : UPC 코드와 유사, "o" + UPC-A코드 + * + * [Code 128] + * - 함축 고밀도 선형 코드로, 물류/배송에서 주문/유통 목적으로 주로 사용 + * - 아스키 128자 인코딩 가능 + * + * [PDF417] + * - 다중 1D 바코드가 다른 1D 바코드위에 쌓여서 구성되는 선형 바코드 + * - 일반적인 선형 바코드기기 사용 가능 + * - 여행 승차권,ID카드,물품목록 관리용으로 사용 + * - 체크숫자 대신 Reed-Solomon 오류 교정 방식 사용 + * + * [QR Codes : Quick Response Code] + * - 바코드 매트릭스 즉,2D 바코드로 가장 많이 쓰여지고 있는 바코드 + * - 제한된 공간에 많은 양의 정보를 담을 수 있음 + * + * 라이브러리 + * - Barbecue : 오픈소스 자바 라이브러리, 1D바코드, PNG/GIF/JPEG/SVG 생성 기능 + * - Barcode4j : 오픈소스 라이브러리, 2D바코드 포멧 지원, DataMarix, PDF417 + * - ZXing(Zebra Crossing) : 오픈소스, 자바로 구현된 멀티포멧 1D/2D바코드 이미지 처리 라이브러리, QR코드 지원하는 주 자바 라이브러리 (본시스템에서 사용하는 LIB) + * - QRGen : ZXing을 사용한 간단한 자바 QR코드 생성 API + * + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 6. 25. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 6. 25. + * @version 1.0 + * + */ +@Service("qrCodeService") +public class QRCodeUtil { + + private static final Logger log = LoggerFactory.getLogger(QRCodeUtil.class); + + /** + * QR코드로 생성할 수 있는 최대문자열 바이트 길이 + * + * QR코드로 생성할 수 있는 코드값은 다음과 같으나, 본 시스템 용도에 충분한 크기인 "2000"자로 크기를 제한한다. + * + * - Numeric only Max. 7,089 characters (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) + * - Alphanumeric Max. 4,296 characters (0–9, A–Z [upper-case only], space, $, %, *, +, -, ., /, :) + * - Binary/byte Max. 2,953 characters (8-bit bytes) (23624 bits) + */ + public static final int MAX_QRTEXT_BYTES = 2000; + + /** + * 입력된 문자열에 대한 QR 2D 바코드를 BufferedImage 로 생성하여 리턴한다. + * + * + * @param barcodeText + * @return + * @throws Exception + */ + public static BufferedImage generateQRCodeImageByZxing(String barcodeText) throws Exception { + + if(StringUtil.isEmpty(barcodeText)) { + throw new Exception("QR 2D바코드로 생성할 문자 정보가 없습니다."); + } + + if(barcodeText.getBytes().length > MAX_QRTEXT_BYTES) { + throw new Exception(String.format("QR 2D바코드로 생성할 문자의 길이는 %d 바이트를 초과할 수 없습니다.", MAX_QRTEXT_BYTES)); + } + + QRCodeWriter barcodeWriter = new QRCodeWriter(); + BitMatrix bitMatrix = barcodeWriter.encode(barcodeText, BarcodeFormat.QR_CODE, 200, 200); + + return MatrixToImageWriter.toBufferedImage(bitMatrix); + } + + /** + * 사용자정보를 가지고, QRCode 바코드를 BufferedImage 로 생성하여 리턴한다. + * + * (1) "사용자고유번호;이메일;이름;" 형식으로 문자열을 구성 + * (2) 앞의 (1)의 문자열을 암호화 처리 + * (3) 앞의 (2) 암호화 문자열로 QRCode 생성하여 BufferedImage형식으로 리턴 + * + * @param loginVO + * @return + * @throws Exception + */ + public static BufferedImage generateMemberQrcodeImage(NlibLoginVO loginVO) throws Exception { + + if(loginVO == null) { + throw new Exception("QR 2D바코드로 생성할 사용자 정보가 없습니다."); + } + + if(StringUtil.isEmpty(loginVO.getMbNo())) { + throw new Exception("QR 2D바코드로 생성에 필요한 회원번호 정보가 없습니다."); + } + + return generateQRCodeImageByZxing(loginVO.getMbNo()); + } + + /** + * 사용자 QR코드 추출 정보를 통해 사용자정보VO를 생성하여 리턴한다. + * + * @param encodedBarcodeText + * @return + * @throws Exception + */ + public static NlibLoginVO getMemberInfoFromQRCode(String encodedBarcodeText) throws Exception { + + if(StringUtil.isEmpty(encodedBarcodeText)) { + throw new Exception("사용자 QR코드 추출 정보가 정보가 없습니다."); + } + + log.debug("getMemberInfoFromQRCode : encodedBarcodeText=" + encodedBarcodeText); + + String barcodeText = new String(EgovFileScrty.decodeBinary(encodedBarcodeText)); + log.debug("getMemberInfoFromQRCode : decodedBarcodeText=" + barcodeText); + + String[] split = barcodeText.split(";"); + + if(split.length < 3) { + throw new Exception("사용자 QR코드 추출 정보가 적합하지 않습니다."); + } + + NlibLoginVO info = new NlibLoginVO(); + + info.setMbInfoId(split[0]); + info.setEmail(split[1]); + info.setName(split[2]); + + return info; + } + +} diff --git a/legacy/nlib/src/main/java/nlib/cmm/service/CodeService.java b/legacy/nlib/src/main/java/nlib/cmm/service/CodeService.java new file mode 100644 index 00000000..636c5cf9 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/service/CodeService.java @@ -0,0 +1,54 @@ + +package nlib.cmm.service; + +import java.util.List; +import java.util.Map; + +/** + *
+ * @Class Name : CodeService.java
+ * 
+ * @Description : 코드 조회 공통 서비스 인터페이스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 07. 26. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 07. 26. + * @version 1.0 + * + */ +public interface CodeService +{ + + /** + * 공통코드를 조회한다. + * + * @param iCodeId + * @return + * @throws Exception + */ + public List> listCodes(String iCodeId) throws Exception; + + /** + * 주제분류코드를 조회한다. + * + * @return + * @throws Exception + */ + public List> listCtClsfs() throws Exception; + + /** + * 자료유형 최상위 코드목록을 조회한다. + */ + public List> listTypeDivCodes() throws Exception; + +} diff --git a/legacy/nlib/src/main/java/nlib/cmm/service/MainService.java b/legacy/nlib/src/main/java/nlib/cmm/service/MainService.java new file mode 100644 index 00000000..842b8a5e --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/service/MainService.java @@ -0,0 +1,106 @@ + +package nlib.cmm.service; + +import java.util.List; +import java.util.Map; + +import nlib.col.service.CollectionVO; + +/** + *
+ * @Class Name : MainService.java
+ * 
+ * @Description : 메인화면 서비스 인터페이스 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 07. 01. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 07. 01. + * @version 1.0 + * + */ +public interface MainService +{ + /** + * 지역문화원의 키워드 리스트를 조회한다. + * + * @param mngOrgCd + * @return + */ + public List> listKeywords(String mngOrgCd); + + + /** + * 문화원 PICK한 자료 리스트를 조회한다. + * + * @param mngOrgCd + * @return + */ + public List listOrgPicks(String mngOrgCd); + + /** + * 유형별인기자료 리스트를 조회한다. + * + * @param mngOrgCd + * @return + */ + public List listPops(CollectionVO searchVO); + + /** + * 유형별인기자료 리스트를 조회한다. : 기본 자료유형 문서로 검색 + * + * @param mngOrgCd + * @return + */ + public List listPops(String mngOrgCd); + + /** + * 유형별인기자료 리스트를 조회한다. + * + * @param mngOrgCd + * @param typeDivCd + * @return + */ + public List listPops(String mngOrgCd, String typeDivCd); + + /** + * 온라인자료관 리스트를 조회한다. + * + * @param mngOrgCd + * @return + */ + public List listOnline(String mngOrgCd); + + /** + * 지방문화원별 배너 정보를 조회한다. + * + * @param mngOrgCd + * @return + */ + public List> listBannerInfos(String mngOrgCd); + + /** + * 메인화면 배너ID에 대한 정보를 가져온다. + * + * @return + */ + public Map getBannerInfo(String bannerId); + + /** + * 메인화면 footer 문화원 전체 이름을 가져온다. + * + * @return + */ + public List> listDeptTree(String mngOrgNm); + +} + diff --git a/legacy/nlib/src/main/java/nlib/cmm/service/NlibProperty.java b/legacy/nlib/src/main/java/nlib/cmm/service/NlibProperty.java new file mode 100644 index 00000000..152d9892 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/service/NlibProperty.java @@ -0,0 +1,173 @@ +package nlib.cmm.service; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Enumeration; +import java.util.Properties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : NlibProperty.java
+ * 
+ * @Description : NLIB용 프로퍼티 파일을 읽어서 메모리에 로딩하고 관리하는 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 16. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 16. + * @version 1.0 + * + */ +@Service("nlibProperty") +public class NlibProperty { + + private static final Logger log = LoggerFactory.getLogger(NlibProperty.class); + + /** + * 메모리에 로딩될 프로퍼티 객체 선언 + */ + public static Properties properties = null; + + /** + * nlib.properties 파일로 부터 속성을 읽어 들인다. + * + * @return 정상적으로 로딩한 건수를 리턴한다. 오류 발생 시, 음수값이 리턴된다. + */ + public static int loadProperties() { + + String nlibPropPath = null; + int propCount = -1; + + if(properties == null) properties = new Properties(); + else properties.clear(); + + nlibPropPath = NlibProperty.class.getResource("").getPath(); + nlibPropPath = nlibPropPath.substring(0, nlibPropPath.lastIndexOf("/nlib/") + 6) + "nlib.properties"; + + log.debug("NLIB Properties File Path : " + nlibPropPath); + + try (InputStream input = new FileInputStream(nlibPropPath)) { + + properties.load(input); + + Enumeration propEnum = (Enumeration)properties.propertyNames(); + + String propName = null; + while(propEnum.hasMoreElements()) { + propName = propEnum.nextElement(); + log.debug("Loading NLIB Properties : " + propName + " = " + properties.getProperty(propName)); + } + + log.debug("Loading is Done!"); + + propCount = properties.size(); + + } catch (FileNotFoundException ex) { // FileNotFoundException + if(properties != null) properties.clear(); + log.error("Error in Loading NLIB Properties FileNotFoundException : " + nlibPropPath); + return -2; + } catch (IOException ex) { // FileNotFoundException + if(properties != null) properties.clear(); + log.error("Error in Loading NLIB Properties : IOException " + nlibPropPath); + return -3; + } + + return propCount; + } + + /** + * name 값을 키로하는 속성값을 리턴한다. + * + * @param name + * @return + */ + public static String getProperty(String name) { + + if(properties == null || properties.size() < 1) { + if(loadProperties() < 0) return null; + } + + String value = properties.getProperty(name); + if(value != null) value = value.trim(); + + return value; + } + + /** + * name 값을 키로하는 속성값을 문자열 형태로 리턴한다. (getProperty(..)와 동일) + * + * @param name + * @return + */ + public static String getString(String name) { + return getProperty(name); + } + + public static String getString(String name, String defaultValue) { + String val = getProperty(name); + + if(StringUtil.isEmpty(val)) return defaultValue; + + return val; + } + + /** + * name 값을 키로하는 속성값을 정부형태로 리턴한다. + * 만일 값이 부재이거나 정부값으로 적합하지 않을 경우, defaultValue를 리턴한다. + * + * @param name + * @param defaultValue + * @return + */ + public static int getInt(String name, int defaultValue) { + try { + return getInt(name); + } catch(NumberFormatException e) { + log.error("[속성값 읽기 오류] NumberFormatException : " + e.toString()); + return defaultValue; + } catch(Exception e) { + log.error("[속성값 읽기 오류] 기타 오류 " + e.toString()); + return defaultValue; + } + } + + /** + * name 값을 키로하는 속성값을 정부형태로 리턴한다. + * + * @param name + * @return + * @throws Exception + */ + public static int getInt(String name) throws Exception { + + if(StringUtil.isEmpty(name)) { + throw new Exception("속성값의 명칭 정보가 부적합합니다."); + } + + String val = getProperty(name); + + if(StringUtil.isEmpty(val)) { + throw new Exception("해당 속성값이 존재하지 않습니다."); + } + + return Integer.parseInt(val.trim()); + } + +} diff --git a/legacy/nlib/src/main/java/nlib/cmm/service/NotificationService.java b/legacy/nlib/src/main/java/nlib/cmm/service/NotificationService.java new file mode 100644 index 00000000..5cc4e0be --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/service/NotificationService.java @@ -0,0 +1,72 @@ +package nlib.cmm.service; + +import java.util.List; + + +/** + *
+ * @Class Name : NotificationService.java
+ * 
+ * @Description : 알림관련 서비스 인터페이스   
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021 09. 06. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021 09. 06. + * @version 1.0 + * + */ +public interface NotificationService +{ + + /* + * 사용자 알림 목록을 조회한다. + */ + public List listNotifications(NotificationVO notificationVO) throws Exception; + + + /** + * 사용자 알림 목록의 건수를 조회한다. + */ + public int countNotifications(String recvUserId) throws Exception; + + /** + * 읽지 않은 알림 건수를 조회한다. + * + * @param mbInfoId + * @return + * @throws Exception + */ + public int countUnreadNotification(String mbInfoId) throws Exception; + + + /** + * 알림을 읽음으로 변경한다. + * 만일, 이미 읽음표시된 경우에는 변경 없다. + * + * @param notiVO (notiId, recvUserId 필수) + * @return + * @throws Exception + */ + public int updateRead(NotificationVO notiVO) throws Exception; + + /** + * 알림내용 상세 조회 + * + * @param notiVO (notiId, recvUserId 필수) + * @return + * @throws Exception + */ + public NotificationVO selectNotification(NotificationVO notiVO) throws Exception; + +} + diff --git a/legacy/nlib/src/main/java/nlib/cmm/service/NotificationVO.java b/legacy/nlib/src/main/java/nlib/cmm/service/NotificationVO.java new file mode 100644 index 00000000..b3efa2fb --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/service/NotificationVO.java @@ -0,0 +1,136 @@ +package nlib.cmm.service; + +/** + *
+ * @Class Name : NotificationVO.java
+ * 
+ * @Description : 알림 정보 VO 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021 09. 06. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021 09. 06. + * @version 1.0 + * + */ +public class NotificationVO extends PagingVO { + + private String notiId; /* 알림ID */ + private String title; /* 알림제목 */ + private String content; /* 알림내용 */ + private String notiMethod; /* 알림방법 */ + private String notiTypeCd; /* 알림유형코드(알림내용구분코드) */ + private String notiTypeNm; /* 알림유형코드명 */ + private String readDd; /* 알림확인일시 */ + private String RegId; /* 등록자아이디 */ + private String regDd; /* 등록일자 */ + + private String recvUserId; /* 알림대상자 회원아이디 */ + private String readYn; /* 알림확인여부 */ + private int totCnt = 0; /* 알림건수(최근1개월) */ + private int rno = 0; /* 행번호 */ + + private String mngOrgCd; /* 관리문화원코드 */ + private String mngOrgNm; /* 관리문화원명 */ + + public String getNotiId() { + return notiId; + } + public void setNotiId(String notiId) { + this.notiId = notiId; + } + public String getTitle() { + return title; + } + public void setTitle(String title) { + this.title = title; + } + public String getContent() { + return content; + } + public void setContent(String content) { + this.content = content; + } + public String getNotiMethod() { + return notiMethod; + } + public void setNotiMethod(String notiMethod) { + this.notiMethod = notiMethod; + } + public String getNotiTypeCd() { + return notiTypeCd; + } + public void setNotiTypeCd(String notiTypeCd) { + this.notiTypeCd = notiTypeCd; + } + public String getReadDd() { + return readDd; + } + public void setReadDd(String readDd) { + this.readDd = readDd; + } + public String getRegId() { + return RegId; + } + public void setRegId(String regId) { + RegId = regId; + } + public String getRegDd() { + return regDd; + } + public void setRegDd(String regDd) { + this.regDd = regDd; + } + public String getRecvUserId() { + return recvUserId; + } + public void setRecvUserId(String recvUserId) { + this.recvUserId = recvUserId; + } + public int getTotCnt() { + return totCnt; + } + public void setTotCnt(int totCnt) { + this.totCnt = totCnt; + } + public String getReadYn() { + return readYn; + } + public void setReadYn(String readYn) { + this.readYn = readYn; + } + public String getNotiTypeNm() { + return notiTypeNm; + } + public void setNotiTypeNm(String notiTypeNm) { + this.notiTypeNm = notiTypeNm; + } + public int getRno() { + return rno; + } + public void setRno(int rno) { + this.rno = rno; + } + public String getMngOrgCd() { + return mngOrgCd; + } + public void setMngOrgCd(String mngOrgCd) { + this.mngOrgCd = mngOrgCd; + } + public String getMngOrgNm() { + return mngOrgNm; + } + public void setMngOrgNm(String mngOrgNm) { + this.mngOrgNm = mngOrgNm; + } + +} diff --git a/legacy/nlib/src/main/java/nlib/cmm/service/PagingVO.java b/legacy/nlib/src/main/java/nlib/cmm/service/PagingVO.java new file mode 100644 index 00000000..143eb1c7 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/service/PagingVO.java @@ -0,0 +1,172 @@ +package nlib.cmm.service; + +/** + *
+ * @Class Name : PagingVO.java
+ * 
+ * @Description : 페이지 정보 VO 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 09. 06. KNKIM 최초 생성 + * @ 2021. 10. 01. JSYOO 화면 페이징 공통 모듈 개발 + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 09. 06. + * @version 1.0 + * + */ +public class PagingVO { + + public final int DEFAULT_PAGE_SIZE = NlibProperty.getInt("list.paging.page.size", 10); + + private int pageIndex = 1; /* 페이지 번호 */ + private int pageSize = DEFAULT_PAGE_SIZE; /* 페이지 크기 (1페이지당 보여줄 자료건수) */ + private int totRecordCount = 0; /* 총건수 */ + + private int pageStart = 0; /* 시작번호 (쿼리 limit용)*/ + private int startPage = 0; /* 시작페이지 */ + private int endPage = 0; /* 현재 노출페이지중 마지막 페이지 (ex << < 1 2 3 4 5 > >> 중 5 ) */ + private int lastPage = 0; /* 마지막페이지 */ + private int cntPage = DEFAULT_PAGE_SIZE; /* 페이지 네비게이션에 표시되는 페이지 개수 (ex) << < 1 2 3 4 5 > >> */ + + public int getStartPage() { + return startPage; + } + + public int getCntPage() { + return cntPage; + } + + public void setCntPage(int cntPage) { + this.cntPage = cntPage; + } + + public void setStartPage(int startPage) { + this.startPage = startPage; + } + + public int getEndPage() { + return endPage; + } + + public void setEndPage(int endPage) { + this.endPage = endPage; + } + + public int getLastPage() { + return lastPage; + } + + public void setLastPage(int lastPage) { + this.lastPage = lastPage; + } + + public int getPageStart() { + return pageStart; + } + + public void setPageStart(int pageStart) { + this.pageStart = pageStart; + } + + public int getPageIndex() { + return pageIndex; + } + + public void setPageIndex(int pageIndex) { + if(pageIndex < 1) pageIndex = 1; + else this.pageIndex = pageIndex; + } + + public void setPageIndex(String sPageIndex) { + try { + pageIndex = Integer.parseInt(sPageIndex); + } catch(NumberFormatException e) { + pageIndex = 1; + } + } + + public int getPageSize() { + return pageSize; + } + + public void setPageSize(int pageSize) { + if(pageSize < 1) pageSize = DEFAULT_PAGE_SIZE; + else this.pageSize = pageSize; + } + + public void setPageSize(String sPageSize) { + try { + pageSize = Integer.parseInt(sPageSize); + } catch(NumberFormatException e) { + pageSize = NlibProperty.getInt("list.paging.page.size", 10); + } + } + + public int getTotRecordCount() { + return totRecordCount; + } + + public void setTotRecordCount(int totRecordCount) { + this.totRecordCount = totRecordCount; + } + + public int getPageStartRowNum() { + + if(pageIndex < 1) pageIndex = 1; + if(pageSize < 1) pageSize = 10; + + return ((pageIndex - 1) * pageSize); + } + + public void setPagingVO(int totRecordCount, int pageIndex, int pageSize) { + setPageIndex(pageIndex); + // 현재 페이지 + setPageSize(pageSize); + // 페이지 당 게시글수 + setTotRecordCount(totRecordCount); + // 게시글 총 갯수 + calcLastPage(totRecordCount, pageSize); + // 제일 마지막 페이지 계산 + + // 시작 끝 페이지 계산 - 아래. + calcStartEndPage(pageIndex, cntPage); + setPageStart(pageIndex, pageSize); + + } + + // 제일 마지막 페이지 계산 + public void calcLastPage(int totRecordCount, int pageSize) { + setLastPage((int) Math.ceil((double) totRecordCount / (double) pageSize)); + } + + // 시작, 끝 페이지 계산 + public void calcStartEndPage(int pageIndex, int cntPage) { + setEndPage(((int) Math.ceil((double) pageIndex / (double) cntPage)) * cntPage); + if (getLastPage() < getEndPage()) { + setEndPage(getLastPage()); + } + if (getTotRecordCount() > 0) { + if (getEndPage() % cntPage == 0) { + setStartPage(1 + (getEndPage() / cntPage - 1) * cntPage); + } else { + setStartPage(getEndPage() / cntPage * cntPage + 1); + } + } + if (getStartPage() < 1) { + setStartPage(1); + } + } + + // DB 쿼리에서 사용할 start값 계산 + public void setPageStart(int pageIndex, int pageSize) { + this.pageStart = ((pageIndex - 1) * pageSize); + } +} diff --git a/legacy/nlib/src/main/java/nlib/cmm/service/impl/CodeDAO.java b/legacy/nlib/src/main/java/nlib/cmm/service/impl/CodeDAO.java new file mode 100644 index 00000000..0518af10 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/service/impl/CodeDAO.java @@ -0,0 +1,54 @@ +package nlib.cmm.service.impl; + +import java.util.List; +import java.util.Map; + +import egovframework.rte.psl.dataaccess.mapper.Mapper; + +/** + *
+ * @Class Name : CodeDAO.java
+ * 
+ * @Description : 공통코드 조회 DAO 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 27. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 27. + * @version 1.0 + * + */ +@Mapper("codeDAO") +public interface CodeDAO { + + /** + * 공통코드를 조회한다. + * + * @param iCodeId + * @return + * @throws Exception + */ + public List> listCodes(String iCodeId) throws Exception; + + /** + * 주제분류코드를 조회한다. + * + * @return + * @throws Exception + */ + public List> listCtClsfs() throws Exception; + + /** + * 자료유형 최상위 코드목록을 조회한다. + */ + public List> listTypeDivCodes() throws Exception; +} diff --git a/legacy/nlib/src/main/java/nlib/cmm/service/impl/CodeServiceImpl.java b/legacy/nlib/src/main/java/nlib/cmm/service/impl/CodeServiceImpl.java new file mode 100644 index 00000000..49b9fd33 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/service/impl/CodeServiceImpl.java @@ -0,0 +1,75 @@ +package nlib.cmm.service.impl; + +import java.util.List; +import java.util.Map; +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import egovframework.rte.fdl.cmmn.EgovAbstractServiceImpl; +import nlib.cmm.service.CodeService; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : CodeServiceImpl.java
+ * 
+ * @Description : 코드 조회 공통 서비스 구현 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 07. 26. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 07. 26. + * @version 1.0 + * + */ +@Service("codeService") +public class CodeServiceImpl extends EgovAbstractServiceImpl implements CodeService +{ + private static final Logger log = LoggerFactory.getLogger(CodeServiceImpl.class); + + @Resource(name="codeDAO") + private CodeDAO codeDAO; + + /** + * 공통코드를 조회한다. + * + * @param iCodeId + * @return + * @throws Exception + */ + public List> listCodes(String iCodeId) throws Exception { + + if(StringUtil.isEmpty(iCodeId)) return null; + + return codeDAO.listCodes(iCodeId.toUpperCase()); + } + + /** + * 주제분류코드를 조회한다. + * + * @return + * @throws Exception + */ + public List> listCtClsfs() throws Exception { + return codeDAO.listCtClsfs(); + } + + /** + * 자료유형 최상위 코드목록을 조회한다. + */ + public List> listTypeDivCodes() throws Exception { + return codeDAO.listTypeDivCodes(); + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/cmm/service/impl/MainDAO.java b/legacy/nlib/src/main/java/nlib/cmm/service/impl/MainDAO.java new file mode 100644 index 00000000..a45ecec0 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/service/impl/MainDAO.java @@ -0,0 +1,66 @@ + +package nlib.cmm.service.impl; + +import java.util.List; +import java.util.Map; + +import egovframework.rte.psl.dataaccess.mapper.Mapper; +import nlib.col.service.CollectionVO; + +@Mapper("mainDAO") +public interface MainDAO { + + /** + * 지역문화원의 키워드 리스트를 조회한다. + * + * @param mngOrgCd + * @return + */ + public List> listKeywords(String mngOrgCd); + + /** + * 문화원 PICK한 자료 리스트를 조회한다. + * + * @param mngOrgCd + * @return + */ + public List listOrgPicks(String mngOrgCd); + + /** + * 유형별인기자료 리스트를 조회한다. + * + * @param mngOrgCd + * @return + */ + public List listPops(CollectionVO searchVO); + + /** + * 온라인자료관 리스트를 조회한다. + * + * @param mngOrgCd + * @return + */ + public List listOnline(String mngOrgCd); + + /** + * 지방문화원별 배너 정보를 조회한다. + * + * @param mngOrgCd + * @return + */ + public List> listBannerInfos(String mngOrgCd); + + /** + * 메인화면 배너ID에 대한 정보를 가져온다. + * + * @return + */ + public Map getBannerInfo(String bannerId); + + /** + * 메인화면 footer 문화원 전체 이름을 가져온다. + * + * @return + */ + public List> listDeptTree(String mngOrgNm); +} diff --git a/legacy/nlib/src/main/java/nlib/cmm/service/impl/MainServiceImpl.java b/legacy/nlib/src/main/java/nlib/cmm/service/impl/MainServiceImpl.java new file mode 100644 index 00000000..a716a6db --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/service/impl/MainServiceImpl.java @@ -0,0 +1,142 @@ + +package nlib.cmm.service.impl; + + +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import nlib.cmm.service.MainService; +import nlib.col.service.CollectionVO; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : MainServiceImpl.java
+ * 
+ * @Description : 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 07. 01. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 07. 01. + * @version 1.0 + * + */ +@Service("mainService") +public class MainServiceImpl implements MainService +{ + private static final Logger log = LoggerFactory.getLogger(MainServiceImpl.class); + + @Resource(name="mainDAO") + private MainDAO mainDAO; + + /** + * 지역문화원의 키워드 리스트를 조회한다. + * + * @param mngOrgCd + * @return + */ + public List> listKeywords(String mngOrgCd) { + return mainDAO.listKeywords(mngOrgCd); + } + + /** + * 문화원 PICK한 자료 리스트를 조회한다. + * + * @param mngOrgCd + * @return + */ + public List listOrgPicks(String mngOrgCd) { + return mainDAO.listOrgPicks(mngOrgCd); + } + + /** + * 유형별인기자료 리스트를 조회한다. : 기본 자료유형 문서로 검색 + * + * @param searchVO + * @return + */ + public List listPops(CollectionVO searchVO) { + return mainDAO.listPops(searchVO); + } + + /** + * 유형별인기자료 리스트를 조회한다. : 기본 자료유형 문서로 검색 + * + * @param mngOrgCd + * @return + */ + public List listPops(String mngOrgCd) { + CollectionVO searchVO = new CollectionVO(); + searchVO.setMngOrgCd(mngOrgCd); + searchVO.setTypeDivCd("IT_DOC"); // 문서 + return listPops(mngOrgCd, null); + } + + /** + * 유형별인기자료 리스트를 조회한다. + * + * @param mngOrgCd + * @param typeDivCd + * @return + */ + public List listPops(String mngOrgCd, String typeDivCd) { + + CollectionVO searchVO = new CollectionVO(); + searchVO.setMngOrgCd(mngOrgCd); + if(StringUtil.isEmpty(typeDivCd)) typeDivCd = "IT_DOC"; + searchVO.setTypeDivCd(typeDivCd); + + return listPops(searchVO); + } + + /** + * 온라인자료관 리스트를 조회한다. + * + * @param mngOrgCd + * @return + */ + public List listOnline(String mngOrgCd) { + return mainDAO.listOnline(mngOrgCd); + } + + /** + * 지방문화원별 배너 정보를 조회한다. + * + * @param mngOrgCd + * @return + */ + public List> listBannerInfos(String mngOrgCd) { + return mainDAO.listBannerInfos(mngOrgCd); + } + + /** + * 메인화면 배너ID에 대한 정보를 가져온다. + * + * @return + */ + public Map getBannerInfo(String bannerId) { + return mainDAO.getBannerInfo(bannerId); + } + + @Override + public List> listDeptTree(String mngOrgNm) { + return mainDAO.listDeptTree(mngOrgNm); + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/cmm/service/impl/NotificationDAO.java b/legacy/nlib/src/main/java/nlib/cmm/service/impl/NotificationDAO.java new file mode 100644 index 00000000..9c1f3384 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/service/impl/NotificationDAO.java @@ -0,0 +1,90 @@ +package nlib.cmm.service.impl; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Repository; + +import egovframework.com.cmm.service.impl.EgovComAbstractDAO; +import egovframework.rte.psl.dataaccess.mapper.Mapper; +import nlib.cmm.service.NotificationVO; +import nlib.cmm.service.NlibProperty; +import nlib.user.service.NlibLoginVO; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : NotificationDAO.java
+ * 
+ * @Description : 알림 정보 제공 DAO 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 27. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 27. + * @version 1.0 + * + */ + + +@Repository("notificationDAO") +public class NotificationDAO extends EgovComAbstractDAO { + + /* + * 사용자 알림 목록을 조회한다. + */ + public List listNotifications(NotificationVO searchNotificationVO) throws Exception { + + return selectList("NotificationDAO.listNotifications", searchNotificationVO); + } + + + /** + * 사용자 알림 목록의 건수를 조회한다. + */ + public int countNotifications(String recvUserId) throws Exception { + + return selectOne("NotificationDAO.countNotifications", recvUserId); + } + + /* + * 사용자가 확인하지 않은 알림 건수를 조회한다. + */ + public int countUnreadNotification(String recvUserId) throws Exception { + + return selectOne("NotificationDAO.countUnreadNotification", recvUserId); + } + + /** + * 알림을 읽음으로 변경한다. + * 만일, 이미 읽음표시된 경우에는 변경 없다. + * + * @param notiVO (notiId, recvUserId 필수) + * @return + * @throws Exception + */ + public int updateRead(NotificationVO notiVO) throws Exception { + return update("NotificationDAO.updateRead", notiVO); + } + + /** + * 알림내용 상세 조회 + * + * @param notiVO (notiId, recvUserId 필수) + * @return + * @throws Exception + */ + public NotificationVO selectNotification(NotificationVO notiVO) throws Exception { + return selectOne("NotificationDAO.selectNotification", notiVO); + } +} diff --git a/legacy/nlib/src/main/java/nlib/cmm/service/impl/NotificationServiceImpl.java b/legacy/nlib/src/main/java/nlib/cmm/service/impl/NotificationServiceImpl.java new file mode 100644 index 00000000..6e0abcd2 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/service/impl/NotificationServiceImpl.java @@ -0,0 +1,93 @@ +package nlib.cmm.service.impl; + +import java.util.List; +import javax.annotation.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import nlib.cmm.service.NotificationService; +import nlib.cmm.service.NotificationVO; + +/** + *
+ * @Class Name : NotificationServiceImpl.java
+ * 
+ * @Description : 알림관련 서비스 구현 클래스  
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021 09. 06. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021 09. 06. + * @version 1.0 + * + */ +@Service("notificationService") +public class NotificationServiceImpl implements NotificationService +{ + private static final Logger log = LoggerFactory.getLogger(NotificationServiceImpl.class); + + @Resource(name="notificationDAO") + private NotificationDAO notificationDAO; + + /** + * 사용자 알림 목록을 조회한다. + */ + public List listNotifications(NotificationVO notificationVO) throws Exception { + + return notificationDAO.listNotifications(notificationVO); + } + + /** + * 사용자 알림 목록의 건수를 조회한다. + */ + public int countNotifications(String recvUserId) throws Exception { + + return notificationDAO.countNotifications(recvUserId); + } + + /** + * 읽지 않은 알림 건수를 조회한다. + * + * @param mbInfoId + * @return + * @throws Exception + */ + public int countUnreadNotification(String recvUserId) throws Exception { + + return notificationDAO.countUnreadNotification(recvUserId); + } + + /** + * 알림을 읽음으로 변경한다. + * 만일, 이미 읽음표시된 경우에는 변경 없다. + * + * @param notiVO (notiId, recvUserId 필수) + * @return + * @throws Exception + */ + public int updateRead(NotificationVO notiVO) throws Exception { + return notificationDAO.updateRead(notiVO); + } + + /** + * 알림내용 상세 조회 + * + * @param notiVO (notiId, recvUserId 필수) + * @return + * @throws Exception + */ + public NotificationVO selectNotification(NotificationVO notiVO) throws Exception { + updateRead(notiVO); + return notificationDAO.selectNotification(notiVO); + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/cmm/session/SessionConfig.java b/legacy/nlib/src/main/java/nlib/cmm/session/SessionConfig.java new file mode 100644 index 00000000..45e665f5 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/session/SessionConfig.java @@ -0,0 +1,180 @@ +package nlib.cmm.session; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.servlet.annotation.WebListener; +import javax.servlet.http.HttpSessionEvent; +import javax.servlet.http.HttpSessionListener; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import egovframework.com.ext.oauth.service.OAuthUniversalUser; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : SessionConfig.java
+ * 
+ * @Description : 멀티도메인에서의 로그인 처리를 위해 지방문화원에서 해당 세션에서 로그인처리 가능한 정보를 관리하는 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 8. 25. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 8. 25. + * @version 1.0 + * + */ +@WebListener +public class SessionConfig implements HttpSessionListener { + + private static final Logger log = LoggerFactory.getLogger(SessionConfig.class); + + /* 사용자 정보를 구분하는 구분자 */ + private static final String DELIMITER = "\t"; + + /* 세션별 로그인 처리 가능한 정보 목록 */ + private static final Map loginSessions = new ConcurrentHashMap<>(); + + /* 세션별 회원가입 처리 가능한 정보 목록 */ + private static final Map memberSessions = new ConcurrentHashMap<>(); + + @Override + public void sessionCreated(HttpSessionEvent se) { + log.debug("Session sessionCreated (O) : " + se.getSession().getId()); + } + + @Override + public void sessionDestroyed(HttpSessionEvent se) { + String sessionId = se.getSession().getId(); + log.debug("Session sessionDestroyed (X) : " + sessionId); + if(loginSessions.get(sessionId) != null){ + removeLoginInfo(sessionId); + } + if(memberSessions.get(sessionId) != null){ + removeNewMemberInfo(sessionId); + } + } + + /** + * 지방문화원 해당 세션에 로그인 처리 가능한 SNS유형 및 SNSID 정보를 저장한다. + * + * @param sessionId + * @param snsType + * @param snsId + */ + public static void setLoginInfo(String sessionId, OAuthUniversalUser oUser) { + log.debug("setLoginInfo : " + sessionId + ", " + oUser.getSnsType() + ", " + oUser.getSnsId()); + loginSessions.put(sessionId, oUser); + } + + /** + * 지방문화원 해당 세션에 로그인 처리 가능한 SNS 유형 및 SNS ID 정보를 리턴한다. + * 리턴유형 문자열 배열 + * [0] : snsType + * [1] : snsId + * + * @param sessionId + * @return + */ + public static OAuthUniversalUser getLoginInfo(String sessionId) { + + if(StringUtil.isEmpty(sessionId)) return null; + + return (OAuthUniversalUser)loginSessions.get(sessionId); + } + + /** + * 지방문화원 해당 세션에 로그인 처리 가능한 SNS 유형 및 SNS ID 정보를 리턴하고 목록에서 삭제한다. + * 리턴유형 문자열 배열 + * [0] : snsType + * [1] : snsId + * + * @param sessionId + * @return + */ + public static OAuthUniversalUser popLoginInfo(String sessionId) { + + OAuthUniversalUser ret = getLoginInfo(sessionId); + removeLoginInfo(sessionId); + + return ret; + } + + /** + * 지방문화원 해당 세션에 로그인 처리 가능한 정보를 삭제한다. + * (로그인 처리 완료 후 또는 세션 종료 시, 삭제) + * + * @param sessionId + * @param snsType + * @param snsId + */ + public static void removeLoginInfo(String sessionId) { + if(StringUtil.isNotEmpty(sessionId)){ + loginSessions.remove(sessionId); + log.debug("removeLoginInfo > sessionId = " + sessionId); + } + } + + /** + * 지방문화원 해당 세션에 회원가입 처리 가능한 SNS유형 및 SNS 프로파일 정보를 저장한다. + * + * @param sessionId + * @param snsType + * @param snsId + */ + public static void setNewMemberInfo(String sessionId, OAuthUniversalUser oUser) { + log.debug("setLoginInfo : " + sessionId + ", " + oUser.getSnsId()); + memberSessions.put(sessionId, oUser); + } + + /** + * 지방문화원 해당 세션에 회원가입 처리 가능한 SNS 유형 및 SNS 프로파일 정보를 리턴한다. + * + * @param sessionId + * @return + */ + public static OAuthUniversalUser getNewMemberInfo(String sessionId) { + if(StringUtil.isEmpty(sessionId)) return null; + + return (OAuthUniversalUser)memberSessions.get(sessionId); + } + + /** + * 지방문화원 해당 세션에 회원가입 처리 가능한 SNS 유형 및 SNS 프로파일 정보를 리턴한다. + * + * @param sessionId + * @return + */ + public static OAuthUniversalUser popNewMemberInfo(String sessionId) { + OAuthUniversalUser ret = getNewMemberInfo(sessionId); + removeNewMemberInfo(sessionId); + + return ret; + } + + /** + * 지방문화원 해당 세션에 회원가입 처리 가능한 정보를 삭제한다. + * (회원가입 처리 완료 후 또는 세션 종료 시, 삭제) + * + * @param sessionId + * @param snsType + * @param snsId + */ + public static void removeNewMemberInfo(String sessionId) { + if(StringUtil.isNotEmpty(sessionId)){ + memberSessions.remove(sessionId); + log.debug("removeNewMemberInfo > sessionId = " + sessionId); + } + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/cmm/snslogin/GoogleOAuthRequest.java b/legacy/nlib/src/main/java/nlib/cmm/snslogin/GoogleOAuthRequest.java new file mode 100644 index 00000000..9e7d6eb2 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/snslogin/GoogleOAuthRequest.java @@ -0,0 +1,90 @@ +package nlib.cmm.snslogin; + +public class GoogleOAuthRequest { + private String redirectUri; + private String clientId; + private String clientSecret; + private String code; + private String responseType; + private String scope; + private String accessType; + private String grantType; + private String state; + private String includeGrantedScopes; + private String loginHint; + private String prompt; + + public String getRedirectUri() { + return redirectUri; + } + public void setRedirectUri(String redirectUri) { + this.redirectUri = redirectUri; + } + public String getClientId() { + return clientId; + } + public void setClientId(String clientId) { + this.clientId = clientId; + } + public String getClientSecret() { + return clientSecret; + } + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } + public String getCode() { + return code; + } + public void setCode(String code) { + this.code = code; + } + public String getResponseType() { + return responseType; + } + public void setResponseType(String responseType) { + this.responseType = responseType; + } + public String getScope() { + return scope; + } + public void setScope(String scope) { + this.scope = scope; + } + public String getAccessType() { + return accessType; + } + public void setAccessType(String accessType) { + this.accessType = accessType; + } + public String getGrantType() { + return grantType; + } + public void setGrantType(String grantType) { + this.grantType = grantType; + } + public String getState() { + return state; + } + public void setState(String state) { + this.state = state; + } + public String getIncludeGrantedScopes() { + return includeGrantedScopes; + } + public void setIncludeGrantedScopes(String includeGrantedScopes) { + this.includeGrantedScopes = includeGrantedScopes; + } + public String getLoginHint() { + return loginHint; + } + public void setLoginHint(String loginHint) { + this.loginHint = loginHint; + } + public String getPrompt() { + return prompt; + } + public void setPrompt(String prompt) { + this.prompt = prompt; + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/cmm/snslogin/GoogleOAuthResponse.java b/legacy/nlib/src/main/java/nlib/cmm/snslogin/GoogleOAuthResponse.java new file mode 100644 index 00000000..6adb25b0 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/snslogin/GoogleOAuthResponse.java @@ -0,0 +1,49 @@ +package nlib.cmm.snslogin; + + +public class GoogleOAuthResponse { + private String accessToken; + private String expiresIn; + private String refreshToken; + private String scope; + private String tokenType; + private String idToken; + + public String getAccessToken() { + return accessToken; + } + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + public String getExpiresIn() { + return expiresIn; + } + public void setExpiresIn(String expiresIn) { + this.expiresIn = expiresIn; + } + public String getRefreshToken() { + return refreshToken; + } + public void setRefreshToken(String refreshToken) { + this.refreshToken = refreshToken; + } + public String getScope() { + return scope; + } + public void setScope(String scope) { + this.scope = scope; + } + public String getTokenType() { + return tokenType; + } + public void setTokenType(String tokenType) { + this.tokenType = tokenType; + } + public String getIdToken() { + return idToken; + } + public void setIdToken(String idToken) { + this.idToken = idToken; + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/cmm/web/EncryptorConfigTest.java b/legacy/nlib/src/main/java/nlib/cmm/web/EncryptorConfigTest.java new file mode 100644 index 00000000..4c307f97 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/web/EncryptorConfigTest.java @@ -0,0 +1,52 @@ +package nlib.cmm.web; + +import java.util.List; + +import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; + +import nlib.cmm.NlibCommonController; + +/** + *
+ * @Class Name : EncryptorConfigTest.java
+ * 
+ * @Description : properties 암호화 로그 및 테스트
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 12. 21. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 12. 21. + * @version 1.0 + * + */ +@Controller +public class EncryptorConfigTest { + + private static final Logger log = LoggerFactory.getLogger(EncryptorConfigTest.class); + + @RequestMapping(value = "/system/EncryptorTest.do") + public String EncryptorTest(String key,String value,ModelMap model) { + StandardPBEStringEncryptor pbeEnc = new StandardPBEStringEncryptor(); + pbeEnc.setAlgorithm("PBEWithMD5AndDES"); + pbeEnc.setPassword(key); // PBE 값(XML PASSWORD설정) + log.info("키값 : "+ key + " 암호화할 값 : " + value + " -> 암호화된 값 : " + pbeEnc.encrypt(value)); + + model.addAttribute("code", "정상"); + model.addAttribute("message", "정상적으로 처리되었습니다."); + return "nlib/cmm/common"; + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/cmm/web/MainController.java b/legacy/nlib/src/main/java/nlib/cmm/web/MainController.java new file mode 100644 index 00000000..3f9ecbce --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/web/MainController.java @@ -0,0 +1,242 @@ +package nlib.cmm.web; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.activation.MimetypesFileTypeMap; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.savedrequest.HttpSessionRequestCache; +import org.springframework.security.web.savedrequest.RequestCache; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import nlib.bbs.service.ArticleVO; +import nlib.bbs.service.BoardService; +import nlib.bbs.service.QnaService; +import nlib.cmm.NlibCommonController; +import nlib.cmm.service.CodeService; +import nlib.cmm.service.MainService; +import nlib.cmm.service.NlibProperty; +import nlib.cmm.service.NotificationService; +import nlib.cmm.service.PagingVO; +import nlib.col.service.CartService; +import nlib.col.service.CollectionVO; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : MainController.java
+ * 
+ * @Description : 메인화면에 표시할 정보를 처리하는 Controller 클래스
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 6. 22. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 6. 22. + * @version 1.0 + * + */ +@Controller +public class MainController extends NlibCommonController { + + private static final Logger log = LoggerFactory.getLogger(MainController.class); + + @Resource(name="notificationService") + private NotificationService notificationService; + + @Resource(name = "cartService") + private CartService cartService; + + @Resource(name = "codeService") + private CodeService codeService; + + @Resource(name = "mainService") + private MainService mainService; + + @Resource(name = "ancmntService") + private BoardService ancmntService; + + @Resource(name = "qnaService") + private QnaService qnaService; + + @RequestMapping( {"/index.do"} ) + public String setContent( + HttpServletRequest request, + HttpServletResponse response, + Authentication authentication, + ModelMap model) throws Exception { + + // 캐쉬된 Reqeust 히스토리 삭제 + RequestCache cache = new HttpSessionRequestCache(); + cache.removeRequest(request, response); + + String mngOrgCd = getCurCouncilCd(request); + + //------------------------------------------------ + // 추천 자료 관련 + //------------------------------------------------ + + // 추천키워드 + List> listKeywords = mainService.listKeywords(mngOrgCd); + model.addAttribute("listKeywords", listKeywords); + + // 문화원 PICK + model.addAttribute("mngOrgNm", getCurCouncilNm(request)); + model.addAttribute("listOrgPicks", mainService.listOrgPicks(mngOrgCd)); + + // 유형별 인기자료 + //List> listTypeDivCodes = codeService.listTypeDivCodes(); + //model.addAttribute("listTypeDivCodes", listTypeDivCodes); + + List listPops = mainService.listPops(mngOrgCd, null); // 전체 + model.addAttribute("listPops", listPops); + + // 온라인자료관 + model.addAttribute("listOnline", mainService.listOnline(mngOrgCd)); + + //------------------------------------------------ + // 게시판관련 + //------------------------------------------------ + ArticleVO searchArticleVO = new ArticleVO(); + searchArticleVO.setPageIndex(1); + searchArticleVO.setPageSize(3); + searchArticleVO.setMngOrgCd(getCurCouncilCd(request)); + + // 공지사항 + List listAncmnt = ancmntService.listArticles(searchArticleVO); + model.addAttribute("listAncmnt", listAncmnt); + + // Q&A + String mbInfoId = getMbInfoId(request); + searchArticleVO.setLoginedMbInfoId(mbInfoId); + List listQna = qnaService.listArticles(searchArticleVO); + model.addAttribute("listQna", listQna); + + // 메인 화면 배너 + List> listBannerInfos = mainService.listBannerInfos(mngOrgCd); + model.addAttribute("listBannerInfos", listBannerInfos); + + return "nlib/cmm/home"; + } + + @RequestMapping( {"/cmm/headerSubPart.do"} ) + public String headerSub( + HttpServletRequest request, + HttpServletResponse response, + Authentication authentication, + ModelMap model) throws Exception { + + // 캐쉬된 Reqeust 히스토리 삭제 + RequestCache cache = new HttpSessionRequestCache(); + cache.removeRequest(request, response); + + log.debug((authentication == null ? "손님 메인 접속" : authentication.getName() + " 메인 접속")); + + String mbInfoId = getMbInfoId(request); + + // 카트 건수 확인 + int cartCnt = 0; + if(StringUtil.isEmpty(mbInfoId)) { + cartCnt = cartService.countCartItemsFromCookie(request, response, "1"); + cartCnt += cartService.countCartItemsFromCookie(request, response, "2"); + } else { + cartCnt = cartService.countCartItems(mbInfoId, "0"); + } + + // 알림 확인 + int unreadNotiCnt = 0; + if(StringUtil.isNotEmpty(mbInfoId)) { + unreadNotiCnt = notificationService.countUnreadNotification(mbInfoId); + } + + if(!isAlerted(request)) { + setAlerted(request, true); + } + + model.addAttribute("cartCnt", cartCnt); + model.addAttribute("unreadNotiCnt", unreadNotiCnt); + model.addAttribute("docViewUrl", NlibProperty.getString("pdf.url")); + model.addAttribute("videoViewUrl", NlibProperty.getString("video.url")); + model.addAttribute("imageViewUrl", NlibProperty.getString("image.url")); + + return "nlib/cmm/headerSubPart"; + } + + /** + * 목록 조회한다. + * + * @param req + * @return + * @return + */ + @RequestMapping(value="/cmm/listDeptTree.do", method = { RequestMethod.POST }) + public String listDeptTree(@RequestParam Map map, ModelMap model) throws Exception { + String mngOrgNm = (String)map.get("mngOrgNm"); + + // 문화원명 조회 + List> listDeptTree = mainService.listDeptTree(mngOrgNm); + model.addAttribute("listDeptTree", listDeptTree); + + return "nlib/cmm/footerSubPart"; + } + + @RequestMapping(value = "/main/bannerImage.do") + public void getBannerImage(HttpServletRequest request, HttpServletResponse response, String atchFileId) throws IOException { + + Map bannerInfo = mainService.getBannerInfo(atchFileId); + boolean exists = false; + + if(bannerInfo != null && StringUtil.isNotEmpty(bannerInfo.get("fileStrePath")) && StringUtil.isNotEmpty(bannerInfo.get("streFileNm")) && StringUtil.isNotEmpty(bannerInfo.get("orignlFileNm"))) { + try { + String fileName = bannerInfo.get("fileStrePath") + bannerInfo.get("streFileNm"); + MimetypesFileTypeMap mimetypesFileTypeMap = new MimetypesFileTypeMap(); + response.setContentType(mimetypesFileTypeMap.getContentType(bannerInfo.get("orignlFileNm"))); + response.getOutputStream().write(Files.readAllBytes(Paths.get(fileName))); + exists = true; + } catch(IOException e) { + log.error("메인 화면 배너 관련 파일을 확인할 수 없습니다. : bannerId=" + atchFileId); + } + } + + if(!exists) { + try { + String fileName = NlibProperty.getString("main.banner.img.path"); + MimetypesFileTypeMap mimetypesFileTypeMap = new MimetypesFileTypeMap(); + response.setContentType(mimetypesFileTypeMap.getContentType(bannerInfo.get("orignlFileNm"))); + response.getOutputStream().write(Files.readAllBytes(Paths.get(fileName))); + exists = true; + } catch(IOException e) { + log.error("메인 화면 배너 기본 배너 파일을 확인할 수 없습니다. : main.banner.img.path=" + NlibProperty.getString("main.banner.img.path")); + } + } + + return; + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/cmm/web/NotificationController.java b/legacy/nlib/src/main/java/nlib/cmm/web/NotificationController.java new file mode 100644 index 00000000..edae594f --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/cmm/web/NotificationController.java @@ -0,0 +1,189 @@ +package nlib.cmm.web; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import nlib.cmm.NlibCommonController; +import nlib.cmm.service.NotificationService; +import nlib.cmm.service.NotificationVO; +import nlib.cmm.service.PagingVO; +import nlib.cmm.service.NlibProperty; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : NotificationController.java
+ * 
+ * @Description : 사용자 홈페이지 알림 안내 컨트롤러 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 6. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 9. 6. + * @version 1.0 + * + */ +@Controller +public class NotificationController extends NlibCommonController { + + private static final Logger log = LoggerFactory.getLogger(NotificationController.class); + + static final int DEFUALT_PAGE_SIZE = NlibProperty.getInt("list.paging.page.size", 10); + + @Resource(name="notificationService") + private NotificationService notificationService; + + + /** + * 알림 목록 화면을 표시한다. + * + * @param req + * @return + */ + @Secured("ROLE_USER") + @RequestMapping("/cmm/listNotifications.do") + public String listNotifications( + HttpServletRequest req, + @RequestParam Map paramMap, + ModelMap model + ) throws Exception { + + String mbInfoId = getMbInfoId(req); + int pageIndex = StringUtil.toNumber(paramMap.get("pageIndex"), 1); + int pageSize = StringUtil.toNumber(paramMap.get("pageSize"), DEFUALT_PAGE_SIZE); + + log.debug("listNotifications > pageIndex = " + pageIndex); + log.debug("listNotifications > pageSize = " + pageSize); + + NotificationVO searchNotificationVO = new NotificationVO(); + searchNotificationVO.setPageIndex(pageIndex); + searchNotificationVO.setPageSize(pageSize); + searchNotificationVO.setRecvUserId(mbInfoId); + List list = notificationService.listNotifications(searchNotificationVO); + + int totRecordCount = (list == null) ? 0 : list.size(); + searchNotificationVO.setTotRecordCount(totRecordCount); + + model.addAttribute("notificationList", list); + model.addAttribute("searchNotificationVO", searchNotificationVO); + model.addAttribute("pageSize", pageSize); + model.addAttribute("pageIndex", pageIndex); + + + return "nlib/cmm/listNotifications"; + } + + /** + * 알림 목록 조회한다. + * + * @param req + * @return + */ + @Secured("ROLE_USER") + @RequestMapping(value="/cmm/listNotificationsAjax.do") + public ResponseEntity listNotificationsAjax(HttpServletRequest req, + Authentication authentication, @RequestBody(required = false) Map paramMap) throws Exception { + + String mbInfoId = getMbInfoId(req); + if(paramMap == null) paramMap = new HashMap(); + int pageIndex = StringUtil.toNumber(paramMap.get("pageIndex"), 1); + int pageSize = StringUtil.toNumber(paramMap.get("pageSize"), DEFUALT_PAGE_SIZE); + + log.debug("listNotificationsAjax > pageIndex = " + pageIndex); + log.debug("listNotificationsAjax > pageSize = " + pageSize); + + + NotificationVO searchNotificationtVO = new NotificationVO(); + searchNotificationtVO.setPageIndex(pageIndex); + searchNotificationtVO.setPageSize(pageSize); + searchNotificationtVO.setRecvUserId(mbInfoId); + List list = notificationService.listNotifications(searchNotificationtVO); + + int totRecordCount = notificationService.countNotifications(mbInfoId); + + //------------------------------- + // JSON변환 응답 처리 + //------------------------------- + // JS-GRID 페이징 처리를 포함한 응답값 처리 + // {data: [{...}], + // itemsCount: 255 + // } + HashMap retMap = new HashMap(); + retMap.put("data", list); + retMap.put("itemsCount", totRecordCount); + + PagingVO pageVO = new PagingVO(); + pageVO.setPagingVO(totRecordCount, pageIndex, pageSize); + retMap.put("pagingPageIndex" , pageVO.getPageIndex()); + retMap.put("pagingTotRecordCount", pageVO.getTotRecordCount()); + retMap.put("pagingStartPage" , pageVO.getStartPage()); + retMap.put("pagingEndPage" , pageVO.getEndPage()); + retMap.put("pagingLastPage" , pageVO.getLastPage()); + + return makeResponseEntityJson(retMap); + } + + + /** + * 알림 상세 내용 조회한다. + * + * @param req + * @return + */ + @Secured("ROLE_USER") + @RequestMapping("/cmm/selectNotificationAjax.do") + public ResponseEntity selectNotificationAjax(HttpServletRequest req, Authentication authentication, @RequestBody Map paramMap) throws Exception { + + String notiId = paramMap.get("notiId"); // 알림ID + String pageIndex = paramMap.get("pageIndex"); + String pageSize = paramMap.get("pageSize"); + + log.debug("selectNotificationAjax > notiId = " + notiId); + + NotificationVO paramNotiVO = new NotificationVO(); + paramNotiVO.setNotiId(notiId); + paramNotiVO.setRecvUserId(getMbInfoId(req)); + paramNotiVO.setPageIndex(pageIndex); + paramNotiVO.setPageSize(pageSize); + + // 읽음처리 및 상세내용 조회 + NotificationVO notiVO = notificationService.selectNotification(paramNotiVO); + + //------------------------------- + // JSON변환 응답 처리 + //------------------------------- + // JS-GRID 페이징 처리를 포함한 응답값 처리 + // {data: [{...}], + // itemsCount: 255 + // } + HashMap retMap = new HashMap(); + retMap.put("data", notiVO); + + return makeResponseEntityJson(retMap); + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/col/service/CartCookieVO.java b/legacy/nlib/src/main/java/nlib/col/service/CartCookieVO.java new file mode 100644 index 00000000..2d306dc4 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/CartCookieVO.java @@ -0,0 +1,110 @@ +package nlib.col.service; + +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : CartCookieVO.java
+ * 
+ * @Description : 비로그인 회원의 카트정보를 담는 쿠키 정보값 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 10. 13. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 10. 13. + * @version 1.0 + * + */ +public class CartCookieVO { + + String rentValues = null; /* 대출 목록으로 ":"로 구분되어 짐 */ + String readValues = null; /* 방문열람 목록으로 ":"로 구분되어 짐 */ + + /** + * 쿠키 카트값에 자료 항목을 추가한다. + * + * @param cartTypeCd + * @param masterId + * @return + */ + public String addCartItem(String cartTypeCd, String masterId) { + + if(StringUtil.isEmpty(cartTypeCd)) return "카트구분 정보가 없습니다."; + if(StringUtil.isEmpty(masterId)) return "자료정보가 없습니다."; + + String cartStr = null; + + if("1".equals(cartTypeCd)) cartStr = getRentValues(); + else if("2".equals(cartTypeCd)) cartStr = getReadValues(); + else return "카트구분 정보가 적합하지 않습니다."; + + cartStr = (StringUtil.isEmpty(cartStr) ? ":" : cartStr); + if(cartStr.contains(":" + masterId + ":")) return "이미 카트에 존재합니다."; + + cartStr += (":" + masterId + ":"); + + if("1".equals(cartTypeCd)) setRentValues(cartStr); + else if("2".equals(cartTypeCd)) setReadValues(cartStr); + + return null; + } + + /** + * 쿠키 카트값에서 자료 항목을 삭제한다. + * + * @param cartTypeCd + * @param masterId + * @return + */ + public String removeCartItem(String cartTypeCd, String masterId) { + + if(StringUtil.isEmpty(cartTypeCd)) return "카트구분 정보가 없습니다."; + if(StringUtil.isEmpty(masterId)) return "자료정보가 없습니다."; + + String cartStr = null; + + if("1".equals(cartTypeCd)) cartStr = getRentValues(); + else if("2".equals(cartTypeCd)) cartStr = getReadValues(); + else return "카트구분 정보가 적합하지 않습니다."; + + + cartStr = (StringUtil.isEmpty(cartStr) ? ":" : cartStr); + if(StringUtil.isEmpty(cartStr) || !cartStr.contains(":" + masterId + ":")) return "해당 자료는 카트에 존재하지 않습니다."; + + int startIdx = cartStr.indexOf(":" + masterId + ":"); + if(startIdx < 0) return "해당 자료는 카트에 존재하지 않습니다."; + + int endIdx = startIdx + (":" + masterId).length(); + + cartStr = cartStr.substring(0, startIdx) + cartStr.substring(endIdx); + + if("1".equals(cartTypeCd)) setRentValues(cartStr); + else if("2".equals(cartTypeCd)) setReadValues(cartStr); + + return null; + } + + // GET & SET + public String getRentValues() { + return rentValues; + } + public void setRentValues(String rentValues) { + this.rentValues = rentValues; + } + public String getReadValues() { + return readValues; + } + public void setReadValues(String readValues) { + this.readValues = readValues; + } + +} diff --git a/legacy/nlib/src/main/java/nlib/col/service/CartService.java b/legacy/nlib/src/main/java/nlib/col/service/CartService.java new file mode 100644 index 00000000..c05f5c6a --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/CartService.java @@ -0,0 +1,142 @@ +package nlib.col.service; + +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + *
+ * @Class Name : CartService.java
+ * 
+ * @Description : 카트 관리 서비스 인터페이스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021-10-08 KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021-10-08 + * @version 1.0 + * + */ +public interface CartService +{ + + /** + * (로그인자용) 로그인한 사용자의 카트 목록을 조회한다. + * + * @param mbInfoId + * @param cartDivCd + * @return + * @throws Exception + */ + public List listCartItems(String mbInfoId, String cartTypeCd) throws Exception; + + /** + * (비로그인자용) 쿠키에서 카트 목록을 조회한다. + * + * @param request + * @param cartDivCd + * @return + * @throws Exception + */ + public List listCartItemsFromCookie(HttpServletRequest request, HttpServletResponse response, String cartDivCd) throws Exception; + + /** + * (로그인자용) 카트 영역 구분코드를 변경한다. (대출 <-> 방문열람) + * + * @param mbInfoId + * @param targetCartItems + * @return + * @throws Exception + */ + public String changeCartType(CollectionVO cartVO) throws Exception; + + /** + * (비로그인자용) 카트 영역 구분코드를 변경한다. (대출 <-> 방문열람) + * + * @param request + * @param targetCartItems + * @return + * @throws Exception + */ + public String changeCartTypeToCookie(HttpServletRequest request, HttpServletResponse response, CollectionVO cartVO) throws Exception; + + /** + * (로그인자용) 카트에 추가한다. + * + * @param cartVO + * @return + * @throws Exception + */ + public String insertCartItem(CollectionVO cartVO); + + /** + * (비로그인자용) 카트에 추가한다. + * + * @param cartVO + * @return + * @throws Exception + */ + public String insertCartItemToCookie(HttpServletRequest request, HttpServletResponse response, CollectionVO cartVO) throws Exception; + + /** + * (로그인자용) 카트에서 선택된 자료들을 삭제한다. + * + * @param targetCartItems + * @return + * @throws Exception + */ + public String deleteCartItems(CollectionVO cartVO) throws Exception; + + /** + * (비로그인자용) 카트에서 선택된 자료들을 삭제한다. + * + * @param targetCartItems + * @return + * @throws Exception + */ + public String deleteCartItemsFromCookie(HttpServletRequest request, HttpServletResponse response, CollectionVO cartVO) throws Exception; + + + /** + * 쿠키 카트(비로그인 상태의 카트정보) 존재하는 경우, 해당 사용자 카트(DB)로 등록한 후, 쿠키 카트 삭제한다. + * + * @param mbInfoId + * @param request + * @param response + * @return + * @throws Exception + */ + public int mergeCart(String mbInfoId, HttpServletRequest request, HttpServletResponse response) throws Exception; + + /** + * 쿠키 카트(비로그인 상태의 카트정보)에 존재하는 자료 개수를 리턴한다. + * + * @param request + * @param response + * @param cartTypeCd + * @return + * @throws Exception + */ + public int countCartItemsFromCookie(HttpServletRequest request, HttpServletResponse response, String cartTypeCd) throws Exception; + + /** + * 사용자 카트의 자료 개수를 리턴한다. + * + * @param mbInfoId + * @param cartTypeCd + * @return + * @throws Exception + */ + public int countCartItems(String mbInfoId, String cartTypeCd) throws Exception; + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/col/service/CollectionService.java b/legacy/nlib/src/main/java/nlib/col/service/CollectionService.java new file mode 100644 index 00000000..2541bcd9 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/CollectionService.java @@ -0,0 +1,116 @@ +package nlib.col.service; + +import java.util.HashMap; +import java.util.List; + +/** + *
+ * @Class Name : CollectionService.java
+ * 
+ * @Description : 소장자료 정보를 조회하는 서비스 인터페이스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 10. 6. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 10. 6. + * @version 1.0 + * + */ +public interface CollectionService { + + /** + * 자료 상세정보를 조회한다. + * + * @param searchVO + * @return + * @throws Exception + */ + public CollectionVO getItemInfo(CollectionVO searchVO); + + /** + * 목록의 자료정보에 상세정보를 조회하여 설정한 후 리턴한다. + * + * @param list + * @return + * @throws Exception + */ + public List setDetailInfoForList(List list) throws Exception; + + + /** + * 목록의 자료정보에 상세정보를 조회하여 설정한 후 리턴한다. + * + * @param list + * @param mbInfoId + * @param defaultThumbnailUrl + * @return + * @throws Exception + */ + public List setDetailInfoForList(List list, String mbInfoId) throws Exception; + + /** + * 목록의 자료정보에 상세정보를 조회하여 설정한 후 리턴한다. + * + * @param list + * @param mbInfoId + * @param defaultThumbnailUrl + * @return + * @throws Exception + */ + public List setDetailInfoForHashList(List> list, String mbInfoId) throws Exception; + + /** + * 자료 마스터ID 목록 문자열을 받아 CollectionVO 리스트 생성하여 리턴한다. + * + * @param masterIds + * @return + */ + public List makeListOfCollectionVO(String masterIds); + + /** + * 자료 마스터ID 목록 문자열을 받아 상세내용을 조회하고, CollectionVO 리스트 생성하여 리턴한다. + * + * @param masterIds + * @return + */ + public List makeInfoListOfCollectionVO(String masterIds, String mbInfoId) throws Exception; + + /** + * 자료상세조회 및 원문보기시에 로그 + * @param colVO + */ + public void insertDataInquiryLog(CollectionVO colVO) throws Exception; + + /** + * 함께 볼만한 자료 리스트 + * @param vo + * @return + * @throws Exception + */ + public List selectSeeTogetherList(CollectionVO vo) throws Exception; + + /** + * 유사한 자료 리스트 + * @param vo + * @return + * @throws Exception + */ + public List selectSimilarList(CollectionVO vo) throws Exception; + + /** + * 문화원 코드 조회 + * + * @param vo + * @return + */ + public CollectionVO selectMngOrgInfo(String masterId) throws Exception; +} diff --git a/legacy/nlib/src/main/java/nlib/col/service/CollectionVO.java b/legacy/nlib/src/main/java/nlib/col/service/CollectionVO.java new file mode 100644 index 00000000..463eea1d --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/CollectionVO.java @@ -0,0 +1,1126 @@ +package nlib.col.service; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import nlib.cmm.service.NlibProperty; +import nlib.cmm.service.PagingVO; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : CollectionVO.java
+ * 
+ * @Description : 소장자료 관련 VO
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 23. JSYOO 최초 생성 + * @ 2021.10. 06. KKN 자료에 대한 세부 항목, 생성자 함수 추가 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 9. 28. + * @version 1.0 + * + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class CollectionVO extends PagingVO { + + //-------------------------------------------- + // 자료항목 + //-------------------------------------------- + protected String masterId; /* 마스터id */ + protected String title; /* 제목 */ + protected String rprsThumbUrl; /* 대표썸네일URL */ + protected String useYn; /* 사용여부 */ + protected String regDd; /* 등록일자 */ + protected String mngOrgNm; /* 관리처리과명 */ + protected String mngOrgCd; /* 관리처리과코드 */ + + protected String typeDivCd; /* 상위자료유형코드 */ + protected String typeDivNm; /* 상위자료유형명 (도서간행물/문서/도면 등) : API 이름이 변경됨 typeCodeNm -> typeDivNm */ + protected String dtlsTypeDivCd; /* 세부유형코드 */ + protected String dtlsTypeDivNm; /* 세부유형명 */ + + protected String subjectNmUp; /* 상위주제분야명(대) */ + protected String subjectCdUp ; /* 상위주제분야코드(대) */ + protected String subjectNm; /* 주제분야명(소) */ + protected String subjectCd; /* 주제분야코드(소) */ + + protected String orgNm; /* 생산기관명 */ + protected String creatYyyy; /* 생산년도 */ + protected String interfaceId; /* 지역N문화서비스ID */ + protected String openDivCd; /* 원문공개코드 */ + protected String openDivNm; /* 원문공개코드명 */ + protected String operReadRangeCd; /* 열람가능코드 */ + protected String operReadRangeNm; /* 열람가능코드명 */ + protected String operOutRangeCd; /* 대출가능코드 */ + protected String operOutRangeNm; /* 대출가능코드명 */ + protected String useStatus; /* 이용상태코드 */ + protected String useStatusNm; /* 이용상태코드명 */ + protected String rtnExpctDd; /* 반납예정일자 */ + protected int awaiterCnt; /* 대출대기자수 */ + protected String bookLentPsblYn; /* 현재대출신청가능여부 */ + protected String rsrvPsblYn; /* 현재대출예약가능여부 */ + protected String reqPsblYn; /* 현재열람신청가능여부 */ + protected String interestYn; /* 사용자관심여부 */ + protected String mngtNo; /* 관리번호 */ + protected String bookAuthor; /* 저자명 */ + protected String bookPublisher; /* 출판사명 */ + protected String bookPlbcTypeNm; /* 발간유형명 */ + protected String bookPlbcMda; /* 발간매채명 */ + protected String bookCallNo; /* 청구기호 */ + protected String themeCodeNm; /* 테마명 */ + protected String ageCodeNm; /* 시대 */ + protected String chronologicalCodeStartNm; /* 연대 start */ + protected String chronologicalCodeEndNm; /* 연대 end */ + protected String keyword; /* 키워드목록 */ + protected String bookIndex; /* 목차정보 */ + protected String docNo; /* (구)문서번호 */ + protected String mapTypeCd; /* 도면지도구분코드 */ + protected String mapTypeNm; /* 도면지도구분코드명 */ + protected String mapLoc; /* 도면지도위치주소 */ + protected String photoMediaCd; /* 사진필름미디어유형구분코드 */ + protected String photoMediaNm; /* 사진필름미디어매체 */ + protected String photoSizeNm; /* 사진필름미디어규격 */ + protected String photoDescription; /* 사진필름미디어설명 */ + protected String photoAdditionalDescription; /* 사진필름미디어부가설명 */ + protected String videoMediaCd; /* 녹음동영상미디어유형구분코드 */ + protected String videoMediaNm; /* 녹음동영상미디어유형구분코드명 */ + protected String videoTime; /* 녹음동영상미디어재생시간 */ + protected String videoStat; /* 녹음동영상미디어재생화질상태 */ + protected String videoDescription; /* 녹음동영상미디어설명 */ + protected String videoAdditionalDescription; /* 녹음동영상미디어부가설명 */ + protected String museTypeCd; /* 박물유형구분코드 */ + protected String museTypeNm; /* 박물유형구분코드명 */ + protected String museKindCd; /* 박물형태 */ + protected String museKindNm; /* 박물형태명 */ + protected String museMeterialCd; /* 박물재질 */ + protected String museMeterialNm; /* 박물재질명 */ + protected String assetLink; /* 자산링크 */ + protected String regId; /* 등록자ID */ + protected String modId; /* 변경자ID */ + protected String mUseYn; /* 관심여부 */ + + + //-------------------------------------------- + // 카트/관심 항목 + //-------------------------------------------- + protected int mbInterestId; /* 관심 id */ + protected String mbInfoId; /* 회원 id */ + protected String mbCartId; /* 카트ID */ + protected String cartTypeCd; /* 카트유형코드 */ + protected String cartProcDivCd; /* 카트처리구분코드 */ + + //-------------------------------------------- + // 대출/열람관련 + //-------------------------------------------- + protected String rsrvId; /* 카트관련 대출/열람 예약ID */ + protected String rsrvDd; /* 대출/열람신청예약일자 */ + protected String bookLtRvStatusCd; /* 대출상태구분코드 */ + protected String bookLtRvStatusNm; /* 대출상태구분코드명 */ + protected String rsrvExpctDd; /* 대출예약만료일자 */ + protected String rtnDd; /* 반납일자 */ + protected String rsrvDivCd; /* 대출/예약 신청구분코드 */ + + //-------------------------------------------- + // 열람관련 + //-------------------------------------------- + protected String reqId; /* 열람신청번호 */ + protected String reqDd; /* 열람신청일자 */ + protected String hopeReqPridDtmFrom; /* 방문희망시작일자 */ + protected String hopeReqPridDtmTo; /* 방문희망종료일자 */ + protected String reqStatusDivCd; /* 열람상태구분코드 */ + protected String reqStatusDivNm; /* 열람상태구분명 */ + protected String reqPsblDtmFrom; /* 방문예정시작일자 */ + protected String reqPsblDtmTo; /* 방문예정종료일자 */ + + //-------------------------------------------- + // 기타 및 처리결과 항목 + //-------------------------------------------- + protected String selItems; /* 다건선택된 카트ID 목록 ","로 구분 */ + protected String resultCode; /* 결과코드 */ + protected String resultMessage; /* 결과메시지 */ + + //--------------------------------------------- + // 상세조회 페이지 함께 볼만한 자료관련 + //--------------------------------------------- + protected String deptNm; /* 관리부서이름 */ + protected String domainHostNm; /* 관리부서 호스트주소 */ + + //--------------------------------------------- + // 자료 자체에 대한 서비스 가능 여부 (2021.11.24 추가, 2021.11.23 관계자 협의에 따라 최종 자료에 대한 서비스 가능 여부 API통해 전달받는 걸로 변경됨) + //--------------------------------------------- + protected String digitalReadYn; /* 디지털열람여부 */ + protected String onReqYn; /* 온라인열람 */ + protected String lentYn; /* 대출가능여부 */ + protected String offReqYn; /* 방문열람가능여부 */ + protected String etcYn; /* 기타 여부 */ + + + //--------------------------------------------- + // 각종 상태 제공 서비스 + //--------------------------------------------- + + /** + * 기본 공개 여부를 리턴한다. + * + * @return + */ + public boolean isPub() { + + // 사용여부 + if(StringUtil.getString(useYn, "Y").equalsIgnoreCase("N")) return false; + + // 공개여부 (공개, 부분공개 포함) + if(StringUtil.getString(openDivCd, "3").equals("3")) return false; + + return true; + } + + /** + * 방문열람 가능여부를 리턴한다. + * @return + */ + public boolean isAbleRead() { + + return "Y".equalsIgnoreCase(StringUtil.getString(getOffReqYn(), "N")); + + /* 각 서비스 가능 여부가 API에 별도 항목으로 추가됨에 따라 이하 주석 처리 2021.11.24) + + // 기본공개 + if(!isPub()) return false; + + // 열람여부 + if(StringUtil.getString(operReadRangeCd, "03").equals("03")) return false; + return true; + + */ + } + + /** + * 대출 가능여부를 리턴한다. + * @return + */ + public boolean isAbleRent() { + + return "Y".equalsIgnoreCase(StringUtil.getString(getLentYn(), "N")); + + /* 각 서비스 가능 여부가 API에 별도 항목으로 추가됨에 따라 이하 주석 처리 2021.11.24) + + // 기본공개 + if(!isPub()) return false; + + // 대출구분 + if(StringUtil.getString(operOutRangeCd, "02").equals("02")) return false; + + return true; + */ + } + + /** + * 온라인열람 가능여부를 리턴한다. + * @return + */ + public boolean isAbleOnline() { + + return "Y".equalsIgnoreCase(StringUtil.getString(getOnReqYn(), "N")); + + /* 각 서비스 가능 여부가 API에 별도 항목으로 추가됨에 따라 이하 주석 처리 2021.11.24) + // 기본공개 + if(!isPub()) return false; + + // 디지털열람여부 + if(!StringUtil.getString(digitalReadYn, "N").equalsIgnoreCase("Y")) return false; + + // 인터페이스ID 존재 + if(StringUtil.isEmpty(interfaceId)) return false; + + return true; + */ + } + + /** + * 기타 가능여부를 리턴한다. + * @return + */ + public boolean isAbleOther() { + + return "Y".equalsIgnoreCase(StringUtil.getString(getEtcYn(), "N")); + + /* 각 서비스 가능 여부가 API에 별도 항목으로 추가됨에 따라 이하 주석 처리 2021.11.24) + // 방문열람여부 + if(isAbleRead()) return false; + + // 대출여부 + if(isAbleRent()) return false; + + // 온라인여부 + if(isAbleOnline()) return false; + + return true; + */ + + } + + /** + * 현재 방문열람 가능여부를 리턴한다. + * @return + */ + public boolean isAbleReadNow() { + + // 방문열람 가능 자료 + if(!isAbleRead()) return false; + + // 이용상태코드 확인 + if(!":01:04:05:06:".contains(":" + StringUtil.getString(useStatus, "00") + ":")) return false; + + return true; + } + + /** + * 현재 대출(신청 또는 예약) 가능여부 상태명을 리턴한다. + * @return + */ + public String getAbleReadNowNm() { + if(isAbleReadNow()) return "신청가능"; + + return "신청불가"; + } + + /** + * 현재 대출(신청 또는 예약) 가능여부를 리턴한다. + * @return + */ + public boolean isAbleRentNow() { + return isAbleRentAppNow() || isAbleRentResNow(); + } + + /** + * 현재 대출(신청 또는 예약) 가능여부 상태명을 리턴한다. + * @return + */ + public String getAbleRentNowNm() { + if(isAbleRentAppNow()) return "신청가능"; + else if(isAbleRentResNow()) return "예약가능"; + + return "신청/예약불가"; + } + + /** + * 현재 대출 [신청] 가능여부를 리턴한다. + * @return + */ + public boolean isAbleRentAppNow() { + + // 대출 가능 자료 + if(!isAbleRent()) return false; + + // 이용상태코드 확인 + if(!":01:".contains(":" + StringUtil.getString(useStatus, "00") + ":")) return false; + + return true; + } + + /** + * 현재 대출 [예약] 가능여부를 리턴한다. + * @return + */ + public boolean isAbleRentResNow() { + + // 대출 가능 자료 + if(!isAbleRent()) return false; + + // 이용상태코드 확인 + if(!":02:".contains(":" + StringUtil.getString(useStatus, "00") + ":")) return false; + + return true; + } + + /** + * 현재 온라인열람 가능여부를 리턴한다. + * @return + */ + public boolean isAbleOnlineNow() { + + // 대출 가능 자료 + if(!isAbleOnline()) return false; + + // 이용상태코드 확인 + if(!":07:".contains(":" + StringUtil.getString(useStatus, "00") + ":")) return false; + + return true; + } + + //--------------------------------------------- + // 생성자 + //--------------------------------------------- + public CollectionVO() { + super(); + } + + public CollectionVO(String resultCode, String resultMessage) { + super(); + setResult(resultCode, resultMessage); + } + + public void setResult(String resultCode, String resultMessage) { + this.resultCode = resultCode; + this.resultMessage = resultMessage; + } + + public static CollectionVO createWithMasterId(String cartTypeCd, String masterId) { + CollectionVO vo = new CollectionVO(); + vo.setCartTypeCd(cartTypeCd); + vo.setMasterId(masterId); + return vo; + } + + // GET & SET + + public String getMasterId() { + return masterId; + } + public void setMasterId(String masterId) { + this.masterId = masterId; + } + public int getMbInterestId() { + return mbInterestId; + } + public void setMbInterestId(int mbInterestId) { + this.mbInterestId = mbInterestId; + } + public void setMbInterestId(String mbInterestId) { + this.mbInterestId = Integer.parseInt(mbInterestId); + } + public String getMbInfoId() { + return mbInfoId; + } + public void setMbInfoId(String mbInfoId) { + this.mbInfoId = mbInfoId; + } + public String getTitle() { + return title; + } + public void setTitle(String title) { + this.title = title; + } + public String getRprsThumbUrl() { + return StringUtil.isNotEmpty(rprsThumbUrl) ? NlibProperty.getString("thumbnail.image.url.prefix", "") + rprsThumbUrl : ""; + } + + public String getRprsThumbUrlWithDefaultSmall() { + return getRprsThumbUrlWithDefaultId("thumbnail.image.url.small"); + } + public String getRprsThumbUrlWithDefaultMiddle() { + return getRprsThumbUrlWithDefaultId("thumbnail.image.url.middle"); + } + public String getRprsThumbUrlWithDefaultBig() { + return getRprsThumbUrlWithDefaultId("thumbnail.image.url.big"); + } + public String getRprsThumbUrlWithDefaultId(String propName) { + + if(StringUtil.isEmpty(rprsThumbUrl)) return NlibProperty.getString(propName); + if(rprsThumbUrl.startsWith("http")) return rprsThumbUrl; + + return NlibProperty.getString("thumbnail.image.url.prefix", "") + rprsThumbUrl; + } + + public void setRprsThumbUrl(String rprsThumbUrl) { + + if(StringUtil.isEmpty(rprsThumbUrl) || !(rprsThumbUrl.startsWith("/") || rprsThumbUrl.startsWith("http"))) { + // 썸네일이 비어있거나, 유효하지 않은 문자로 시작되는 경우 + this.rprsThumbUrl = null; + } else { + // 그렇지 않은 경우, 입력된 썸네일로 설정 + this.rprsThumbUrl = rprsThumbUrl; + } + } + public String getUseYn() { + return useYn; + } + public void setUseYn(String useYn) { + this.useYn = useYn; + } + public String getRegDd() { + return regDd; + } + public void setRegDd(String regDd) { + this.regDd = regDd; + } + public String getMngOrgNm() { + return mngOrgNm; + } + public void setMngOrgNm(String mngOrgNm) { + this.mngOrgNm = mngOrgNm; + } + public String getMngOrgCd() { + return mngOrgCd; + } + public void setMngOrgCd(String mngOrgCd) { + this.mngOrgCd = mngOrgCd; + } + public String getTypeDivCd() { + return typeDivCd; + } + public void setTypeDivCd(String typeDivCd) { + this.typeDivCd = typeDivCd; + } + public String getTypeCodeNm() { + return typeDivNm; + } + public void setTypeCodeNm(String typeCodeNm) { + this.typeDivNm = typeCodeNm; + } + public String getSubjectNm() { + return subjectNm; + } + public void setSubjectNm(String subjectNm) { + this.subjectNm = subjectNm; + } + public String getOrgNm() { + return orgNm; + } + public void setOrgNm(String orgNm) { + this.orgNm = orgNm; + } + public String getCreatYyyy() { + return creatYyyy; + } + public void setCreatYyyy(String creatYyyy) { + this.creatYyyy = creatYyyy; + } + public String getInterfaceId() { + return interfaceId; + } + public void setInterfaceId(String interfaceId) { + this.interfaceId = interfaceId; + } + public String getOpenDivCd() { + return openDivCd; + } + public void setOpenDivCd(String openDivCd) { + this.openDivCd = openDivCd; + } + public String getOpenDivNm() { + return openDivNm; + } + public void setOpenDivNm(String openDivNm) { + this.openDivNm = openDivNm; + } + public String getOperReadRangeCd() { + return operReadRangeCd; + } + public void setOperReadRangeCd(String operReadRangeCd) { + this.operReadRangeCd = operReadRangeCd; + } + public String getOperReadRangeNm() { + /* 01:전체열람 02: 목록열람 03:열람불가 */ + if("01".equals(operReadRangeCd)) return "전체열람"; + else if("02".equals(operReadRangeCd)) return "목록열람"; + else if("03".equals(operReadRangeCd)) return "열람불가"; + + return operReadRangeNm; + } + public void setOperReadRangeNm(String operReadRangeNm) { + this.operReadRangeNm = operReadRangeNm; + } + public String getOperOutRangeCd() { + return operOutRangeCd; + } + public void setOperOutRangeCd(String operOutRangeCd) { + this.operOutRangeCd = operOutRangeCd; + } + public String getOperOutRangeNm() { + /* 01:대출가능 02: 대출불가 */ + if("01".equals(operOutRangeCd)) return "대출가능"; + else if("02".equals(operOutRangeCd)) return "대출불가"; + + return operOutRangeNm; + } + public void setOperOutRangeNm(String operOutRangeNm) { + this.operOutRangeNm = operOutRangeNm; + } + public String getUseStatus() { + return useStatus; + } + public void setUseStatus(String useStatus) { + this.useStatus = useStatus; + } + public String getUseStatusNm() { + + /* 01 : 이용가능 + 02 : 대출중 (대기자 0명) + 03 : 대출중 (대기자 1명) + 04 : 열람대기(대출가능) + 05 : 이용가능 + 06 : 열람대기(대출불가능) + 07 : 온라인열람만 + 99 : 서비스 불가 + */ + if("01".equals(useStatus)) return "이용가능"; + else if("02".equals(useStatus)) return String.format("대출중 (대기자 %s명)", awaiterCnt); + else if("03".equals(useStatus)) return String.format("대출중 (대기자 %s명)", awaiterCnt); + else if("04".equals(useStatus)) return "열람대기(대출가능)"; + else if("05".equals(useStatus)) return "이용가능"; + else if("06".equals(useStatus)) return "열람대기(대출불가능)"; + else if("07".equals(useStatus)) return "온라인열람만"; + else if("99".equals(useStatus)) return "서비스 불가"; + + return useStatusNm; // 이외인 경우, 별도 설정 처리된 문구 반환 + } + public void setUseStatusNm(String useStatusNm) { + this.useStatusNm = useStatusNm; + } + public String getRtnExpctDd() { + return rtnExpctDd; + } + public void setRtnExpctDd(String rtnExpctDd) { + this.rtnExpctDd = rtnExpctDd; + } + public int getAwaiterCnt() { + return awaiterCnt; + } + public void setAwaiterCnt(int awaiterCnt) { + this.awaiterCnt = awaiterCnt; + } + public String getBookLentPsblYn() { + return bookLentPsblYn; + } + public void setBookLentPsblYn(String bookLentPsblYn) { + this.bookLentPsblYn = bookLentPsblYn; + } + public String getRsrvPsblYn() { + return rsrvPsblYn; + } + public void setRsrvPsblYn(String rsrvPsblYn) { + this.rsrvPsblYn = rsrvPsblYn; + } + public String getReqPsblYn() { + return reqPsblYn; + } + public void setReqPsblYn(String reqPsblYn) { + this.reqPsblYn = reqPsblYn; + } + public String getInterestYn() { + return interestYn; + } + public void setInterestYn(String interestYn) { + this.interestYn = interestYn; + } + public String getDtlsTypeDivCd() { + return dtlsTypeDivCd; + } + public void setDtlsTypeDivCd(String dtlsTypeDivCd) { + this.dtlsTypeDivCd = dtlsTypeDivCd; + } + public String getDtlsTypeDivNm() { + return dtlsTypeDivNm; + } + public void setDtlsTypeDivNm(String dtlsTypeDivNm) { + this.dtlsTypeDivNm = dtlsTypeDivNm; + } + public String getMngtNo() { + return mngtNo; + } + public void setMngtNo(String mngtNo) { + this.mngtNo = mngtNo; + } + public String getBookAuthor() { + return bookAuthor; + } + public void setBookAuthor(String bookAuthor) { + this.bookAuthor = bookAuthor; + } + public String getBookPublisher() { + return bookPublisher; + } + public void setBookPublisher(String bookPublisher) { + this.bookPublisher = bookPublisher; + } + public String getBookPlbcTypeNm() { + return bookPlbcTypeNm; + } + public void setBookPlbcTypeNm(String bookPlbcTypeNm) { + this.bookPlbcTypeNm = bookPlbcTypeNm; + } + public String getBookPlbcMda() { + return bookPlbcMda; + } + public void setBookPlbcMda(String bookPlbcMda) { + this.bookPlbcMda = bookPlbcMda; + } + public String getBookCallNo() { + return bookCallNo; + } + public void setBookCallNo(String bookCallNo) { + this.bookCallNo = bookCallNo; + } + public String getThemeCodeNm() { + return themeCodeNm; + } + public void setThemeCodeNm(String themeCodeNm) { + this.themeCodeNm = themeCodeNm; + } + public String getAgeCodeNm() { + return ageCodeNm; + } + public void setAgeCodeNm(String ageCodeNm) { + this.ageCodeNm = ageCodeNm; + } + public String getChronologicalCodeStartNm() { + return chronologicalCodeStartNm; + } + public void setChronologicalCodeStartNm(String chronologicalCodeStartNm) { + this.chronologicalCodeStartNm = chronologicalCodeStartNm; + } + public String getChronologicalCodeEndNm() { + return chronologicalCodeEndNm; + } + public void setChronologicalCodeEndNm(String chronologicalCodeEndNm) { + this.chronologicalCodeEndNm = chronologicalCodeEndNm; + } + public String getKeyword() { + return keyword; + } + public void setKeyword(String keyword) { + this.keyword = keyword; + } + public String getBookIndex() { + return bookIndex; + } + public void setBookIndex(String bookIndex) { + this.bookIndex = bookIndex; + } + public String getDocNo() { + return docNo; + } + public void setDocNo(String docNo) { + this.docNo = docNo; + } + public String getMapTypeCd() { + return mapTypeCd; + } + public void setMapTypeCd(String mapTypeCd) { + this.mapTypeCd = mapTypeCd; + } + public String getMapTypeNm() { + return mapTypeNm; + } + public void setMapTypeNm(String mapTypeNm) { + this.mapTypeNm = mapTypeNm; + } + public String getMapLoc() { + return mapLoc; + } + public void setMapLoc(String mapLoc) { + this.mapLoc = mapLoc; + } + public String getPhotoMediaCd() { + return photoMediaCd; + } + public void setPhotoMediaCd(String photoMediaCd) { + this.photoMediaCd = photoMediaCd; + } + public String getPhotoMediaNm() { + return photoMediaNm; + } + public void setPhotoMediaNm(String photoMediaNm) { + this.photoMediaNm = photoMediaNm; + } + public String getPhotoSizeNm() { + return photoSizeNm; + } + public void setPhotoSizeNm(String photoSizeNm) { + this.photoSizeNm = photoSizeNm; + } + public String getPhotoDescription() { + return photoDescription; + } + public void setPhotoDescription(String photoDescription) { + this.photoDescription = photoDescription; + } + public String getPhotoAdditionalDescription() { + return photoAdditionalDescription; + } + public void setPhotoAdditionalDescription(String photoAdditionalDescription) { + this.photoAdditionalDescription = photoAdditionalDescription; + } + public String getVideoMediaCd() { + return videoMediaCd; + } + public void setVideoMediaCd(String videoMediaCd) { + this.videoMediaCd = videoMediaCd; + } + public String getVideoMediaNm() { + return videoMediaNm; + } + public void setVideoMediaNm(String videoMediaNm) { + this.videoMediaNm = videoMediaNm; + } + public String getVideoTime() { + return videoTime; + } + public void setVideoTime(String videoTime) { + this.videoTime = videoTime; + } + public String getVideoStat() { + return videoStat; + } + public void setVideoStat(String videoStat) { + this.videoStat = videoStat; + } + public String getVideoDescription() { + return videoDescription; + } + public void setVideoDescription(String videoDescription) { + this.videoDescription = videoDescription; + } + public String getVideoAdditionalDescription() { + return videoAdditionalDescription; + } + public void setVideoAdditionalDescription(String videoAdditionalDescription) { + this.videoAdditionalDescription = videoAdditionalDescription; + } + public String getMuseTypeCd() { + return museTypeCd; + } + public void setMuseTypeCd(String museTypeCd) { + this.museTypeCd = museTypeCd; + } + public String getMuseTypeNm() { + return museTypeNm; + } + public void setMuseTypeNm(String museTypeNm) { + this.museTypeNm = museTypeNm; + } + public String getMuseKindCd() { + return museKindCd; + } + public void setMuseKindCd(String museKindCd) { + this.museKindCd = museKindCd; + } + public String getMuseKindNm() { + return museKindNm; + } + public void setMuseKindNm(String museKindNm) { + this.museKindNm = museKindNm; + } + public String getMuseMeterialCd() { + return museMeterialCd; + } + public void setMuseMeterialCd(String museMeterialCd) { + this.museMeterialCd = museMeterialCd; + } + public String getMuseMeterialNm() { + return museMeterialNm; + } + public void setMuseMeterialNm(String museMeterialNm) { + this.museMeterialNm = museMeterialNm; + } + public String getAssetLink() { + return assetLink; + } + public void setAssetLink(String assetLink) { + this.assetLink = assetLink; + } + public String getResultCode() { + return resultCode; + } + public void setResultCode(String resultCode) { + this.resultCode = resultCode; + } + public String getResultMessage() { + return resultMessage; + } + public void setResultMessage(String resultMessage) { + this.resultMessage = resultMessage; + } + + public String getMbCartId() { + return mbCartId; + } + + public void setMbCartId(String mbCartId) { + this.mbCartId = mbCartId; + } + + public String getCartTypeCd() { + return cartTypeCd; + } + + public void setCartTypeCd(String cartTypeCd) { + this.cartTypeCd = cartTypeCd; + } + + public String getRsrvId() { + return rsrvId; + } + + public void setRsrvId(String rsrvId) { + this.rsrvId = rsrvId; + } + + public String getCartProcDivCd() { + return cartProcDivCd; + } + + public void setCartProcDivCd(String cartProcDivCd) { + this.cartProcDivCd = cartProcDivCd; + } + + public String getRegId() { + return regId; + } + + public void setRegId(String regId) { + this.regId = regId; + } + + public String getModId() { + return modId; + } + + public void setModId(String modId) { + this.modId = modId; + } + + public String getSelItems() { + return selItems; + } + + public void setSelItems(String selItems) { + this.selItems = selItems; + } + + public String getBookLtRvStatusCd() { + return bookLtRvStatusCd; + } + + public void setBookLtRvStatusCd(String bookLtRvStatusCd) { + this.bookLtRvStatusCd = bookLtRvStatusCd; + } + + public String getRsrvDd() { + return rsrvDd; + } + + public void setRsrvDd(String rsrvDd) { + this.rsrvDd = rsrvDd; + } + + public String getBookLtRvStatusNm() { + return bookLtRvStatusNm; + } + + public void setBookLtRvStatusNm(String bookLtRvStatusNm) { + this.bookLtRvStatusNm = bookLtRvStatusNm; + } + + public String getRsrvExpctDd() { + return rsrvExpctDd; + } + + public void setRsrvExpctDd(String rsrvExpctDd) { + this.rsrvExpctDd = rsrvExpctDd; + } + + public String getRtnDd() { + return rtnDd; + } + + public void setRtnDd(String rtnDd) { + this.rtnDd = rtnDd; + } + + public String getmUseYn() { + return getMUseYn(); + } + + public String getMUseYn() { + return StringUtil.isEmpty(mUseYn) ? "N" : mUseYn; + } + + public void setmUseYn(String mUseYn) { + setMUseYn(mUseYn); + } + + public void setMUseYn(String mUseYn) { + this.mUseYn = mUseYn; + } + + public String getHopeReqPridDtmFrom() { + return hopeReqPridDtmFrom; + } + + public void setHopeReqPridDtmFrom(String hopeReqPridDtmFrom) { + this.hopeReqPridDtmFrom = hopeReqPridDtmFrom; + } + + public String getHopeReqPridDtmTo() { + return hopeReqPridDtmTo; + } + + public void setHopeReqPridDtmTo(String hopeReqPridDtmTo) { + this.hopeReqPridDtmTo = hopeReqPridDtmTo; + } + public String getSubjectNmUp() { + return subjectNmUp; + } + + public void setSubjectNmUp(String subjectNmUp) { + this.subjectNmUp = subjectNmUp; + } + + public String getSubjectCdUp() { + return subjectCdUp; + } + + public void setSubjectCdUp(String subjectCdUp) { + this.subjectCdUp = subjectCdUp; + } + + public String getSubjectCd() { + return subjectCd; + } + + public void setSubjectCd(String subjectCd) { + this.subjectCd = subjectCd; + } + + public String getRsrvDivCd() { + return rsrvDivCd; + } + + public void setRsrvDivCd(String rsrvDivCd) { + this.rsrvDivCd = rsrvDivCd; + } + + public String getRsrvDivNm() { + + if("1".equals(rsrvDivCd)) return "대출신청"; + else if("2".equals(rsrvDivCd)) return "대출예약"; + + return null; + } + + public String getReqStatusDivCd() { + return reqStatusDivCd; + } + + public void setReqStatusDivCd(String reqStatusDivCd) { + this.reqStatusDivCd = reqStatusDivCd; + } + + public String getReqStatusDivNm() { + return reqStatusDivNm; + } + + public void setReqStatusDivNm(String reqStatusDivNm) { + this.reqStatusDivNm = reqStatusDivNm; + } + + public String getReqPsblDtmFrom() { + return reqPsblDtmFrom; + } + + public void setReqPsblDtmFrom(String reqPsblDtmFrom) { + this.reqPsblDtmFrom = reqPsblDtmFrom; + } + + public String getReqPsblDtmTo() { + return reqPsblDtmTo; + } + + public void setReqPsblDtmTo(String reqPsblDtmTo) { + this.reqPsblDtmTo = reqPsblDtmTo; + } + + public String getReqId() { + return reqId; + } + + public void setReqId(String reqId) { + this.reqId = reqId; + } + + public String getReqDd() { + return reqDd; + } + + public void setReqDd(String reqDd) { + this.reqDd = reqDd; + } + + public String getTypeDivNm() { + return typeDivNm; + } + + public void setTypeDivNm(String typeDivNm) { + this.typeDivNm = typeDivNm; + } + public String getDeptNm() { + return deptNm; + } + + public void setDeptNm(String deptNm) { + this.deptNm = deptNm; + } + + public String getDomainHostNm() { + return domainHostNm; + } + + public void setDomainHostNm(String domainHostNm) { + this.domainHostNm = domainHostNm; + } + + public String getDigitalReadYn() { + return digitalReadYn; + } + + public void setDigitalReadYn(String digitalReadYn) { + this.digitalReadYn = digitalReadYn; + } + + public String getOnReqYn() { + return onReqYn; + } + + public void setOnReqYn(String onReqYn) { + this.onReqYn = onReqYn; + } + + public String getLentYn() { + return lentYn; + } + + public void setLentYn(String lentYn) { + this.lentYn = lentYn; + } + + public String getOffReqYn() { + return offReqYn; + } + + public void setOffReqYn(String offReqYn) { + this.offReqYn = offReqYn; + } + + public String getEtcYn() { + return etcYn; + } + + public void setEtcYn(String etcYn) { + this.etcYn = etcYn; + } + + +} + diff --git a/legacy/nlib/src/main/java/nlib/col/service/DeptVO.java b/legacy/nlib/src/main/java/nlib/col/service/DeptVO.java new file mode 100644 index 00000000..4e54943b --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/DeptVO.java @@ -0,0 +1,244 @@ +package nlib.col.service; + +import nlib.cmm.service.PagingVO; + +import java.io.Serializable; + +/** + *
+ * @Class Name : DeptVO.java
+ * 
+ * @Description : 부서(문화원) VO
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 30. JSYOO 최초 생성 + + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 9. 30. + * @version 1.0 + * + */ +public class DeptVO { + private String deptSeq; /* 조직코드 */ + private String orgCd; /* 처리과코드 */ + private String deptNm; /* 조직명 */ + private String deptAbbrNm; /* 조직약칭 */ + private String hupperDeptSeq; /* 최상위조직코드 */ + private String upDeptSeq; /* 상위조직코드 */ + private String topDeptYn; /* 최상위여부 */ + private String deptLv; /* 기관레벨-차수 */ + private String sortSeq; /* 서열 */ + private String closeFlag; /* 폐지여부(0:미폐지, 1:폐지) */ + private String chngRsn; /* 변경사유 */ + private String applyStartYmd; /* 적용시작일 */ + private String applyCloseYmd; /* 적용종료일 */ + private String syncYn; /* RMS연계여부 */ + private String useYn; /* 사용여부 */ + private String regId; /* 등록자 */ + private String regDd; /* 등록일자 */ + private String modId; /* 수정자 */ + private String modDd; /* 수정일자 */ + private String regionCd; /* 지역 */ + private String remark; /* 비고 */ + private String cloudId; /* 클라우드ID */ + private String zipCode; /* 우편번호 */ + private String address; /* 주소 */ + private String addressDetail; /* 상세주소 */ + private String phoneNo; /* 전화번호 */ + private String faxNo; /* 팩스번호 */ + private String latitude; /* 위도 */ + private String longitude; /* 경도 */ + private String domainHostNm; /* 도메인호스트명 */ + + public String getDeptSeq() { + return deptSeq; + } + public void setDeptSeq(String deptSeq) { + this.deptSeq = deptSeq; + } + public String getOrgCd() { + return orgCd; + } + public void setOrgCd(String orgCd) { + this.orgCd = orgCd; + } + public String getDeptNm() { + return deptNm; + } + public void setDeptNm(String deptNm) { + this.deptNm = deptNm; + } + public String getDeptAbbrNm() { + return deptAbbrNm; + } + public void setDeptAbbrNm(String deptAbbrNm) { + this.deptAbbrNm = deptAbbrNm; + } + public String getHupperDeptSeq() { + return hupperDeptSeq; + } + public void setHupperDeptSeq(String hupperDeptSeq) { + this.hupperDeptSeq = hupperDeptSeq; + } + public String getUpDeptSeq() { + return upDeptSeq; + } + public void setUpDeptSeq(String upDeptSeq) { + this.upDeptSeq = upDeptSeq; + } + public String getTopDeptYn() { + return topDeptYn; + } + public void setTopDeptYn(String topDeptYn) { + this.topDeptYn = topDeptYn; + } + public String getDeptLv() { + return deptLv; + } + public void setDeptLv(String deptLv) { + this.deptLv = deptLv; + } + public String getSortSeq() { + return sortSeq; + } + public void setSortSeq(String sortSeq) { + this.sortSeq = sortSeq; + } + public String getCloseFlag() { + return closeFlag; + } + public void setCloseFlag(String closeFlag) { + this.closeFlag = closeFlag; + } + public String getChngRsn() { + return chngRsn; + } + public void setChngRsn(String chngRsn) { + this.chngRsn = chngRsn; + } + public String getApplyStartYmd() { + return applyStartYmd; + } + public void setApplyStartYmd(String applyStartYmd) { + this.applyStartYmd = applyStartYmd; + } + public String getApplyCloseYmd() { + return applyCloseYmd; + } + public void setApplyCloseYmd(String applyCloseYmd) { + this.applyCloseYmd = applyCloseYmd; + } + public String getSyncYn() { + return syncYn; + } + public void setSyncYn(String syncYn) { + this.syncYn = syncYn; + } + public String getUseYn() { + return useYn; + } + public void setUseYn(String useYn) { + this.useYn = useYn; + } + public String getRegId() { + return regId; + } + public void setRegId(String regId) { + this.regId = regId; + } + public String getRegDd() { + return regDd; + } + public void setRegDd(String regDd) { + this.regDd = regDd; + } + public String getModId() { + return modId; + } + public void setModId(String modId) { + this.modId = modId; + } + public String getModDd() { + return modDd; + } + public void setModDd(String modDd) { + this.modDd = modDd; + } + public String getRegionCd() { + return regionCd; + } + public void setRegionCd(String regionCd) { + this.regionCd = regionCd; + } + public String getRemark() { + return remark; + } + public void setRemark(String remark) { + this.remark = remark; + } + public String getCloudId() { + return cloudId; + } + public void setCloudId(String cloudId) { + this.cloudId = cloudId; + } + public String getZipCode() { + return zipCode; + } + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } + public String getAddress() { + return address; + } + public void setAddress(String address) { + this.address = address; + } + public String getAddressDetail() { + return addressDetail; + } + public void setAddressDetail(String addressDetail) { + this.addressDetail = addressDetail; + } + public String getPhoneNo() { + return phoneNo; + } + public void setPhoneNo(String phoneNo) { + this.phoneNo = phoneNo; + } + public String getFaxNo() { + return faxNo; + } + public void setFaxNo(String faxNo) { + this.faxNo = faxNo; + } + public String getLatitude() { + return latitude; + } + public void setLatitude(String latitude) { + this.latitude = latitude; + } + public String getLongitude() { + return longitude; + } + public void setLongitude(String longitude) { + this.longitude = longitude; + } + public String getDomainHostNm() { + return domainHostNm; + } + public void setDomainHostNm(String domainHostNm) { + this.domainHostNm = domainHostNm; + } + + +} diff --git a/legacy/nlib/src/main/java/nlib/col/service/InterestService.java b/legacy/nlib/src/main/java/nlib/col/service/InterestService.java new file mode 100644 index 00000000..0118841b --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/InterestService.java @@ -0,0 +1,22 @@ +package nlib.col.service; + +import java.util.List; + +import nlib.restful.DataApiReqVO; +import nlib.restful.DataApiResVO; + +public interface InterestService +{ + public List listInterests(CollectionVO vo); + + public int countListInterests(CollectionVO vo); + + public void deleteInterests(List masterIdList, String mbInfoId); + + public void insertInterest(CollectionVO vo); + + public int countInterest(CollectionVO vo); + + public List selectOrgList(CollectionVO vo); + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/col/service/ReadService.java b/legacy/nlib/src/main/java/nlib/col/service/ReadService.java new file mode 100644 index 00000000..a1a523e1 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/ReadService.java @@ -0,0 +1,78 @@ +package nlib.col.service; + +import java.util.HashMap; +import java.util.List; + +import nlib.restful.DataApiResVO; + +/** + *
+ * @Class Name : ReadService.java
+ * 
+ * @Description : 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 10. 27. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 10. 27. + * @version 1.0 + * + */ +public interface ReadService { + + /** + * 열람신청희망 가능 일자 목록을 조회한다. + * + * @param mbInfoId + * @return + */ + public List> listDates(); + + + /** + * 열람을 신청한다. + * + * @param list + * @param mbInfoId + * @param mngOrgCd + * @return + */ + public List insertReadItems(List list, String mbInfoId, CollectionVO readVO, boolean fromCart) throws Exception; + + + /** + * 사용자의 열람건이 존재하는 문화원 정보 목록을 조회한다. + * + * @param mbInfoId + * @return + */ + public List> listReadMngOrg(String mbInfoId); + + /** + * 열람 목록 조회한다. + * + * @param searchVO + * @return + */ + public DataApiResVO listReadItems(CollectionVO searchVO); + + + /** + * 열람신청을 취소한다. + * + * @param searchVO + * @return + */ + public DataApiResVO cancelReadItem(CollectionVO searchVO); + + +} diff --git a/legacy/nlib/src/main/java/nlib/col/service/RentService.java b/legacy/nlib/src/main/java/nlib/col/service/RentService.java new file mode 100644 index 00000000..1d98ea37 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/RentService.java @@ -0,0 +1,78 @@ + +package nlib.col.service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import nlib.restful.DataApiResVO; + +/** + *
+ * @Class Name : RentService.java
+ * 
+ * @Description : 대출 관련 서비스 인터페이스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021-07-01 KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021-07-01 + * @version 1.0 + * + */ +public interface RentService +{ + + /** + * 사용자의 대출건이 존재하는 문화원 정보 목록을 조회한다. + * + * @param mbInfoId + * @return + */ + public List> listRentMngOrg(String mbInfoId); + + /** + * 대출 목록 조회한다. + * + * @param searchVO + * @return + */ + public DataApiResVO listRentItems(CollectionVO searchVO); + + + /** + * 대출(예약)신청을 취소한다. + * + * @param searchVO + * @return + */ + public DataApiResVO cancelRentItem(CollectionVO searchVO); + + /** + * 대출을 신청한다. + * + * @param list + * @param mbInfoId + * @param mngOrgCd + * @return + */ + public List insertRentItems(List list, String mbInfoId, String mngOrgCd, boolean fromCart) throws Exception; + + /** + * 사용자의 대출현황을 조회한다. + * + * @param mbInfoId + * @return + */ + public Map getRentStats(String mbInfoId); + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/col/service/RisService.java b/legacy/nlib/src/main/java/nlib/col/service/RisService.java new file mode 100644 index 00000000..9dba70cd --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/RisService.java @@ -0,0 +1,42 @@ + +package nlib.col.service; + +import java.util.List; +/** + *
+ * @Class Name : RisService.java
+ * 
+ * @Description : RIS 관련 서비스 인터페이스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021-07-01 JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021-07-01 + * @version 1.0 + * + */ +public interface RisService +{ + /** + * RIS파일 다운로드 데이터를 조회한다. + * @param vo + * @return + */ + public RisVO selectRisInfo(RisVO vo); + + /** + * 문화원 목록 조회(검색 필터용) + * @return + */ + public List selectOrgList(); + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/col/service/RisVO.java b/legacy/nlib/src/main/java/nlib/col/service/RisVO.java new file mode 100644 index 00000000..de440d9c --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/RisVO.java @@ -0,0 +1,152 @@ +package nlib.col.service; + +import java.io.Serializable; + +/** + *
+ * @Class Name : RisVO.java
+ * 
+ * @Description : Ris 통신규약 항목 VO
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 23. JSYOO 최초 생성 + + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 9. 23. + * @version 1.0 + * + */ +public class RisVO implements Serializable { + + /* 기존 지역 n 문화 사이트 RIS 항목 */ + private String typeDivCd; /* 참조유형 TY */ + private String title; /* 제목 TI */ + private String subTitle; /* 부제목 T2 */ + private String creatYyyy; /* 생산일자 (YYYY) PY */ + private String keyword; /* 키워드 (ex: 수원사랑) KW */ + private String UR; /* URL */ + + /*private String AB; 요약 + private String DA; 날짜 + private String LA; 언어 (ex: Korean) */ + + /* RIS 추가 항목 */ + private String masterId; /* 자료번호 ID */ + private String M3; /* 주제분야명 */ + private String rprsThumbUrl; /* 썸네일이미지 URL L4 */ + private String stakrmMngNo; /* 관리번호 M1 */ + private String producer; /* 생산자(저자) A1 */ + private String orgNm; /* 생산기관명 PP */ + + public String getTypeDivCd() { + return typeDivCd; + } + public String getTy() { + return typeDivCd; + } + public void setTypeDivCd(String typeDivCd) { + this.typeDivCd = typeDivCd; + } + public String getTitle() { + return title; + } + public String getTt() { + return title; + } + public void setTitle(String title) { + this.title = title; + } + public String getSubTitle() { + return subTitle; + } + public String getT2() { + return subTitle; + } + public void setSubTitle(String subTitle) { + this.subTitle = subTitle; + } + public String getCreatYyyy() { + return creatYyyy; + } + public String getPy() { + return creatYyyy; + } + public void setCreatYyyy(String creatYyyy) { + this.creatYyyy = creatYyyy; + } + public String getKeyword() { + return keyword; + } + public String getKw() { + return keyword; + } + public void setKeyword(String keyword) { + this.keyword = keyword; + } + public String getUR() { + return UR; + } + public void setUR(String uR) { + UR = uR; + } + public String getMasterId() { + return masterId; + } + public String getId() { + return masterId; + } + public void setMasterId(String masterId) { + this.masterId = masterId; + } + public String getM3() { + return M3; + } + public void setM3(String m3) { + M3 = m3; + } + public String getRprsThumbUrl() { + return rprsThumbUrl; + } + public String getL4() { + return rprsThumbUrl; + } + public void setRprsThumbUrl(String rprsThumbUrl) { + this.rprsThumbUrl = rprsThumbUrl; + } + public String getStakrmMngNo() { + return stakrmMngNo; + } + public String getM1() { + return stakrmMngNo; + } + public void setStakrmMngNo(String stakrmMngNo) { + this.stakrmMngNo = stakrmMngNo; + } + public String getProducer() { + return producer; + } + public String getA1() { + return producer; + } + public void setProducer(String producer) { + this.producer = producer; + } + public String getOrgNm() { + return orgNm; + } + public String getPp() { + return orgNm; + } + public void setOrgNm(String orgNm) { + this.orgNm = orgNm; + } +} diff --git a/legacy/nlib/src/main/java/nlib/col/service/impl/CartDAO.java b/legacy/nlib/src/main/java/nlib/col/service/impl/CartDAO.java new file mode 100644 index 00000000..4ce03e85 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/impl/CartDAO.java @@ -0,0 +1,51 @@ +package nlib.col.service.impl; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import egovframework.rte.psl.dataaccess.mapper.Mapper; +import nlib.col.service.CollectionVO; + +/** + *
+ * @Class Name : CartDAO.java
+ * 
+ * @Description : 카트 DAO 인터페이스  
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021-10-01 KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021-10-01 + * @version 1.0 + * + */ +@Mapper("cartDAO") +public interface CartDAO { + + public List listCartItems(@Param("mbInfoId") String mbInfoId, @Param("cartTypeCd") String cartTypeCd); + + public int changeCartDiv(CollectionVO cartVO); + + public int countCartItem(CollectionVO cartVO); + + public int insertCartItem(CollectionVO cartVO); + + public int deleteCartItems(CollectionVO cartVO); + + public int changeCartType(CollectionVO cartVO); + + public int countCartItems(@Param("mbInfoId") String mbInfoId, @Param("cartTypeCd") String cartTypeCd); + + public int changeCartProcDivCd(CollectionVO cartVO); + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/col/service/impl/CartServiceImpl.java b/legacy/nlib/src/main/java/nlib/col/service/impl/CartServiceImpl.java new file mode 100644 index 00000000..a39cb5c4 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/impl/CartServiceImpl.java @@ -0,0 +1,601 @@ +package nlib.col.service.impl; + +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.Resource; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import nlib.cmm.service.NlibProperty; +import nlib.col.service.CartCookieVO; +import nlib.col.service.CartService; +import nlib.col.service.CollectionService; +import nlib.col.service.CollectionVO; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : CartServiceImpl.java
+ * 
+ * @Description : 카트관련 기능 서비스 구현 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 10. 5. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 10. 5. + * @version 1.0 + * + */ +@Service("cartService") +public class CartServiceImpl implements CartService +{ + private static final Logger log = LoggerFactory.getLogger(CartServiceImpl.class); + + // 비로그인회원의 카트정보 쿠키명 + public static final String CART_COOKIE_NAME = NlibProperty.getString("cart.cookie.name"); + + + @Resource(name="cartDAO") + private CartDAO cartDAO; + + @Resource(name = "collectionService") + private CollectionService collectionService; + + /** + * (로그인자용) 로그인한 사용자의 카트 목록을 조회한다. + * + * @param mbInfoId + * @param cartDivCd + * @return + * @throws Exception + */ + public List listCartItems(String mbInfoId, String cartTypeCd) throws Exception { + return cartDAO.listCartItems(mbInfoId, cartTypeCd); + } + + /** + * (비로그인자용) 쿠키에서 카트 목록을 조회한다. + * + * @param request + * @param cartTypeCd + * @return + * @throws Exception + */ + public List listCartItemsFromCookie(HttpServletRequest request, HttpServletResponse response, String cartTypeCd) throws Exception { + + if(StringUtil.isEmpty(cartTypeCd)) return null; + List list = new ArrayList(); + + String targetCookieName = CART_COOKIE_NAME + cartTypeCd; + + // _NLIB_COOKIE1=:masterId:masterId: + String cartStr = getCookie(request, targetCookieName); + if(StringUtil.isEmpty(cartStr)) return null; + + String[] cartItemsStr = cartStr.split(":"); + for(String itemStr : cartItemsStr) { + if(StringUtil.isEmpty(itemStr)) continue; + CollectionVO vo = CollectionVO.createWithMasterId(targetCookieName.substring(targetCookieName.length()-2), itemStr); + vo.setMbCartId(vo.getMasterId()); // 비회원 쿠키 카트의 경우, 카트ID를 자료ID로 대체한다. + if(vo != null) list.add(vo); + } + + if(list.size() < 1) return null; + + return list; + } + + /** + * (로그인자용) 카트 영역 구분코드를 변경한다. (대출 <-> 방문열람) + * + * @param mbInfoId + * @param targetCartItems + * @return + * @throws Exception + */ + public String changeCartType(CollectionVO cartVO) throws Exception { + if(cartVO == null || StringUtil.isEmpty(cartVO.getMbInfoId())) return "회원 정보가 없습니다."; + if(StringUtil.isEmpty(cartVO.getSelItems())) return "변경할 대상 정보가 없습니다."; + + String checkResult = checkValidCartItems(cartVO.getCartTypeCd(), cartVO.getSelItems()); + if(checkResult != null) return checkResult; + + updateSelItemsForDB(cartVO); + int resultCnt = cartDAO.changeCartType(cartVO); + + if(resultCnt > 0) return null; + + return "변경 처리에 실패하였습니다. 관리자에게 문의하여 주시기 바랍니다."; + } + + /** + * (비로그인자용) 카트 영역 구분코드를 변경한다. (대출 <-> 방문열람) + * + * @param request + * @param targetCartItems + * @return + * @throws Exception + */ + public String changeCartTypeToCookie(HttpServletRequest request, HttpServletResponse response, CollectionVO cartVO) throws Exception { + + if(cartVO == null) return "요청 정보가 없습니다."; + if(StringUtil.isEmpty(cartVO.getSelItems())) return "변경할 대상 정보가 없습니다."; + + String checkResult = checkValidCartItems(cartVO.getCartTypeCd(), cartVO.getSelItems()); + if(checkResult != null) return checkResult; + + int totCnt = 0; + int sucCnt = 0; + int errCnt = 0; + + String addCartTypeCd = null; + String delCartTypeCd = null; + + if("1".equals(cartVO.getCartTypeCd())) { + addCartTypeCd = "1"; + delCartTypeCd = "2"; + } else if("2".equals(cartVO.getCartTypeCd())) { + addCartTypeCd = "2"; + delCartTypeCd = "1"; + } else { + return "카트 구분값 정보가 정확하지 않습니다."; + } + + String[] masterIds = cartVO.getSelItems().split(","); + String resultMsgAdd = null; + String resultMsgDel = null; + + // 쿠키 카트 정보 가져오기 + CartCookieVO cartCookie = getCartCookieInfo(request); + + for(int i=0; i " + delCartTypeCd + "카트 " + masterIds[i] + " : 삭제오류 => " + resultMsgDel); + } else { + errCnt++; + log.error("changeCartTypeFromCookie adding > " + addCartTypeCd + "카트 " + masterIds[i] + " : 추가 오류 => " + resultMsgAdd); + } + + } + + if(sucCnt > 0) { + String result = setCookieCart(response, cartCookie); + if(result == null) { + if(totCnt == sucCnt) return null; + else return String.format("총 %d건의 자료 중 %d건에 대한 변경 처리가 정상적으로 처리되었습니다.", totCnt, sucCnt); + } else { + return result; + } + } + + return StringUtil.getString(resultMsgAdd, "") + StringUtil.getString(resultMsgDel, ""); + } + + /** + * (로그인자용) 카트에 추가한다. + * + * @param cartVO + * @return + * @throws Exception + */ + public String insertCartItem(CollectionVO cartVO) { + + cartVO = checkValidCartItem(cartVO); + + if(cartVO.getResultCode().charAt(0) != 'S') return cartVO.getResultMessage(); + + //----------------------------------------------- + // 등록 처리 + //----------------------------------------------- + int resultCnt = cartDAO.insertCartItem(cartVO); + + if(resultCnt > 0) return null; + + return "등록 처리에 실패하였습니다. 관리자에게 문의하여 주시기 바랍니다."; + } + + /** + * (비로그인자용) 카트에 추가한다. + * + * @param cartVO + * @return + * @throws Exception + */ + public String insertCartItemToCookie(HttpServletRequest request, HttpServletResponse response, CollectionVO cartVO) throws Exception { + + cartVO = checkValidCartItem(cartVO); + + if(cartVO.getResultCode().charAt(0) != 'S') return cartVO.getResultMessage(); + + + //----------------------------------------------- + // 등록 처리 + //----------------------------------------------- + + // 쿠키 카트 정보 가져오기 + CartCookieVO cartCookie = getCartCookieInfo(request); + String result = cartCookie.addCartItem(cartVO.getCartTypeCd(), cartVO.getMasterId()); + + if(result != null) return result; + + return setCookieCart(response, cartCookie); + } + + /** + * (비로그인자용) 쿠키에서 카트 정보를 조회하여 CartCookieVO 생성하여 리턴한다. + * + * @param request + * @return + */ + public CartCookieVO getCartCookieInfo(HttpServletRequest request) { + CartCookieVO cartCookieInfo = new CartCookieVO(); + cartCookieInfo.setRentValues(getCookie(request, CART_COOKIE_NAME + "1")); + cartCookieInfo.setReadValues(getCookie(request, CART_COOKIE_NAME + "2")); + + return cartCookieInfo; + } + + /** + * (비로그인자용) 쿠키 카트에 자료 항목을 추가한다. + * + * @param request + * @param response + * @param cartTypeCd + * @param masterId + * @return + */ + public String setCookieCart(HttpServletResponse response, CartCookieVO cartCookie) { + + if(response == null) return "쿠키를 저장할 Response 객체 정보가 없습니다."; + if(cartCookie == null) return "쿠키에 저장할 카트정보가 없습니다."; + + setCookie(response, CART_COOKIE_NAME + "1", cartCookie.getRentValues()); + setCookie(response, CART_COOKIE_NAME + "2", cartCookie.getReadValues()); + + return null; + } + + /** + * (비로그인자용) 쿠키값을 설정한다. + * + * @param response + * @param name + * @param value + */ + public void setCookie(HttpServletResponse response, String name, String value) { + Cookie cookie = new Cookie(name, value); + cookie.setSecure(true); + cookie.setDomain(NlibProperty.getString("cart.cookie.domain")); + cookie.setPath(NlibProperty.getString("cart.cookie.path")); + response.addCookie(cookie); + } + + /** + * (비로그인자용) 쿠키값을 가져온다. + * + * @param request + * @param cookieName + * @return + */ + public String getCookie(HttpServletRequest request, String cookieName) { + Cookie[] cookies = request.getCookies(); + + if(cookies == null || cookies.length < 1) return null; + if(StringUtil.isEmpty(cookieName)) return null; + + for(Cookie cookie : cookies) { + if(cookieName.equalsIgnoreCase(cookie.getName())) { + return cookie.getValue(); + } + } + + return null; + } + + + /** + * 해당 자료가 대출/열람 카트 유형에 추가될 수 있는지 검증한다. + * + * @param String : null 정상 + * @return + * @throws Exception + */ + public String checkValidCartItems(String cartTypeCd, String selItems) throws Exception { + + if(StringUtil.isEmpty(cartTypeCd)) return "카트 유형 정보가 존재하지 않습니다."; + if(StringUtil.isEmpty(selItems)) return "대상 자료 정보가 존재하지 않습니다."; + + String masterIds[] = selItems.split(","); + for(int i=0; i 0) { + cartVO.setResult("FCART01", "이미 카트에 등록된 자료입니다."); + return cartVO; + } + + //----------------------------------------------- + // 해당 카트 구분값으로 등록가능한지 여부 체크 + //----------------------------------------------- + CollectionVO searchColVO = new CollectionVO(); + searchColVO.setMasterId(cartVO.getMasterId()); + searchColVO.setMngOrgCd(cartVO.getMngOrgCd()); + searchColVO.setTypeDivCd(cartVO.getTypeDivCd()); + searchColVO.setMbInfoId(cartVO.getMbInfoId()); + CollectionVO collectionVO = collectionService.getItemInfo(searchColVO); + + // 자료 상세 조회 성공한 경우 + if(collectionVO.getResultCode().startsWith("S")) { + + cartVO.setTitle(collectionVO.getTitle()); + + // 대출인 경우 + if("1".equals(cartVO.getCartTypeCd())) { + + // 대출불가인 경우 + if("02".equals(collectionVO.getOperOutRangeCd())) { // 대출가능여부 확인 : 02 대출불가 + + // 열람 가능인 경우 열람 처리 + if(!"03".equals(collectionVO.getOperReadRangeCd())) { + cartVO.setCartTypeCd("2"); // 대출가능하지 않으나 열람 가능한 경우, 열람으로 강제 변경 + } else { + cartVO.setResult("FCART02", "대출 및 열람이 불가한 자료입니다."); + return cartVO; + } + } + } + // 열람인 경우 + else if("2".equals(cartVO.getCartTypeCd())) { + + // 열람불가인 경우 + if("03".equals(collectionVO.getOperReadRangeCd())) { // 열람가능여부 확인 : 03 열람불가 + + // 대출가능한 경우, 대출로 처리 + if(!"02".equals(collectionVO.getOperOutRangeCd())) { + cartVO.setCartTypeCd("1"); // 대출가능한 경우, 대출로 강제 변경 + } else { + cartVO.setResult("FCART03", "열람 및 대출이 불가한 자료입니다."); + return cartVO; + } + } + + } + // 카드유형구분이 없는 경우, 대출->열람 우선순위서 설정 + else { + if(!"02".equals(collectionVO.getOperOutRangeCd())) { // 대출가능여부 확인 : 02 대출불가 + cartVO.setCartTypeCd("1"); // 대출가능한 경우, 대출로 설정 + } else if(!"03".equals(collectionVO.getOperReadRangeCd())) { // 열람가능여부 확인 : 03 열람불가 + cartVO.setCartTypeCd("2"); // 열람가능한 경우, 열람으로 설정 + } else { + cartVO.setResult("FCART04", "대출 및 열람이 불가한 자료입니다."); + return cartVO; + } + } + } + // 자료 상세 조회 실패한 경우, 처리결과 메시지를 리턴한다. + else { + cartVO.setResult("FCART05", collectionVO.getResultMessage()); + return cartVO; + } + + cartVO.setResult("S", null); + return cartVO; + + } + + /** + * (로그인자용) 카트에서 선택된 자료들을 삭제한다. + * + * @param targetCartItems + * @return + * @throws Exception + */ + public String deleteCartItems(CollectionVO cartVO) throws Exception { + if(cartVO == null || StringUtil.isEmpty(cartVO.getMbInfoId())) return "회원 정보가 없습니다."; + + String selItems = cartVO.getSelItems(); + if(StringUtil.isEmpty(selItems)) return "삭제할 자료 정보가 없습니다."; + + updateSelItemsForDB(cartVO); + int resultCnt = cartDAO.deleteCartItems(cartVO); + + if(resultCnt > 0) return null; + return "변경 처리에 실패하였습니다. 관리자에게 문의하여 주시기 바랍니다."; + } + + /** + * (비로그인자용) 카트에서 선택된 자료들을 삭제한다. + * + * @param targetCartItems + * @return + * @throws Exception + */ + public String deleteCartItemsFromCookie(HttpServletRequest request, HttpServletResponse response, CollectionVO cartVO) throws Exception { + + if(cartVO == null) return "요청 정보가 없습니다."; + if(StringUtil.isEmpty(cartVO.getSelItems())) return "변경할 대상 정보가 없습니다."; + + int totCnt = 0; + int sucCnt = 0; + int errCnt = 0; + + String delCartTypeCd = cartVO.getCartTypeCd(); + + if(!"1".equals(delCartTypeCd) && !"2".equals(delCartTypeCd)) { + return "카트 구분값 정보가 정확하지 않습니다."; + } + + // 쿠키 카트 정보 가져오기 + CartCookieVO cartCookie = getCartCookieInfo(request); + + String[] masterIds = cartVO.getSelItems().split(","); + String resultMsgDel = null; + for(int i=0; i " + delCartTypeCd + "카트 " + masterIds[i] + " : 삭제 오류 => " + resultMsgDel); + } + } + + if(sucCnt > 0) { + String result = setCookieCart(response, cartCookie); + if(result == null) { + if(totCnt == sucCnt) return null; + else return String.format("총 %d건의 자료 중 %d건에 대한 삭제가 정상적으로 처리되었습니다.", totCnt, sucCnt); + } else { + return result; + } + } + + return StringUtil.getString(resultMsgDel, ""); + } + + public void updateSelItemsForDB(CollectionVO cartVO) { + + if(cartVO == null || StringUtil.isEmpty(cartVO.getMbInfoId())) return; + + String selItems = cartVO.getSelItems(); + + if(!selItems.startsWith("'")) { + String[] items = selItems.split(","); + String newSelItems = ""; + for(String item : items) { + + if(StringUtil.isEmpty(item)) continue; + + if(newSelItems.length() > 0) newSelItems += ","; + + newSelItems += "'" + item + "'"; + } + cartVO.setSelItems(newSelItems); + } + + log.debug("updateSelItemsForDB > " + cartVO.getSelItems()); + } + + /** + * 쿠키 카트(비로그인 상태의 카트정보) 존재하는 경우, 해당 사용자 카트(DB)로 등록한 후, 쿠키 카트 삭제한다. + * + * @param request + * @param response + * @return + * @throws Exception + */ + public int mergeCart(String mbInfoId, HttpServletRequest request, HttpServletResponse response) throws Exception { + + // 대출 카트 + String cartTypeCds[] = {"1", "2"}; + int mergeCnt = 0; + + for(String cartTypeCd : cartTypeCds) { + List list = listCartItemsFromCookie(request, response, cartTypeCd); + if(list == null || list.size() < 1) continue; + + for(CollectionVO item : list) { + item.setCartTypeCd(cartTypeCd); + item.setMbInfoId(mbInfoId); + item.setRegId(mbInfoId); + if(insertCartItem(item) != null) continue; + mergeCnt++; + } + } + + // 쿠키 카트 정보 초기화 + setCookieCart(response, new CartCookieVO()); + + return mergeCnt; + } + + + /** + * 쿠키 카트(비로그인 상태의 카트정보)에 존재하는 자료 개수를 리턴한다. + * + * @param request + * @param response + * @param cartTypeCd + * @return + * @throws Exception + */ + public int countCartItemsFromCookie(HttpServletRequest request, HttpServletResponse response, String cartTypeCd) throws Exception { + + if(StringUtil.isEmpty(cartTypeCd)) return 0; + + String targetCookieName = CART_COOKIE_NAME + cartTypeCd; + + String cartStr = getCookie(request, targetCookieName); + if(StringUtil.isEmpty(cartStr)) return 0; + + String[] cartItemsStr = cartStr.split(":"); + int retCnt = 0; + for(String itemStr : cartItemsStr) { + if(StringUtil.isEmpty(itemStr)) continue; + retCnt++; + } + + return retCnt; + } + + + /** + * 사용자 카트의 자료 개수를 리턴한다. + * + * @param mbInfoId + * @param cartTypeCd + * @return + * @throws Exception + */ + public int countCartItems(String mbInfoId, String cartTypeCd) throws Exception { + return cartDAO.countCartItems(mbInfoId, cartTypeCd); + } + +} diff --git a/legacy/nlib/src/main/java/nlib/col/service/impl/CollectionDAO.java b/legacy/nlib/src/main/java/nlib/col/service/impl/CollectionDAO.java new file mode 100644 index 00000000..dc80f715 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/impl/CollectionDAO.java @@ -0,0 +1,40 @@ +package nlib.col.service.impl; + +import java.util.List; + +import egovframework.rte.psl.dataaccess.mapper.Mapper; +import nlib.col.service.CollectionVO; + +/** + *
+ * @Class Name : CollectionDAO.java
+ * 
+ * @Description : 소장자료관 자료정보 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021-07-01 KNKIM 최초 생성 + * @ 2021-10-01 JSYOO 문화원목록, RIS 데이터조회 추가 + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021-07-01 + * @version 1.0 + * + */ +@Mapper("collectionDAO") +public interface CollectionDAO { + + public CollectionVO selectMngOrgInfo(String masterId) throws Exception; + + public void insertDataInquiryLog(CollectionVO vo) throws Exception; + + public List selectSeeTogetherList(CollectionVO vo) throws Exception; + + public List selectSimilarList(CollectionVO vo) throws Exception; +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/col/service/impl/CollectionServiceImpl.java b/legacy/nlib/src/main/java/nlib/col/service/impl/CollectionServiceImpl.java new file mode 100644 index 00000000..6bfe0a95 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/impl/CollectionServiceImpl.java @@ -0,0 +1,323 @@ +package nlib.col.service.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Service; + +import nlib.col.service.CollectionService; +import nlib.col.service.CollectionVO; +import nlib.restful.DataApi; +import nlib.restful.DataApiReqVO; +import nlib.restful.DataApiResVO; +import nlib.restful.XmlConverter; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : CollectionServiceImpl.java
+ * 
+ * @Description : 소장자료 정보를 조회하는 서비스
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 10. 6. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 10. 6. + * @version 1.0 + * + */ +@Service("collectionService") +public class CollectionServiceImpl implements CollectionService { + + private static final Logger log = LoggerFactory.getLogger(CollectionServiceImpl.class); + + /** RESTFul API 송수신 모듈 */ + @Resource(name = "dataApi") + private DataApi dataApi; + + @Resource(name="collectionDAO") + private CollectionDAO collectionDAO; + + + /** + * 자료 상세정보를 조회한다. + * + * @param searchVO + * @return + * @throws Exception + */ + public CollectionVO getItemInfo(CollectionVO searchVO) { + + String message = null; + + // 입력값 확인 + String masterId = searchVO.getMasterId(); + String mbInfoId = searchVO.getMbInfoId(); + + if(StringUtil.isEmpty(masterId)) { + message = "[필수값 미입력] 자료 ID 정보가 입력되지 않았습니다."; + return new CollectionVO("E102", message); + } + + // 변수 설정 + DataApiReqVO reqVO = new DataApiReqVO("/uac/service/nlib/col/getItemInfo", HttpMethod.GET); + reqVO.putInfoItem("masterId", masterId); + reqVO.setMbInfoId(mbInfoId); // 통신 시, 암호화되어 송수신됨 + + // API 호출 + DataApiResVO resVO = dataApi.request(reqVO); + + // 결과값 전달 + CollectionVO retVO = (CollectionVO)XmlConverter.convertMapToObject(resVO.getInfo(), CollectionVO.class); + if(retVO == null) { + log.error("getItemInfo > 조회된 자료 정보가 없습니다."); + return null; + } + + retVO.setResultCode(resVO.getResultCode()); + retVO.setResultMessage(resVO.getResultMessage()); + + return retVO; + } + + /** + * 목록의 자료정보에 상세정보를 조회하여 설정한 후 리턴한다. + * + * @param list + * @return + * @throws Exception + */ + public List setDetailInfoForList(List list) throws Exception { + return setDetailInfoForList(list, null); + } + + /** + * 목록의 자료정보에 상세정보를 조회하여 설정한 후 리턴한다. + * + * @param list + * @param mbInfoId + * @param defaultThumbnailUrl + * @return + * @throws Exception + */ + public List setDetailInfoForList(List list, String mbInfoId) throws Exception { + + if(list == null || list.size() < 1) return list; + + int cnt = list.size(); + HashMap collectionMap = new HashMap(); + + // 문화원별 API 요청 처리 + String jsonMasterId = ""; + for(int i=0; i 0) jsonMasterId += ","; + jsonMasterId += "{\"masterId\":\"" + vo.getMasterId() + "\"}"; + } + if(StringUtil.isEmpty(jsonMasterId)) return list; + jsonMasterId = "[" + jsonMasterId + "]"; + + // API 호출 + DataApiReqVO reqVO = new DataApiReqVO("/uac/service/nlib/col/listItemInfo", HttpMethod.GET); + reqVO.setMbInfoId(mbInfoId); // 통신 시, 암호화되어 송수신됨 + reqVO.putInfoItem("jsonMasterId", jsonMasterId); + + DataApiResVO resVO = dataApi.request(reqVO); + + // 결과 처리 + if(resVO.getResultCode().charAt(0) == 'S') { + List> recordList = resVO.getList("record"); + if(recordList == null || recordList.size() < 1) return list; + + for(HashMap record : recordList) { + CollectionVO cVO = (CollectionVO)XmlConverter.convertMapToObject(record, CollectionVO.class); + if(cVO != null && StringUtil.isNotEmpty(cVO.getMasterId())) { + collectionMap.put(cVO.getMasterId(), cVO); + } + } + } else { + log.error("setDetailInfoForCartItems > 소장자료 다건 메타정보 조회 오류(API) : " + resVO.getResultCode() + " : " + resVO.getResultMessage()); + } + + + // 목록에 업데이트 설정 + for(int i=0; i setDetailInfoForHashList(List> list, String mbInfoId) throws Exception { + + List listObj = new ArrayList(); + + if(list == null || list.size() < 1) return null; + + for(HashMap record : list) { + CollectionVO cVO = (CollectionVO)XmlConverter.convertMapToObject(record, CollectionVO.class); + if(cVO != null && StringUtil.isNotEmpty(cVO.getMasterId())) { + listObj.add(cVO); + } + } + + return setDetailInfoForList(listObj, mbInfoId); + } + + + /** + * 자료 마스터ID 목록 문자열을 받아 CollectionVO 리스트 생성하여 리턴한다. + * + * @param masterIds + * @return + */ + public List makeListOfCollectionVO(String masterIds) { + + if(masterIds == null || StringUtil.isEmpty(masterIds)) return null; + + String[] items = masterIds.split(","); + + if(items == null || items.length < 1) return null; + + List retList = new ArrayList(); + for(String item : items) { + + if(StringUtil.isEmpty(item)) continue; + + CollectionVO itemVO = new CollectionVO(); + itemVO.setMasterId(item); + retList.add(itemVO); + } + if(retList.size() < 1) return null; + + return retList; + } + + + /** + * 자료 마스터ID 목록 문자열을 받아 상세내용을 조회하고, CollectionVO 리스트 생성하여 리턴한다. + * + * @param masterIds + * @return + */ + public List makeInfoListOfCollectionVO(String masterIds, String mbInfoId) throws Exception { + + List retList = makeListOfCollectionVO(masterIds); + + if(retList == null || retList.size() < 1) return null; + + return setDetailInfoForList(retList, mbInfoId); + } + + /** + * 자료상세조회 및 원문보기시에 로그 + * + * @param colVO + * @return + */ + public void insertDataInquiryLog(CollectionVO colVO) throws Exception { + collectionDAO.insertDataInquiryLog(colVO); + } + + /** + * 함께 볼만한 자료 리스트 + * + * @param vo + * @return + */ + public List selectSeeTogetherList(CollectionVO vo) throws Exception { + return collectionDAO.selectSeeTogetherList(vo); + } + + /** + * 유사한 자료 리스트 + * + * @param vo + * @return + */ + public List selectSimilarList(CollectionVO vo) throws Exception { + return collectionDAO.selectSimilarList(vo); + } + + /** + * 문화원 코드 조회 + * + * @param vo + * @return + */ + public CollectionVO selectMngOrgInfo(String masterId) throws Exception { + return collectionDAO.selectMngOrgInfo(masterId); + } + +} diff --git a/legacy/nlib/src/main/java/nlib/col/service/impl/InterestDAO.java b/legacy/nlib/src/main/java/nlib/col/service/impl/InterestDAO.java new file mode 100644 index 00000000..c5d37977 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/impl/InterestDAO.java @@ -0,0 +1,94 @@ +package nlib.col.service.impl; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Repository; + +import egovframework.com.cmm.service.impl.EgovComAbstractDAO; +import nlib.col.service.CollectionVO; +import nlib.col.service.DeptVO; +import nlib.restful.DataApi; +import nlib.restful.DataApiReqVO; +import nlib.restful.DataApiResVO; + +/** + *
+ * @Class Name : InterestDAO.java
+ * 
+ * @Description : 관심자료 관련 DAO 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021-07-01 JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021-07-01 + * @version 1.0 + * + */ + +@Repository("interestDAO") +public class InterestDAO extends EgovComAbstractDAO +{ + private static final Logger log = LoggerFactory.getLogger(InterestDAO.class); + + /** + * 관심 자료 목록을 조회한다. + * + * @param CollectionVO + * @return + */ + public List listInterests(CollectionVO vo) { + return selectList("InterestDAO.listInterests", vo); + } + /** + * 관심 자료 목록의 개수를 조회한다. + * + * @param CollectionVO + * @return + */ + public int countListInterests(CollectionVO vo) { + return selectOne("InterestDAO.countListInterests", vo); + } + + /** + * 관심자료 목록 삭제 + * @param masterIdList + */ + public void deleteInterests(CollectionVO vo) { + delete("InterestDAO.deleteInterests", vo); + } + + /** + * 관심자료 추가시 중복체크용 count + * @param vo + * @return + */ + public int countInterest(CollectionVO vo) { + return selectOne("InterestDAO.countInterest",vo); + } + + /** + * 관심자료 추가 + * @param vo + */ + public void insertInterest(CollectionVO vo) { + insert("InterestDAO.insertInterest",vo); + } + /** + * 문화원 목록 조회 + * @return + */ + public List selectOrgList(CollectionVO vo) { + return selectList("InterestDAO.selectOrgList",vo); + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/col/service/impl/InterestServiceImpl.java b/legacy/nlib/src/main/java/nlib/col/service/impl/InterestServiceImpl.java new file mode 100644 index 00000000..2290d704 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/impl/InterestServiceImpl.java @@ -0,0 +1,78 @@ +package nlib.col.service.impl; + +import java.util.List; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import nlib.col.service.CollectionVO; +import nlib.col.service.DeptVO; +import nlib.col.service.InterestService; + +@Service("interestService") +public class InterestServiceImpl implements InterestService +{ + private static final Logger log = LoggerFactory.getLogger(InterestServiceImpl.class); + + @Resource(name="interestDAO") + private InterestDAO interestDAO; + + /* + * 관심자료 목록을 조회한다. + * + * (non-Javadoc) + * @see nlib.col.service.CollectionService#listInterests(nlib.restful.service.DataApiReqVO) + */ + public List listInterests(CollectionVO vo) { + return interestDAO.listInterests(vo); + } + /* + * 관심자료목록의 총 개수를 조회한다. + * (non-Javadoc) + * @see nlib.col.service.CollectionService#countListInterests(nlib.col.service.CollectionVO) + */ + public int countListInterests(CollectionVO vo) { + return interestDAO.countListInterests(vo); + } + /* + * 관심자료 목록 삭제 + * (non-Javadoc) + * @see nlib.col.service.CollectionService#deleteInterests(java.util.List) + */ + public void deleteInterests(List masterIdList,String mbInfoId) { + CollectionVO vo = new CollectionVO(); + vo.setMbInfoId(mbInfoId); + for(String masterId : masterIdList) { + vo.setMasterId(masterId); + interestDAO.deleteInterests(vo); + } + } + /* + * 관심자료 추가시 중복체크용 count + * (non-Javadoc) + * @see nlib.col.service.CollectionService#countInterest(nlib.col.service.CollectionVO) + */ + public int countInterest(CollectionVO vo) { + return interestDAO.countInterest(vo); + } + + /* + * 관심자료 추가 + * (non-Javadoc) + * @see nlib.col.service.CollectionService#insertInterest(nlib.col.service.CollectionVO) + */ + public void insertInterest(CollectionVO vo) { + interestDAO.insertInterest(vo); + } + /* + * 문화원 목록 조회 + * (non-Javadoc) + * @see nlib.col.service.CollectionService#selectOrgList() + */ + public List selectOrgList(CollectionVO vo) { + return interestDAO.selectOrgList(vo); + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/col/service/impl/ReadDAO.java b/legacy/nlib/src/main/java/nlib/col/service/impl/ReadDAO.java new file mode 100644 index 00000000..06ff4b1a --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/impl/ReadDAO.java @@ -0,0 +1,38 @@ + +package nlib.col.service.impl; + +import java.util.HashMap; +import java.util.List; + +import egovframework.rte.psl.dataaccess.mapper.Mapper; + +/** + *
+ * @Class Name : ReadDAO.java
+ * 
+ * @Description : 열람신청 관리 DAO 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021-10-27 KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021-10-27 + * @version 1.0 + * + */ +@Mapper("readDAO") +public interface ReadDAO { + + public List> listDates(); + + public List> listReadMngOrg(String mbInfoId); + +} diff --git a/legacy/nlib/src/main/java/nlib/col/service/impl/ReadServiceImpl.java b/legacy/nlib/src/main/java/nlib/col/service/impl/ReadServiceImpl.java new file mode 100644 index 00000000..d695e1b3 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/impl/ReadServiceImpl.java @@ -0,0 +1,289 @@ +package nlib.col.service.impl; + +import java.util.HashMap; +import java.util.List; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Service; + +import nlib.col.service.CollectionVO; +import nlib.col.service.ReadService; +import nlib.info.service.InformService; +import nlib.restful.DataApi; +import nlib.restful.DataApiReqVO; +import nlib.restful.DataApiResVO; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : ReadServiceImpl.java
+ * 
+ * @Description : 열람신청관리 서비스 구현 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021-10-27 KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021-10-27 + * @version 1.0 + * + */ +@Service("readService") +public class ReadServiceImpl implements ReadService { + + private static final Logger log = LoggerFactory.getLogger(ReadServiceImpl.class); + + @Resource(name="readDAO") + private ReadDAO readDAO; + + @Resource(name="cartDAO") + private CartDAO cartDAO; + + @Resource(name="informService") + private InformService informService; + + /** RESTFul API 송수신 모듈 */ + @Resource(name = "dataApi") + private DataApi dataApi; + + /** + * 열람신청희망 가능 일자 목록을 조회한다. + * + * @param mbInfoId + * @return + */ + public List> listDates() { + return readDAO.listDates(); + } + + + /** + * 열람을 신청한다. + * + * @param list + * @param mbInfoId + * @param mngOrgCd + * @return + */ + public List insertReadItems(List list, String mbInfoId, CollectionVO readVO, boolean fromCart) throws Exception { + + if(list == null || list.size() < 1) { + log.error("insertReadItems > 열람 신청 대상 목록이 없습니다."); + return null; + } + if(readVO == null) { + log.error("insertReadItems > 매개변수 readVO는 null일 수 없습니다."); + return null; + } + + if(StringUtil.isEmpty(mbInfoId)) { + log.error("insertReadItems > 사용자ID를 확인할 수 없습니다."); + return null; + } + + if(StringUtil.isEmpty(readVO.getMngOrgCd())) { + log.error("insertReadItems > 관리문화원 코드를 확인할 수 없습니다."); + return null; + } + + if(StringUtil.isEmpty(readVO.getHopeReqPridDtmFrom() )) { + log.error("insertReadItems > 방문희망일 시작일자를 확인할 수 없습니다."); + return null; + } + + if(StringUtil.isEmpty(readVO.getHopeReqPridDtmTo() )) { + log.error("insertReadItems > 방문희망일 종료일자를 확인할 수 없습니다."); + return null; + } + + if(readVO.getHopeReqPridDtmFrom().compareTo(readVO.getHopeReqPridDtmTo()) > 0) { + log.error("insertReadItems > 방문희망일 종료일자는 시작일자 이후이어야 합니다."); + return null; + } + + // 해당 문화원의 업무시간 조회 + HashMap operation = informService.selectNCultureOpenTime(readVO.getMngOrgCd()); + if(operation == null) { + log.error("insertReadItems > 지방문화원 정보를 확인할 수 없습니다."); + return null; + } + + // API 호출 + /* + mngOrgCd 문화원코드 O String SU01 + mbInfoId 사용자아이디 O String "BDCCAF34CF8AA365C660ADB121CE6741 + (ARIAUtil 암호화)" + jsonMasterId 자료번호목록 O String [{"masterId":"xxxx"}, {"masterId":"xxxb"},…] + hopeReqPridDtmFrom 희망열람기간시작일자 O String 202109071300 + hopeReqPridDtmTo 희망열람기간종료일자 O String 202109101400 + purpose 열람목적 String 열람목적 + */ + DataApiReqVO reqVO = new DataApiReqVO("/uac/service/nlib/col/insertReserveItem", HttpMethod.POST); + reqVO.setMbInfoId(mbInfoId); // 통신 시, 암호화되어 송수신됨 + reqVO.putInfoItem("mngOrgCd" , readVO.getMngOrgCd()); + reqVO.putInfoItem("hopeReqPridDtmFrom", readVO.getHopeReqPridDtmFrom().replaceAll("-", "") + StringUtil.getString(operation.get("OPEN_TIME"), "0900").replaceAll(":", "").substring(0, 4)); + reqVO.putInfoItem("hopeReqPridDtmTo" , readVO.getHopeReqPridDtmTo().replaceAll("-", "") + StringUtil.getString(operation.get("CLOSED_TIME"), "1800").replaceAll(":", "").substring(0, 4)); + CollectionVO cVO = null; + DataApiResVO resVO = null; + String jsonMasterId = ""; + + for(int i=0; i 열람 신청 대상으로 생성된 목록이 없습니다."); + return null; + } + + jsonMasterId = "[" + jsonMasterId.substring(1) + "]"; + + reqVO.putInfoItem("jsonMasterId", jsonMasterId); + resVO = dataApi.request(reqVO); + cVO.setResult(resVO.getResultCode(), resVO.getResultMessage()); + + // 카트에서 신청하여 성공한 경우, 카트 처리완료 변경 작업 + if(resVO != null && resVO.getResultCode() != null && resVO.getResultCode().startsWith("S") && fromCart) { + CollectionVO vVO = null; + for(int i=0; i changeCartProcDivCd=" + retUpdateProc); + } + } + } + + readVO.setResultCode(resVO.getResultCode()); + readVO.setResultMessage(resVO.getResultMessage()); + + // 신청 처리 정보 + if(resVO.isSuccess()) { + readVO.setHopeReqPridDtmFrom(StringUtil.formatDateStr(resVO.getInfoItem("hopeReqPridDtmFrom", ""),"")); + readVO.setHopeReqPridDtmTo(StringUtil.formatDateStr(resVO.getInfoItem("hopeReqPridDtmTo", ""),"")); + readVO.setReqId(resVO.getInfoItem("reqId", "")); // 열람신청번호 + readVO.setReqDd(resVO.getInfoItem("reqDd", "")); // 열람신청일자 + readVO.setSelItems(resVO.getInfoItem("masterId")); // 자료번호 + } else { + readVO.setRsrvId(null); // 열람신청번호 + readVO.setRsrvId(null); // 열람신청일자 + } + + return list; + } + + /** + * 사용자의 열람건이 존재하는 문화원 정보 목록을 조회한다. + * + * @param mbInfoId + * @return + */ + public List> listReadMngOrg(String mbInfoId) { + return readDAO.listReadMngOrg(mbInfoId); + } + + /** + * 열람 목록 조회한다. + * + * @param searchVO + * @return + */ + public DataApiResVO listReadItems(CollectionVO searchVO) { + + if(searchVO == null || StringUtil.isEmpty(searchVO.getMbInfoId())) { + log.error("listRentItems > 열람 목록 조회 요청 정보가 없습니다."); + return new DataApiResVO("F", "열람 목록 조회 요청 정보가 없습니다."); + } + + // API 호출 + /* + mngOrgCd 문화원코드 + mbInfoId 사용자아이디 + rows 페이지크기(페이지당최대표출건수) + page 페이지번호 + bookLtRvStatusCd 대출상태구분코드("": 전체, A:신청, B:대출준비완료, C:취소, W:대출중, R0:정상반납, R1:연체반납 P:연체) + */ + DataApiReqVO reqVO = new DataApiReqVO("/uac/service/nlib/col/listReserveItem", HttpMethod.GET); + reqVO.setMbInfoId(searchVO.getMbInfoId()); // 통신 시, 암호화되어 송수신됨 + reqVO.setPageSize(searchVO.getPageSize()); + reqVO.setPageIndex(searchVO.getPageIndex()); + reqVO.putInfoItem("mngOrgCd", searchVO.getMngOrgCd()); + reqVO.putInfoItem("reqStatusDivCd", searchVO.getReqStatusDivCd()); + return dataApi.request(reqVO); + } + + + /** + * 열람신청을 취소한다. + * + * @param searchVO + * @return + */ + public DataApiResVO cancelReadItem(CollectionVO searchVO) { + + String message = null; + + if(searchVO == null || StringUtil.isEmpty(searchVO.getMbInfoId())) { + message = "로그인하신 후, 이용바랍니다."; + log.error("cancelRentItem > " + message); + return new DataApiResVO("E", message); + } + + if(StringUtil.isEmpty(searchVO.getMngOrgCd())) { + message = "문화원정보가 부적합합니다. 다시 요청하여 주시기 바랍니다."; + log.error("cancelRentItem > " + message); + return new DataApiResVO("E", message); + } + + if(StringUtil.isEmpty(searchVO.getReqId())) { + message = "취소할 방문열람신청번호 정보가 부적합합니다. 다시 요청하여 주시기 바랍니다."; + log.error("cancelRentItem > " + message); + return new DataApiResVO("E", message); + } + + if(StringUtil.isEmpty(searchVO.getMasterId())) { + message = "취소할 자료정보 정보가 부적합합니다. 다시 요청하여 주시기 바랍니다."; + log.error("cancelRentItem > " + message); + return new DataApiResVO("E", message); + } + + // API 호출 + /* + mngOrgCd 문화원코드 + mbInfoId 사용자아이디 + reqId 열람신청번호 + masterId 자료번호 + */ + DataApiReqVO reqVO = new DataApiReqVO("/uac/service/nlib/col/deleteReserveItem", HttpMethod.POST); + reqVO.setMbInfoId(searchVO.getMbInfoId()); // 통신 시, 암호화되어 송수신됨 + reqVO.putInfoItem("mngOrgCd", searchVO.getMngOrgCd()); + reqVO.putInfoItem("reqId", searchVO.getReqId()); + reqVO.putInfoItem("masterId", searchVO.getMasterId()); + return dataApi.request(reqVO); + } + +} diff --git a/legacy/nlib/src/main/java/nlib/col/service/impl/RentDAO.java b/legacy/nlib/src/main/java/nlib/col/service/impl/RentDAO.java new file mode 100644 index 00000000..681ad04e --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/impl/RentDAO.java @@ -0,0 +1,36 @@ + +package nlib.col.service.impl; + +import java.util.HashMap; +import java.util.List; + +import egovframework.rte.psl.dataaccess.mapper.Mapper; + +/** + *
+ * @Class Name : RentDAO.java
+ * 
+ * @Description : 대출관련 DAO 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021-07-01 KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021-07-01 + * @version 1.0 + * + */ +@Mapper("rentDAO") +public interface RentDAO { + + public List> listRentMngOrg(String mbInfoId); + +} diff --git a/legacy/nlib/src/main/java/nlib/col/service/impl/RentServiceImpl.java b/legacy/nlib/src/main/java/nlib/col/service/impl/RentServiceImpl.java new file mode 100644 index 00000000..2b7b9e40 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/impl/RentServiceImpl.java @@ -0,0 +1,253 @@ +package nlib.col.service.impl; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Service; + +import nlib.col.service.CollectionVO; +import nlib.col.service.RentService; +import nlib.restful.DataApi; +import nlib.restful.DataApiReqVO; +import nlib.restful.DataApiResVO; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : RentServiceImpl.java
+ * 
+ * @Description : 대출관련 서비스 구현 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021-07-01 KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021-07-01 + * @version 1.0 + * + */ +@Service("rentService") +public class RentServiceImpl implements RentService +{ + private static final Logger log = LoggerFactory.getLogger(RentServiceImpl.class); + + @Resource(name="rentDAO") + private RentDAO rentDAO; + + @Resource(name="cartDAO") + private CartDAO cartDAO; + + + /** RESTFul API 송수신 모듈 */ + @Resource(name = "dataApi") + private DataApi dataApi; + + + /** + * 사용자의 대출건이 존재하는 문화원 정보 목록을 조회한다. + * + * @param mbInfoId + * @return + */ + public List> listRentMngOrg(String mbInfoId) { + return rentDAO.listRentMngOrg(mbInfoId); + } + + /** + * 대출 목록 조회한다. + * + * @param searchVO + * @return + */ + public DataApiResVO listRentItems(CollectionVO searchVO) { + + if(searchVO == null || StringUtil.isEmpty(searchVO.getMbInfoId())) { + log.error("listRentItems > 대출 목록 조회 요청 정보가 없습니다."); + return new DataApiResVO("F", "회원정보가 부적합합니다."); + } + + // API 호출 + /* + mngOrgCd 문화원코드 + mbInfoId 사용자아이디 + rows 페이지크기(페이지당최대표출건수) + page 페이지번호 + bookLtRvStatusCd 대출상태구분코드("": 전체, A:신청, B:대출준비완료, C:취소, W:대출중, R0:정상반납, R1:연체반납 P:연체) + */ + DataApiReqVO reqVO = new DataApiReqVO("/uac/service/nlib/rent/listRentItem", HttpMethod.GET); + reqVO.setMbInfoId(searchVO.getMbInfoId()); // 통신 시, 암호화되어 송수신됨 + reqVO.setPageSize(searchVO.getPageSize()); + reqVO.setPageIndex(searchVO.getPageIndex()); + reqVO.putInfoItem("mngOrgCd", searchVO.getMngOrgCd()); + reqVO.putInfoItem("bookLtRvStatusCd", searchVO.getBookLtRvStatusCd()); + return dataApi.request(reqVO); + } + + + /** + * 대출(예약)신청을 취소한다. + * + * @param searchVO + * @return + */ + public DataApiResVO cancelRentItem(CollectionVO searchVO) { + + String message = null; + + if(searchVO == null || StringUtil.isEmpty(searchVO.getMbInfoId())) { + message = "대출(예약)신청 취소 요청 정보가 부적합합니다 (MbInfoId)"; + log.error("cancelRentItem > " + message); + return new DataApiResVO("E", message); + } + + if(StringUtil.isEmpty(searchVO.getMngOrgCd())) { + message = "문화원정보가 부적합합니다. 다시 요청하여 주시기 바랍니다."; + log.error("cancelRentItem > " + message); + return new DataApiResVO("E", message); + } + + if(StringUtil.isEmpty(searchVO.getRsrvId())) { + message = "취소할 대출(예약)선청번호 정보가 부적합합니다. 다시 요청하여 주시기 바랍니다."; + log.error("cancelRentItem > " + message); + return new DataApiResVO("E", message); + } + + // API 호출 + /* + mngOrgCd 문화원코드 + mbInfoId 사용자아이디 + rsrvId 대출신청예약번호 + */ + DataApiReqVO reqVO = new DataApiReqVO("/uac/service/nlib/rent/deleteRentItem", HttpMethod.POST); + reqVO.setMbInfoId(searchVO.getMbInfoId()); // 통신 시, 암호화되어 송수신됨 + reqVO.putInfoItem("mngOrgCd", searchVO.getMngOrgCd()); + reqVO.putInfoItem("rsrvId", searchVO.getRsrvId()); + return dataApi.request(reqVO); + } + + + /** + * 대출을 신청한다. + * + * @param list + * @param mbInfoId + * @param mngOrgCd + * @return + */ + public List insertRentItems(List list, String mbInfoId, String mngOrgCd, boolean fromCart) throws Exception { + + if(list == null || list.size() < 1) return null; + + if(StringUtil.isEmpty(mbInfoId)) { + log.error("insertRentItems > 사용자ID를 확인할 수 없습니다."); + return null; + } + + if(StringUtil.isEmpty(mngOrgCd)) { + log.error("insertRentItems > 관리문화원 코드를 확인할 수 없습니다."); + return null; + } + + + // API 호출 + /* + mngOrgCd 문화원코드 O String SU01 + mbInfoId 사용자아이디 O String "BDCCAF34CF8AA365C660ADB121CE6741 + (ARIAUtil 암호화)" + masterId -> jsonMasterId 자료번호 : 다건 가능하여야 함 O String UR-013ABB95CCD84FDA9600CCAE97032C4D + + */ + DataApiReqVO reqVO = new DataApiReqVO("/uac/service/nlib/rent/insertRentItem", HttpMethod.POST); + reqVO.setMbInfoId(mbInfoId); // 통신 시, 암호화되어 송수신됨 + reqVO.putInfoItem("mngOrgCd", mngOrgCd); + CollectionVO cVO = null; + DataApiResVO resVO = null; + for(int i=0; i retUpdateProc=" + retUpdateProc); + } + + } else { + cVO.setRsrvId(null); + cVO.setRsrvDd(null); + cVO.setResultCode(resVO.getResultCode()); + cVO.setResultMessage(resVO.getResultMessage()); + } + + } + + return list; + } + + /** + * 사용자의 대출현황을 조회한다. + * + * @param mbInfoId + * @return + */ + public Map getRentStats(String mbInfoId) { + + if(StringUtil.isEmpty(mbInfoId)) return null; + + DataApiReqVO reqVO = new DataApiReqVO("/uac/service/nlib/col/getLentReqStatCnt", HttpMethod.GET); + reqVO.setMbInfoId(mbInfoId); // 통신 시, 암호화되어 송수신됨 + DataApiResVO resVO = dataApi.request(reqVO); + Map retMap = new HashMap(); + + if(StringUtil.isNotEmpty(resVO.getResultCode()) && resVO.getResultCode().charAt(0) == 'S') { + + retMap.put("lentAppCnt" , resVO.getInfoItem("lentAppCnt" , "0")); // 대출-신청 + retMap.put("lentResvCnt" , resVO.getInfoItem("lentResvCnt" , "0")); // 대출-예약 + retMap.put("lentCancelCnt", resVO.getInfoItem("lentCancelCnt", "0")); // 대출-취소 + retMap.put("lentCnt" , resVO.getInfoItem("lentCnt" , "0")); // 대출-대출중 + retMap.put("lentRtnCnt" , resVO.getInfoItem("lentRtnCnt" , "0")); // 대출-반납 + retMap.put("lentOverCnt" , resVO.getInfoItem("lentOverCnt" , "0")); // 대출-연체 + + retMap.put("reqAppCnt" , resVO.getInfoItem("reqAppCnt" , "0")); // 열람현황-신청 + retMap.put("reqCancelCnt" , resVO.getInfoItem("reqCancelCnt" , "0")); // 열람현황-취소 + retMap.put("reqOkCnt" , resVO.getInfoItem("reqOkCnt" , "0")); // 열람현황-승인 + retMap.put("reqCompCnt" , resVO.getInfoItem("reqCompCnt" , "0")); // 열람현황-반려 + + } else { + + retMap.put("resultMessage" , resVO.getResultMessage()); + } + + return retMap; + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/col/service/impl/RisDAO.java b/legacy/nlib/src/main/java/nlib/col/service/impl/RisDAO.java new file mode 100644 index 00000000..5748a40f --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/impl/RisDAO.java @@ -0,0 +1,72 @@ + +package nlib.col.service.impl; + +import java.util.List; + +/** + *
+ * @Class Name : RisDAO.java
+ * 
+ * @Description : Ris 관련 DAO 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021-07-01 JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021-07-01 + * @version 1.0 + * + */ + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Repository; + +import nlib.col.service.CollectionVO; +import nlib.col.service.DeptVO; +import nlib.col.service.RisVO; +import nlib.restful.DataApi; +import nlib.restful.DataApiReqVO; +import nlib.restful.DataApiResVO; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Repository; + +import egovframework.com.cmm.service.impl.EgovComAbstractDAO; +import egovframework.rte.psl.dataaccess.mapper.Mapper; +import nlib.cmm.service.NotificationVO; +import nlib.cmm.service.NlibProperty; +import nlib.user.service.NlibLoginVO; +import nlib.util.StringUtil; +@Repository("risDAO") +public class RisDAO extends EgovComAbstractDAO +{ + private static final Logger log = LoggerFactory.getLogger(RisDAO.class); + /** + * RIS파일 다운로드 데이터를 조회한다. + * @param vo + * @return + */ + public RisVO selectRisInfo(RisVO vo) { + return selectOne("RisDAO.selectRisInfo", vo); + } + /** + * 문화원 목록 조회(검색필터용) + * @return + */ + public List selectOrgList() { + return selectList("CollectionDAO.selectOrgList"); + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/col/service/impl/RisServiceImpl.java b/legacy/nlib/src/main/java/nlib/col/service/impl/RisServiceImpl.java new file mode 100644 index 00000000..b81a1fa5 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/service/impl/RisServiceImpl.java @@ -0,0 +1,64 @@ + +package nlib.col.service.impl; + +import java.util.List; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import nlib.col.service.CollectionVO; +import nlib.col.service.DeptVO; +import nlib.col.service.RisService; +import nlib.col.service.RisVO; + +/** + *
+ * @Class Name : RisServiceImpl.java
+ * 
+ * @Description : RIS관련 서비스 구현 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021-07-01 JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021-07-01 + * @version 1.0 + * + */ +@Service("risService") +public class RisServiceImpl implements RisService +{ + private static final Logger log = LoggerFactory.getLogger(RisServiceImpl.class); + + @Resource(name = "risDAO") + private RisDAO risDAO; + + /** + * RIS파일 다운로드 데이터를 조회한다. + * (non-Javadoc) + * @see nlib.col.service.CollectionService#selectRisInfo(nlib.col.service.CollectionVO) + */ + public RisVO selectRisInfo(RisVO vo) { + return risDAO.selectRisInfo(vo); + } + + /** + * 문화원 목록 조회(검색 필터용) + * (non-Javadoc) + * @see nlib.col.service.CollectionService#selectOrgList() + */ + public List selectOrgList() { + return risDAO.selectOrgList(); + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/col/web/CartController.java b/legacy/nlib/src/main/java/nlib/col/web/CartController.java new file mode 100644 index 00000000..27420db8 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/web/CartController.java @@ -0,0 +1,300 @@ +package nlib.col.web; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; + +import nlib.cmm.NlibCommonController; +import nlib.col.service.CartService; +import nlib.col.service.CollectionService; +import nlib.col.service.CollectionVO; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : CartController.java
+ * 
+ * @Description : 소장자료 카트 컨트롤러
+ * 로그인하지 않은 사용자도 카트 추가 가능하며, 추가 시 정보가 저장되는 영역은 다음과 같다.
+ * - 비회원 카트정보 쿠키 저장 
+ * - 회원 카트정보 DB 저장 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 10. 5. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 10. 5. + * @version 1.0 + * + */ +@Controller +public class CartController extends NlibCommonController +{ + private static final Logger log = LoggerFactory.getLogger(CartController.class); + + @Value("#{properties['list.paging.page.size']}") + private String DEFUALT_PAGE_SIZE; + + @Resource(name = "cartService") + private CartService cartService; + + @Resource(name = "collectionService") + private CollectionService collectionService; + + /** + * 카트 목록을 조회한다. + * 로그인되지 않은 사용자의 경우, 쿠키에 저장된 값으로 처리한다. + * + * @param request + * @param cartTyp + * eCd + * @param model + * @return + * @throws Exception + */ + @RequestMapping(value= {"/cart/listCartItems.do", "/login/listCartItems.do"}) + public String listCartItems(HttpServletRequest request, HttpServletResponse response, String message, String cartTypeCd, ModelMap model) throws Exception { + + if(StringUtil.isEmpty(cartTypeCd)) cartTypeCd = "1"; // 대출 기본 설정 + + String mbInfoId = getMbInfoId(request); + + List list = null; + int cartTypeCd1Cnt = 0; // 대출 카트건수 + int cartTypeCd2Cnt = 0; // 열람 카트건수 + + // 카트 목록 가져오기 + if(StringUtil.isEmpty(mbInfoId)) { + // 쿠키에서 값 가져오기 + list = cartService.listCartItemsFromCookie(request, response, cartTypeCd); + + // 카트 목록 자료에 대한 상세자료 설정 + collectionService.setDetailInfoForList(list, null); + + // 문화원별 정렬 처리 + list = sortCollectionListByMngOrgCd(list); + + // 카트 건수 + cartTypeCd1Cnt = cartService.countCartItemsFromCookie(request, response, "1"); + cartTypeCd2Cnt = cartService.countCartItemsFromCookie(request, response, "2"); + + } else { + list = cartService.listCartItems(mbInfoId, cartTypeCd); + + // 카트 목록 자료에 대한 상세자료 설정 + collectionService.setDetailInfoForList(list, getMbInfoId(request)); + + // 카트 건수 + cartTypeCd1Cnt = cartService.countCartItems(mbInfoId, "1"); + cartTypeCd2Cnt = cartService.countCartItems(mbInfoId, "2"); + } + + if(StringUtil.isNotEmpty(message) && message.startsWith("%")) { + message = StringUtil.decodeUrl(message); + } + + // CSRF 토큰 생성 + String token = generateCsrfToken(request); + model.addAttribute("csrfToken", token); + + model.addAttribute("cartTypeCd1Cnt", cartTypeCd1Cnt); + model.addAttribute("cartTypeCd2Cnt", cartTypeCd2Cnt); + + model.addAttribute("list", list); + model.addAttribute("cartTypeCd", cartTypeCd); + model.addAttribute("message", message); + + return "nlib/cart/listCartItems"; + } + + /** + * 자료 목록을 문화원별로 정렬하여 리턴한다. + * + * @param list + * @return + */ + public List sortCollectionListByMngOrgCd(List list) { + + if(list == null || list.size() < 1) return list; + + Map> orgMap = new HashMap>(); + + for(CollectionVO vo : list) { + String mngOrgCd = vo.getMngOrgCd(); + + if(StringUtil.isEmpty(mngOrgCd)) { + mngOrgCd = "NONE"; + vo.setMngOrgCd(mngOrgCd); + vo.setMngOrgNm("(없음)"); + } + List orgList = orgMap.get(mngOrgCd); + if(orgList == null) { + orgList = new ArrayList(); + } + + orgList.add(vo); + + orgMap.put(mngOrgCd, orgList); + } + + List retList = new ArrayList(); + for(String key : orgMap.keySet()) { + List orgList = orgMap.get(key); + + for(CollectionVO vo : orgList) { + retList.add(vo); + } + } + + return retList; + } + + /** + * 카트 영역 구분코드를 변경한다. (대출 <-> 방문열람) + * + * @param request + * @param cartVO + * @param model + * @return + * @throws Exception + */ + @RequestMapping("/cart/changeCartType.do") + public String changeCartType(HttpServletRequest request, HttpServletResponse response, CollectionVO cartVO, ModelMap model) throws Exception { + + String message = null; + String mbInfoId = getMbInfoId(request); + + if(StringUtil.isEmpty(mbInfoId)) { + message = cartService.changeCartTypeToCookie(request, response, cartVO); + } else { + cartVO.setMbInfoId(getMbInfoId(request)); + message = cartService.changeCartType(cartVO); + } + + if(message == null) message = "정상적으로 변경되었습니다."; + model.addAttribute("message", StringUtil.encodeUrl(message)); + model.addAttribute("cartTypeCd", cartVO.getCartTypeCd()); + return "redirect:/cart/listCartItems.do"; + } + + /** + * 카트에 추가한다. + * + * @param request + * @param cartVO + * @param model + * @return + * @throws Exception + */ + @RequestMapping("/cart/insertCartItemAjax.do") + public ResponseEntity insertCartItemAjax(HttpServletRequest request, HttpServletResponse response, @RequestBody CollectionVO cartVO, ModelMap model) throws Exception { + + log.debug("insertCartItemAjax > masterId = " + cartVO.getMasterId()); + + String code = "S"; + String message = null; + + String mbInfoId = getMbInfoId(request); + + int changedCnt = 0; + + // 로그인한 경우 + if(!StringUtil.isEmpty(mbInfoId)) { + log.debug("insertCartItemAjax > masterId = " + cartVO.getMasterId()); + log.debug("insertCartItemAjax > cartDivCd = " + cartVO.getCartTypeCd()); + cartVO.setMbInfoId(mbInfoId); + cartVO.setRegId(mbInfoId); + message = cartService.insertCartItem(cartVO); + } + // 비회원인 경우 + else { + message = cartService.insertCartItemToCookie(request, response, cartVO); + } + + if(message == null) { + code = "S"; + message = "정상적으로 추가되었습니다."; + } else { + code = "F"; + } + + //------------------------------- + // JSON변환 응답 처리 + //------------------------------- + // JS-GRID 페이징 처리를 포함한 응답값 처리 + // {data: [{...}], + // itemsCount: 255 + // } + HashMap retMap = new HashMap(); + retMap.put("code", code); + retMap.put("message", message); + + return makeResponseEntityJson(retMap); + } + + @RequestMapping("/cart/deleteCartItems.do") + public String deleteCartItems(HttpServletRequest request, HttpServletResponse response, CollectionVO cartVO, ModelMap model) throws Exception { + String mbInfoId = getMbInfoId(request); + cartVO.setMbInfoId(mbInfoId); + String message = null; + + if(!StringUtil.isEmpty(mbInfoId)) { + message = cartService.deleteCartItems(cartVO); + } else { + message = cartService.deleteCartItemsFromCookie(request, response, cartVO); + } + + if(message == null) message = "정상적으로 삭제되었습니다."; + model.addAttribute("message", StringUtil.encodeUrl(message)); + model.addAttribute("cartTypeCd", cartVO.getCartTypeCd()); + return "redirect:/cart/listCartItems.do"; + } + + /** + * 비로그인시 카트에 저장된 내역을 로그인한 후 해당 사용자의 카트로 저장하고, 쿠키 카트내용은 초기화한다. + * + * @param request + * @param model + * @return + * @throws Exception + */ + @Secured("ROLE_USER") + @RequestMapping("/cart/mergeCartItemsAjax.do") + public ResponseEntity mergeCartItemsAjax(HttpServletRequest request, HttpServletResponse response, ModelMap model) throws Exception { + + String mbInfoId = getMbInfoId(request); + int mergedCnt = 0; + + if(StringUtil.isEmpty(mbInfoId)) mergedCnt = -1; + else mergedCnt = cartService.mergeCart(mbInfoId, request, response); + + HashMap retMap = new HashMap(); + retMap.put("mergedCnt", mergedCnt); + + return makeResponseEntityJson(retMap); + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/col/web/InterestController.java b/legacy/nlib/src/main/java/nlib/col/web/InterestController.java new file mode 100644 index 00000000..a3259b44 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/web/InterestController.java @@ -0,0 +1,224 @@ +package nlib.col.web; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import nlib.cmm.NlibCommonController; +import nlib.cmm.service.CodeService; +import nlib.cmm.service.PagingVO; +import nlib.col.service.CollectionService; +import nlib.col.service.CollectionVO; +import nlib.col.service.DeptVO; +import nlib.col.service.InterestService; +import nlib.col.service.RisService; +import nlib.user.service.NlibLoginVO; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : InterestController.java
+ * 
+ * @Description : 관심자료 컨트롤러
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 10. 01. JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 10. 01. + * @version 1.0 + * + */ +@Controller +public class InterestController extends NlibCommonController +{ + private static final Logger log = LoggerFactory.getLogger(InterestController.class); + + @Value("#{properties['list.paging.page.size']}") + private String DEFUALT_PAGE_SIZE; + + @Resource(name = "interestService") + private InterestService interestService; + + @Resource(name = "risService") + private RisService risService; + + @Resource(name = "codeService") + private CodeService codeService; + + @Resource(name = "collectionService") + private CollectionService collectionService; + + /** + * 관심 자료 화면을 호출한다. + * + * @param req + * @return + */ + @Secured("ROLE_USER") + @RequestMapping("/interest/listInterests.do") + public String listInterests(HttpServletRequest req, HttpServletRequest request, Authentication authentication, + @RequestParam Map paramMap, + CollectionVO searchCollectionVO, ModelMap model) throws Exception { + String message = ""; + + //사용자 정보를 가져온다. + NlibLoginVO loginVO = getNlibLoginVO(authentication); + + if(loginVO == null) { + message = "로그인하신 후, 이용바랍니다."; + model.addAttribute("message", message); + model.addAttribute("url", "/login/loginForm.do"); + return "nlib/cmm/alert"; + } + + searchCollectionVO.setMbInfoId(loginVO.getMbInfoId()); + + //문화원 목록 조회 + List vo = interestService.selectOrgList(searchCollectionVO); + model.addAttribute("deptList",vo); + model.addAttribute("searchCollection", searchCollectionVO); + return "nlib/collection/listInterests"; + } + + /** + * 관심 자료를 조회한다. + * + * @param req + * @return + * @throws Exception + */ + @RequestMapping(value="/interest/listInterestsAjax.do") + public ResponseEntity listInterestsAjax(HttpServletRequest req, HttpServletRequest request, + Authentication authentication, @RequestBody CollectionVO searchCollectionVO) throws Exception { + + if(searchCollectionVO.getPageIndex() < 1) searchCollectionVO.setPageIndex(1); + if(searchCollectionVO.getPageSize() < 1) searchCollectionVO.setPageSize(DEFUALT_PAGE_SIZE); + + List operList = new ArrayList(); + + int totalCount= 0; + //사용자 정보를 가져온다. + NlibLoginVO loginVO = getNlibLoginVO(authentication); + + searchCollectionVO.setMbInfoId(loginVO.getMbInfoId()); + searchCollectionVO.setPageStart(searchCollectionVO.getPageIndex(), searchCollectionVO.getPageSize()); + + // 요청 + List interestList = interestService.listInterests(searchCollectionVO); + totalCount = interestService.countListInterests(searchCollectionVO); + + + operList = collectionService.setDetailInfoForList(interestList, getMbInfoId(request)); + //------------------------------- + // JSON변환 응답 처리 + //------------------------------- + // JS-GRID 페이징 처리를 포함한 응답값 처리 + // {data: [{...}], + // itemsCount: 255 + // } + HashMap retMap = new HashMap(); + retMap.put("data", operList); + retMap.put("itemsCount", totalCount); + + PagingVO pageVO = new PagingVO(); + pageVO.setPagingVO(totalCount, searchCollectionVO.getPageIndex(), searchCollectionVO.getPageSize()); + retMap.put("pagingPageIndex" , pageVO.getPageIndex()); + retMap.put("pagingTotRecordCount", pageVO.getTotRecordCount()); + retMap.put("pagingStartPage" , pageVO.getStartPage()); + retMap.put("pagingEndPage" , pageVO.getEndPage()); + retMap.put("pagingLastPage" , pageVO.getLastPage()); + + return makeResponseEntityJson(retMap); + } + + /** + * 관심자료 목록 삭제 + * @param masterIdList + */ + @RequestMapping(value="/interest/deleteInterests.ajax") + @ResponseBody + public String deleteInterests(HttpServletRequest request, @RequestParam(value="masterIdList[]") List masterIdList,Authentication authentication) { + String mbInfoId = getMbInfoId(request); + String message=""; + + if(StringUtil.isEmpty(mbInfoId)) { + message="notLogin"; + return message; + } + + interestService.deleteInterests(masterIdList,mbInfoId); + message ="success"; + return message; + } + + /** + * 관심자료 추가 + * @param masterIdList + */ + @RequestMapping(value="/interest/insertInterest.ajax") + @ResponseBody + public String insertInterest(@RequestParam(value="masterId") String masterId, HttpServletResponse response, Authentication authentication, HttpServletRequest request) { + int count = 0; + String message = ""; + String mbInfoId = getMbInfoId(request); + + if(StringUtil.isEmpty(mbInfoId)) { + message="notLogin"; + return message; + } + CollectionVO vo = new CollectionVO(); + vo.setMbInfoId(mbInfoId); + vo.setMasterId(masterId); + + if(vo.getMbInfoId() == null) + { + message="notLogin"; + return message; + } + + count = interestService.countInterest(vo); + + if(!StringUtil.getString(masterId,"").equals("")) + { + //중복된 관심자료가 있을시 + if(count > 0) + { + message="alreadyAdded"; + }else { + interestService.insertInterest(vo); + message="success"; + } + }else { + message="fail"; + } + return message; + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/col/web/ReadController.java b/legacy/nlib/src/main/java/nlib/col/web/ReadController.java new file mode 100644 index 00000000..1b1af01c --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/web/ReadController.java @@ -0,0 +1,340 @@ +package nlib.col.web; + +import java.util.HashMap; +import java.util.List; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; + +import nlib.cmm.NlibCommonController; +import nlib.cmm.service.PagingVO; +import nlib.col.service.CollectionService; +import nlib.col.service.CollectionVO; +import nlib.col.service.ReadService; +import nlib.restful.DataApiResVO; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : ReadController.java
+ * 
+ * @Description : 방문열람을 관리하는 컨트롤러 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 10. 27. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 10. 27. + * @version 1.0 + * + */ +@Controller +public class ReadController extends NlibCommonController { + + private static final Logger log = LoggerFactory.getLogger(ReadController.class); + + @Resource(name = "readService") + private ReadService readService; + + + @Resource(name = "collectionService") + private CollectionService collectionService; + + + /** + * 열람신청을 등록하는 화면을 표출한다. + * + * @param request + * @param readVO + * @param model + * @return + * @throws Exception + */ + @Secured("ROLE_USER") + @RequestMapping(value={"/read/confirmReadFromCart.do", "/read/confirmRead.do"}) + public String confirmRead(HttpServletRequest request, CollectionVO readVO, String csrfToken, String fromPage, ModelMap model) throws Exception { + + String retJsp = "nlib/read/confirmRead"; + boolean fromCart = request.getServletPath().contains("Cart.do"); + + String mbInfoId = getMbInfoId(request); + + if(StringUtil.isEmpty(mbInfoId)) { + model.addAttribute("message", "로그인 후, 이용해 주시기 바랍니다."); + return retJsp; + } + + if(readVO == null || StringUtil.isEmpty(readVO.getSelItems())) { + if(fromCart && StringUtil.getString(fromPage, "").equalsIgnoreCase("login")) { + // 비로그인자의 카트에서 신청을 실행하여 로그인 후 신청 진입으로 돌아온 경우 + return "redirect:/cart/listCartItems.do"; + } else { + model.addAttribute("message", "신청할 정보가 없습니다."); + return "nlib/read/confirmRead"; + } + } + + String selItems = readVO.getSelItems(); + + List list = collectionService.makeInfoListOfCollectionVO(selItems, mbInfoId); + List> listDates = readService.listDates(); + + if(StringUtil.isEmpty(readVO.getMngOrgNm()) && list != null && list.size() > 0) { + readVO.setMngOrgCd(list.get(0).getMngOrgCd()); + readVO.setMngOrgNm(list.get(0).getMngOrgNm()); + } + + // CSRF 토큰 생성 + String token = generateCsrfToken(request); + model.addAttribute("csrfToken", token); + + model.addAttribute("readVO", readVO); + model.addAttribute("list", list); + model.addAttribute("listDates", listDates); + if(fromCart) model.addAttribute("fromCart", fromCart ? "Y" : "N"); + + return retJsp; + } + + /** + * 열람신청을 등록한다. + * + * @param request + * @param readVO + * @param model + * @return + * @throws Exception + */ + @Secured("ROLE_USER") + @RequestMapping(value={"/read/insertReadItemsFromCart.do", "/read/insertReadItems.do"}) + public String insertReadItems(HttpServletRequest request, CollectionVO readVO, String csrfToken, ModelMap model) throws Exception { + + boolean fromCart = request.getServletPath().contains("Cart.do"); + String retJsp = "nlib/read/insertReadItems"; + String mbInfoId = getMbInfoId(request); + + if(StringUtil.isEmpty(mbInfoId)) { + model.addAttribute("message", "로그인 후, 이용해 주시기 바랍니다."); + return retJsp; + } + + if(!isValidCsrfToken(request, csrfToken)) { + model.addAttribute("message", "잘못된 접근입니다."); + return retJsp; + } + + if(readVO == null || StringUtil.isEmpty(readVO.getSelItems())) { + model.addAttribute("message", "대출(예약)신청할 정보가 없습니다."); + return retJsp; + } + + if(StringUtil.isEmpty(readVO.getMngOrgCd())) { + model.addAttribute("message", "관리문화원 정보가 없습니다."); + return retJsp; + } + + if(StringUtil.isEmpty(readVO.getHopeReqPridDtmFrom() )) { + model.addAttribute("message", "방문희망일 시작일자를 확인할 수 없습니다."); + return retJsp; + } + + if(StringUtil.isEmpty(readVO.getHopeReqPridDtmTo() )) { + model.addAttribute("message", "방문희망일 종료일자를 확인할 수 없습니다."); + return retJsp; + } + + if(readVO.getHopeReqPridDtmFrom().compareTo(readVO.getHopeReqPridDtmTo()) > 0) { + model.addAttribute("message", "방문희망일 종료일자는 시작일자 이후이어야 합니다."); + return retJsp; + } + + + String selItems = readVO.getSelItems(); + + List list = collectionService.makeListOfCollectionVO(selItems); + + list = readService.insertReadItems(list, mbInfoId, readVO, fromCart); + list = collectionService.setDetailInfoForList(list, mbInfoId); + + model.addAttribute("readVO", readVO); + model.addAttribute("list", list); + if(fromCart) model.addAttribute("fromCart", fromCart ? "Y" : "N"); + + return retJsp; + } + + + /** + * 열람 목록 화면을 호출한다. + * + * @param request + * @param searchVO + * @param model + * @param message + * @return + * @throws Exception + */ + @Secured("ROLE_USER") + @RequestMapping("/read/listReadItems.do") + public String listReadItems(HttpServletRequest request, CollectionVO searchVO, ModelMap model, String message) throws Exception { + + String mbInfoId = getMbInfoId(request); + + if(StringUtil.isEmpty(mbInfoId)) { + message = "로그인하신 후, 이용바랍니다."; + model.addAttribute("message", message); + return "nlib/read/listReadItems"; + } + + // CSRF 토큰 생성 + String token = generateCsrfToken(request); + model.addAttribute("csrfToken", token); + + // 대출자료 문화원 목록 조회 + List> readMngOrgList = readService.listReadMngOrg(mbInfoId); + model.addAttribute("rentMngOrgList" , readMngOrgList); + + model.addAttribute("reqStatusDivCd", StringUtil.getString(searchVO.getReqStatusDivCd(), "A")); // 기본값 신청 + model.addAttribute("pageSize" , searchVO.getPageSize()); + model.addAttribute("pageIndex" , searchVO.getPageIndex()); + model.addAttribute("message" , message); + + return "nlib/read/listReadItems"; + } + + /** + * 대출 목록을 조회한다. + * + * @param req + * @return + */ + @Secured("ROLE_USER") + @RequestMapping(value="/read/listReadItemsAjax.do") + public ResponseEntity listReadItemsAjax( + HttpServletRequest request, + @RequestBody CollectionVO searchVO) { + + String message = null; + String mbInfoId = getMbInfoId(request); + int totCount = 0; + + if(StringUtil.isEmpty(mbInfoId)) { + message = "로그인하신 후, 이용바랍니다."; + } + + if(StringUtil.isEmpty(searchVO.getReqStatusDivCd())) { + searchVO.setReqStatusDivCd("A"); // 신청/예약 기본 설정 + } + + //------------------------------- + // JSON변환 응답 처리 + //------------------------------- + // JS-GRID 페이징 처리를 포함한 응답값 처리 + // {data: [{...}], + // itemsCount: 255 + // } + HashMap retMap = new HashMap(); + + if(StringUtil.isNotEmpty(mbInfoId)) { + + // 로그인 사용자 정보 설정 + searchVO.setMbInfoId(mbInfoId); + + // 조회 + // 대출상태구분코드("": 전체, A:신청, B:대출준비완료, C:취소, W:대출중, R0:정상반납, R1:연체반납, P:연체) + DataApiResVO resVO = readService.listReadItems(searchVO); + totCount = resVO.getRecordTotCount(); + retMap.put("data" , resVO.getRecordList()); + retMap.put("pageIndex" , resVO.getPageIndex()); + } else { + retMap.put("pageIndex" , searchVO.getPageIndex()); + retMap.put("message" , "로그인하신 후, 이용바랍니다."); + } + retMap.put("itemsCount", totCount); + + PagingVO pageVO = new PagingVO(); + pageVO.setPagingVO(totCount, searchVO.getPageIndex(), searchVO.getPageSize()); + retMap.put("pagingPageIndex" , pageVO.getPageIndex()); + retMap.put("pagingTotRecordCount", pageVO.getTotRecordCount()); + retMap.put("pagingStartPage" , pageVO.getStartPage()); + retMap.put("pagingEndPage" , pageVO.getEndPage()); + retMap.put("pagingLastPage" , pageVO.getLastPage()); + + return makeResponseEntityJson(retMap); + } + + @Secured("ROLE_USER") + @RequestMapping(value="/read/cancelReadItemAjax.do") + public ResponseEntity cancelReadItemAjax ( + HttpServletRequest request, + String csrfToken, + @RequestBody CollectionVO searchVO) { + + String resultMessage = null; + String resultCode = "F"; + String mbInfoId = getMbInfoId(request); + int totCount = 0; + + if(StringUtil.isEmpty(mbInfoId)) { + resultMessage = "로그인하신 후, 이용바랍니다."; + } + + if(!isValidCsrfToken(request, csrfToken)) { + resultMessage = "잘못된 접근입니다."; + } + + if(resultMessage != null && StringUtil.isEmpty(searchVO.getMngOrgCd())) { + resultMessage = "문화원정보가 부적합합니다. 다시 요청하여 주시기 바랍니다."; + } + + if(resultMessage != null && StringUtil.isEmpty(searchVO.getReqId())) { + resultMessage = "취소할 방문열람신청번호 정보가 부적합합니다. 다시 요청하여 주시기 바랍니다."; + } + + if(resultMessage != null && StringUtil.isEmpty(searchVO.getMasterId())) { + resultMessage = "취소할 자료정보 정보가 부적합합니다. 다시 요청하여 주시기 바랍니다."; + } + + //------------------------------- + // JSON변환 응답 처리 + //------------------------------- + // JS-GRID 페이징 처리를 포함한 응답값 처리 + // {data: [{...}], + // itemsCount: 255 + // } + HashMap retMap = new HashMap(); + + if(resultMessage == null) { + + // 로그인 사용자 정보 설정 + searchVO.setMbInfoId(mbInfoId); + + // 대출취소신청 + DataApiResVO resVO = readService.cancelReadItem(searchVO); + resultCode = resVO.getResultCode(); + resultMessage = resVO.getResultMessage(); + } + + retMap.put("resultCode" , resultCode); + retMap.put("resultMessage" , resultMessage); + + return makeResponseEntityJson(retMap); + } +} diff --git a/legacy/nlib/src/main/java/nlib/col/web/RentController.java b/legacy/nlib/src/main/java/nlib/col/web/RentController.java new file mode 100644 index 00000000..b5b00c22 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/web/RentController.java @@ -0,0 +1,306 @@ + +package nlib.col.web; + +import java.util.HashMap; +import java.util.List; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; + +import nlib.cmm.NlibCommonController; +import nlib.cmm.service.CodeService; +import nlib.cmm.service.NlibProperty; +import nlib.cmm.service.PagingVO; +import nlib.col.service.CollectionService; +import nlib.col.service.CollectionVO; +import nlib.col.service.RentService; +import nlib.restful.DataApiResVO; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : RentController.java
+ * 
+ * @Description : 대출 Controller
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 21. JSYOO 최초 생성 + * @ 2021.10. 14. KNKIM 대출목록 API방식 변경 및 화면설계서 적용 개발 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 7. 21. + * @version 1.0 + * + */ +@Controller +public class RentController extends NlibCommonController +{ + private static final Logger log = LoggerFactory.getLogger(RentController.class); + static final String DEFUALT_PAGE_SIZE = NlibProperty.getProperty("list.paging.page.size"); + + @Resource(name = "rentService") + private RentService rentService; + + @Resource(name = "collectionService") + private CollectionService collectionService; + + @Resource(name = "codeService") + private CodeService codeService; + + + /** + * 대출 목록 화면을 호출한다. + * + * @param request + * @param searchVO + * @param model + * @param message + * @return + * @throws Exception + */ + @Secured("ROLE_USER") + @RequestMapping("/rent/listRentItems.do") + public String listRentItems(HttpServletRequest request, CollectionVO searchVO, ModelMap model, String message) throws Exception { + + String mbInfoId = getMbInfoId(request); + + if(StringUtil.isEmpty(mbInfoId)) { + message = "로그인하신 후, 이용바랍니다."; + model.addAttribute("message", message); + return "nlib/rent/listRentItems"; + } + + // 대출자료 문화원 목록 조회 + List> rentMngOrgList = rentService.listRentMngOrg(mbInfoId); + model.addAttribute("rentMngOrgList" , rentMngOrgList); + + // CSRF 토큰 생성 + String token = generateCsrfToken(request); + model.addAttribute("csrfToken", token); + + model.addAttribute("bookLtRvStatusCd", StringUtil.getString(searchVO.getBookLtRvStatusCd(), "A")); + model.addAttribute("pageSize" , searchVO.getPageSize()); + model.addAttribute("pageIndex" , searchVO.getPageIndex()); + model.addAttribute("message" , message); + + return "nlib/rent/listRentItems"; + } + + /** + * 대출 목록을 조회한다. + * + * @param req + * @return + */ + @Secured("ROLE_USER") + @RequestMapping(value="/rent/listRentItemsAjax.do") + public ResponseEntity listRentItemsAjax( + HttpServletRequest request, + @RequestBody CollectionVO searchVO) { + + String message = null; + String mbInfoId = getMbInfoId(request); + int totCount = 0; + + if(StringUtil.isEmpty(mbInfoId)) { + message = "로그인하신 후, 이용바랍니다."; + } + + if(StringUtil.isEmpty(searchVO.getBookLtRvStatusCd())) { + searchVO.setBookLtRvStatusCd("A"); // 신청/예약 기본 설정 + } + + //------------------------------- + // JSON변환 응답 처리 + //------------------------------- + // JS-GRID 페이징 처리를 포함한 응답값 처리 + // {data: [{...}], + // itemsCount: 255 + // } + HashMap retMap = new HashMap(); + + if(StringUtil.isNotEmpty(mbInfoId)) { + + // 로그인 사용자 정보 설정 + searchVO.setMbInfoId(mbInfoId); + + // 조회 + // 대출상태구분코드("": 전체, A:신청, B:대출준비완료, C:취소, W:대출중, R0:정상반납, R1:연체반납, P:연체) + DataApiResVO resVO = rentService.listRentItems(searchVO); + totCount = resVO.getRecordTotCount(); + retMap.put("data" , resVO.getRecordList()); + retMap.put("pageIndex" , resVO.getPageIndex()); + } else { + retMap.put("pageIndex" , searchVO.getPageIndex()); + retMap.put("message" , "로그인하신 후, 이용바랍니다."); + } + retMap.put("itemsCount", totCount); + + PagingVO pageVO = new PagingVO(); + pageVO.setPagingVO(totCount, searchVO.getPageIndex(), searchVO.getPageSize()); + retMap.put("pagingPageIndex" , pageVO.getPageIndex()); + retMap.put("pagingTotRecordCount", pageVO.getTotRecordCount()); + retMap.put("pagingStartPage" , pageVO.getStartPage()); + retMap.put("pagingEndPage" , pageVO.getEndPage()); + retMap.put("pagingLastPage" , pageVO.getLastPage()); + + return makeResponseEntityJson(retMap); + } + + @Secured("ROLE_USER") + @RequestMapping(value="/rent/cancelRentItemAjax.do") + public ResponseEntity cancelRentItemAjax( + HttpServletRequest request, + String csrfToken, + @RequestBody CollectionVO searchVO) { + + String resultMessage = null; + String resultCode = "F"; + String mbInfoId = getMbInfoId(request); + int totCount = 0; + + if(StringUtil.isEmpty(mbInfoId)) { + resultMessage = "로그인하신 후, 이용바랍니다."; + } + + if(!isValidCsrfToken(request, csrfToken)) { + resultMessage = "잘못된 접근입니다."; + } + + if(StringUtil.isEmpty(searchVO.getMngOrgCd())) { + resultMessage = "문화원정보가 부적합합니다. 다시 요청하여 주시기 바랍니다."; + } + + if(StringUtil.isEmpty(searchVO.getRsrvId())) { + resultMessage = "취소할 대출(예약)선청번호 정보가 부적합합니다. 다시 요청하여 주시기 바랍니다."; + } + + //------------------------------- + // JSON변환 응답 처리 + //------------------------------- + // JS-GRID 페이징 처리를 포함한 응답값 처리 + // {data: [{...}], + // itemsCount: 255 + // } + HashMap retMap = new HashMap(); + + if(resultMessage == null) { + + // 로그인 사용자 정보 설정 + searchVO.setMbInfoId(mbInfoId); + + // 대출취소신청 + DataApiResVO resVO = rentService.cancelRentItem(searchVO); + resultCode = resVO.getResultCode(); + resultMessage = resVO.getResultMessage(); + } + + retMap.put("resultCode" , resultCode); + retMap.put("resultMessage" , resultMessage); + + return makeResponseEntityJson(retMap); + } + + @Secured("ROLE_USER") + @RequestMapping(value={"/rent/confirmRentFromCart.do", "/rent/confirmRent.do"}) + public String confirmRent(HttpServletRequest request, CollectionVO rentVO, ModelMap model, String csrfToken, String fromPage) throws Exception { + + boolean fromCart = request.getServletPath().contains("Cart.do"); + + String mbInfoId = getMbInfoId(request); + + if(StringUtil.isEmpty(mbInfoId)) { + model.addAttribute("message", "로그인 후, 이용해 주시기 바랍니다."); + return "nlib/rent/confirmRent"; + } + + if(rentVO == null || StringUtil.isEmpty(rentVO.getSelItems())) { + if(fromCart && StringUtil.getString(fromPage, "").equalsIgnoreCase("login")) { + // 비로그인자의 카트에서 신청을 실행하여 로그인 후 신청 진입으로 돌아온 경우 + return "redirect:/cart/listCartItems.do"; + } else { + model.addAttribute("message", "대출(예약)신청할 정보가 없습니다."); + return "nlib/rent/confirmRent"; + } + } + + String selItems = rentVO.getSelItems(); + + List list = collectionService.makeInfoListOfCollectionVO(selItems, mbInfoId); + + if(StringUtil.isEmpty(rentVO.getMngOrgNm()) && list != null && list.size() > 0) { + rentVO.setMngOrgCd(list.get(0).getMngOrgCd()); + rentVO.setMngOrgNm(list.get(0).getMngOrgNm()); + } + + // CSRF 토큰 생성 + String token = generateCsrfToken(request); + model.addAttribute("csrfToken", token); + + model.addAttribute("rentVO", rentVO); + model.addAttribute("list", list); + if(fromCart) model.addAttribute("fromCart", fromCart ? "Y" : "N"); + + return "nlib/rent/confirmRent"; + } + + @Secured("ROLE_USER") + @RequestMapping(value={"/rent/insertRentItemsFromCart.do", "/rent/insertRentItems.do"}) + public String insertRentItems(HttpServletRequest request, CollectionVO rentVO, String csrfToken, ModelMap model) throws Exception { + + boolean fromCart = request.getServletPath().contains("Cart.do"); + String retJsp = "nlib/rent/insertRentItems"; + String mbInfoId = getMbInfoId(request); + + if(StringUtil.isEmpty(mbInfoId)) { + model.addAttribute("message", "로그인 후, 이용해 주시기 바랍니다."); + return retJsp; + } + + if(!isValidCsrfToken(request, csrfToken)) { + model.addAttribute("message", "잘못된 접근입니다."); + return retJsp; + } + + if(rentVO == null || StringUtil.isEmpty(rentVO.getSelItems())) { + model.addAttribute("message", "대출(예약)신청할 정보가 없습니다."); + return retJsp; + } + + if(StringUtil.isEmpty(rentVO.getMngOrgCd())) { + model.addAttribute("message", "관리문화원 정보가 없습니다."); + return retJsp; + } + + String selItems = rentVO.getSelItems(); + + List list = collectionService.makeListOfCollectionVO(selItems); + + list = rentService.insertRentItems(list, mbInfoId, rentVO.getMngOrgCd(), fromCart); + list = collectionService.setDetailInfoForList(list, mbInfoId); + + model.addAttribute("rentVO", rentVO); + model.addAttribute("list", list); + if(fromCart) model.addAttribute("fromCart", fromCart ? "Y" : "N"); + + return retJsp; + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/col/web/RisController.java b/legacy/nlib/src/main/java/nlib/col/web/RisController.java new file mode 100644 index 00000000..646d263f --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/col/web/RisController.java @@ -0,0 +1,130 @@ + +package nlib.col.web; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URLEncoder; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +import nlib.cmm.NlibCommonController; +import nlib.cmm.service.CodeService; +import nlib.col.service.InterestService; +import nlib.col.service.RisService; +import nlib.col.service.RisVO; +import nlib.util.StringUtil; + + +/** + *
+ * @Class Name : RisController.java
+ * 
+ * @Description : Ris Controller
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 21. JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 7. 21. + * @version 1.0 + * + */ +@Controller +public class RisController extends NlibCommonController +{ + private static final Logger log = LoggerFactory.getLogger(RisController.class); + + @Resource(name = "codeService") + private CodeService codeService; + + @Resource(name="risService") + private RisService risService; + + @Resource(name = "interestService") + private InterestService interestService; + + /** + * RIS파일 다운로드 + * @param vo + * @throws IOException + */ + @RequestMapping(value="/ris/downloadRis.do") + public void downloadRis(HttpServletRequest request,HttpServletResponse response) throws IOException { + RisVO vo = new RisVO(); + vo.setMasterId(request.getParameter("risId")); + + vo = risService.selectRisInfo(vo); + + response.setContentType("text/plain"); + + String fileName = vo.getTt(); + String Ty=""; + // 브라우저 별 한글 인코딩 + String header = request.getHeader("User-Agent"); + if (header.contains("Edge")){ + fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20"); + response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + ".ris;\""); + } else if (header.contains("MSIE") || header.contains("Trident")) { // IE 11버전부터 Trident로 변경되었기때문에 추가해준다. + fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20"); + response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".ris;"); + } else if (header.contains("Chrome")) { + fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20"); + response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + ".ris\""); + } else if (header.contains("Opera")) { + fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1"); + response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + ".ris\""); + } else if (header.contains("Firefox")) { + fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1"); + response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".ris"); + } + + + Ty = StringUtil.getString(vo.getTy(), ""); + + if(Ty.length() > 3) + { + Ty = Ty.replaceFirst("IT_", ""); + } + + String s = "TY - " + Ty; + s+= "\nTI - " + StringUtil.getString(vo.getTt(), ""); + s+= "\nPY - " + StringUtil.getString(vo.getPy(), ""); + s+= "\nKW - " + StringUtil.getString(vo.getKw(), ""); + s+= "\nT2 - " + StringUtil.getString(vo.getT2(), ""); + s+= "\nA1 - " + StringUtil.getString(vo.getA1(), ""); + s+= "\nPP - " + StringUtil.getString(vo.getPp(), ""); + s+= "\nM1 - " + StringUtil.getString(vo.getM1(), ""); + s+= "\nL4 - " + StringUtil.getString(vo.getL4(), ""); + s+= "\nER - "; + + InputStream input = new ByteArrayInputStream(s.getBytes("UTF8")); + + int read = 0; + byte[] bytes = new byte[1024]; + OutputStream os = response.getOutputStream(); + + while ((read = input.read(bytes)) != -1) { + os.write(bytes, 0, read); + } + os.flush(); + os.close(); + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/info/service/InformService.java b/legacy/nlib/src/main/java/nlib/info/service/InformService.java new file mode 100644 index 00000000..afb6abde --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/info/service/InformService.java @@ -0,0 +1,67 @@ + +package nlib.info.service; + +import java.util.HashMap; + +/** + *
+ * @Class Name : InformService.java
+ * 
+ * @Description : 정보성 컨텐츠를 조회하는 서비스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 8. 27. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 8. 27. + * @version 1.0 + * + */ +public interface InformService +{ + + /* + * 이용약관을 조회한다. + */ + public HashMap selectInfoContent(String councilCd, String contentType) throws Exception; + + /* + * 이용약관을 조회한다. + */ + public HashMap selectTermsInfo(String councilCd) throws Exception; + + /* + * 개인정보처리방침을 조회한다. + */ + public HashMap selectPrivacyInfo(String councilCd) throws Exception; + + /* + * 인사말을 조회한다. + */ + public HashMap selectGreeting(String councilCd) throws Exception; + + /* + * 이용안내를 조회한다. + */ + public HashMap selectNCultureOperationInfo(String councilCd) throws Exception ; + + + /** + * 해당 문화원의 운영 시간 및 공휴일 추가 정보를 조회한다. + */ + public HashMap selectNCultureOpenTime(String orgCd) throws Exception; + + /* + * 찾아오는길 조회한다. + */ + public HashMap selectNCultureLocationInfo(String councilCd) throws Exception; + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/info/service/impl/InformDAO.java b/legacy/nlib/src/main/java/nlib/info/service/impl/InformDAO.java new file mode 100644 index 00000000..095515f6 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/info/service/impl/InformDAO.java @@ -0,0 +1,49 @@ +package nlib.info.service.impl; + +import java.util.HashMap; + +import egovframework.rte.psl.dataaccess.mapper.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *
+ * @Class Name : InformDAO.java
+ * 
+ * @Description : 이용안내 및 약관관련 정보 제공 DAO 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 27. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 27. + * @version 1.0 + * + */ +@Mapper("informDAO") +public interface InformDAO +{ + + /** + * 컨텐츠를 조회한다. + * + * @param reqVO + * @return + */ + public HashMap selectInfoContent(@Param("mngOrgCd") String mngOrgCd, @Param("contentType") String contentType) throws Exception; + + public HashMap selectOperationEnv(String orgCd) throws Exception; + + public HashMap selectNCultureAddr(String orgCd) throws Exception; + + public HashMap selectNCultureOpenTime(String orgCd) throws Exception; + + +} diff --git a/legacy/nlib/src/main/java/nlib/info/service/impl/InformServiceImpl.java b/legacy/nlib/src/main/java/nlib/info/service/impl/InformServiceImpl.java new file mode 100644 index 00000000..4979beb3 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/info/service/impl/InformServiceImpl.java @@ -0,0 +1,160 @@ +package nlib.info.service.impl; + +import java.util.HashMap; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import nlib.cmm.service.NlibProperty; +import nlib.info.service.InformService; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : InformServiceImpl.java
+ * 
+ * @Description : 정보성 컨텐츠를 조회하는 서비스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 27. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 27. + * @version 1.0 + * + */ +@Service("informService") +public class InformServiceImpl implements InformService +{ + private static final Logger log = LoggerFactory.getLogger(InformServiceImpl.class); + + @Resource(name="informDAO") + private InformDAO informDAO; + + /* + * 이용약관을 조회한다. + * + */ + public HashMap selectInfoContent(String orgCd, String contentType) throws Exception { + + if(StringUtil.isEmpty(orgCd)) orgCd = NlibProperty.getString("nlib.council.cd"); + + HashMap ret = informDAO.selectInfoContent(orgCd, contentType); + if(ret == null) { + ret = new HashMap(); + ret.put("TITLE", "(없음)"); + ret.put("CONTENT", "(해당 자료가 존재하지 않습니다.)"); + } + + return ret; + } + + /* + * 이용약관을 조회한다. + * + * (non-Javadoc) + * @see nlib.info.service.InformService#selectTermsInfo(nlib.restful.service.DataApiReqVO) + */ + public HashMap selectTermsInfo(String orgCd) throws Exception { + + return selectInfoContent(orgCd, "TERMS"); + } + + /* + * 개인정보처리방침을 조회한다. + * + * (non-Javadoc) + * @see nlib.info.service.InformService#selectPrivacyInfo(nlib.restful.service.DataApiReqVO) + */ + public HashMap selectPrivacyInfo(String orgCd) throws Exception { + + return selectInfoContent(orgCd, "PRIVACY"); + } + + /* + * 인사말을 조회한다. + * + * (non-Javadoc) + * @see nlib.info.service.InformService#selectGreeting(nlib.restful.service.DataApiReqVO) + */ + public HashMap selectGreeting(String orgCd) throws Exception { + + return selectInfoContent(orgCd, "GREETING"); + } + + /* + * 이용안내를 조회한다. + * + */ + public HashMap selectNCultureOperationInfo(String orgCd) throws Exception { + + HashMap operationInfo = new HashMap(); + + HashMap envValues = informDAO.selectOperationEnv(orgCd); + + // 대출안내 : 전체 문화원 공통 사항 + HashMap operation = selectInfoContent(NlibProperty.getString("nlib.council.cd"), "OPERATION"); + String content = (operation != null ? operation.get("CONTENT") : ""); + + if(envValues != null && StringUtil.isNotEmpty(content)) { + + for(String key : envValues.keySet()) { + content = content.replaceAll("%" + key + "%", StringUtil.getString(envValues.get(key), "")); + } + } + + // 문화원별 개폐시간 및 휴관일 + HashMap openTime = selectNCultureOpenTime(orgCd); + + operationInfo.put("informTitle" , (operation != null ? operation.get("TITLE") : "")); + operationInfo.put("informContent" , content); + operationInfo.put("openTime" , (openTime != null ? openTime.get("OPEN_TIME") : "")); + operationInfo.put("closeTime" , (openTime != null ? openTime.get("CLOSED_TIME") : "")); + operationInfo.put("closingInfo" , (openTime != null ? openTime.get("CLOSING_INFO") : "")); + + return operationInfo; + } + + /** + * 해당 문화원의 운영 시간 및 공휴일 추가 정보를 조회한다. + * + * @param orgCd + * @return + * @throws Exception + */ + public HashMap selectNCultureOpenTime(String orgCd) throws Exception { + return informDAO.selectNCultureOpenTime(orgCd); + } + + /* + * 찾아오는길 조회한다. + * + * (non-Javadoc) + * @see nlib.info.service.InformService#selectNCultureLocationInfo(nlib.restful.service.DataApiReqVO) + */ + public HashMap selectNCultureLocationInfo(String orgCd) throws Exception { + + HashMap locInfo = selectInfoContent(orgCd, "LOCATION"); + HashMap addrInfo = informDAO.selectNCultureAddr(orgCd); + + if(addrInfo != null) { + for(String key : addrInfo.keySet()) { + locInfo.put(key, addrInfo.get(key)); + } + } + + return locInfo; + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/info/web/InformController.java b/legacy/nlib/src/main/java/nlib/info/web/InformController.java new file mode 100644 index 00000000..aac23f91 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/info/web/InformController.java @@ -0,0 +1,184 @@ +package nlib.info.web; + +import java.util.HashMap; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; + +import nlib.cmm.NlibCommonController; +import nlib.cmm.service.NlibProperty; +import nlib.info.service.InformService; + +/** + *
+ * @Class Name : InformController.java
+ * 
+ * @Description : 이용안내 및 약관관련 정보 제공 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 27. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 27. + * @version 1.0 + * + */ +@Controller +public class InformController extends NlibCommonController { + + private static final Logger log = LoggerFactory.getLogger(InformController.class); + + @Resource(name="informService") + private InformService informService; + + + /** + * 이용약관을 조회한다. + * + * @param req + * @param authentication + * @param model + * @return + */ + @RequestMapping("/inform/selectTermsInfo.do") + public String selectTermsInfo(HttpServletRequest request, ModelMap model) throws Exception { + + HashMap ret = informService.selectTermsInfo(NlibProperty.getString("nlib.council.cd")); + + model.addAttribute("informTitle", ret.get("TITLE")); + model.addAttribute("informContent", ret.get("CONTENT")); + + return "nlib/inform/selectTermsInfo"; + } + + /** + * 개인정보처리방침을 조회한다. + * + * @param req + * @param authentication + * @param model + * @return + */ + @RequestMapping("/inform/selectPrivacyInfo.do") + public String selectPrivacyInfo(HttpServletRequest request, Authentication authentication, ModelMap model) throws Exception { + + HashMap ret = informService.selectPrivacyInfo(NlibProperty.getString("nlib.council.cd")); + + model.addAttribute("informTitle", ret.get("TITLE")); + model.addAttribute("informContent", ret.get("CONTENT")); + + return "nlib/inform/selectPrivacyInfo"; + } + + /** + * 인사말을 조회한다. + * + * @param req + * @param authentication + * @param model + * @return + */ + @RequestMapping("/inform/selectGreeting.do") + public String selectGreeting(HttpServletRequest request, Authentication authentication, ModelMap model) throws Exception { + + + HashMap ret = informService.selectGreeting(getCurCouncilCd(request)); + + model.addAttribute("informTitle", ret.get("TITLE")); + model.addAttribute("informContent", ret.get("CONTENT")); + model.addAttribute("councilNm", getCurCouncilNm(request)); + + return "nlib/inform/selectGreeting"; + } + + /** + * 이용안내를 조회한다. + * + * @param req + * @param authentication + * @param model + * @return + */ + @RequestMapping("/inform/selectNCultureOperationInfo.do") + public String selectNCultureOperationInfo(HttpServletRequest request, Authentication authentication, ModelMap model) throws Exception { + + // 이용안내 내용 + HashMap ret = informService.selectNCultureOperationInfo(getCurCouncilCd(request)); + model.addAttribute("informTitle", ret.get("informTitle")); + model.addAttribute("informContent", ret.get("informContent")); + model.addAttribute("openTime", ret.get("openTime")); + model.addAttribute("closeTime", ret.get("closeTime")); + model.addAttribute("closingInfo", ret.get("closingInfo")); + + return "nlib/inform/selectNCultureOperationInfo"; + } + + + /** + * 찾아오는길 조회한다. + * + * @param req + * @param authentication + * @param model + * @return + */ + @RequestMapping("/inform/selectNCultureLocationInfo.do") + public String selectNCultureLocationInfo(HttpServletRequest request, Authentication authentication, ModelMap model) throws Exception { + + HashMap ret = informService.selectNCultureLocationInfo(getCurCouncilCd(request)); + + model.addAttribute("mngOrgNm" , getCurCouncilNm(request)); + + model.addAttribute("informTitle" , ret.get("TITLE")); + model.addAttribute("informContent", ret.get("CONTENT")); + + model.addAttribute("openTime", ret.get("OPEN_TIME")); + model.addAttribute("closeTime", ret.get("CLOSED_TIME")); + model.addAttribute("closingInfo", ret.get("CLOSING_INFO")); + + model.addAttribute("zipCode" , ret.get("ZIP_CODE")); + model.addAttribute("address" , ret.get("ADDRESS")); + model.addAttribute("addressDetail", ret.get("ADDRESS_DETAIL")); + model.addAttribute("phoneNo" , ret.get("PHONE_NO")); + model.addAttribute("faxNo" , ret.get("FAX_NO")); + model.addAttribute("latitude" , ret.get("LATITUDE")); + model.addAttribute("longitude" , ret.get("LONGITUDE")); + + return "nlib/inform/selectNCultureLocationInfo"; + } + + /** + * 찾아오는길 조회한다. + * + * @param req + * @param authentication + * @param model + * @return + */ + @RequestMapping("/inform/selectNCultureLocationInfoPopup.do") + public String selectNCultureLocationInfoPopup(HttpServletRequest request, Authentication authentication, ModelMap model) throws Exception { + + HashMap ret = informService.selectNCultureLocationInfo(getCurCouncilCd(request)); + + model.addAttribute("informTitle", ret.get("TITLE")); + model.addAttribute("informContent", ret.get("CONTENT")); + + return "nlib/inform/selectNCultureLocationInfoPopup"; + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/mail/EmailSender.java b/legacy/nlib/src/main/java/nlib/mail/EmailSender.java new file mode 100644 index 00000000..9d5ea8de --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/mail/EmailSender.java @@ -0,0 +1,70 @@ +package nlib.mail; + +import java.io.Reader; +import java.util.Properties; + +import javax.mail.internet.MimeMessage; + +import org.apache.ibatis.io.Resources; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Component; + +import nlib.mail.service.EmailVO; + + +/** + *
+ * @Class Name : EmailSender.java
+ * 
+ * @Description : 메일전송
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 21. JSYOO 최초 생성 + * @ 2021.10. 14. KNKIM 대출목록 API방식 변경 및 화면설계서 적용 개발 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 7. 21. + * @version 1.0 + * + */ +@Component +public class EmailSender { + + @Autowired + protected JavaMailSender mailSender; + + /** + * 메일전송 + * @param email + * @throws Exception + */ + public void SendEmail(EmailVO email) throws Exception { + String resource = "egovframework/egovProps/globals.properties"; + Properties properties = new Properties(); + + Reader reader = Resources.getResourceAsReader(resource); + properties.load(reader); + + String senderName = properties.getProperty("system.notification.email.sender.name"); + String sender = properties.getProperty("system.notification.email.sender"); + + MimeMessage msg = mailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(msg, true, "utf-8"); + helper.setText(email.getContent(), true); //***HTML 적용 + helper.setTo(email.getReciver()); + helper.setSubject(email.getSubject()); + helper.setFrom(sender,senderName); + + mailSender.send(msg); + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/mail/service/EmailVO.java b/legacy/nlib/src/main/java/nlib/mail/service/EmailVO.java new file mode 100644 index 00000000..f4a05ddc --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/mail/service/EmailVO.java @@ -0,0 +1,35 @@ +package nlib.mail.service; + +public class EmailVO { + + private String subject; + private String content; + private String regdate; + private String reciver; + + public String getReciver() { + return reciver; + } + public void setReciver(String reciver) { + this.reciver = reciver; + } + + public String getSubject() { + return subject; + } + public void setSubject(String subject) { + this.subject = subject; + } + public String getContent() { + return content; + } + public void setContent(String content) { + this.content = content; + } + public String getRegdate() { + return regdate; + } + public void setRegdate(String regdate) { + this.regdate = regdate; + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/restful/DataApi.java b/legacy/nlib/src/main/java/nlib/restful/DataApi.java new file mode 100644 index 00000000..f5deb200 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/restful/DataApi.java @@ -0,0 +1,431 @@ +package nlib.restful; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.stereotype.Repository; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +import nlib.util.StringUtil; + + +/** + *
+ * @Class Name : DataApi.java
+ * 
+ * @Description : 통합자료관리시스템에 RESTful API를 통해 질의/응답을 처리한다.
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 9. KNKIM 최초 생성 + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 9. + * @version 1.0 + * + */ +@Repository("dataApi") +public class DataApi { + + private static final Logger log = LoggerFactory.getLogger(DataApi.class); + + /* DataApi 접속 서버 정보 */ + @Value("#{properties['dataapi.server.ip']}") + private String DAPI_SERVER_IP; + + @Value("#{properties['dataapi.server.port']}") + private String DAPI_SERVER_PORT; + + @Value("#{properties['dataapi.server.protocol']}") + private String DAPI_SERVER_PROTOCOL; + + /** + * 실제 RESTful API 서버로 요청을 전송하고, 응답받은 자료를 응답VO에 담아서 리턴한다. + * + * @param reqVO + * @param method + * @return + */ + public DataApiResVO request(DataApiReqVO reqVO) { + + log.debug("request > " + reqVO.getReqMethod()); + + DataApiResVO resVO = null; + + try { + + //----------------------------------- + // 입력값 검증작업 + //----------------------------------- + resVO = checkReqCommonParams(reqVO); + if(resVO != null) return resVO; + HttpMethod method = reqVO.getReqMethod(); + + //----------------------------------- + // 폼 파라메터 생성 작업 및 요청 처리 + //----------------------------------- + String url = DAPI_SERVER_PROTOCOL + "://" + DAPI_SERVER_IP + ("80".equals(DAPI_SERVER_PORT) ? "" : ":" + DAPI_SERVER_PORT) + reqVO.getReqUrl(); + log.debug("REQ URL : " + url); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + + ResponseEntity responseEntity = null; + RestTemplate restTemplate = new RestTemplate(); + restTemplate.getMessageConverters() + .add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8)); + + HttpStatus statusCode = HttpStatus.OK; + String resultXML = null; + + if(method == HttpMethod.GET) { + HttpEntity requestEntity = new HttpEntity(headers); + try { + responseEntity = restTemplate.exchange (makeRequestParamUrl(url, reqVO), method, requestEntity, String.class); + statusCode = responseEntity.getStatusCode(); + resultXML = responseEntity.getBody(); + } catch(HttpClientErrorException e) { + log.error("request > HttpClientErrorException 발생 : " + e.toString()); + resultXML = e.getResponseBodyAsString(); + statusCode = e.getStatusCode(); + } catch(HttpServerErrorException e) { + log.error("request > HttpServerErrorException 발생 : " + e.toString()); + resultXML = e.getResponseBodyAsString(); + statusCode = e.getStatusCode(); + } + } else if(method == HttpMethod.POST) { + MultiValueMap parameters = makeRequestParamMultiValueMap(reqVO); + parameters.forEach((k, v) -> log.debug("params > " + k + " : " + v)); + HttpEntity> requestEntity = new HttpEntity(parameters, headers); + try { + responseEntity = restTemplate.postForEntity(url, requestEntity , String.class); + statusCode = responseEntity.getStatusCode(); + resultXML = responseEntity.getBody(); + } catch(HttpClientErrorException e) { + log.error("request > HttpClientErrorException 발생 : " + e.toString()); + resultXML = e.getResponseBodyAsString(); + statusCode = e.getStatusCode(); + } catch(HttpServerErrorException e) { + log.error("request > HttpServerErrorException 발생 : " + e.toString()); + resultXML = e.getResponseBodyAsString(); + statusCode = e.getStatusCode(); + } + } else { + String message = "RESTFul API Http Method 설정 오류입니다. : POST, GET 방식만 허용됩니다."; + log.error("request > " + message); + return makeErrorRes("E_ERR_METHOD", message); + } + + //----------------------------------- + // 응답 처리 + //----------------------------------- + log.debug("RES StatusCode : " + statusCode); + log.debug("RES resultXML : " + resultXML); + + // 응답 자료 객체화 + resVO = convertXmlToResVO(resultXML); + + // 처리결과 코드 확인 + if(StringUtil.isEmpty(resVO.getResultCode())) { + String resultMessage = resVO.getResultMessage(); + if (statusCode == HttpStatus.OK) { + resVO.setResultCode("S_HTTP_STATUS_OK"); + resVO.setResultMessage(StringUtil.isEmpty(resultMessage) ? "정상처리되었습니다." : resultMessage); + } else { + resVO.setResultCode("E_STATUS_CODE_FAIL"); + resVO.setResultMessage(StringUtil.isEmpty(resultMessage) ? String.format("처리에 실패하였습니다. (HTTP상태코드 : %s)", statusCode.toString()) : resultMessage); + } + } + + log.debug("RES resVO : resultCode = " + resVO.getResultCode()); + log.debug("RES resVO : resultMessage = " + resVO.getResultMessage()); + + }catch(HttpClientErrorException e) { + log.error("request > HttpClientErrorException 발생 : " + e.toString()); + return makeErrorRes("E_REQ_HTTPCLIENTERROREXCEPTION", e.toString()); + }catch(HttpServerErrorException e) { + log.error("request > HttpServerErrorException 발생 : " + e.toString()); + return makeErrorRes("E_REQ_HTTPSERVERERROREXCEPTION", e.toString()); + } catch(Exception e) { + log.error("request > Exception 발생 : " + e.toString()); + return makeErrorRes("E_REQ_EXCEPTION", e.toString()); + } + + return resVO; + } + + /** + * [POST용] 요청 VO의 입력변수값을 API 요청을 위한 MultiValueMap 형태로 변환한다. + * + * @param reqVO + * @return + */ + public static MultiValueMap makeRequestParamMultiValueMap(DataApiReqVO reqVO) { + + MultiValueMap map = new LinkedMultiValueMap(); + + // 추가 정보 + if(reqVO.hasInfo()) { + HashMap info = reqVO.getInfo(); + for(String key : info.keySet()) { + String val = null; + if(DataApiVO.XML_EL_NAME_MB_INFO_ID.equals(key)) { + val = reqVO.getEncMbInfoId(); + } else { + val = info.get(key); + } + + /* + String encVal = null; + try { + encVal = URLEncoder.encode((String)val, "UTF-8"); + } catch(Exception e) { + log.error("makeRequestParamUrl > " + e.toString()); + continue; + } + */ + + map.add(key, val); + } + } + + if(reqVO.hasList()) { + HashMap>> listMap = reqVO.getListMap(); + if(listMap != null) { + for(String listName : listMap.keySet() ) { + List> list = listMap.get(listName); + + // 목록변수명은 있으나, 값이 없는 경우, 빈 배열 JSON값 설정 + if(list == null || list.size() < 1) { + map.add(listName, "[]"); + continue; + } + + // 목록변수명에 대한 목록 자료 존재하는 경우, JSON 생성 처리 + map.add(listName, makeJsonStrFromListMap(list)); + + } // for + } // if(listMap != null) + } // if(reqVO.hasList()) + + // 요청 파라메타 확인 + for(String key : map.keySet()) { + log.debug("MultiValueMap > " + key + "=" + map.get(key)); + } + + return map; + } + + /** + * [GET용] 요청 VO의 입력변수값을 API 요청을 위한 URL 쿼리 형태의 문자열로 리턴한다. + * + * @param url + * @param reqVO + * @return + */ + public static String makeRequestParamUrl(String url, DataApiReqVO reqVO) { + + UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url); + + // 추가 정보 + if(reqVO.hasInfo()) { + HashMap info = reqVO.getInfo(); + for(String key : info.keySet()) { + Object val = null; + if(DataApiVO.XML_EL_NAME_MB_INFO_ID.equals(key)) { + val = reqVO.getEncMbInfoId(); + } else { + val = info.get(key); + } + /* + String encVal = null; + try { + encVal = URLEncoder.encode((String)val, "UTF-8"); + } catch(Exception e) { + log.error("makeRequestParamUrl > " + e.toString()); + continue; + }*/ + builder.queryParam(key, (String)val); + } + } + + if(reqVO.hasList()) { + HashMap>> listMap = reqVO.getListMap(); + if(listMap != null) { + for(String listName : listMap.keySet() ) { + List> list = listMap.get(listName); + + // 목록변수명은 있으나, 값이 없는 경우, 빈 배열 JSON값 설정 + if(list == null || list.size() < 1) { + builder.queryParam(listName, "[]"); + continue; + } + + // 목록변수명에 대한 목록 자료 존재하는 경우, JSON 생성 처리 + builder.queryParam(listName, makeJsonStrFromListMap(list)); + + } // for + } // if(listMap != null) + } // if(reqVO.hasList()) + + String retUrl = builder.toUriString(); + log.debug("makeRequestParamUrl > queryUrl = " + retUrl); + + return retUrl; + } + + /** + * HashMap를 목록의 요소로 하는 리스트를 받아서 해당 요소들의 배열을 가진 JSON 객체 문자열을 생성하여 리턴한다. + * 예 : [{"name":"James", "city":"Miracle", ...}, ..., {"name":"James", "city":"Miracle", ...}] + * + * @param list + * @return + */ + public static String makeJsonStrFromListMap(List> list) { + + // 목록변수명은 있으나, 값이 없는 경우, 빈 배열 JSON값 설정 + if(list == null || list.size() < 1) { + return "[]"; + } + + // 목록변수명에 대한 목록 자료 존재하는 경우, JSON 생성 처리 + String jsonListStr = ""; + for(int i=0; i record = list.get(i); + + String jsonRecordStr = makeJsonStrFromMap(record); + if(StringUtil.isEmpty(jsonRecordStr)) continue; + + if(jsonListStr.length() > 0) jsonListStr += ","; + jsonListStr += jsonRecordStr; + } + return "[" + jsonListStr + "]"; + } + + /** + * HashMap을 받아서 해당 요소들을 맴버변수로 하는 JSON객체 문자열을 생성하여 리턴한다. + * 예 : {"name":"James", "city":"Miracle", ...} + * + * @param record + * @return + */ + public static String makeJsonStrFromMap(HashMap record) { + if(record == null || record.size() < 1) return null; + + String jsonRecordStr = ""; + for(String subKey : record.keySet()) { + String subVal = record.get(subKey); + if(jsonRecordStr.length() > 0) jsonRecordStr += ","; + jsonRecordStr += "\"" + subKey + ":" + (subVal == null? "null" : "\"" + subVal + "\""); + } + + return "{" + jsonRecordStr + "}"; + } + + /** + * 요청전 공통 필수 입력 매개변수를 체크하여 결과를 리턴한다. + * + * @param reqVO + * @return + * @throws Exception : + */ + public static DataApiResVO checkReqCommonParams(DataApiReqVO reqVO) { + + if(reqVO == null) { + return new DataApiResVO("ERR_NO_REQ", "데이터송수신 요청객체가 존재하지 않습니다."); + } + + if(StringUtil.isEmpty(reqVO.getReqUrl())) { + return new DataApiResVO("ERR_NO_RURL", "데이터 요청 업무ID에 대한 URL/RUI 정보가 존재하지 않습니다."); + } + + if(reqVO.getReqMethod() == null) { + return new DataApiResVO("ERR_NO_METHOD", "데이터 요청 방식 정보가 존재하지 않습니다."); + } + + return null; + } + + /** + * 처리결과 정보를 입력받아 DataApiResVO를 생성한다. + * + * @param resultCode + * @param resultMessage + * @return + */ + public static DataApiResVO makeErrorRes(String resultCode, String resultMessage) { + return new DataApiResVO(resultCode, resultMessage); + } + + /** + * 응답받은 XML 문자열을 DataApiResVO (내부 Map객체 포함) 객체로 변환하여 리턴한다. + * + * @param xmlStr + * @return + */ + public static DataApiResVO convertXmlToResVO(String xmlStr) { + + DataApiResVO resVO = new DataApiResVO(); + Map map = null; + + try { + map = XmlConverter.convert(xmlStr, DataApiVO.XML_EL_NAME_ROOT_NAME); + } catch(Exception e) { + resVO.setResultCode("ERR_RES_XML_FORMAT"); + resVO.setResultMessage(String.format("올바르지 않은 XML 형식의 응답입니다. : [%s]", xmlStr)); + log.error("convertXmlToResVO > " + resVO.getResultMessage()); + e.printStackTrace(); + return resVO; + } + + // 처리결과 확인 + List> recordList = null; + for( String key : map.keySet()) { + if(key.equalsIgnoreCase(DataApiVO.XML_EL_NAME_RESULT_CODE)) resVO.setResultCode((String)map.get(key)); + else if(key.equalsIgnoreCase(DataApiVO.XML_EL_NAME_RESULT_MESSAGE)) resVO.setResultMessage((String)map.get(key)); + else if(key.equalsIgnoreCase(DataApiVO.XML_EL_NAME_RECORD)) { + // 다건 목록 데이터인 경우 + Object obj = map.get(DataApiVO.XML_EL_NAME_RECORD); + if(obj instanceof HashMap) { + // 맵인 경우, 리스트형식으로 저장 처리 + List> list = new ArrayList>(); + list.add((HashMap)obj); + resVO.setList(DataApiVO.XML_EL_NAME_RECORD, list); + } else if(obj instanceof List) { + resVO.setList(DataApiVO.XML_EL_NAME_RECORD, (List)obj); + } else { + resVO.setResultCode("ERR_RES_XML_FORMAT_RECORD"); + resVO.setResultMessage(DataApiVO.XML_EL_NAME_RECORD + " 요소가 알수 없는 형식으로 객체화되었습니다. 확인바랍니다. : " + obj.toString()); + log.error("convertXmlToResVO > " + resVO.getResultMessage()); + return resVO; + } + } else resVO.putInfoItem(key, (String)map.get(key)); + } + + return resVO; + } + +} diff --git a/legacy/nlib/src/main/java/nlib/restful/DataApiReqVO.java b/legacy/nlib/src/main/java/nlib/restful/DataApiReqVO.java new file mode 100644 index 00000000..419a74bd --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/restful/DataApiReqVO.java @@ -0,0 +1,76 @@ +package nlib.restful; + +import org.springframework.http.HttpMethod; +import nlib.cmm.crypto.AriaCrypto; + +/** + *
+ * @Class Name : DataApiReqVO.java
+ * 
+ * @Description : RESTful API 요청 VO
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 6. 22. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 6. 22. + * @version 1.0 + * + */ +public class DataApiReqVO extends DataApiVO { + + /** + * 메소드를 GET으로 기본설정하여 객체 생성하는 생성자 + */ + public DataApiReqVO() { + this(null, HttpMethod.GET); + } + + /** + * 요청 URL을 받아 객체 생성하는 생성자 + * 메소드는 GET으로 설정된다. + * + * @param reqUrl + */ + public DataApiReqVO(String reqUrl) { + this(reqUrl, HttpMethod.GET); + } + + /** + * 요청 URL과 메소드를 받아 객체 생성하는 생성자 + * + * @param reqUrl + * @param reqMethod + */ + public DataApiReqVO(String reqUrl, HttpMethod reqMethod) { + this.reqUrl = reqUrl; + this.reqMethod = reqMethod; + } + + /** + * 사용자ID 값을 디코딩하여 리턴한다. + * + * @return + */ + public String getMbInfoIdWithDec() { + return AriaCrypto.decode(getMbInfoId()); + } + + /** + * 사용자ID를 인코딩하여 설정한다. + * + * @param mbInfoId + */ + public void setMbInfoIdWithEnc(String mbInfoId) { + setMbInfoId(mbInfoId); + } + +} diff --git a/legacy/nlib/src/main/java/nlib/restful/DataApiResVO.java b/legacy/nlib/src/main/java/nlib/restful/DataApiResVO.java new file mode 100644 index 00000000..73e0af61 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/restful/DataApiResVO.java @@ -0,0 +1,62 @@ +package nlib.restful; + +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : DataApiResVO.java
+ * 
+ * @Description : RESTful API 응답 VO
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 6. 22. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 6. 22. + * @version 1.0 + * + */ +public class DataApiResVO extends DataApiVO { + + /** + * 생성자 + * + * @param resultCode + * @param resultMessage + */ + public DataApiResVO() { + this.resultCode = null; + this.resultMessage = null; + } + + /** + * 처리결과 코드와 메시지를 입력받아 객체를 생성하는 생성자 + * + * @param resultCode + * @param resultMessage + */ + public DataApiResVO(String resultCode, String resultMessage) { + this.resultCode = resultCode; + this.resultMessage = resultMessage; + } + + /** + * 응답 처리결과가 성공인지의 여부를 리턴한다. + * 결과코드(resultCode)의 값이 "S"로 시작하는 경우 true 리턴한다. 이외 false 리턴한다. + * + * @return + */ + public boolean isSuccess() { + if(StringUtil.isEmpty(resultCode)) return false; + return (resultCode.trim().charAt(0) == 'S' || resultCode.trim().charAt(0) == 's'); + } + +} diff --git a/legacy/nlib/src/main/java/nlib/restful/DataApiVO.java b/legacy/nlib/src/main/java/nlib/restful/DataApiVO.java new file mode 100644 index 00000000..8fbf42bf --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/restful/DataApiVO.java @@ -0,0 +1,306 @@ +package nlib.restful; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpMethod; + +import nlib.cmm.crypto.AriaCrypto; +import nlib.cmm.service.NlibProperty; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : DataApiReqVO.java
+ * 
+ * @Description : RESTful API 송수신 공통 정보 VO 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 6. 22. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 6. 22. + * @version 1.0 + * + */ +public class DataApiVO { + + private static final Logger log = LoggerFactory.getLogger(DataApiVO.class); + + /* 입출력 정보 중 공통 및 특정 항목들에 대한 처리를 위한 API 요소명 */ + public static final String XML_EL_NAME_ROOT_NAME = "results"; // 결과값 최상위 요소명 + public static final String XML_EL_NAME_PAGE_SIZE = "rows"; // 페이지크기 : 한페이지에 보여줄 레코드수 + public static final String XML_EL_NAME_PAGE_INDEX = "page"; // 페이지번호 + public static final String XML_EL_NAME_PAGE_LAST_INDEX = "totPages"; // 총페이지수 + public static final String XML_EL_NAME_RECORD_TOT_COUNT = "records"; // 총레코드수 + public static final String XML_EL_NAME_MB_INFO_ID = "mbInfoId"; // 시스템 내부 사용자ID + public static final String XML_EL_NAME_RECORD = "record"; // 다건 목록 자료인 레코드 요소명 + public static final String XML_EL_NAME_RESULT_CODE = "resultCode"; // 처리결과 코드 + public static final String XML_EL_NAME_RESULT_MESSAGE = "resultMessage"; // 처리결과 메시지 + + /* 페이지 처리 기본값 */ + public static final int DEFAULT_PAGE_SIZE = NlibProperty.getInt("list.paging.page.size", 10); + public static final int DEFAULT_PAGE_INDEX = 1; + + String reqUrl = null; /* 요청업무ID에 대한 통합시스템의 응답 처리 프로그램 URI */ + HttpMethod reqMethod = HttpMethod.GET; /* 요청메소드구분값 */ + + String resultCode; /* 결과코드 */ + String resultMessage; /* 결과내용(오류내용) */ + + HashMap info = null; /* 입출력 정보 맵 */ + HashMap>> listMap = null; /* 다건 레코드 리스트를 관리하는 맵 */ + + public DataApiVO() { + super(); + } + + //-------------------------------------------------------------- + // 정보 항목 관련 IN/OUT 함수 + //-------------------------------------------------------------- + public void putInfoItem(String key, String value) { + if(StringUtil.isEmpty(key)) return; + if(info == null) info = new HashMap(); + + info.put(key, value); + } + public String getInfoItem(String key) { + return getInfoItem(key, null); + } + public String getInfoItem(String key, String defValue) { + if(StringUtil.isEmpty(key)) return defValue; + if(info == null) return defValue; + + String value = info.get(key); + + return StringUtil.isEmpty(value) ? defValue : value; + } + public void removeInfoItem(String key) { + if(StringUtil.isEmpty(key)) return; + if(info == null) return; + info.remove(key); + } + public boolean hasInfo() { + return (info != null && info.size() > 0); + } + + public boolean hasList() { + return (listMap != null && listMap.size() > 0); + } + + public boolean hasList(String listName) { + List list = getList(listName); + return (list != null && list.size() > 0); + } + + //-------------------------------------------------------------- + // 다건 레코드관련 함수 + //-------------------------------------------------------------- + public void addListItem(String listName, HashMap map) { + if(StringUtil.isEmpty(listName)) return; + List> list = getList(listName); + + if(list == null) list = new ArrayList>(); + list.add(map); + setList(listName, list); + return; + } + + public void removeListItem(String listName, int idx) { + if(StringUtil.isEmpty(listName)) return; + if(idx < 0) return; + + List> list = getList(listName); + if(list != null && list.size() > idx) list.remove(idx); + return; + } + + public void clearList(String listName) { + if(StringUtil.isEmpty(listName)) return; + + List> list = getList(listName); + if(list != null) list.clear(); + return; + } + + public List> getList(String listName) { + if(StringUtil.isEmpty(listName)) return null; + if(listMap == null || listMap.size() < 1) return null; + + return listMap.get(listName); + } + + public List> getRecordList() { + return getList(XML_EL_NAME_RECORD); + } + + public List getRecordList(Class clazz) { + List> list = getList(XML_EL_NAME_RECORD); + + if(list == null || list.size() < 1) return null; + + List retList = new ArrayList(); + for(HashMap map : list) { + T vo = (T)XmlConverter.convertMapToObject(map, clazz); + retList.add(vo); + } + + return retList; + } + + public void setList(String listName, List> list) { + if(StringUtil.isEmpty(listName)) return; + if(listMap == null) initList(); + + List> listOld = getList(listName); + if(listOld != null) listOld.clear(); + + listMap.put(listName, list); + return; + } + + private void initList() { + if(listMap == null) listMap = new HashMap>>(); + return; + } + + //-------------------------------------------------------------- + // 페이징 처리 관련 + //-------------------------------------------------------------- + public int getPageIndex() { + int pageIndex = 0; + try { + pageIndex = Integer.parseInt(getInfoItem(XML_EL_NAME_PAGE_INDEX, "0")); + } catch(NumberFormatException e) { + log.error("getPageIndex > " + e.toString()); + return 0; + } + return pageIndex; + } + public void setPageIndex(int pageIndex) { + setPageIndex("" + pageIndex); + } + public void setPageIndex(String pageIndex) { + putInfoItem(XML_EL_NAME_PAGE_INDEX, pageIndex); + } + public int getPageLastIndex() { + int pageLastIndex = 0; + try { + pageLastIndex = Integer.parseInt(getInfoItem(XML_EL_NAME_PAGE_LAST_INDEX, "0")); + } catch(NumberFormatException e) { + log.error("getPageLastIndex > " + e.toString()); + return 0; + } + return pageLastIndex; + } + public void setPageLastIndex(int pageLastIndex) { + setPageLastIndex("" + pageLastIndex); + } + public void setPageLastIndex(String pageLastIndex) { + putInfoItem("XML_EL_NAME_PAGE_LAST_INDEX", pageLastIndex); + } + public int getPageSize() { + int pageSize = 0; + try { + pageSize = Integer.parseInt(getInfoItem(XML_EL_NAME_PAGE_SIZE, "0")); + } catch(NumberFormatException e) { + log.error("getPageSize > " + e.toString()); + return 0; + } + return pageSize; + } + public void setPageSize(int pageSize) { + setPageSize("" + pageSize); + } + public void setPageSize(String pageSize) { + putInfoItem(XML_EL_NAME_PAGE_SIZE, pageSize); + } + public int getRecordTotCount() { + int recordTotCount = 0; + try { + recordTotCount = Integer.parseInt(getInfoItem(XML_EL_NAME_RECORD_TOT_COUNT, "0")); + } catch(NumberFormatException e) { + log.error("getRecordTotCount > " + e.toString()); + return 0; + } + return recordTotCount; + } + public void setRecordTotCount(int recordTotCount) { + setRecordTotCount("" + recordTotCount); + } + public void setRecordTotCount(String recordTotCount) { + putInfoItem(XML_EL_NAME_RECORD_TOT_COUNT, recordTotCount); + } + + //-------------------------------------------------------------- + // 사용자ID 처리 관련 + //-------------------------------------------------------------- + public String getMbInfoId() { + return getInfoItem(XML_EL_NAME_MB_INFO_ID); + } + public String getEncMbInfoId() { + return AriaCrypto.encode(getInfoItem(XML_EL_NAME_MB_INFO_ID)); + } + public void setMbInfoId(String mbInfoId) { + putInfoItem(XML_EL_NAME_MB_INFO_ID, mbInfoId); + } + + //-------------------------------------------------------------- + // GET & SET + //-------------------------------------------------------------- + public String getReqUrl() { + return reqUrl; + } + + public void setReqUrl(String reqUrl) { + this.reqUrl = reqUrl; + } + + public HttpMethod getReqMethod() { + return reqMethod; + } + + public void setReqMethod(HttpMethod reqMethod) { + this.reqMethod = reqMethod; + } + + public String getResultCode() { + return resultCode; + } + + public void setResultCode(String resultCode) { + this.resultCode = resultCode; + } + + public String getResultMessage() { + return resultMessage; + } + + public void setResultMessage(String resultMessage) { + this.resultMessage = resultMessage; + } + + public HashMap getInfo() { + return info; + } + + public void setInfo(HashMap info) { + this.info = info; + } + + public HashMap>> getListMap() { + return listMap; + } + +} diff --git a/legacy/nlib/src/main/java/nlib/restful/XmlConverter.java b/legacy/nlib/src/main/java/nlib/restful/XmlConverter.java new file mode 100644 index 00000000..193b2979 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/restful/XmlConverter.java @@ -0,0 +1,266 @@ +package nlib.restful; + +import java.io.ByteArrayInputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : XmlConverter.java
+ * 
+ * @Description : XML을 객체(HashMap, 기타 클래스)로 전환하는 유틸리티  
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021-07-20 KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021-07-20 + * @version 1.0 + * + */ +public class XmlConverter { + + private static final Logger log = LoggerFactory.getLogger(XmlConverter.class); + + public static HashMap convert(String xmlStr, String rootEleName) throws Exception { + + if(xmlStr == null) return null; + + ByteArrayInputStream bIn = new ByteArrayInputStream(xmlStr.getBytes()); + HashMap resMap = new HashMap(); + + try { + XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + XMLEventReader eventReader = inputFactory.createXMLEventReader(bIn); + + resMap = getElementValue(rootEleName, eventReader, null); + //log.debug("Converting XML to HashMap : Done >> " + resMap); + } catch (XMLStreamException e) { + log.error("convert XMLStreamException : " + e.toString()); + } catch (Exception e) { + log.error("convert Error : " + e.toString()); + } + + return resMap; + } + + /** + * @param rootElementName + * @param eventReader + * @param alreadyRootOpened : 부모 요소 찾기 없이 작업 진행할지 여부. false인 경우, rootElementName 요소를 찾아서 이후 값 추출 수행 + * @param startElement + * @return + * @throws Exception + */ + public static HashMap getElementValue( + String rootElementName + , XMLEventReader eventReader + , XMLEvent firstChildElement) throws Exception { + + HashMap retMap = new HashMap(); + + try { + + int depth = (firstChildElement == null ? 0 : 1); + StartElement startElement = null; + + XMLEvent event = firstChildElement; + + String upperElementName = null; + String elementName = null; //(firstChildElement == null ? null : firstChildElement.asStartElement().getName().getLocalPart()); + String content = null; + String elementValue = ""; + HashMap elementValues = null; + boolean hasSubElements = false; + boolean isFirst = true; + + while (eventReader.hasNext()) { + + // 이벤트가 함께 매개변수로 넘어온 경우, 처음 읽기 생략 + if(!isFirst || event == null) { + event = eventReader.nextEvent(); + } + + if(isFirst) isFirst = false; + + + // 1 레벨 엘리먼트 찾기 + if (depth == 0 && event.isStartElement() && event.asStartElement().getName().getLocalPart().equals(rootElementName)) { + depth++; + continue; + } + + // 1 레벨 엘리먼트내의 2 레벨 엘리먼트 찾기 + if(depth == 1 && elementName == null && event.isStartElement()) { + elementName = event.asStartElement().getName().getLocalPart(); + elementValue = ""; + elementValues = null; + hasSubElements = false; + depth++; + continue; + } + + // 2 레벨 엘리먼트 내용 찾기 + if(depth == 2 && elementName != null && event.isCharacters()) { + content = event.asCharacters().getData(); + if(StringUtil.isNotEmpty(content)) { + elementValue += content; + } + continue; + } + + // 2 레벨 엘리먼트 종료 + if(depth == 2 && elementName != null && event.isEndElement()) { + + if(!elementName.equals(event.asEndElement().getName().getLocalPart())) { + throw new Exception("XML문의 요소 시작/종료 태그가 일치하지 않습니다. : " + elementName + " 요소가 " + event.asEndElement().getName().getLocalPart() + "로 종료되었습니다."); + } + + addValue(retMap, elementName, elementValue); + //log.debug(elementName + " : -" + elementValue + "_"); + + elementName = null; + elementValue = ""; + depth--; + } + + // 2 레벨 엘리먼트 > 하위 엘리먼트 존재하는 경우 + if(depth == 2 && elementName != null && event.isStartElement()) { + HashMap subMap = getElementValue(elementName, eventReader, event); + addValue(retMap, elementName, subMap); + depth--; + elementName = null; + } + + // 1 레벨 엘리먼트 종료된 경우, 돌아가기 + if(depth == 1 && elementName == null && event.isEndElement() && rootElementName.equals(event.asEndElement().getName().getLocalPart())) { + depth--; + return retMap; + } + + } // while + + } catch (XMLStreamException e) { + log.error("getElementValue Error : " + e.toString()); + } catch (Exception e) { + log.error("getElementValue Error : " + e.toString()); + } + + return retMap; + } + + public static void addValue(HashMap map, String key, Object value) throws Exception { + if(map == null) throw new Exception("값을 넣을 Map 변수가 초기화되지 않았습니다."); + + if(key == null) return; + if(value == null) return; + + Object curValObj = map.get(key); + if(curValObj == null) { + map.put(key, value); + return; + } + + if(curValObj instanceof String || curValObj instanceof HashMap) { + List values = new ArrayList(); + values.add(curValObj); + values.add(value); + map.put(key, values); + } else if(curValObj instanceof List) { + ((ArrayList)curValObj).add(value); + } + + return; + } + + public static Object convertMapToObject(HashMap map, Class voClass) { + final ObjectMapper mapper = new ObjectMapper(); // jackson's objectmapper + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + final Object voObj = mapper.convertValue(map, voClass); + return voObj; + } + +/* + public static void main(String argv[]) throws Exception { + + XmlConverter xmlConverter = new XmlConverter(); + String xmlStr = "\r\n" + + "\r\n" + + "\r\n" + + " S\r\n" + + " 성공적으로 조회되었습니다.\r\n" + + " 10\r\n" + + " 1\r\n" + + " 15\r\n" + + " \r\n" + + " 1\r\n" + + " 101\r\n" + + " 공지사항 테스트\r\n" + + " 15\r\n" + + " 2021-07-19\r\n" + + " \r\n" + + " \r\n" + + " 2\r\n" + + " 101\r\n" + + " 공지사항 테스트\r\n" + + " 55\r\n" + + " 2021-07-19\r\n" + + " \r\n" + + " \r\n" + + " 3\r\n" + + " 101\r\n" + + " 공지사항 테스트\r\n" + + " 55\r\n" + + " 2021-07-19\r\n" + + " \r\n" + + " \r\n" + + " 4\r\n" + + " 101\r\n" + + " 공지사항 테스트\r\n" + + " 55\r\n" + + " 2021-07-19\r\n" + + " \r\n" + + " \r\n" + + " 5\r\n" + + " 101\r\n" + + " 공지사항 테스트\r\n" + + " 55\r\n" + + " 2021-07-19\r\n" + + " \r\n" + + " \r\n" + + " 6\r\n" + + " 101\r\n" + + " 공지사항 테스트\r\n" + + " 55\r\n" + + " 2021-07-19\r\n" + + " \r\n" + + " 3333\r\n" + + ""; + + HashMap resMap = xmlConverter.convert(xmlStr); + } + */ +} diff --git a/legacy/nlib/src/main/java/nlib/sch/service/NlibSearchCollectionVO.java b/legacy/nlib/src/main/java/nlib/sch/service/NlibSearchCollectionVO.java new file mode 100644 index 00000000..f43a9b45 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/sch/service/NlibSearchCollectionVO.java @@ -0,0 +1,65 @@ +package nlib.sch.service; + +import nlib.col.service.CollectionVO; + +/** + *
+ * @Class Name : NlibSearchCollectionVO.java
+ * 
+ * @Description : 소장자료 결과리스트 VO
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 23. JSYOO 최초 생성 + * @ 2021.10. 06. KKN 자료에 대한 세부 항목, 생성자 함수 추가 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 10. 22. + * @version 1.0 + * + */ +public class NlibSearchCollectionVO extends CollectionVO { + public String getTITLE() { + return title; + } + public void setTITLE(String tITLE) { + title = tITLE; + } + public String getMNGT_NO() { + return mngtNo; + } + public void setMNGT_NO(String mNGT_NO) { + mngtNo = mNGT_NO; + } + public String getCREAT_YYYY() { + return creatYyyy; + } + public void setCREAT_YYYY(String cREAT_YYYY) { + creatYyyy = cREAT_YYYY; + } + public String getMASTER_ID() { + return masterId; + } + public void setMASTER_ID(String mASTER_ID) { + masterId = mASTER_ID; + } + public String getORG_NM() { + return title; + } + public void setORG_NM(String oRG_NM) { + orgNm = oRG_NM; + } + public String getRPRS_THUMB_URL() { + return rprsThumbUrl; + } + public void setRPRS_THUMB_URL(String rPRS_THUMB_URL) { + rprsThumbUrl = rPRS_THUMB_URL; + } +} diff --git a/legacy/nlib/src/main/java/nlib/sch/service/NlibSearchService.java b/legacy/nlib/src/main/java/nlib/sch/service/NlibSearchService.java new file mode 100644 index 00000000..a1567de4 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/sch/service/NlibSearchService.java @@ -0,0 +1,33 @@ +package nlib.sch.service; + +import nlib.sch.service.NlibSearchVO; + + + +/** + *
+ * @Class Name : NlibSearchService.java
+ * 
+ * @Description : 소장자료 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 23. JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 9. 23. + * @version 1.0 + * + */ +public interface NlibSearchService { + /** 검색결과 받기 + * @return */ + NlibSearchVO getSearch(NlibSearchVO searchVO) throws Exception; +} diff --git a/legacy/nlib/src/main/java/nlib/sch/service/NlibSearchVO.java b/legacy/nlib/src/main/java/nlib/sch/service/NlibSearchVO.java new file mode 100644 index 00000000..401b8b4b --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/sch/service/NlibSearchVO.java @@ -0,0 +1,434 @@ +package nlib.sch.service; + +import java.util.ArrayList; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +import nlib.cmm.crypto.AriaCrypto; +import nlib.cmm.service.NlibProperty; +import nlib.cmm.service.PagingVO; +import nlib.col.service.CollectionVO; +import nlib.sch.service.impl.NlibSearchServiceImpl; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : NlibSearchVO.java
+ * 
+ * @Description : 소장자료 VO
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 23. JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 9. 23. + * @version 1.0 + * + */ +public class NlibSearchVO extends PagingVO { + private static final Logger log = LoggerFactory.getLogger(NlibSearchVO.class); + + private String query =""; //검색어 + private String collection = "lib_total"; //검색 대상 컬렉션 지정 + private String listCount = "10"; //컬렉션별 출력 결과수 + private String sort = "DATE"; //결과 정렬 DATE 날짜 내림차, RANK 정확도 내림차 + private String startCount = ""; //검색 결과 시작 페이지 + private String sfield = ""; //검색 영역 + private String creatYyyyStart = ""; //생산년도 검색(시작일) + private String creatYyyyEnd = ""; //생산년도 검색(종료일) + private String creatYyyyYn = ""; //미상포함 Y N + + private String collectionList = ""; //상세검색시 콜렉션 셀렉트 검색 + private String bookIndex = ""; //목차검색 + private String createStartDate = ""; //연대 검색(시작일) + private String createEndDate = ""; //연대 검색(종료일) + private String mngtNo = ""; //관리번호 + private String ageCode = ""; //시대 + private String useStatus = ""; //이용구분 + private String typeDivCd = ""; //자료유형 + private String subjectCode = ""; //주제분야 + private String orgNm = ""; //생산기관 + private String mngOrgCd = ""; //문화원코드 + + private String reQuery = ""; //결과내 재검색 + private String reQueryChk ="query"; //결과내재검색 체크 유지 + private String realQuery =""; //사용자페이지에 보여줄 검색내용 + private String lib_total_totalCount = "0"; //전체의 총 COUNT + private String lib_loan_totalCount = "0"; //대출의 총 COUNT + private String lib_online_totalCount = "0"; //온라인열람의 총 COUNT + private String lib_offline_totalCount = "0"; //방문열람의 총 COUNT + private String lib_etc_totalCount = "0"; //기타의 총 COUNT + + private String totalCount = "0"; //현재 선택된 콜렉션의 총 COUNT + + private String filter_class = ""; //필터 더보기버튼 유지+depth1 open + private String filter_category ; //필터 더보기버튼 유지+depth1 open + private String filter_agency ; // 생산기관은 depth1 이므로 filter_agency로 checked,검색필터유지 + private String filter_mylist; //검색결과 필터 순서 저장 + private String filter_creatYyyy =""; //생산년도 필터 + + private String first_agency ; //생산기관 선택 + private String first_category ; //주제분야(대) 선택 + private String second_category ; //주제분야(소) 선택 + private String first_class ; //자료유형(대) 선택 + private String second_class; //자료유형(소) 선택 + + private List resultList = new ArrayList<>(); // 자료 리스트 + private List> typeCountList = new ArrayList>(); // 자료유형 count 리스트 + private List> subjectCountList = new ArrayList>(); // 주제분야 count 리스트 + private List> orgCountList = new ArrayList>(); // 생산기관 count 리스트 + + public String getFilter_class() { + return filter_class; + } + public void setFilter_class(String filter_class) { + this.filter_class = filter_class; + } + public String getFilter_category() { + return filter_category; + } + public void setFilter_category(String filter_category) { + this.filter_category = filter_category; + } + public String getFilter_mylist() { + return filter_mylist; + } + public void setFilter_mylist(String filter_mylist) { + this.filter_mylist = filter_mylist; + } + public String getReQuery() { + return reQuery; + } + public void setReQuery(String reQuery) { + this.reQuery = reQuery; + } + public String getReQueryChk() { + return reQueryChk; + } + public void setReQueryChk(String reQueryChk) { + this.reQueryChk = reQueryChk; + } + public String getListCount() { + return listCount; + } + public void setListCount(String listCount) { + this.listCount = listCount; + } + public String getSort() { + return sort; + } + public void setSort(String sort) { + this.sort = sort; + } + public String getStartCount() { + return startCount; + } + public void setStartCount(String startCount) { + this.startCount = startCount; + } + public String getSfield() { + return sfield; + } + public void setSfield(String sfield) { + this.sfield = sfield; + } + public String getCreatYyyyStart() { + return creatYyyyStart; + } + public void setCreatYyyyStart(String creatYyyyStart) { + this.creatYyyyStart = creatYyyyStart; + } + public String getCreatYyyyEnd() { + return creatYyyyEnd; + } + public void setCreatYyyyEnd(String creatYyyyEnd) { + this.creatYyyyEnd = creatYyyyEnd; + } + public String getCreateStartDate() { + return createStartDate; + } + public void setCreateStartDate(String createStartDate) { + this.createStartDate = createStartDate; + } + public String getCreateEndDate() { + return createEndDate; + } + public void setCreateEndDate(String createEndDate) { + this.createEndDate = createEndDate; + } + public String getMngtNo() { + return mngtNo; + } + public void setMngtNo(String mngtNo) { + this.mngtNo = mngtNo; + } + public String getAgeCode() { + return ageCode; + } + public void setAgeCode(String ageCode) { + this.ageCode = ageCode; + } + public String getUseStatus() { + return useStatus; + } + public void setUseStatus(String useStatus) { + this.useStatus = useStatus; + } + public String getTypeDivCd() { + return typeDivCd; + } + public void setTypeDivCd(String typeDivCd) { + this.typeDivCd = typeDivCd; + } + public String getSubjectCode() { + return subjectCode; + } + public void setSubjectCode(String subjectCode) { + this.subjectCode = subjectCode; + } + public String getOrgNm() { + return orgNm; + } + public void setOrgNm(String orgNm) { + this.orgNm = orgNm; + } + public String getQuery() { + return query; + } + public void setQuery(String query) { + this.query = query; + } + public String getCollection() { + return collection; + } + public void setCollection(String collection) { + this.collection = collection; + } + public String getLib_total_totalCount() { + return lib_total_totalCount; + } + public void setLib_total_totalCount(String lib_total_totalCount) { + this.lib_total_totalCount = lib_total_totalCount; + } + public String getLib_loan_totalCount() { + return lib_loan_totalCount; + } + public void setLib_loan_totalCount(String lib_loan_totalCount) { + this.lib_loan_totalCount = lib_loan_totalCount; + } + public String getLib_online_totalCount() { + return lib_online_totalCount; + } + public void setLib_online_totalCount(String lib_online_totalCount) { + this.lib_online_totalCount = lib_online_totalCount; + } + public String getLib_offline_totalCount() { + return lib_offline_totalCount; + } + public void setLib_offline_totalCount(String lib_offline_totalCount) { + this.lib_offline_totalCount = lib_offline_totalCount; + } + public String getLib_etc_totalCount() { + return lib_etc_totalCount; + } + public void setLib_etc_totalCount(String lib_etc_totalCount) { + this.lib_etc_totalCount = lib_etc_totalCount; + } + public List getResultList() { + return resultList; + } + public void setResultList(List resultList) { + this.resultList = resultList; + } + public String getFirst_category() { + return first_category; + } + public void setFirst_category(String first_category) { + this.first_category = first_category; + } + public String getSecond_category() { + return second_category; + } + public void setSecond_category(String second_category) { + this.second_category = second_category; + } + public String getFirst_class() { + return first_class; + } + public void setFirst_class(String first_class) { + this.first_class = first_class; + } + public String getSecond_class() { + return second_class; + } + public void setSecond_class(String second_class) { + this.second_class = second_class; + } + public String getTotalCount() { + return totalCount; + } + public void setTotalCount(String totalCount) { + this.totalCount = totalCount; + } + public void add(MultiValueMap map,String name, String value) { + if(!"".equals(StringUtil.getString(value,""))) + { + map.add(name,value); + } + } + public String getFilter_creatYyyy() { + return filter_creatYyyy; + } + public void setFilter_creatYyyy(String filter_creatYyyy) { + this.filter_creatYyyy = filter_creatYyyy; + } + public String getCreatYyyyYn() { + return creatYyyyYn; + } + public void setCreatYyyyYn(String creatYyyyYn) { + this.creatYyyyYn = creatYyyyYn; + } + + public List> getTypeCountList() { + return typeCountList; + } + public void setTypeCountList(List> typeCountList) { + this.typeCountList = typeCountList; + } + public List> getSubjectCountList() { + return subjectCountList; + } + public void setSubjectCountList(List> subjectCountList) { + this.subjectCountList = subjectCountList; + } + public List> getOrgCountList() { + return orgCountList; + } + public void setOrgCountList(List> orgCountList) { + this.orgCountList = orgCountList; + } + public String getRealQuery() { + String realQuery=""; + if(StringUtil.getString(this.query,"") != "") + realQuery = this.query; + if(StringUtil.getString(this.reQuery,"") != "") + { + if(realQuery.length() > 0) + { + realQuery += "(" + this.reQuery + ")"; + }else + { + realQuery = this.reQuery; + } + } + return realQuery; + } + + //검색요청시 URL 생성 + public MultiValueMap getSearchMap() { + + MultiValueMap map = new LinkedMultiValueMap(); + + try { + if(!StringUtil.isEmpty(this.query + " " + this.reQuery)) + add(map,"query",URLEncoder.encode(this.query + " " + this.reQuery , "UTF-8")); + + add(map,"collection",URLEncoder.encode(this.collection , "UTF-8")); + add(map,"sort",URLEncoder.encode(this.sort , "UTF-8")); + add(map,"startCount",URLEncoder.encode(this.startCount , "UTF-8")); + add(map,"sfield",URLEncoder.encode(this.sfield , "UTF-8")); + add(map,"CREAT_YYYY_START",URLEncoder.encode(this.creatYyyyStart , "UTF-8")); + add(map,"CREAT_YYYY_END",URLEncoder.encode(this.creatYyyyEnd , "UTF-8")); + add(map,"CREAT_YYYY_YN",URLEncoder.encode(this.creatYyyyYn , "UTF-8")); + add(map,"createStartDate",URLEncoder.encode(this.createStartDate , "UTF-8")); + add(map,"createEndDate",URLEncoder.encode(this.createEndDate , "UTF-8")); + add(map,"MNGT_NO",URLEncoder.encode(this.mngtNo , "UTF-8")); + add(map,"BOOK_INDEX",URLEncoder.encode(this.bookIndex , "UTF-8")); + add(map,"AGE_CODE",URLEncoder.encode(this.ageCode.replaceAll("[,]", "|") , "UTF-8")); + add(map,"USE_STATUS",URLEncoder.encode(this.useStatus , "UTF-8")); + add(map,"TYPE_DIV_CD",URLEncoder.encode(this.typeDivCd , "UTF-8")); + add(map,"SUBJECT_CODE",URLEncoder.encode(this.subjectCode , "UTF-8")); + add(map,"listCount",URLEncoder.encode(this.listCount , "UTF-8")); + add(map,"SUBJECT_CATE_DEPTH",URLEncoder.encode("2" , "UTF-8")); //주제분야 2뎁스까지 나오게 고정 + add(map,"DIV_CATE_DEPTH",URLEncoder.encode("2" , "UTF-8")); //자료유형 2뎁스까지 나오게 고정 + + add(map,"DTLS_TYPE_DIV_CD",URLEncoder.encode(StringUtil.getString(this.second_class,"").replace(",","|") , "UTF-8")); + add(map,"SUBJECT_CODE",URLEncoder.encode(StringUtil.getString(this.second_category,"").replace(",","|") , "UTF-8")); + add(map,"ORG_NM",URLEncoder.encode(StringUtil.getString(this.filter_agency,"").replace(",","|") , "UTF-8")); + add(map,"MNG_ORG_CD",URLEncoder.encode(this.mngOrgCd , "UTF-8")); //자료유형 2뎁스까지 나오게 고정 + } catch (UnsupportedEncodingException e) { + // TODO Auto-generated catch block + log.error("nlibSearchVO 검색엔진파라미터 매핑 > Exception 발생 : " + e.toString()); + } + + return map; + } + + // 탭별 total count set + public void setCollectionTotalCount (String collection, String totalCount) { + if(collection.equals("lib_loan")) + { + this.lib_loan_totalCount = totalCount; + }else if(collection.equals("lib_online")) + { + this.lib_online_totalCount = totalCount; + }else if(collection.equals("lib_offline")) + { + this.lib_offline_totalCount = totalCount; + }else if(collection.equals("lib_etc")) + { + this.lib_etc_totalCount = totalCount; + }else if(collection.equals("lib_total")) + { + this.lib_total_totalCount = totalCount; + } + } + public String getFirst_agency() { + return first_agency; + } + public void setFirst_agency(String first_agency) { + this.first_agency = first_agency; + } + public String getFilter_agency() { + return filter_agency; + } + public void setFilter_agency(String filter_agency) { + this.filter_agency = filter_agency; + } + public String getBookIndex() { + return bookIndex; + } + public void setBookIndex(String bookIndex) { + this.bookIndex = bookIndex; + } + public String getCollectionList() { + return collectionList; + } + public void setCollectionList(String collectionList) { + this.collectionList = collectionList; + } + public String getMngOrgCd() { + return mngOrgCd; + } + public void setMngOrgCd(String mngOrgCd) { + this.mngOrgCd = mngOrgCd; + } +} diff --git a/legacy/nlib/src/main/java/nlib/sch/service/impl/NlibSearchServiceImpl.java b/legacy/nlib/src/main/java/nlib/sch/service/impl/NlibSearchServiceImpl.java new file mode 100644 index 00000000..ab4146fb --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/sch/service/impl/NlibSearchServiceImpl.java @@ -0,0 +1,306 @@ +package nlib.sch.service.impl; + + + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.stereotype.Service; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import nlib.col.service.CollectionVO; +import nlib.sch.service.NlibSearchService; +import nlib.sch.service.NlibSearchVO; +import nlib.util.StringUtil; + + +/** + *
+ * @Class Name : NlibSearchServiceImpl.java
+ * 
+ * @Description : 소장자료
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 23. JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 9. 23. + * @version 1.0 + * + */ +@Service("nlibSearchService") +public class NlibSearchServiceImpl implements NlibSearchService{ + + private static final Logger log = LoggerFactory.getLogger(NlibSearchServiceImpl.class); + + /* DataApi 접속 서버 정보 */ + @Value("#{properties['search.searchIp']}") + private String SEARCH_IP; + + @Value("#{properties['search.searchPort']}") + private String SEARCH_PORT; + + @Value("#{properties['search.protocol']}") + private String SEARCH_PROTOCOL; + + public NlibSearchVO getSearch(NlibSearchVO searchVO) throws Exception + { + try + { + //검색엔진 페이지 셋팅 + searchVO.setListCount(Integer.toString(searchVO.getPageSize())); + searchVO.setStartCount(Integer.toString(searchVO.getPageIndex())); + + String collectionTemp=""; + String nameTemp=""; + + //----------------------------------- + // 폼 파라메터 생성 작업 및 요청 처리 + //----------------------------------- + String url = SEARCH_PROTOCOL + "://" + SEARCH_IP + ("80".equals(SEARCH_PORT) ? "" : ":" + SEARCH_PORT) + "/searchApi/searchApi.jsp"; + log.debug("REQ URL : " + url); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + + ResponseEntity responseEntity = null; + ResponseEntity allResponseEntity = null; + RestTemplate restTemplate = new RestTemplate(); + restTemplate.getMessageConverters() + .add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8)); + + //단일 탭 검색 + MultiValueMap parameters= searchVO.getSearchMap(); + + //전체 검색 (각 탭별 count가 목적) + collectionTemp = searchVO.getCollection(); + if("".equals(StringUtil.getString(searchVO.getCollectionList(), "")) || "ALL".equals(StringUtil.getString(searchVO.getCollectionList(), ""))) + { + searchVO.setCollection("ALL"); + }else + { + //상세검색시 콜렉션리스트만 카운트하기위해 추가. + searchVO.setCollection(searchVO.getCollectionList()); + } + + MultiValueMap allParameters= searchVO.getSearchMap(); + searchVO.setCollection(collectionTemp); + //post방식 + parameters.forEach((k, v) -> log.debug("params > " + k + " : " + v)); + allParameters.forEach((k, v) -> log.debug("allParams > " + k + " : " + v)); + HttpEntity> requestEntity = new HttpEntity(parameters, headers); + HttpEntity> allRequestEntity = new HttpEntity(allParameters, headers); + + responseEntity = restTemplate.postForEntity(url, requestEntity , String.class); + allResponseEntity = restTemplate.postForEntity(url, allRequestEntity , String.class); + + //----------------------------------- + // 응답 처리 + //----------------------------------- + HttpStatus statusCode = responseEntity.getStatusCode(); + log.debug("RES StatusCode : " + statusCode); + String resultXML = responseEntity.getBody(); + log.debug("RES resultXML : " + resultXML); + + HttpStatus allStatusCode = allResponseEntity.getStatusCode(); + log.debug("RES allStatusCode : " + allStatusCode); + String allResultXML = allResponseEntity.getBody(); + log.debug("RES allResultXML : " + allResultXML); + + //검색엔진 결과 json 파싱 + JsonParser jsonParser = new JsonParser(); + + + JsonObject jsonObject = null; + JsonObject tmp = null; + String collection = ""; + String totalCount = ""; + JsonArray jsonArray = null; + + //전체검색 결과 탭별 count + jsonObject = (JsonObject) jsonParser.parse(allResultXML); + jsonObject = (JsonObject) jsonObject.get("SearchQueryResult"); + jsonArray = (JsonArray) jsonObject.get("Collection"); + + for(int i=0;i list = new ArrayList<>(); + List> subjectMap = new ArrayList>(); + List> typeMap = new ArrayList>(); + List> orgMap = new ArrayList>(); + String code=""; + String code_up=""; + int j; + int k; + + for(int i=0;i0) + { + filterObject =(JsonObject) subjectList.get(0); + filterObject = (JsonObject) filterObject.get("Categories"); + subjectList = (JsonArray) filterObject.get("Category"); + }; + if(typeList.size()>0) + { + filterObject =(JsonObject) typeList.get(0); + filterObject = (JsonObject) filterObject.get("Categories"); + typeList = (JsonArray) filterObject.get("Category"); + }; + if(orgList.size()>0) + { + filterObject =(JsonObject) orgList.get(0); + filterObject = (JsonObject) filterObject.get("Categories"); + orgList = (JsonArray) filterObject.get("Category"); + }; + for(k = 0; k < subjectList.size(); k++){ + HashMap temp = new HashMap(); + filterObject = (JsonObject)subjectList.get(k); + nameTemp = filterObject.get("Name").getAsString(); + //상위코드값 + code_up = nameTemp.substring(nameTemp.indexOf("@")+1,nameTemp.indexOf("^")); + temp.put("category_nm_up",code_up); + + //코드값 + code = nameTemp.substring(nameTemp.lastIndexOf("@")+1); + temp.put("category_nm",code); + temp.put("category_cnt",filterObject.get("Count").getAsString()); + subjectMap.add(temp); + } + for(k = 0; k < typeList.size(); k++){ + HashMap temp = new HashMap(); + filterObject = (JsonObject)typeList.get(k); + nameTemp = filterObject.get("Name").getAsString(); + //상위코드값 + code_up = nameTemp.substring(nameTemp.indexOf("@")+1,nameTemp.indexOf("^")); + temp.put("class_nm_up",code_up); + + //코드값 + code = nameTemp.substring(nameTemp.lastIndexOf("@")+1); + temp.put("class_nm",code); + temp.put("class_cnt",filterObject.get("Count").getAsString()); + typeMap.add(temp); + } + for(k = 0; k < orgList.size(); k++){ + HashMap temp = new HashMap(); + filterObject = (JsonObject)orgList.get(k); + nameTemp = filterObject.get("Name").getAsString(); + if(!"null".equals(nameTemp)) { + temp.put("org_nm",nameTemp); + temp.put("org_cnt",filterObject.get("Count").getAsString()); + orgMap.add(temp); + } + } + } + + tmp = (JsonObject) tmp.get("DocumentSet"); + searchVO.setTotalCount(tmp.get("TotalCount").getAsString()); + colArray = (JsonArray) tmp.get("Document"); + + if(colArray != null) + { + //vo list로 json list 파싱 + for(j=0;j Exception 발생 : " + e.toString()); + } + return searchVO; + } +} + diff --git a/legacy/nlib/src/main/java/nlib/sch/util/DataMap.java b/legacy/nlib/src/main/java/nlib/sch/util/DataMap.java new file mode 100644 index 00000000..b9e8179d --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/sch/util/DataMap.java @@ -0,0 +1,196 @@ +package nlib.sch.util; + +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import egovframework.rte.psl.dataaccess.util.CamelUtil; + +/** + * @Class Name : DataMap.java + * @author Kdmistrator + * @version 1.0 + * DB 리턴 받을때 사용하거나 Map 타입으로 사용할때 사용한다. + */ +public class DataMap extends LinkedHashMap implements Map{ + private static final long serialVersionUID = 1L; + private static final Logger LOGGER = LoggerFactory.getLogger(DataMap.class); + + public static DataMap getNewDataMap(){ + return new DataMap(); + } + public static DataMap getNewDataMap(HttpServletRequest request){ + DataMap map = new DataMap(); + map.defaultSetInfo(request, map); + return map; + } + private void defaultSetInfo(HttpServletRequest request, DataMap map){ + map.setString("contentType",request.getContentType()); + map.setString("contextPath",request.getContextPath()); + map.setString("uri",request.getRequestURI()); + map.setString("protocol",request.getProtocol()); + map.setString("ip", NlibCmmUtil.getIpAddress(request)); + } + @SuppressWarnings("unchecked") + private static DataMap makePrameterMap(HttpServletRequest request){ + DataMap resultMap = new DataMap(); + Map maps = request.getParameterMap(); + Set keySet = maps.keySet(); + Iterator keys = keySet.iterator(); + while (keys.hasNext()) { + String key = keys.next(); + String[] value = maps.get(key); + if (value.length > 1){ + //for (String val : value) { + //resultMap.put(key, val); + //} + resultMap.put(key, value); + } else { + if(value[0] instanceof String) { + resultMap.put(key, value[0].toString()); + } else { + resultMap.put(key, value[0]); + } + } + } + resultMap.defaultSetInfo(request, resultMap); + return resultMap; + } + public static DataMap getParamMap(HttpServletRequest request){ + return makePrameterMap(request); + } + private static String nvlTrim(String obj) { + String result = ""; + if (obj != null) + result = obj.trim(); + return result; + } + public Object get(String key){ + Object o = null; + try { + o = super.get(key); + } catch (NullPointerException e) { + LOGGER.error("Error in get() key="+key, e); + } + return o; + } + public String [] getStringArray(String key) { + String [] r = null; + try { + if(super.get(key) instanceof String[]){ + r = (String [])super.get(key); + }else{ + r = new String[1]; + r[0]= getString(key); + } + } catch (NullPointerException e) { + LOGGER.error("Error in getStringArray() key="+key, e); + } + return r; + } + public String getString(String key) { + String r = ""; + try { + if(super.get(key) != null){ + r = super.get(key).toString(); + } + } catch (NullPointerException e) { + LOGGER.error("Error in getString() key="+key, e); + } + return r; + } + public int getInt(String key) { + return getInt(key, 0); + } + public int getInt(String key, int defaultInt) { + int result = 0; + String str = getString(key); + try { + if(StringUtils.isNotEmpty(str)) { + result = new Integer(str).intValue(); + } + } catch (NumberFormatException e) { + LOGGER.error("Error in getInt() key="+key+", getString(key)=="+getString(key), e); + result = defaultInt; + } + return result; + } + public long getLong(String key) { + return getLong(key, 0); + } + public long getLong(String key, long defaultLong) { + long result = 0; + String str = getString(key); + try { + if(StringUtils.isNotEmpty(str)) { + Double tmp = Double.parseDouble(str); + result = tmp.longValue(); + } + } catch (NumberFormatException e) { + LOGGER.error("Error in getLong() key="+key+", getString(key)=="+getString(key), e); + result = defaultLong; + } + return result; + } + public double getDouble(String key) { + return getDouble(key, 0); + } + public double getDouble(String key, double defaultDouble) { + double result = 0; + String str = getString(key); + try { + if(StringUtils.isNotEmpty(str)) { + result = new Long(str).doubleValue(); + } + } catch (NumberFormatException e) { + LOGGER.error("Error in getDouble() key="+key+", getString(key)="+getString(key), e); + result = defaultDouble; + } + return result; + } + public boolean getBoolean(String key){ + return getBoolean(key, false); + } + public boolean getBoolean(String key, boolean defaltValue){ + boolean result = defaltValue; + String strObj = nvlTrim(key); + if (strObj.length() > 0){ + result = strObj.toLowerCase().equals("true"); + } + return result; + } + public void setString(String key, String value){ + super.put(key, value); + } + public void setInt(String key, int value){ + super.put(key, value); + } + public void setInt(String key, String value){ + super.put(key, new Integer(value).intValue()); + } + public void setLong(String key, long value){ + super.put(key, value); + } + public void setLong(String key, String value){ + super.put(key, new Long(value).longValue()); + } + public void setDouble(String key, double value){ + super.put(key, value); + } + public void setDouble(String key, String value){ + super.put(key, new Double(value).doubleValue()); + } + public void setBoolean(String key, boolean value){ + super.put(key, new Boolean(value)); + } + public Object put(String key, Object value) { + return super.put(CamelUtil.convert2CamelCase((String) key), value); + } +} diff --git a/legacy/nlib/src/main/java/nlib/sch/util/NlibCmmUtil.java b/legacy/nlib/src/main/java/nlib/sch/util/NlibCmmUtil.java new file mode 100644 index 00000000..f325f9af --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/sch/util/NlibCmmUtil.java @@ -0,0 +1,281 @@ +package nlib.sch.util; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.math.NumberUtils; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import egovframework.rte.fdl.property.EgovPropertyService; +import egovframework.rte.psl.dataaccess.util.EgovMap; + + +/** + *
+ * @Class Name : NlibCmmUtil.java
+ * 
+ * @Description : Nlib 공통유틸
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 21. JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 7. 21. + * @version 1.0 + * + */ +@Component +public class NlibCmmUtil { + + private static final Logger LOGGER = LoggerFactory.getLogger(NlibCmmUtil.class); + public static String DEFAULT_DELIMITER = "-"; + protected static EgovPropertyService propertyService; + + @Resource(name = "propertiesService") + private EgovPropertyService propertyServiceInstance; + + @PostConstruct + private void init() { + propertyService = propertyServiceInstance; + } + public static String reflectionToString(Object obj) { + return ToStringBuilder.reflectionToString(obj); + } + + public static String clearXSS(String value) { + if (value == null || value.trim().equals("")) { + return ""; + } + String returnValue = value; + returnValue = returnValue.replaceAll("&", "&"); + returnValue = returnValue.replaceAll("<", "<"); + returnValue = returnValue.replaceAll(">", ">"); + returnValue = returnValue.replaceAll("'", "'"); + returnValue = returnValue.replaceAll("eval\\((.*)\\)", ""); + returnValue = returnValue.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\""); + returnValue = returnValue.replaceAll("\"", """); + returnValue = returnValue.replaceAll("\\(", "(").replaceAll("\\)", ")"); + returnValue = returnValue.replaceAll("script", ""); + returnValue = returnValue.replaceAll("alert", ""); + return returnValue; + } + + public static String escapeNewlineToBr(String text) { + String str = text; + if (StringUtils.isEmpty(str)) return str; + + if (str.indexOf("\\r") >= 0) str = str.replaceAll("\\\\r", "\r"); + if (str.indexOf("\\n") >= 0) str = str.replaceAll("\\\\n", "\n"); + if (str.indexOf("\r\n") >= 0 || str.indexOf("\n") >= 0 || str.indexOf("\r") >= 0) { + str = str.replaceAll("\\r\\n", "
"); + str = str.replaceAll("\\r", "
"); + str = str.replaceAll("\\n", "
"); + } + return str; + } + public static String escapeNewlineToSpace(String text) { + String str = text; + if (StringUtils.isEmpty(str)) return str; + if (str.indexOf("\\r") >= 0) str = str.replaceAll("\\\\r", "\r"); + if (str.indexOf("\\n") >= 0) str = str.replaceAll("\\\\n", "\n"); + if (str.indexOf("\r\n") >= 0 || str.indexOf("\n") >= 0 || str.indexOf("\r") >= 0) { + str = str.replaceAll("\\r\\n", ""); + str = str.replaceAll("\\r", ""); + str = str.replaceAll("\\n", ""); + } + str = str.replaceAll("\"", ""); + str = str.replaceAll("'", ""); + return str; + } + public static String cut(String text, int size) { + return cut(text, size, ""); + } + public static String cut(String text, int size, String suffix) { + if (text == null) { + return ""; + } + if (text.length() < size) { + return text; + } + size = size - suffix.length(); + return StringUtils.substring(text, 0, size) + suffix; + } + public static boolean isConsecutive(String str, int n) { + int sumOfDifferences = 0; + int lastTemp = 0; + Boolean consecutive = false; + for (int i = 0; i < str.length() - 1; i++) { + int temp = str.charAt(i) - str.charAt(i + 1); + if (temp != lastTemp) { + sumOfDifferences = 0; + } + if (temp == 1 || temp == -1) { + sumOfDifferences += temp; + } else { + sumOfDifferences = 0; + } + if (sumOfDifferences == n - 1 || sumOfDifferences == ((n - 1) * -1)) { + consecutive = true; + break; + } + lastTemp = temp; + } + return consecutive; + } + public static boolean regexFind(String str, String regex) { + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(str); + return matcher.find(); + } + public static String getIpAddress(HttpServletRequest req) { + String ipAddress = ""; + if (req.getHeader("X-Forwarded-For") == null) { + ipAddress = req.getRemoteAddr(); + } else { + ipAddress = req.getHeader("X-Forwarded-For"); + int idx = ipAddress.indexOf(','); + if (idx > -1) { + ipAddress = ipAddress.substring(0, idx); + } + } + return ipAddress; + } + + public static String getUrl(HttpServletRequest req, String domain) { + final String uri = req.getRequestURI(); + final String queryString = req.getQueryString(); + String url = ""; + url = domain + uri; + if (StringUtils.isNotBlank(queryString)) { + url += "?" + queryString; + } + return url; + } + public static int getTridentVersion(String userAgent) { + String lowerUserAgent = userAgent.toLowerCase(); + int start = lowerUserAgent.indexOf("trident/"); + if (start == -1) { + return 0; + } + String trident = lowerUserAgent.substring(start + 8, start + 9); + return NumberUtils.toInt(trident); + } + public static String getPropertyStr(String key) { + String str = ""; + if (org.apache.commons.lang3.StringUtils.isNotBlank(key)) str = propertyService.getString(key); + return str; + } + public static String deleteChar(String str) { + if (StringUtils.isEmpty(str)) return str; + + String regExpNumber = "[^0-9]"; + return str.replaceAll(regExpNumber, ""); + } + @SuppressWarnings("rawtypes") + public static boolean isEmpty(Map map, String key) { + boolean isEmpty = true; + if (map == null) return isEmpty; + + Object obj = map.get(key); + if ( obj != null + && !StringUtils.isEmpty(obj.toString()) + && !(obj+"").equals("null")) { + + isEmpty = false; + } + return isEmpty; + } + public static String[] getValueArr(List list, String key) { + String[] exidArr = null; + if (list == null || list.size() == 0) return exidArr; + exidArr = new String[list.size()]; + for (int i=0; i + * @Class Name : NlibSearchController.java + * + * @Description : 소장자료 Controller + * + * + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021) + * + * + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 21. JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 7. 21. + * @version 1.0 + * + */ +@Controller +public class NlibSearchController extends NlibCommonController { + + private static final Logger log = LoggerFactory.getLogger(NlibSearchController.class); + + @Value("#{properties['list.paging.page.size']}") + private String DEFUALT_PAGE_SIZE; + + @Resource(name = "cartService") + private CartService cartService; + + @Resource(name = "codeService") + private CodeService codeService; + + @Resource(name="risService") + private RisService risService; + + @Resource(name = "interestService") + private InterestService interestService; + + @Resource(name = "nlibProperty") + protected NlibProperty nlibProperty; + + @Resource(name = "collectionService") + private CollectionService collectionService; + + @Resource(name = "nlibSearchService") + private NlibSearchService nlibSearchService; + + + /** + * 소장자료 화면을 호출한다. + * + * @param req + * @return + */ + @RequestMapping(value = {"/search/searchList.do"} ) + public String searchList( + HttpServletRequest req + , Authentication authentication + , ModelMap model + , @ModelAttribute("searchVO") NlibSearchVO searchVO + , HttpServletRequest request + , HttpServletResponse res + , String csrfToken) throws Exception { + HttpSession session = request.getSession(); + String councilCd = (String)session.getAttribute("councilCd"); + + + //검색엔진파라미터로 문화원코드 + searchVO.setMngOrgCd(councilCd); + + List operList = new ArrayList(); + // 페이징 사이즈 코드 목록 조회 (DB방식으로 변경 2021.08.06 KNKIM) + List> pageSizeCodes = codeService.listCodes("PAGE_SIZE_OPTION"); + + if(searchVO.getPageIndex() < 1) searchVO.setPageIndex(1); + if(searchVO.getPageSize() < 1) searchVO.setPageSize(DEFUALT_PAGE_SIZE); + + searchVO.setQuery(StringUtil.getString(searchVO.getQuery(), "")); + searchVO.setReQuery(StringUtil.getString(searchVO.getReQuery(), "")); + + //결과내재검색만 입력했을경우 + if(searchVO.getQuery().length() == 0 && searchVO.getReQuery().length() > 0) + { + searchVO.setQuery(searchVO.getReQuery()); + searchVO.setReQuery(""); + searchVO.setReQueryChk("query"); + } + //검색엔진 + try + { + + searchVO = nlibSearchService.getSearch(searchVO); + + //페이지 셋팅 + PagingVO pageVO = new PagingVO(); + pageVO.setPagingVO(Integer.parseInt(searchVO.getTotalCount()), searchVO.getPageIndex(), searchVO.getPageSize()); + + String mbInfoId = getMbInfoId(request); + + if(StringUtil.isEmpty(mbInfoId)) { + // 검색엔진에서 받아온 masterId로 상세정보 조회 + operList = collectionService.setDetailInfoForList(searchVO.getResultList(), null); + } else { + // 검색엔진에서 받아온 masterId로 상세정보 조회 + operList = collectionService.setDetailInfoForList(searchVO.getResultList(), getMbInfoId(request)); + } + + // 원문보기·방문열람신청 둘 다 불가한 자료 목록에서 제외 + operList = operList.stream() + .filter(vo -> vo.isAbleOnline() || vo.isAbleReadNow()) + .collect(java.util.stream.Collectors.toList()); + + //결과 데이터 담기 + searchVO.setResultList(operList); + + model.addAttribute("pageVO", pageVO); + model.addAttribute("searchVO", searchVO); + + } + catch(NumberFormatException e) + { + log.error("searchList.do paging > NumberFormatException 발생 : " + e.toString()); + } + catch(Exception e) + { + log.error("searchList.do getSearch > Exception 발생 : " + e.toString()); + } + + //주제분야 목록 조회 + List> clsf = codeService.listCtClsfs(); + //자료유형 + List> firstClassList = codeService.listCodes("MASTER_TYPE_DIV_CD"); + List> secondClassList = codeService.listCodes("DTLS_TYPE_DIV_CD"); + + //검색엔진 주제분야 카운트 + List> subject= searchVO.getSubjectCountList(); + List> type= searchVO.getTypeCountList(); + + int count = 0; + // 검색엔진 건수 자료 조합 + for(int i=0; i paramMap + , ModelMap model + , @ModelAttribute("searchVO") NlibSearchVO searchVO + , HttpServletRequest request + , HttpServletResponse res + ) throws Exception { + HttpSession session = request.getSession(); + + String masterId = request.getParameter("masterId"); + String mbInfoId = getMbInfoId(request); + String councilCd = (String)session.getAttribute("councilCd"); + + CollectionVO colVO = new CollectionVO(); + + colVO.setMasterId(masterId); + colVO.setMbInfoId(StringUtil.getString(mbInfoId,"")); + colVO.setMngOrgCd(councilCd); + + collectionService.insertDataInquiryLog(colVO); + } + + /** + * 소장자료 상세조회 + * + * @param req + * @return + */ + @RequestMapping(value = "/search/searchItemDetail.do") + public String searchItemDetail( + Authentication authentication + , @RequestParam Map paramMap + , ModelMap model + , @ModelAttribute("searchVO") NlibSearchVO searchVO + , HttpServletRequest request + , HttpServletResponse res + ) throws Exception { + String new_addr = ""; + String m_url = request.getRequestURL().toString(); + String domainUrl = StringUtil.getHostName(m_url); + + String masterId = request.getParameter("masterId"); + CollectionVO collectionVO = collectionService.selectMngOrgInfo(masterId); + + new_addr = "https://" + domainUrl + ".nculture.org/search/searchItemDetail.do?masterId=" + masterId; + + + if(collectionVO != null && StringUtil.isNotEmpty(collectionVO.getDomainHostNm()) && !collectionVO.getDomainHostNm().equals(domainUrl)) + { + new_addr = "https://" + collectionVO.getDomainHostNm() + ".nculture.org/search/searchItemDetail.do?masterId=" + masterId; + res.sendRedirect(new_addr); + return null; + } + + HttpSession session = request.getSession(); + List mngOrgList = new ArrayList<>(); + List keywordList = new ArrayList<>(); + + CollectionVO vo = new CollectionVO(); + vo.setMasterId(masterId); + vo.setMbInfoId(getMbInfoId(request)); + + vo = collectionService.getItemInfo(vo); + + if(vo == null) + { + model.addAttribute("msg", "해당 자료를 조회할 수 없습니다.\\n관리자에게 문의하여 주시기 바랍니다."); + model.addAttribute("url","/search/searchList.do"); + return "nlib/cmm/alert"; + } + + String councilCd = (String)session.getAttribute("councilCd"); + vo.setMngOrgCd(councilCd); + //함께 볼만한 자료 + List seeTogetherListVO = collectionService.selectSeeTogetherList(vo); + //유사한 자료 + List similarListVO = collectionService.selectSimilarList(vo); + + //관리부서명 중복 제외하고 리스트생성 + for(int i=0; similarListVO.size() > i; i++) + { + if(!mngOrgList.contains(similarListVO.get(i).getDeptNm())) + { + mngOrgList.add(similarListVO.get(i).getDeptNm()); + } + } + + model.addAttribute("seeTogetherListVO", seeTogetherListVO); + model.addAttribute("similarListVO", similarListVO); + model.addAttribute("mngOrgList",mngOrgList); + //반납예정일 편집 + if(!(vo == null) && !StringUtil.getString(vo.getRtnExpctDd(),"").equals("")) + { + String strDate = vo.getRtnExpctDd(); + SimpleDateFormat dtFormat = new SimpleDateFormat("yyyyMMdd"); + SimpleDateFormat newDtFormat = new SimpleDateFormat("yyyy-MM-dd"); + Date formatDate = dtFormat.parse(strDate); + String strNewDtFormat = newDtFormat.format(formatDate); + vo.setRtnExpctDd(strNewDtFormat); + } + //키워드 편집 + if(!(vo == null) && !StringUtil.getString(vo.getKeyword(),"").equals("")) + { + String keyword_arr[] = vo.getKeyword().replace(',',';').split(";"); + + for(int i = 0; keyword_arr.length > i; i++) + { + //데이터마이그레이션으로 -데이터가 들어가있어서 키워드에서 -하나인 자료는 제외 + if(!keyword_arr[i].equals("-")) + { + keywordList.add(keyword_arr[i]); + } + } + } + //목차 편집 + if(!(vo == null) && !StringUtil.getString(vo.getBookIndex(),"").equals("")) + { + String bookIndex = vo.getBookIndex(); + bookIndex = bookIndex.replace("---","-"); + + if(bookIndex.indexOf("***") != -1) + bookIndex = bookIndex.substring(0, bookIndex.indexOf("***")); + + vo.setBookIndex(bookIndex); + } + MimetypesFileTypeMap mimetypesFileTypeMap = new MimetypesFileTypeMap(); + String imageType = mimetypesFileTypeMap.getContentType(vo.getRprsThumbUrl()); + String imagePath = ""; + String councilDnsHost = StringUtil.getHostName(request.getRequestURL().toString()); + + //이미지 확장자를 판별할 수 없을때 + if(!imageType.startsWith("image")) + { + imageType = "jpeg"; + imagePath = "https://" + councilDnsHost + ".nculture.org/images/meta_og_image.jpg"; + }else { + imagePath = StringUtil.getString(vo.getRprsThumbUrl(),""); + } + + model.addAttribute("imageType",imageType); + model.addAttribute("imagePath",imagePath); + model.addAttribute("keywordList",keywordList); + model.addAttribute("result", vo); + model.addAttribute("searchVO", searchVO); + return "nlib/collection/searchItemDetail"; + } + + /** + * 소장자료 상세조회 + * + * @param req + * @return + */ + @RequestMapping(value = "/search/searchItemGate.do") + public void searchItemGate( + Authentication authentication + , @RequestParam Map paramMap + , ModelMap model + , @ModelAttribute("searchVO") NlibSearchVO searchVO + , HttpServletRequest request + , HttpServletResponse res + ) throws Exception { + String new_addr = ""; + String m_url = request.getRequestURL().toString(); + String domainUrl = m_url.substring(m_url.indexOf("//") + 2 , m_url.indexOf(".")); + + String masterId = request.getParameter("masterId"); + CollectionVO collectionVO = collectionService.selectMngOrgInfo(masterId); + + new_addr = "https://" + domainUrl + ".nculture.org/search/searchItemDetail.do?masterId=" + masterId; + if(collectionVO == null) + { + res.sendRedirect(new_addr); + }else { + if(StringUtil.isNotEmpty(collectionVO.getDomainHostNm()) && !collectionVO.getDomainHostNm().equals(domainUrl)) + { + new_addr = "https://" + collectionVO.getDomainHostNm() + ".nculture.org/search/searchItemDetail.do?masterId=" + masterId; + } + res.sendRedirect(new_addr); + } + } + /** + * YOURLS의 API를 통해서 단축URL 가져오기 + * @param model + * @param commandMap + * @param req + * @param res + * @return + * @throws EgovBizException + */ + @RequestMapping(value="/search/shorturl-data.do") + @ResponseBody + public String shorturl ( + ModelMap model + , HttpServletRequest req + , HttpServletResponse res + ) throws EgovBizException { + String returnUrl = ""; + DataMap paramMap = DataMap.getParamMap(req); + BufferedReader br = null; + try { + String originUrl = URLEncoder.encode(paramMap.getString("url"), "UTF-8"); + URL url = new URL( NlibProperty.getProperty("shorturl.api") + "&action=shorturl&format=xml&title=nculture&url=" + originUrl); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("GET"); + //con.setRequestProperty("Authorization", header); + int responseCode = con.getResponseCode(); + if(responseCode==200) { // 정상 호출 + br = new BufferedReader(new InputStreamReader(con.getInputStream())); + } else { // 에러 발생 + br = new BufferedReader(new InputStreamReader(con.getErrorStream())); + + } + + String inputLine; + StringBuffer response = new StringBuffer(); + while ((inputLine = br.readLine()) != null) { + response.append(inputLine); + } + + String str = response.toString(); + Pattern pattern = Pattern.compile("(.+?)"); + Matcher matcher = pattern.matcher(str); + + while (matcher.find()) { + returnUrl = matcher.group(1); + if(matcher.group(1) == null){ + break; + } + } + } catch (IOException e) { + log.error("shorturl-data.do 단축url > IOException 발생 : " + e.toString()); + } + finally + { + try + { + if(br != null)br.close(); + } + catch (IOException e) + { + log.error("shorturl-data.do 단축url > IOException 발생 : " + e.toString()); + } + } + return returnUrl; + } + /** + * 상세검색 팝업. + * + * (2021.10.19 YJS 추가) + * + * @param request + * @param model + * @return + * @throws Exception + */ + @RequestMapping(value="/search/getDetailedSearchFormPopup.do") + public String getDetailedSearchFormPopup(HttpServletRequest request, ModelMap model) throws Exception { + + //주제분야 목록 조회 + List> clsf = codeService.listCtClsfs(); + model.addAttribute("firstCategoryList", clsf); + model.addAttribute("secondCategoryList", clsf); + + //자료유형 + model.addAttribute("firstClassList", codeService.listCodes("MASTER_TYPE_DIV_CD")); + model.addAttribute("secondClassList", codeService.listCodes("DTLS_TYPE_DIV_CD")); + + // CSRF 토큰 생성 + String token = generateCsrfToken(request); + model.addAttribute("csrfToken", token); + return "nlib/search/getDetailedSearchFormPopup"; + } + +} diff --git a/legacy/nlib/src/main/java/nlib/security/CustomRequestCache.java b/legacy/nlib/src/main/java/nlib/security/CustomRequestCache.java new file mode 100644 index 00000000..64ec938f --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/security/CustomRequestCache.java @@ -0,0 +1,38 @@ +package nlib.security; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.web.savedrequest.HttpSessionRequestCache; + +/** + *
+ * @Class Name : CustomRequestCache.java
+ * 
+ * @Description : 스프링 시큐리티에 권한 실패시 HttpSessionRequestCache에 저장되는 정보 커스터마이징 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 11. 16. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 11. 16. + * @version 1.0 + * + */ +public class CustomRequestCache extends HttpSessionRequestCache { + + @Override + public void saveRequest(HttpServletRequest request, HttpServletResponse response) { + + // Ajax Reqeust 들도 캐쉬되도록 처리함 + super.saveRequest(request, response); + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/security/SecUserDAO.java b/legacy/nlib/src/main/java/nlib/security/SecUserDAO.java new file mode 100644 index 00000000..96e9f8b3 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/security/SecUserDAO.java @@ -0,0 +1,63 @@ +package nlib.security; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Repository; + +import egovframework.com.cmm.service.impl.EgovComAbstractDAO; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : SecUserDAO.java
+ * 
+ * @Description : 스프링 시큐리티용 사용자VO인  UserDetails(SecUserVO)의 형식으로 사용자 정보를 조회하여 저장하게 제공하는 DAO 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 9. KNKIM 최초 생성 + * @ 2021.08.13. KNKIM RESTfulAPI -> DB직접 접근 방식으로 변경 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 9. + * @version 1.0 + * + */ +@Repository("secUserDAO") +public class SecUserDAO extends EgovComAbstractDAO { + + private static final Logger log = LoggerFactory.getLogger(SecUserDAO.class); + + public SecUserVO loadUserByUsername(String loginUserId) { + + SecUserVO uInfo = (SecUserVO)selectOne("SecUserDAO.loadUserByUsername", loginUserId); + + if(uInfo == null) { + uInfo = new SecUserVO(); + } else { + // 개인정보 복호화 + uInfo.decodePrivateInfo(); + + // 다중 권한 설정 + String authorities = (String)uInfo.getAuthorityList(); + if(StringUtil.isEmpty(authorities)) { + uInfo.addAuthority(SecUserVO.DEFAULT_ROLE); + } else { + String[] authArr = authorities.split(","); + for(String auth : authArr) { + uInfo.addAuthority(auth); + } + } + } + + return uInfo; + } + +} diff --git a/legacy/nlib/src/main/java/nlib/security/SecUserDetailsService.java b/legacy/nlib/src/main/java/nlib/security/SecUserDetailsService.java new file mode 100644 index 00000000..c2f10641 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/security/SecUserDetailsService.java @@ -0,0 +1,58 @@ +package nlib.security; + + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +/** + *
+ * @Class Name : NlibUserDetailsService.java
+ * 
+ * @Description : 스프링 시큐리티용으로, 통합자료시스템으로 부터 사용자 정보를 조회하여 UserDetails 형식으로 제공하는 클래스  
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 7. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 7. + * @version 1.0 + * + */ +@Service("userDetailsService") +public class SecUserDetailsService implements UserDetailsService { + + private static final Logger log = LoggerFactory.getLogger(SecUserDetailsService.class); + + @Resource (name = "secUserDAO") + private SecUserDAO secUserDAO; + + + /* + * 사용자명(ID)으로 사용자정보를 조회해 온다. + */ + @Override + public UserDetails loadUserByUsername(String loginUserId) throws UsernameNotFoundException { + + SecUserVO secUserVO = secUserDAO.loadUserByUsername(loginUserId); + + if(secUserVO == null) { + throw new UsernameNotFoundException(loginUserId); + } + return secUserVO; + } + +} diff --git a/legacy/nlib/src/main/java/nlib/security/SecUserVO.java b/legacy/nlib/src/main/java/nlib/security/SecUserVO.java new file mode 100644 index 00000000..770ebd6a --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/security/SecUserVO.java @@ -0,0 +1,126 @@ +package nlib.security; + +import java.util.ArrayList; +import java.util.Collection; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import nlib.cmm.service.NlibProperty; +import nlib.user.service.NlibLoginVO; + +/** + *
+ * @Class Name : SecUserVO.java (VO)
+ * 
+ * @Description : 스프링 시큐리티용으로, UserDtails 인터페이스를 구현한 사용자정보 VO 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 7. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 7. + * @version 1.0 + * + */ +public class SecUserVO extends NlibLoginVO implements UserDetails { + + private static final long serialVersionUID = -8274004534207618048L; + + /* 권한 ROLE 명칭 */ + public static final String ROLE_USER = NlibProperty.getString("auth.role.user"); // 일반사용자 + public static final String ROLE_ADMIN = NlibProperty.getString("auth.role.admin"); // 관리자 + public static final String ROLE_SYSTEM = NlibProperty.getString("auth.role.system"); // 시스템관리자 + + /* 기본권한 ROLE */ + public static final String DEFAULT_ROLE = ROLE_USER; + + ArrayList auth = null; /* 권한 목록 */ + + public void addAuthority(String authName) { + if(auth == null) auth = new ArrayList(); + auth.add(new SimpleGrantedAuthority(authName)); + } + + /* 계정이 갖고있는 권한 목록을 리턴한다. + * (non-Javadoc) + * @see org.springframework.security.core.userdetails.UserDetails#getAuthorities() + */ + @Override + public Collection getAuthorities() { + return auth; + } + + /* 계정의 비밀번호를 리턴한다. + * (non-Javadoc) + * @see org.springframework.security.core.userdetails.UserDetails#getPassword() + */ + @Override + public String getPassword() { + return super.getPassword(); + } + + /* 계정의 이름을 리턴한다. (사용자ID:email형식의 LOGIN_USER_ID 정보) + * (non-Javadoc) + * @see org.springframework.security.core.userdetails.UserDetails#getUsername() + */ + @Override + public String getUsername() { + // 로그인하는 지방문화원 코드 + 로그인사용자ID + return super.getUsername(); + } + + /* 계정이 만료되지 않았는 지 여부를 리턴한다. (true: 만료안됨) + * (non-Javadoc) + * @see org.springframework.security.core.userdetails.UserDetails#isAccountNonExpired() + */ + @Override + public boolean isAccountNonExpired() { + + // 계정 만료 기능 사용안함 + return true; + } + + /* 계정이 잠겨있지 않은 지 여부를 리턴한다. (true: 잠기지 않음) + * (non-Javadoc) + * @see org.springframework.security.core.userdetails.UserDetails#isAccountNonLocked() + */ + @Override + public boolean isAccountNonLocked() { + + // SNS 로그인만 허용하므로, 별도 계정 LOCK 기능 불필요 + return true; + } + + /* 비밀번호가 만료되지 않았는 지 리턴한다. (true: 만료안됨) + * (non-Javadoc) + * @see org.springframework.security.core.userdetails.UserDetails#isCredentialsNonExpired() + */ + @Override + public boolean isCredentialsNonExpired() { + + // 비밀번호 만료 기능 사용안함 + return true; + } + + /* 계정이 활성화(사용가능)된 상태인 지 여부를 리턴한다. (true: 활성화) + * (non-Javadoc) + * @see org.springframework.security.core.userdetails.UserDetails#isEnabled() + */ + @Override + public boolean isEnabled() { + + // 계정 활성화, 비활성화 기능 사용 안함 + return true; + } + +} diff --git a/legacy/nlib/src/main/java/nlib/security/SpringSecurityConfig.java b/legacy/nlib/src/main/java/nlib/security/SpringSecurityConfig.java new file mode 100644 index 00000000..aecd96a2 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/security/SpringSecurityConfig.java @@ -0,0 +1,110 @@ +package nlib.security; + + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.password.PasswordEncoder; + +import nlib.cmm.crypto.NlibPasswordEncoder; +import nlib.cmm.service.NlibProperty; + +/** + *
+ * @Class Name : SpringSecurityConfig.java
+ * 
+ * @Description : Spring Security 환경설정 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 6. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 6. + * @version 1.0 + * + */ +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(securedEnabled = true) +public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + public void configure(WebSecurity web) throws Exception { + + // 권한/인증과 무관한 오픈된 정적 리소트 + web.ignoring() + .antMatchers("/resources/**") + .antMatchers("/css/**") + .antMatchers("/images/**") + .antMatchers("/js/**") + .antMatchers("/temp/**") + .antMatchers("/favicon/**") + .antMatchers("/html/**") + .antMatchers("/banner/**") + ; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests() + .antMatchers("/**").permitAll() + .and().requestCache().requestCache(new CustomRequestCache()) + .and().formLogin() + .loginPage(NlibProperty.getString("login.url") + "?login=req") + .permitAll() + .and().csrf() + .disable(); + http.logout() + .logoutSuccessUrl("/login/logout.do") + .invalidateHttpSession(true).deleteCookies("JSESSIONID") + ; + + //-------------------------------------- + // 안내 + //-------------------------------------- + // 로그인이 필요한 컨에 대하여 컨트롤러의 해당 함수에 + // @Secured(SecUserVO.ROLE_USER) + // 선언할 것 + // + // (ex) + // + // @Secured("ROLE_USER") + // @RequestMapping(value="/userInfo/getMyHome.do") + // public String getMyHome(HttpServletRequest request, ModelMap model) throws Exception { ... } + //-------------------------------------- + + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Bean + public UserDetailsService userDetailsService() { + return new SecUserDetailsService(); + } + + @Bean + public PasswordEncoder getPasswordEncoder() { + return new NlibPasswordEncoder(); + } + +} + + diff --git a/legacy/nlib/src/main/java/nlib/user/service/LoginService.java b/legacy/nlib/src/main/java/nlib/user/service/LoginService.java new file mode 100644 index 00000000..7127f541 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/user/service/LoginService.java @@ -0,0 +1,62 @@ + +package nlib.user.service; + +import java.util.HashMap; + +import javax.servlet.http.HttpServletRequest; + +import egovframework.com.ext.oauth.service.OAuthUniversalUser; +import nlib.restful.DataApiReqVO; +import nlib.restful.DataApiResVO; + +/** + *
+ * @Class Name : LoginService.java
+ * 
+ * @Description : 로그인 서비스 인터페이스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021-07-09 KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021-07-09 + * @version 1.0 + * + */ +public interface LoginService +{ + //------------------------------- + // 로그인 오류코드 + //------------------------------- + public final String ERR_CODE_REQ_MEMBERSHIP = "ERR_REQ_MEMBERSHIP"; /* 오류코드 : 회원가입 필요 */ + public final String ERR_CODE_REQ_SNSLOGIN = "ERR_REQ_SNSLOGIN"; /* 오류코드 : SNS 로그인 필요 */ + public final String ERR_CODE_LOCKED = "ERR_CODE_LOGIN_LOCKED"; /* 오류코드 : 계정잠김 */ + public final String ERR_CODE_DISABLE = "ERR_CODE_LOGIN_DISABLE"; /* 오류코드 : 계정유효하지 않음 */ + public final String ERR_CODE_MISMATCH = "ERR_CODE_LOGIN_MISMATCH"; /* 오류코드 : ID,PW일치하지 않음 */ + public final String ERR_CODE_EXC = "ERR_CODE_LOGIN_EXC"; /* 오류코드 : 기타오류 */ + + public final String WRN_CODE_DORMANT = "WRN_CODE_DOMANT"; /* 경고코드 : 휴면계정 */ + + public String login(HttpServletRequest req, String username, String password); + + public String loginOauth(HttpServletRequest req, String oauthServiceName, String snsId, String joinCouncilCd, String councilJsessionId); + + public String loginCouncilSSO(HttpServletRequest req, String councilCd, OAuthUniversalUser oUser); + + public DataApiResVO logout(DataApiReqVO reqVO); + + public HashMap selectCouncilInfoByDnsHost(String councilDnsHost); + + public int activateDormantAcc(NlibLoginVO loginVO); + + public NlibLoginVO selectLoginUserInfo(NlibLoginVO loginVO); + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/user/service/MemberService.java b/legacy/nlib/src/main/java/nlib/user/service/MemberService.java new file mode 100644 index 00000000..e956d0db --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/user/service/MemberService.java @@ -0,0 +1,108 @@ + +package nlib.user.service; + +import java.util.HashMap; +import java.util.List; + +import egovframework.com.ext.oauth.service.OAuthUniversalUser; +import nlib.restful.DataApiReqVO; +import nlib.restful.DataApiResVO; + +/** + *
+ * @Class Name : MemberService.java
+ * 
+ * @Description : 회원가입 관련 Service
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 12. JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 7. 12. + * @version 1.0 + * + */ +public interface MemberService +{ + + /** + * 회원가입 + * @param vo + * @throws Exception + */ + public void insertMemberInfo(NlibLoginVO vo) throws Exception; + + /** + * 비밀번호 변경 + * @param vo + * @throws Exception + */ + public void changePassword(NlibLoginVO vo) throws Exception; + + /** + * 핸드폰 인증번호 난수 생성 + * @param i + * @param j + * @return + */ + public String numberGen(int i, int j); + + /** + * 초기화 비밀번호 랜덤생성 + * @return + */ + public String createInitPwd(); + + /** + * 회원가입시 SNS인증한 계정 ID와 일치하는 계정이 있는지 체크 + * @param oauthUser + * @return + * @throws Exception + */ + public NlibLoginVO selectAlreadySignUpId(OAuthUniversalUser oauthUser) throws Exception; + + /** + * 회원가입시 sns 계정 추가 , 기존 계정 ID와 일치시 통합처리시 추가 + * @param oauthUser + */ + public void insertMemberSns(OAuthUniversalUser oauthUser); + + /** + * 회원가입시 입력한 휴대폰번호와 일치하는 계정이 있는지 체크 + * @param loginVO + * @return + * @throws Exception + */ + public List selectAlreadySignUpMobile(NlibLoginVO loginVO) throws Exception; + + /** + * SnsId로 기가입자인지 판별 + * @param oauthUser + * @return + */ + public int selectSnsIdCount(OAuthUniversalUser oauthUser); + + /** + * 회원 탈퇴 + * @param loginVO + * @throws Exception + */ + public void deleteMembership(NlibLoginVO loginVO) throws Exception; + + /** + * sms 발송 + * @param smsVO + * @throws Exception + */ + public void sendSms(NlibSmsVO smsVO) throws Exception; + + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/user/service/NlibLoginVO.java b/legacy/nlib/src/main/java/nlib/user/service/NlibLoginVO.java new file mode 100644 index 00000000..2c148426 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/user/service/NlibLoginVO.java @@ -0,0 +1,484 @@ +package nlib.user.service; + +import java.io.Serializable; + +import nlib.cmm.crypto.AriaCrypto; + +/** + *
+ * @Class Name : NlibLoginVO.java
+ * 
+ * @Description : 로그인VO
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 12. JSYOO 최초 생성 + * @ 2021. 8. 17. KNKIM DB컬럼명으로 변경 처리 + * @ 2021. 8. 24. KNKIM 테이블 변경에 따른 컬럼명 전체 변경 + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 7. 12. + * @version 1.0 + * + */ +public class NlibLoginVO implements Serializable { + + private static final long serialVersionUID = -8274004534207618049L; + + /* MB_INFO : 소장자료관 회원 관련 */ + private String mbInfoId; /* 회원아이디 (ex: M1000000001) */ + private String loginUserId; /* 로그인사용자ID (이메일주소) */ + private String name; /* 사용자명 */ + private String nameTemp = ""; /* 비밀번호찾기시 사용자이름 임시저장용 */ + private String mobileNo; /* 휴대전화번호 */ + private String password; /* 비밀번호 */ + private String email; /* 이메일 */ + private String gender; /* 성별(M:남자,F:여자) */ + private String zipCode; /* 우편번호 */ + private String address; /* 주소 */ + private String addressDetail; /* 상세주소 */ + private String birthday; /* 생년월일 */ + private String status; /* 상태 : S정상, D탈퇴, P휴면 */ + private String dmtProcDd; /* 휴면처리일자 (YYYYMMDDHHMISS) */ + private String joinDate; /* 가입일자 (YYYYMMDD) */ + private String verificationDd; /* 본인확인일시 (YYYYMMDDHHMISS) */ + private String lastAccessDd; /* 마지막접근일시 (YYYYMMDDHHMISS) */ + private String leaveSiteDate; /* 탈퇴일자 (YYYYMMDD) */ + private String regId; /* 등록자 */ + private String regDd; /* 등록일자 */ + private String modId; /* 수정자 */ + private String modDd; /* 수정일자 */ + + /* MB_SITE : 로그인된 문화원정보 관련 */ + private String joinType; /* 가입유형 : SNS 및 로그인을 연계하는 포털시스템 아이디(naver, daum 등) */ + private String joinCouncilCd; /* 가입문화원코드 */ + private String joinCouncilNm; /* 가입문화원명 */ + + /* MB_SNS : 회원SNS 관련 */ + private String snsType; /* SNS유형 */ + private String snsId; /* SNS식별코드 */ + + /* 보완 및 기타 사항 */ + private String ip; /* 접속IP */ + private String authorityList; /* 권한ROLE 리스트 */ + + private String error = null; /* 처리 오류코드 */ + private String message = null; /* 처리 관련 메시지 */ + + private String emailTemp = ""; /* 이메일 수정시 임시저장 변수 */ + private String emailVrfctNo = null; /* 이메일 인증번호 */ + private String emailVrfctDd = null; /* 이메일 인증번호 발송일자 */ + + private String mobileTemp = ""; /* 휴대전화번호 변경시 임시저장 변수 */ + private String mobileVrfctNo = null; /* 본인확인 인증번호 */ + private String mobileVrfctDd = null; /* 본인확인 인증번호 발송일자 */ + + private boolean alerted = false; /* 로그인 후, 읽지 않은 알림 표출 여부 */ + + private String infoRecvEmailYn = ""; /* 대출/열람 수신동의(이메일) */ + private String infoRecvSmsYn = ""; /* 대출/열람 수신동의(SMS) */ + private String mktRecvEmailYn = ""; /* 지방문화원 소식/홍보 수신동의(이메일) */ + private String mktRecvSmsYn = ""; /* 지방문화원 소식/홍보 수신동의 (SMS)*/ + + private String previousPage =""; /* 이전 페이지명 저장 */ + + private String mbNo =""; /* 회원증에 이용되는 회원번호 */ + /** + * 개인정보 암호화 내용 양방황 암호화 처리 대상인 항목에 대하여 인코딩 처리 + */ + public void encodePrivateInfo() { + + setMobileNo (AriaCrypto.encode(getMobileNo())); + setEmail (AriaCrypto.encode(getEmail())); + setZipCode (AriaCrypto.encode(getZipCode())); + setAddress (AriaCrypto.encode(getAddress())); + setAddressDetail(AriaCrypto.encode(getAddressDetail())); + setBirthday (AriaCrypto.encode(getBirthday())); + } + + /** + * 개인정보 암호화 내용 양방황 암호화 처리 대상인 항목에 대하여 복호화 처리 + */ + public void decodePrivateInfo() { + + setMobileNo (AriaCrypto.decode(getMobileNo())); + setEmail (AriaCrypto.decode(getEmail())); + setZipCode (AriaCrypto.decode(getZipCode())); + setAddress (AriaCrypto.decode(getAddress())); + setAddressDetail(AriaCrypto.decode(getAddressDetail())); + setBirthday (AriaCrypto.decode(getBirthday())); + } + + /** + * 지방문화원코드+계정의 이름을 리턴한다. (사용자ID:email형식의 LOGIN_USER_ID 정보) + * Spring Security 처리 용 + * (non-Javadoc) + * @see org.springframework.security.core.userdetails.UserDetails#getUsername() + */ + public String getUsername() { + // 로그인하는 지방문화원 코드 + 로그인사용자ID + return getLoginUserId(); + } + + //---------------------------------------------------------------- + // SETTER.GETTER + //---------------------------------------------------------------- + + public String getMbInfoId() { + return mbInfoId; + } + + public void setMbInfoId(String mbInfoId) { + this.mbInfoId = mbInfoId; + } + + public String getLoginUserId() { + return loginUserId; + } + + public void setLoginUserId(String loginUserId) { + this.loginUserId = loginUserId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getMobileNo() { + return mobileNo; + } + + public void setMobileNo(String mobileNo) { + this.mobileNo = mobileNo; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getGender() { + return gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public String getZipCode() { + return zipCode; + } + + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getAddressDetail() { + return addressDetail; + } + + public void setAddressDetail(String addressDetail) { + this.addressDetail = addressDetail; + } + + public String getBirthday() { + return birthday; + } + + public void setBirthday(String birthday) { + this.birthday = birthday; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getJoinDate() { + return joinDate; + } + + public void setJoinDate(String joinDate) { + this.joinDate = joinDate; + } + + public String getVerificationDd() { + return verificationDd; + } + + public void setVerificationDd(String verificationDd) { + this.verificationDd = verificationDd; + } + + public String getLastAccessDd() { + return lastAccessDd; + } + + public void setLastAccessDd(String lastAccessDd) { + this.lastAccessDd = lastAccessDd; + } + + public String getLeaveSiteDate() { + return leaveSiteDate; + } + + public void setLeaveSiteDate(String leaveSiteDate) { + this.leaveSiteDate = leaveSiteDate; + } + + public String getRegId() { + return regId; + } + + public void setRegId(String regId) { + this.regId = regId; + } + + public String getRegDd() { + return regDd; + } + + public void setRegDd(String regDd) { + this.regDd = regDd; + } + + public String getModId() { + return modId; + } + + public void setModId(String modId) { + this.modId = modId; + } + + public String getModDd() { + return modDd; + } + + public void setModDd(String modDd) { + this.modDd = modDd; + } + + public String getJoinType() { + return joinType; + } + + public void setJoinType(String joinType) { + this.joinType = joinType; + } + + public String getJoinCouncilCd() { + return joinCouncilCd; + } + + public void setJoinCouncilCd(String joinCouncilCd) { + this.joinCouncilCd = joinCouncilCd; + } + + public String getJoinCouncilNm() { + return joinCouncilNm; + } + + public void setJoinCouncilNm(String joinCouncilNm) { + this.joinCouncilNm = joinCouncilNm; + } + + public String getSnsType() { + return snsType; + } + + public void setSnsType(String snsType) { + this.snsType = snsType; + } + + public String getSnsId() { + return snsId; + } + + public void setSnsId(String snsId) { + this.snsId = snsId; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getAuthorityList() { + return authorityList; + } + + public void setAuthorityList(String authorityList) { + this.authorityList = authorityList; + } + + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + public String getMobileVrfctNo() { + return mobileVrfctNo; + } + + public void setMobileVrfctNo(String mobileVrfctNo) { + this.mobileVrfctNo = mobileVrfctNo; + } + + public String getMobileVrfctDd() { + return mobileVrfctDd; + } + + public void setMobileVrfctDd(String mobileVrfctDd) { + this.mobileVrfctDd = mobileVrfctDd; + } + public String getEmailVrfctNo() { + return emailVrfctNo; + } + + public String getDmtProcDd() { + return dmtProcDd; + } + + public void setDmtProcDd(String dmtProcDd) { + this.dmtProcDd = dmtProcDd; + } + + public void setEmailVrfctNo(String emailVrfctNo) { + this.emailVrfctNo = emailVrfctNo; + } + + public String getEmailVrfctDd() { + return emailVrfctDd; + } + + public void setEmailVrfctDd(String emailVrfctDd) { + this.emailVrfctDd = emailVrfctDd; + } + + public boolean isAlerted() { + return alerted; + } + + public void setAlerted(boolean alerted) { + this.alerted = alerted; + } + + public String getMobileTemp() { + return mobileTemp; + } + + public void setMobileTemp(String mobileTemp) { + this.mobileTemp = mobileTemp; + } + + public String getEmailTemp() { + return emailTemp; + } + + public void setEmailTemp(String emailTemp) { + this.emailTemp = emailTemp; + } + + public String getInfoRecvEmailYn() { + return infoRecvEmailYn; + } + + public void setInfoRecvEmailYn(String infoRecvEmailYn) { + this.infoRecvEmailYn = infoRecvEmailYn; + } + + public String getInfoRecvSmsYn() { + return infoRecvSmsYn; + } + + public void setInfoRecvSmsYn(String infoRecvSmsYn) { + this.infoRecvSmsYn = infoRecvSmsYn; + } + + public String getMktRecvEmailYn() { + return mktRecvEmailYn; + } + + public void setMktRecvEmailYn(String mktRecvEmailYn) { + this.mktRecvEmailYn = mktRecvEmailYn; + } + + public String getMktRecvSmsYn() { + return mktRecvSmsYn; + } + + public void setMktRecvSmsYn(String mktRecvSmsYn) { + this.mktRecvSmsYn = mktRecvSmsYn; + } + + public String getNameTemp() { + return nameTemp; + } + + public void setNameTemp(String nameTemp) { + this.nameTemp = nameTemp; + } + + public String getPreviousPage() { + return previousPage; + } + + public void setPreviousPage(String previousPage) { + this.previousPage = previousPage; + } + + public String getMbNo() { + return mbNo; + } + + public void setMbNo(String mbNo) { + this.mbNo = mbNo; + } + +} diff --git a/legacy/nlib/src/main/java/nlib/user/service/NlibSmsVO.java b/legacy/nlib/src/main/java/nlib/user/service/NlibSmsVO.java new file mode 100644 index 00000000..5a2bc029 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/user/service/NlibSmsVO.java @@ -0,0 +1,81 @@ +package nlib.user.service; + +import java.io.Serializable; + +/** + *
+ * @Class Name : NlibSmsVO.java
+ * 
+ * @Description : SMS발송 VO
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 10. 19. JSYOO 최초 생성 + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 7. 12. + * @version 1.0 + * + */ +public class NlibSmsVO implements Serializable { + + private static final long serialVersionUID = -8274004534207618049L; + + private String cmid; /* 데이터 ID */ + private String msgType; /* 데이터 타입 (SMS 0/FAX 2/PHONE 3 /MMS 5/AT 6/FT 7/RCS 8/BI 11/BW 12) */ + private String requestTime; /* 데이터 등록 시간 */ + private String sendTime; /* 발송 기준 시간 */ + private String destPhone; /* 수신번호 */ + private String sendPhone; /* 발신자번호 */ + private String msgBody; /* 메시지 내용 */ + + + public String getCmid() { + return cmid; + } + public void setCmid(String cmid) { + this.cmid = cmid; + } + public String getMsgType() { + return msgType; + } + public void setMsgType(String msgType) { + this.msgType = msgType; + } + public String getRequestTime() { + return requestTime; + } + public void setRequestTime(String requestTime) { + this.requestTime = requestTime; + } + public String getSendTime() { + return sendTime; + } + public void setSendTime(String sendTime) { + this.sendTime = sendTime; + } + public String getDestPhone() { + return destPhone; + } + public void setDestPhone(String destPhone) { + this.destPhone = destPhone; + } + public String getSendPhone() { + return sendPhone; + } + public void setSendPhone(String sendPhone) { + this.sendPhone = sendPhone; + } + public String getMsgBody() { + return msgBody; + } + public void setMsgBody(String msgBody) { + this.msgBody = msgBody; + } +} diff --git a/legacy/nlib/src/main/java/nlib/user/service/UserInfoService.java b/legacy/nlib/src/main/java/nlib/user/service/UserInfoService.java new file mode 100644 index 00000000..d6e04763 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/user/service/UserInfoService.java @@ -0,0 +1,79 @@ + +package nlib.user.service; + +import java.util.List; +import java.util.Map; + +import egovframework.com.ext.oauth.service.OAuthUniversalUser; + +/** + *
+ * @Class Name : userInfoService.java
+ * 
+ * @Description : 회원 정보 관련 Service
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 14. JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 7. 14. + * @version 1.0 + * + */ +public interface UserInfoService +{ + + /** 사용자의 SNS 연동 리스트를 조회한다. + * @param vo + * @return + * @throws Exception + */ + public List selectSnsSignUpList(NlibLoginVO vo) throws Exception; + + /** 내 정보를 수정한다. + * @param vo + * @throws Exception + */ + public void updateMyInfo(NlibLoginVO vo) throws Exception; + + + /** SNS연동을 해지한다. + * @param oAuthVO + * @throws Exception + */ + public void deleteSnsLink(OAuthUniversalUser oAuthVO) throws Exception; + + /** 사용자의 정보를 조회한다. + * @param vo + * @return + * @throws Exception + */ + public NlibLoginVO selectMyInfo(NlibLoginVO vo) throws Exception; + + /** + * 직전 로그인 시간을 조회한다. + * + * @param mbInfoId + * @return + * @throws Exception + */ + public List> getLastLogin(String mbInfoId) throws Exception; + + /** + * 최근 1건이내 접속한 문화원 정보를 조회한다. + * + * @param mbInfoId + * @return + * @throws Exception + */ + public List> getVisitedOrgs(String mbInfoId) throws Exception; + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/user/service/impl/LoginDAO.java b/legacy/nlib/src/main/java/nlib/user/service/impl/LoginDAO.java new file mode 100644 index 00000000..6ba32d6e --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/user/service/impl/LoginDAO.java @@ -0,0 +1,73 @@ + +package nlib.user.service.impl; + +import java.util.HashMap; + +import org.springframework.stereotype.Repository; + +import egovframework.com.cmm.service.impl.EgovComAbstractDAO; +import nlib.restful.DataApiReqVO; +import nlib.restful.DataApiResVO; +import nlib.user.service.NlibLoginVO; + +/** + *
+ * @Class Name : LoginDAO.java
+ * 
+ * @Description : 로그인 DAO 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021-07-09 KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021-07-09 + * @version 1.0 + * + */ +@Repository("loginDAO") +public class LoginDAO extends EgovComAbstractDAO { + + public DataApiResVO login(DataApiReqVO reqVO) { + return null; + } + + public DataApiResVO logout(DataApiReqVO reqVO) { + return null; + } + + public NlibLoginVO selectLoginUserInfo(NlibLoginVO nLoginParamVO) { + + NlibLoginVO nlibLoginVO = selectOne("LoginDAO.selectLoginUserInfo", nLoginParamVO); + + // 개인정보 암호화 내용 복호화 처리 + if(nlibLoginVO != null) { + nlibLoginVO.decodePrivateInfo(); + } + return (NlibLoginVO) nlibLoginVO; + } + + public void insertLoginLog(NlibLoginVO userVO) { + + // 사용자 최종 접속정보 업데이트 + update("LoginDAO.updateLoginTimeStamp", userVO); + + // 사용자 접속 로그 등록 + insert("LoginDAO.insertLoginLog", userVO); + } + + public HashMap selectCouncilInfoByDnsHost(String councilDnsHost) { + return (HashMap) selectOne("LoginDAO.selectCouncilInfoByDnsHost", councilDnsHost); + } + + public int activateDormantAcc(NlibLoginVO loginVO) { + return update("LoginDAO.activateDormantAcc", loginVO); + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/user/service/impl/LoginServiceImpl.java b/legacy/nlib/src/main/java/nlib/user/service/impl/LoginServiceImpl.java new file mode 100644 index 00000000..5e514bfe --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/user/service/impl/LoginServiceImpl.java @@ -0,0 +1,247 @@ + +package nlib.user.service.impl; + +import java.util.HashMap; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.DisabledException; +import org.springframework.security.authentication.LockedException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; + +import egovframework.com.ext.oauth.service.OAuthUniversalUser; +import nlib.cmm.session.SessionConfig; +import nlib.restful.DataApiReqVO; +import nlib.restful.DataApiResVO; +import nlib.user.service.LoginService; +import nlib.user.service.NlibLoginVO; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : LoginServiceImpl.java
+ * 
+ * @Description : 로그인 서비스 구현 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021-07-09 KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021-07-09 + * @version 1.0 + * + */ +@Service("loginService") +public class LoginServiceImpl implements LoginService +{ + private static final Logger log = LoggerFactory.getLogger(LoginServiceImpl.class); + + @Autowired + private AuthenticationManager authenticationManager; + + @Resource(name="loginDAO") + private LoginDAO loginDAO; + + /* + * 입력된 로그인정보를 받아 로그인 처리한다. + * 정상인 경우 null을 리턴하고, 오류발생시 오류코드를 리턴한다 + * + * (non-Javadoc) + * @see nlib.user.service.LoginService#login(javax.servlet.http.HttpServletRequest, java.lang.String, java.lang.String) + */ + public String login(HttpServletRequest req, String username, String password) { + + // 아이디와 패스워드로, Security 가 알아 볼 수 있는 token 객체로 변경한다. + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password); + + NlibLoginVO userVO = loginProcSecurity(req, token); + + if(StringUtil.isNotEmpty(userVO.getError())) { + return userVO.getError(); + } + + // 로그인 로그 정보 저장 + loginDAO.insertLoginLog(userVO); + + return null; + } + + + + /* + * SNS 연동 SSO를 처리를 위한 확인작업을 수행한다. + * (nlib에서 호출됨) + * + * return값이 null인 경우, 정상적인 로그인 가능 상태 + * null이 아닌 경우, 오류 코드 + * - ERR_CODE_REQ_SNSLOGIN : SNS 정상적인 로그인이 필요 + * - ERR_CODE_REQ_MEMBERSHIP : 신규회원가입/회원통합 필요 + */ + public String loginOauth(HttpServletRequest req, String oauthServiceName, String snsId, String joinCouncilCd, String councilJsessionId) { + + if(StringUtil.isEmpty(snsId)) return ERR_CODE_REQ_SNSLOGIN; + + // SNS 연동 사용자UID로 사용자정보 조회 + NlibLoginVO nLoginParamVO = new NlibLoginVO(); + nLoginParamVO.setSnsId(snsId); + nLoginParamVO.setSnsType(oauthServiceName); + nLoginParamVO.setJoinCouncilCd(joinCouncilCd); + NlibLoginVO nLoginVO = loginDAO.selectLoginUserInfo(nLoginParamVO); + + if(nLoginVO == null) { + return ERR_CODE_REQ_MEMBERSHIP; + } + + // 세션목록관리에 로그인 정상 가능 정보 추가 + // TODO + //SessionConfig.setLoginInfo(councilJsessionId, o); + + // 회원가입정보 존재하는 SNS 아이디임을 확인 완료 + return null; + } + + /* + * 지방문화원 해당 세션에 대한 최종 로그인 세션을 처리한다. + * 정상인 경우 null을 리턴하고, 오류발생시 오류코드를 리턴한다. + * + */ + public String loginCouncilSSO(HttpServletRequest req, String councilCd, OAuthUniversalUser oUser) { + + if(oUser == null) return ERR_CODE_REQ_SNSLOGIN; + + if(!oUser.isValid()) return ERR_CODE_REQ_SNSLOGIN; + + // SNS 연동 사용자UID로 사용자정보 조회 + NlibLoginVO nLoginParamVO = new NlibLoginVO(); + nLoginParamVO.setSnsId(oUser.getSnsId()); + nLoginParamVO.setSnsType(oUser.getSnsType()); + nLoginParamVO.setJoinCouncilCd(councilCd); + NlibLoginVO nLoginVO = loginDAO.selectLoginUserInfo(nLoginParamVO); + + if(nLoginVO == null) { + return ERR_CODE_REQ_MEMBERSHIP; + } + + // 휴면계정 확인 + if("P".equals(nLoginVO.getStatus())) { + oUser.setNlibVO(nLoginVO); + return WRN_CODE_DORMANT; + } + + // 탈퇴계정 확인 + if("D".equals(nLoginVO.getStatus())) { + oUser.setNlibVO(nLoginVO); + return ERR_CODE_REQ_MEMBERSHIP; + } + + // Spring Security 로그인처리위한 token 생성하여 로그인 처리 + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(nLoginVO.getUsername(), nLoginVO.getPassword()); + NlibLoginVO nlibLoginedVO = loginProcSecurity(req, token); + + if(StringUtil.isNotEmpty(nlibLoginedVO.getError())) { + return nlibLoginedVO.getError(); + } + + // 로그인 로그 정보 저장 + nlibLoginedVO.setIp(req.getRemoteAddr()); + loginDAO.insertLoginLog(nlibLoginedVO); + + return null; + } + + /** + * 스프링 시큐리티 로그인 처리를 수행한다. + * + * @param req + * @param token + * @return + */ + public NlibLoginVO loginProcSecurity(HttpServletRequest req, UsernamePasswordAuthenticationToken token) { + + NlibLoginVO nlibLoginVO = null; + + try { + // AuthenticationManager 에 token 을 넘기면 UserDetailsService 가 받아 처리하도록 한다. + Authentication authentication = authenticationManager.authenticate(token); + + // 기타 정보 저장 + String sessionId = req.getSession().getId(); + nlibLoginVO = (NlibLoginVO)authentication.getPrincipal(); + nlibLoginVO.setIp(req.getRemoteAddr()); + + // 지방문화원 정보 + HttpSession session = req.getSession(); + nlibLoginVO.setJoinCouncilCd((String)session.getAttribute("councilCd")); + nlibLoginVO.setJoinCouncilNm((String)session.getAttribute("councilNm")); + + OAuthUniversalUser ousr = SessionConfig.getLoginInfo(sessionId); + if(ousr == null) { + throw new Exception("잘모된 접근으로 사용자 로그인 정보를 확인할 수 없습니다."); + } + nlibLoginVO.setSnsType(ousr.getSnsType()); + + // 실제 SecurityContext 에 authentication 정보를 등록한다. + SecurityContextHolder.getContext().setAuthentication(authentication); + + SessionConfig.removeLoginInfo(sessionId); + + + } catch (DisabledException e) { + log.error("loginProcSecurity > " + ERR_CODE_LOCKED); + if(nlibLoginVO == null) nlibLoginVO = new NlibLoginVO(); + nlibLoginVO.setError(ERR_CODE_LOCKED); + } catch (LockedException e) { + log.error("loginProcSecurity > " + ERR_CODE_DISABLE); + if(nlibLoginVO == null) nlibLoginVO = new NlibLoginVO(); + nlibLoginVO.setError(ERR_CODE_DISABLE); + } catch (BadCredentialsException e) { + log.error("loginProcSecurity > " + ERR_CODE_MISMATCH); + if(nlibLoginVO == null) nlibLoginVO = new NlibLoginVO(); + nlibLoginVO.setError(ERR_CODE_MISMATCH); + } catch (Exception e) { + log.error("loginProcSecurity > " + ERR_CODE_EXC + " : " + e.toString()); + if(nlibLoginVO == null) nlibLoginVO = new NlibLoginVO(); + nlibLoginVO.setError(ERR_CODE_EXC + " : " + e.toString()); + } + + return nlibLoginVO; + } + + public DataApiResVO logout(DataApiReqVO reqVO) { + return null; + } + + /* + * DNS 호스트명으로 지방문화원 정보를 조회한다. (지방문화원코드, 명칭) + */ + public HashMap selectCouncilInfoByDnsHost(String councilDnsHost) { + return loginDAO.selectCouncilInfoByDnsHost(councilDnsHost); + } + + public int activateDormantAcc(NlibLoginVO loginVO) { + return loginDAO.activateDormantAcc(loginVO); + } + + public NlibLoginVO selectLoginUserInfo(NlibLoginVO loginVO) { + return loginDAO.selectLoginUserInfo(loginVO); + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/user/service/impl/MemberDAO.java b/legacy/nlib/src/main/java/nlib/user/service/impl/MemberDAO.java new file mode 100644 index 00000000..b9c67d41 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/user/service/impl/MemberDAO.java @@ -0,0 +1,98 @@ + +package nlib.user.service.impl; + +import java.util.HashMap; +import java.util.List; + +import org.springframework.stereotype.Repository; + +import egovframework.com.ext.oauth.service.OAuthUniversalUser; +import egovframework.rte.psl.dataaccess.mapper.Mapper; +import nlib.restful.DataApiReqVO; +import nlib.restful.DataApiResVO; +import nlib.user.service.NlibLoginVO; +import nlib.user.service.NlibSmsVO; + +/** + *
+ * @Class Name : MemberDAO.java
+ * 
+ * @Description : 회원가입 관련 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 12. JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 7. 12. + * @version 1.0 + * + */ + +@Mapper("memberDAO") +public interface MemberDAO +{ + /** + * 회원가입 + * @param vo + * @throws Exception + */ + public void insertMemberInfo(NlibLoginVO vo) throws Exception; + + /** + * 비밀번호 변경 + * @param vo + * @throws Exception + */ + public void changePassword(NlibLoginVO vo) throws Exception; + + /** + * 회원가입시 sns 계정 추가 , 기존 계정 ID와 일치시 통합처리시 추가 + * @param oauthUser + */ + public void insertMemberSns(OAuthUniversalUser oauthUser); + + /** + * 회원가입시 SNS인증한 계정 ID와 일치하는 계정이 있는지 체크 + * @param oauthUser + * @return + * @throws Exception + */ + public NlibLoginVO selectAlreadySignUpId(OAuthUniversalUser oauthUser) throws Exception; + + /** + * 회원가입시 입력한 휴대폰번호와 일치하는 계정이 있는지 체크 + * @param loginVO + * @return + * @throws Exception + */ + public List selectAlreadySignUpMobile(NlibLoginVO loginVO) throws Exception; + + /** + * SnsId로 기가입자인지 판별 + * @param oauthUser + * @return + */ + public int selectSnsIdCount(OAuthUniversalUser oauthUser); + + /** + * 회원 탈퇴 + * @param loginVO + * @throws Exception + */ + public void deleteMembership(NlibLoginVO loginVO) throws Exception; + + /** + * sms 발송 + * @param smsVO + * @throws Exception + */ + public void sendSms(NlibSmsVO smsVO) throws Exception; +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/user/service/impl/MemberServiceImpl.java b/legacy/nlib/src/main/java/nlib/user/service/impl/MemberServiceImpl.java new file mode 100644 index 00000000..4b2ff52a --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/user/service/impl/MemberServiceImpl.java @@ -0,0 +1,271 @@ + +package nlib.user.service.impl; + +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Random; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Service; + +import egovframework.com.ext.oauth.service.OAuthUniversalUser; +import egovframework.rte.fdl.cryptography.EgovPasswordEncoder; +import nlib.cmm.crypto.AriaCrypto; +import nlib.restful.DataApiReqVO; +import nlib.restful.DataApiResVO; +import nlib.user.service.MemberService; +import nlib.user.service.NlibLoginVO; +import nlib.user.service.NlibSmsVO; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : MemberServiceImpl.java
+ * 
+ * @Description : 회원가입 관련 ServiceImpl
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 12. JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 7. 12. + * @version 1.0 + * + */ +@Service("memberService") +public class MemberServiceImpl implements MemberService +{ + @Resource(name="memberDAO") + private MemberDAO memberDAO; + + @Resource(name = "egovEnvPasswordEncoderService") + EgovPasswordEncoder egovPasswordEncoder; + + @Resource(name = "ariaCrypto") + AriaCrypto ariaCrypto; + + /** + * 회원가입 + * (non-Javadoc) + * @see nlib.user.service.MemberService#insertMemberInfo(nlib.user.service.NlibLoginVO) + */ + public void insertMemberInfo(NlibLoginVO vo) throws Exception { + //회원정보 암호화 + String encodedText=null; + encodedText = egovPasswordEncoder.encryptPassword(vo.getLoginUserId()+vo.getPassword()); + vo.setPassword(encodedText); + vo.encodePrivateInfo(); + //회원가입 정보 + memberDAO.insertMemberInfo(vo); + + } + + /** + * 비밀번호 변경 + * (non-Javadoc) + * @see nlib.user.service.MemberService#changePassword(nlib.user.service.NlibLoginVO) + */ + public void changePassword(NlibLoginVO vo) throws Exception { + memberDAO.changePassword(vo); + } + //핸드폰 인증번호 난수 생성 + /** + * 전달된 파라미터에 맞게 난수를 생성한다 + * @param len : 생성할 난수의 길이 + * @param dupCd : 중복 허용 여부 (1: 중복허용, 2:중복제거) + * + */ + public String numberGen(int len, int dupCd ) { + + SecureRandom rand = new SecureRandom(); + String numStr = ""; //난수가 저장될 변수 + + for(int i=0;i dummylist=new ArrayList(); + + // 대문자사용 1 + int useU = 1; + String upperStr=""; + + // 소문자 사용 1 + int useL = 1; + String lowerStr=""; + + // 숫자 사용 1 + int useN = 1; + String ranNumberStr=""; + + // 특수문자 사용 1 + int useS = 1; + String ranSkeyStr=""; + + // 사용할 특수문자 + String specialKey="!=#$+@%*"; + + // 제외시킬 대,소문자(비슷하게 생긴것들) + String exceptionKey="IOiol"; + + char upperChar; + char lowerChar; + char ranSkey; + int startSkey; + int ranNumber; + int whileNum = 0; + boolean whileFlag = true; + + do { + int loopNum=(int)(rand.nextDouble() * 4); + // 대문자생성 + if((whileFlag && upperStr.equals("1")) || (!whileFlag && useU == 1 && loopNum == 0)){ + do { + upperChar = (char)(rand.nextDouble() * 26 + 65); + upperStr=String.valueOf(upperChar); + } while (exceptionKey.indexOf(upperStr)!=-1); + dummylist.add(upperStr); + whileNum++; + } + + // 소문자생성 + if((whileFlag && lowerStr.equals("1")) || (!whileFlag && useL == 1 && loopNum == 1)){ + do { + lowerChar = (char)(rand.nextDouble() * 26 + 97); + lowerStr=String.valueOf(lowerChar); + } while (exceptionKey.indexOf(lowerStr)!=-1); + dummylist.add(lowerStr); + whileNum++; + } + + // 숫자생성(숫자 0,1 제외) + if((whileFlag && ranNumberStr.equals("1")) || (!whileFlag && useN == 1 && loopNum == 2)){ + ranNumber=(int)(rand.nextDouble() * 8 + 2); + ranNumberStr=String.valueOf(ranNumber); + dummylist.add(ranNumberStr); + whileNum++; + } + + // 특수문자생성 + if((whileFlag && ranSkeyStr.equals("1")) || (!whileFlag && useS == 1 && loopNum == 3)){ + startSkey=(int)(Math.random() * (specialKey.length()-1))+1; + ranSkey=specialKey.charAt(startSkey); + ranSkeyStr=String.valueOf(ranSkey); + dummylist.add(ranSkeyStr); + whileNum++; + } + whileFlag = false; + } while (whileNum selectAlreadySignUpMobile(NlibLoginVO loginVO) throws Exception { + loginVO.setMobileNo(ariaCrypto.encode(loginVO.getMobileNo())); + return memberDAO.selectAlreadySignUpMobile(loginVO); + } + + /** + * SnsId로 기가입자인지 판별 + * (non-Javadoc) + * @see nlib.user.service.MemberService#selectSnsIdCount(egovframework.com.ext.oauth.service.OAuthUniversalUser) + */ + public int selectSnsIdCount(OAuthUniversalUser oauthUser) { + return memberDAO.selectSnsIdCount(oauthUser); + } + + /** + * 회원 탈퇴 + * (non-Javadoc) + * @see nlib.user.service.MemberService#deleteMembership(nlib.user.service.NlibLoginVO) + */ + public void deleteMembership(NlibLoginVO loginVO) throws Exception { + memberDAO.deleteMembership(loginVO); + } + + /** + * sms 발송 + * (non-Javadoc) + * @see nlib.user.service.MemberService#sendSms(nlib.user.service.NlibSmsVO) + */ + public void sendSms(NlibSmsVO smsVO) throws Exception { + memberDAO.sendSms(smsVO); + } + +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/user/service/impl/UserInfoDAO.java b/legacy/nlib/src/main/java/nlib/user/service/impl/UserInfoDAO.java new file mode 100644 index 00000000..ea11eb88 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/user/service/impl/UserInfoDAO.java @@ -0,0 +1,77 @@ +package nlib.user.service.impl; + +import java.util.List; +import java.util.Map; + +import egovframework.com.ext.oauth.service.OAuthUniversalUser; +import egovframework.rte.psl.dataaccess.mapper.Mapper; +import nlib.user.service.NlibLoginVO; + +/** + *
+ * @Class Name : UserInfoDAO.java
+ * 
+ * @Description : 사용자의 관련 정보 제공 DAO 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 7. JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 9. 7. + * @version 1.0 + * + */ + +@Mapper("userInfoDAO") +public interface UserInfoDAO +{ + /** 사용자의 SNS 연동 리스트를 조회한다. + * @param vo + * @return + * @throws Exception + */ + public List selectSnsSignUpList(NlibLoginVO vo) throws Exception; + + /** 내 정보를 수정한다. + * @param vo + * @throws Exception + */ + public void updateMyInfo(NlibLoginVO vo) throws Exception; + + /** SNS연동을 해지한다. + * @param oAuthVO + */ + public void deleteSnsLink(OAuthUniversalUser oAuthVO) throws Exception; + + /** 사용자의 정보를 조회한다. + * @param vo + * @return + */ + public NlibLoginVO selectMyInfo(NlibLoginVO vo) throws Exception; + + /** + * 직전 로그인 시간을 조회한다. + * + * @param mbInfoId + * @return + * @throws Exception + */ + public List> getLastLogin(String mbInfoId) throws Exception; + + /** + * 최근 1건이내 접속한 문화원 정보를 조회한다. + * + * @param mbInfoId + * @return + * @throws Exception + */ + public List> getVisitedOrgs(String mbInfoId) throws Exception; +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/user/service/impl/UserInfoServiceImpl.java b/legacy/nlib/src/main/java/nlib/user/service/impl/UserInfoServiceImpl.java new file mode 100644 index 00000000..769a5587 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/user/service/impl/UserInfoServiceImpl.java @@ -0,0 +1,119 @@ +package nlib.user.service.impl; + +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Service; + +import egovframework.com.ext.oauth.service.OAuthUniversalUser; +import egovframework.rte.fdl.cryptography.EgovPasswordEncoder; +import nlib.cmm.crypto.AriaCrypto; +import nlib.user.service.MemberService; +import nlib.user.service.NlibLoginVO; +import nlib.user.service.UserInfoService; + +/** + *
+ * @Class Name : UserInfoServiceImpl.java
+ * 
+ * @Description : 사용자의 정보를 조회하는 서비스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 7. JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 9. 7. + * @version 1.0 + * + */ + +@Service("userInfoService") +public class UserInfoServiceImpl implements UserInfoService +{ + @Resource(name="userInfoDAO") + private UserInfoDAO userInfoDAO; + + @Resource(name = "egovEnvPasswordEncoderService") + EgovPasswordEncoder egovPasswordEncoder; + + @Resource(name = "ariaCrypto") + AriaCrypto ariaCrypto; + + /** + * 사용자의 SNS 연동 리스트를 조회한다. + * (non-Javadoc) + * @see nlib.user.service.UserInfoService#selectSnsSignUpList(nlib.user.service.NlibLoginVO) + */ + public List selectSnsSignUpList(NlibLoginVO vo) throws Exception { + return userInfoDAO.selectSnsSignUpList(vo); + } + /** + * 내 정보를 수정한다. + * (non-Javadoc) + * @see nlib.user.service.UserInfoService#updateMyInfo(nlib.user.service.NlibLoginVO) + */ + public void updateMyInfo(NlibLoginVO vo) throws Exception { + //회원정보 암호화 + vo.encodePrivateInfo(); + + userInfoDAO.updateMyInfo(vo); + } + + /** + * SNS연동을 해지한다. + * (non-Javadoc) + * @see nlib.user.service.UserInfoService#deleteSnsLink(egovframework.com.ext.oauth.service.OAuthUniversalUser) + */ + public void deleteSnsLink(OAuthUniversalUser oAuthVO) throws Exception { + userInfoDAO.deleteSnsLink(oAuthVO); + } + /** + * 사용자의 정보를 조회한다. + * (non-Javadoc) + * @see nlib.user.service.UserInfoService#selectMyInfo(nlib.user.service.NlibLoginVO) + */ + public NlibLoginVO selectMyInfo(NlibLoginVO vo) throws Exception { + vo.setMobileNo(ariaCrypto.encode(vo.getMobileNo())); + vo.setEmail(ariaCrypto.encode(vo.getEmail())); + NlibLoginVO loginVO =userInfoDAO.selectMyInfo(vo); + // 개인정보 암호화 내용 복호화 처리 + if(loginVO != null) { + loginVO.setMobileNo(AriaCrypto.decode(loginVO.getMobileNo())); + loginVO.setEmail(AriaCrypto.decode(loginVO.getEmail())); + } + return loginVO; + } + + + /** + * 직전 로그인 시간을 조회한다. + * + * @param mbInfoId + * @return + * @throws Exception + */ + public List> getLastLogin(String mbInfoId) throws Exception { + return userInfoDAO.getLastLogin(mbInfoId); + } + + /** + * 최근 1건이내 접속한 문화원 정보를 조회한다. + * + * @param mbInfoId + * @return + * @throws Exception + */ + public List> getVisitedOrgs(String mbInfoId) throws Exception { + return userInfoDAO.getVisitedOrgs(mbInfoId); + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/user/web/LoginController.java b/legacy/nlib/src/main/java/nlib/user/web/LoginController.java new file mode 100644 index 00000000..eb6e47e3 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/user/web/LoginController.java @@ -0,0 +1,698 @@ + +package nlib.user.web; + +import java.util.HashMap; +import java.util.Map; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.web.savedrequest.HttpSessionRequestCache; +import org.springframework.security.web.savedrequest.RequestCache; +import org.springframework.security.web.savedrequest.SavedRequest; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import egovframework.com.ext.oauth.service.OAuthConfig; +import egovframework.com.ext.oauth.service.OAuthLogin; +import egovframework.com.ext.oauth.service.OAuthUniversalUser; +import egovframework.com.ext.oauth.service.OAuthVO; +import nlib.cmm.NlibCommonController; +import nlib.cmm.crypto.AriaCrypto; +import nlib.cmm.service.NlibProperty; +import nlib.cmm.session.SessionConfig; +import nlib.col.service.CartService; +import nlib.user.service.LoginService; +import nlib.user.service.NlibLoginVO; +import nlib.util.StringUtil; + +/** + *
+ * @Class Name : LoginController.java
+ * 
+ * @Description : 스프링 시큐리티를 이용한 로그인 처리 컨트롤러 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 9. KNKIM 최초 생성 + * @ 2021. 8.18. KNKIM RESTful -> DB접속 방식으로 변경 처리 + * @ 2021. 8.19. KNKIM 지방문화원별 다른 도메인 호스트 접속 처리를 위한 Spring Security 변경 작업, 네이버 전자정보 프레임워크 기반으로 변경 + * @ 2021. 8.24. KNKIM 테이블 변경에 따른 항목명 변경 및 코드 정리작업 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 9. + * @version 1.0 + * + */ +@Controller +public class LoginController extends NlibCommonController { + + private static final Logger log = LoggerFactory.getLogger(LoginController.class); + + //------------------------------------------- + // SNS 연동 환경설정 정보 : context-oauth.xml 참고 + //------------------------------------------- + @Inject + private OAuthVO naverAuthVO; /* 네이버 */ + + @Inject + private OAuthVO googleAuthVO; /* 구글 */ + + @Inject + private OAuthVO kakaoAuthVO; /* 카카오 */ + //------------------------------------------- + + + @Resource(name = "loginService") + private LoginService loginService; + + @Resource(name = "cartService") + private CartService cartService; + + + /** + * 접속한 지방문화원정보를 세션에 설정한다. + * + * @param req + * @param res + * @param returnUrl + * @param callType + * @throws Exception + */ + public void setCouncilInfo( + HttpServletRequest req, + HttpServletResponse res, + String returnUrl, + String callType) throws Exception { + + HttpSession session = req.getSession(); + String url = req.getRequestURL().toString(); + String councilHomeUrl = url.replaceAll(req.getRequestURI(), "") + req.getContextPath(); + String councilReturnUrl = councilHomeUrl + (StringUtil.isEmpty(returnUrl) ? "/" : returnUrl); + String councilDnsHost = StringUtil.getHostName(url); + String councilJsessionId = session.getId(); + + // 캐쉬된 요청URL인 존재하는 경우, 리턴URL로 설정 + RequestCache cache = new HttpSessionRequestCache(); + SavedRequest savedRequest = cache.getRequest(req, res); + if (savedRequest != null) { + if(savedRequest.getRedirectUrl().contains("Ajax.do")) { + cache.removeRequest(req, res); + } else { + councilReturnUrl = savedRequest.getRedirectUrl(); + } + log.debug("setCouncilInfo > HttpSessionRequestCache에서 획득 councilReturnUrl = " + councilReturnUrl); + } + + // 지방문화원 코드 확인 + HashMap councilInfo = loginService.selectCouncilInfoByDnsHost(councilDnsHost); + String councilCd = (councilInfo == null ? null : councilInfo.get("councilCd")); + String councilNm = (councilInfo == null ? null : councilInfo.get("councilNm")); + + session.setAttribute("councilReturnUrl", councilReturnUrl); + session.setAttribute("councilHomeUrl", councilHomeUrl); + session.setAttribute("councilDnsHost", councilDnsHost); + session.setAttribute("councilCd", councilCd); + session.setAttribute("councilNm", councilNm); + session.setAttribute("callType", callType); + + log.debug("setCouncilInfo > REQ URL = " + url); + log.debug("setCouncilInfo > councilJsessionId = " + councilJsessionId); + log.debug("setCouncilInfo > councilDnsHost = " + councilDnsHost); + log.debug("setCouncilInfo > councilReturnUrl = " + councilReturnUrl); + log.debug("setCouncilInfo > councilHomeUrl = " + councilHomeUrl); + log.debug("setCouncilInfo > councilCd = " + councilCd); + log.debug("setCouncilInfo > councilNm = " + councilNm); + log.debug("setCouncilInfo > callType = " + callType); + + // 세션 추가정보 저장소에 회귀 문화원 정보 담기 + OAuthUniversalUser oauthUser = new OAuthUniversalUser(); + oauthUser.setCouncilJsessionId(councilJsessionId); + oauthUser.setCouncilHomeUrl(councilHomeUrl); + SessionConfig.setLoginInfo(councilJsessionId, oauthUser); + + return; + } + + /** + * 로그인 콜백을 위한 설정을 처리한 후, 로그인 페이지로 전환한다. + * + * @param req + * @param error + * @param logout + * @param model + * @return + */ + @RequestMapping("/login/loginPreSet.do") + public String loginPreSet(HttpServletRequest req, + HttpServletResponse response, + @RequestParam(required = false) String error, + @RequestParam(required = false) String message, + @RequestParam(required = false) String logout, + RedirectAttributes redirectAttrs, + @RequestParam Map paramMap, + Model model, + HttpSession session) { + + //response.setHeader("X-Frame-Options", "ALLOW-FROM https://nlib-dev.nculture.org"); + //response.setHeader("X-Frame-Options", "ALLOW-FROM https://seoul.nculture.org/"); + + //---------------------------------------------- + // 지방문화원 사이트에서 접속한 경우, 지방문화원 정보 확인 + //---------------------------------------------- + String councilJsessionId = paramMap.get("councilJsessionId"); + String councilDnsHost = paramMap.get("councilDnsHost"); + String councilReturnUrl = StringUtil.decodeBase64(paramMap.get("councilReturnUrl")); + String councilHomeUrl = StringUtil.decodeBase64(paramMap.get("councilHomeUrl")); + String councilCd = paramMap.get("councilCd"); + String councilNm = StringUtil.decodeBase64(paramMap.get("councilNm")); + String callType = paramMap.get("callType"); + + log.debug("loginPreSet > sessionid=" + session.getId()); + log.debug("loginPreSet > councilJsessionId = " + councilJsessionId); + log.debug("loginPreSet > councilDnsHost = " + councilDnsHost); + log.debug("loginPreSet > councilReturnUrl = " + councilReturnUrl); + log.debug("loginPreSet > councilHomeUrl = " + councilHomeUrl); + log.debug("loginPreSet > councilCd = " + councilCd); + log.debug("loginPreSet > councilNm = " + councilNm); + log.debug("loginPreSet > callType = " + callType); + + session.setAttribute("councilJsessionId", councilJsessionId); + session.setAttribute("councilReturnUrl", councilReturnUrl); + session.setAttribute("councilHomeUrl" , councilHomeUrl); + + session.setAttribute("councilDnsHost", councilDnsHost); + session.setAttribute("councilCd" , councilCd); + session.setAttribute("councilNm" , councilNm); + session.setAttribute("callType" , callType); + + String redirect = null; + if(OAuthLogin.CALL_TYPE_MEMBER.equalsIgnoreCase(callType)) { + redirect = councilHomeUrl + NlibProperty.getString("nculture.member.redirect.uri"); + } else { + redirect = councilHomeUrl + NlibProperty.getString("nculture.login.redirect.uri"); + redirect = StringUtil.addWebParamOfUrl(redirect, "logout", logout); + } + + return "redirect:" + redirect; + } + + /** + * Ajax 요청에 대한 권한 부재시 오류 처리 + * + * @param req + * @param res + * @return + * @throws Exception + */ + @RequestMapping(value= {"/login/responseDeniedAuth.do"}) + public ResponseEntity responseDeniedAuth(HttpServletRequest req, HttpServletResponse res) throws Exception { + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8"); + String errorStr = "로그인 후, 이용해 주시기 바랍니다."; + log.debug("responseDeniedAuth > errorStr=" + errorStr); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(headers).body(errorStr); + } + + /** + * 로그인 정보 입력 화면을 출력한다. + * + * @param req + * @param error + * @param logout + * @param model + * @return + */ + @RequestMapping(value= {"/login/loginForm.do", "/login/loginFormPopup.do", "/login/memberSnsForm.do"}) + public String loginForm( + HttpServletRequest req, + HttpServletResponse res, + @RequestParam(required = false) String callType, + @RequestParam(required = false) String returnUrl, + @RequestParam(required = false) String login, + @RequestParam(required = false) String logout, + @RequestParam(required = false) String error, + @RequestParam(required = false) String message, + RedirectAttributes redirectAttrs, + Model model) throws Exception { + + String reqPath = req.getServletPath(); + + // Ajax 호출이면서 인증 오류에 따른 요청인 경우, Ajax용 RES 생성 함수로 전환 + if("req".equals(login)) { + RequestCache cache = new HttpSessionRequestCache(); + SavedRequest savedRequest = cache.getRequest(req, res); + if (savedRequest != null && savedRequest.getRedirectUrl().contains("Ajax.do")) { + cache.removeRequest(req, res); + return "redirect:/login/responseDeniedAuth.do"; + } + } + + // callType + if(StringUtil.isEmpty(callType)) { + if(reqPath.startsWith("/login/member")) callType = OAuthLogin.CALL_TYPE_MEMBER; + else callType = OAuthLogin.CALL_TYPE_LOGIN; + } + + // 지방문화원 사이트 정보를 세션 및 추가정보에 담는다. + setCouncilInfo(req, res, returnUrl, callType); + HttpSession session = req.getSession(); + + //---------------------------------------------- + // 지방문화원 사이트에서 접속한 경우, 지방문화원 정보 확인 + //---------------------------------------------- + String councilJsessionId = session.getId(); + String councilDnsHost = (String)session.getAttribute("councilDnsHost"); + String councilReturnUrl = (String)session.getAttribute("councilReturnUrl"); + String councilHomeUrl = (String)session.getAttribute("councilHomeUrl"); + String councilCd = (String)session.getAttribute("councilCd"); + String councilNm = (String)session.getAttribute("councilNm"); + + log.debug("loginForm > sessionid=" + session.getId()); + log.debug("loginForm > councilJsessionId = " + councilJsessionId); + log.debug("loginForm > councilDnsHost = " + councilDnsHost); + log.debug("loginForm > councilReturnUrl = " + councilReturnUrl); + log.debug("loginForm > councilHomeUrl = " + councilHomeUrl); + log.debug("loginForm > councilCd = " + councilCd); + log.debug("loginForm > councilNm = " + councilNm); + + //---------------------------------------------- + // SNS 연동 URL 생성 + //---------------------------------------------- + String encCouncilJsessionId = AriaCrypto.encode(councilJsessionId); + OAuthLogin naverLogin = new OAuthLogin(naverAuthVO, callType, councilJsessionId); + log.debug("naverLogin.getOAuthURL() = "+naverLogin.getOAuthURL(encCouncilJsessionId)); + model.addAttribute("naverUrl", naverLogin.getOAuthURL(encCouncilJsessionId)); + + OAuthLogin googleLogin = new OAuthLogin(googleAuthVO, callType, councilJsessionId); + log.debug("googleLogin.getOAuthURL() = "+googleLogin.getOAuthURL(encCouncilJsessionId)); + model.addAttribute("googleUrl", googleLogin.getOAuthURL(encCouncilJsessionId)); + + OAuthLogin kakaoLogin = new OAuthLogin(kakaoAuthVO, callType, councilJsessionId); + log.debug("kakaoLogin.getOAuthURL() = "+kakaoLogin.getOAuthURL(encCouncilJsessionId)); + model.addAttribute("kakaoUrl", kakaoLogin.getOAuthURL(encCouncilJsessionId)); + + model.addAttribute("error", error); + model.addAttribute("message", message); + if(StringUtil.equalsIgnoreCase(logout, "logout")) { + model.addAttribute("message", "로그아웃되었습니다. 감사합니다."); + } + + model.addAttribute("login", login); // "req"인 경우, 로그인 필수 안내 표출 + + String retScreen = "nlib/login/loginFormPopup"; + if(OAuthLogin.CALL_TYPE_MEMBER.equalsIgnoreCase(callType)) retScreen = "nlib/login/memberSnsForm"; + else if(reqPath.equalsIgnoreCase("/login/loginForm.do")) retScreen = "nlib/login/loginForm"; + + return retScreen; + } + + @RequestMapping(value = {"/login/loginMessage.do"}) + public String loginMessage( + HttpServletRequest req, + String message, + Model model) { + + model.addAttribute("message", message); + return "nlib/login/loginMessage"; + } + + /** + * SNS 로그인 후, 콜백으로 호출되며 회원가입된 사용자가 존재하는 지 확인하여 로그인 처리가 진행될 수 있도록 한다. + * 정상 회원가입자인 경우, 해당 지방문화원 도메인(호스트)주소로 loginCouncilSSO(..)가 재호출되어 실제 세션 로그인 처리 마무리가 이루어진다. + * + * @param req + * @param oauthServiceName + * @param paramMap + * @param model + * @param session + * @return + * @throws Exception + */ + @RequestMapping(value = {"/{callType}/{oauthServiceName}/callback.do"}) // /login/{oauthServiceName}/callback.do, /member/{oauthServiceName}/callback.do + public String callbackOauth( + HttpServletRequest req, + @PathVariable String callType, + @PathVariable String oauthServiceName, + @RequestParam(required = false) String code, + @RequestParam(name = "state" , required = false) String councilJsessionId, + @RequestParam(required = false) String error, + Model model, + HttpSession session) throws Exception { + String redirectUrl = NlibProperty.getString("home.uri"); // "/index.do"; + if(StringUtil.isEmpty(councilJsessionId)) { + model.addAttribute("message", "잘못된 접근입니다. (접속문화원 세션정보 오류)"); + model.addAttribute("loginBtnYn", "Y"); + model.addAttribute("memberBtnYn", "Y"); + return "nlib/login/loginMessage"; + } + councilJsessionId = AriaCrypto.decode(councilJsessionId); + OAuthUniversalUser tmpUser = SessionConfig.getLoginInfo(councilJsessionId); + if(tmpUser == null || StringUtil.isEmpty(tmpUser.getCouncilHomeUrl())) { + model.addAttribute("message", "잘못된 접근입니다. (접속문화원 정보 오류)"); + model.addAttribute("loginBtnYn", "Y"); + model.addAttribute("memberBtnYn", "Y"); + return "nlib/login/loginMessage"; + } + String councilHomeUrl = tmpUser.getCouncilHomeUrl(); + if(StringUtil.isEmpty(councilHomeUrl)) { + model.addAttribute("message", "잘못된 접근입니다. (접속문화원 URL 정보 오류)"); + model.addAttribute("loginBtnYn", "Y"); + model.addAttribute("memberBtnYn", "Y"); + return "nlib/login/loginMessage"; + } + + if(StringUtil.isNotEmpty(error)) { + + // 구글 정보 제공 동의 거절한 경우 + // https://nlib-dev.nculture.org/member/google/callback.do?error=access_denied + if(StringUtil.equalsIgnoreCase("access_denied", error)) { + if(OAuthLogin.CALL_TYPE_LOGIN.equalsIgnoreCase(callType)) { + // 로그인인 경우 + model.addAttribute("loginBtnYn", "Y"); + } else { + // 회원가입인 경우 + model.addAttribute("memberBtnYn", "Y"); + } + redirectUrl = councilHomeUrl + "/login/loginMessage.do"; + model.addAttribute("url", redirectUrl); + model.addAttribute("message", StringUtil.encodeUrl("서비스를 이용하시려면 SNS의 정보제공 동의가 필요합니다.")); + return "nlib/login/loginPreSet"; + } + } + + log.debug("callbackOauth > sessionid = " + session.getId()); + log.debug("callbackOauth > code = ", code); + + // SNS 클라이언트 설정 정보 할당 + OAuthVO oauthVO = null; + if (StringUtil.equalsIgnoreCase(OAuthConfig.NAVER_SERVICE_NAME, oauthServiceName)) { + log.debug("callbackOauth > NAVER_SERVICE_NAME"); + oauthVO = naverAuthVO; + } + else if (StringUtil.equalsIgnoreCase(OAuthConfig.GOOGLE_SERVICE_NAME, oauthServiceName)) { + log.debug("callbackOauth > GOOGLE_SERVICE_NAME"); + oauthVO = googleAuthVO; + } + else if (StringUtil.equalsIgnoreCase(OAuthConfig.KAKAO_SERVICE_NAME, oauthServiceName)) { + log.debug("callbackOauth > KAKAO_SERVICE_NAME"); + oauthVO = kakaoAuthVO; + } + else { + log.debug("callbackOauth > SNS 연동 콜백정보가 올바르지 않습니다."); + throw new Exception("SNS 연동 콜백정보가 올바르지 않습니다."); + } + + //----------------------------------------------- + // 1. code를 이용해서 Access Token 받기 + // 2. Access Token을 이용해서 사용자 제공 정보 가져오기 + //----------------------------------------------- + + OAuthLogin oauthLogin = new OAuthLogin(oauthVO, callType); + OAuthUniversalUser oauthUser = null; + try { + oauthUser = oauthLogin.getUserProfile(code); // 1,2번 동시 + } catch(Exception e) { + log.debug("oauthLoginCallback > SNS 연동 콜백정보 코드가 업습니다. error ===>>" + e.toString()); + throw new Exception("SNS 연동 콜백정보 코드가 업습니다."); + } + + // oAuth를 통한 SNS연동이 실패한 경우 + if(oauthUser == null || !oauthUser.isValid()) { + redirectUrl = NlibProperty.getString("member.new.url"); // "/member/insertMemberInfoForm.do" + model.addAttribute("url", redirectUrl); + model.addAttribute("message", StringUtil.encodeUrl("먼저 회원가입하신 후, 이용하여 주시기 바랍니다.")); + return "nlib/login/loginPreSet"; + } + + log.debug("oauthLoginCallback > Profile ===>>" + oauthUser.getSnsId() + ", " + oauthUser.getSnsName()); + + //----------------------------------------------- + // 해당 처리기로 전환 + //----------------------------------------------- + if(OAuthLogin.CALL_TYPE_LOGIN.equalsIgnoreCase(callType)) { + // 로그인인 경우 + SessionConfig.setLoginInfo(councilJsessionId, oauthUser); + redirectUrl = councilHomeUrl + NlibProperty.getString("nculture.login.post.login.redirect.uri"); + } else { + // 회원가입인 경우 + SessionConfig.setNewMemberInfo(councilJsessionId, oauthUser); + redirectUrl = councilHomeUrl + NlibProperty.getString("nculture.login.post.member.redirect.uri"); + } + + model.addAttribute("url", redirectUrl); + return "nlib/login/loginPreSet"; + } + + /** + * ID, PW를 입력받아 로그인을 처리한다. + * (스프링 시큐리티 로그인 수행) + * + * @param request + * @param response + * @param username + * @param password + * @param model + * @return + */ + @RequestMapping("/login/login.do") + public String login(HttpServletRequest request, HttpServletResponse response, + @RequestParam(required = false) String username, @RequestParam(required = false) String password, + ModelMap model) throws Exception { + + String loginResult = loginService.login(request, username, password); + String redirectUrl = NlibProperty.getString("home.uri"); + + // 정상적으로 로그인된 경우 + if (StringUtil.isEmpty(loginResult)) { + RequestCache cache = new HttpSessionRequestCache(); + SavedRequest savedRequest = cache.getRequest(request, response); + if (savedRequest != null) { + redirectUrl = savedRequest.getRedirectUrl(); + } + + // 쿠키 카트(비로그인 상태의 카트정보) 존재하는 경우, 해당 사용자 카트(DB)로 등록한 후, 쿠키 카트 삭제 + //String mbInfoId = getMbInfoId(request); + //cartService.mergeCart(mbInfoId, request, response); + } + // 로그인 실패 + else { + redirectUrl = NlibProperty.getString("login.back.url") + "?error=" + loginResult; + } + + log.debug("login.do > loginResult = " + loginResult); + log.debug("login.do > redirectUrl = " + redirectUrl); + + return "redirect:" + redirectUrl; + } + + /** + * 정상적인 사용자의 로그인 요청이 검증된 후, 실제 해당 지방문화원 사이트 URL로 호출되는 함수로써 로그인 최종 처리를 진행한다. + * + * @param req + * @param res + * @param session + * @param model + * @return + * @throws Exception + */ + @RequestMapping(value= {"/login/loginCouncilSSO.do"}) + public String loginCouncilSSO( + HttpServletRequest request, + HttpServletResponse response, + HttpSession session, + ModelMap model) throws Exception { + + String jsessionId = session.getId(); + String councilCd = (String)session.getAttribute("councilCd"); + String councilReturnUrl = (String)session.getAttribute("councilReturnUrl"); + OAuthUniversalUser oauthUser = SessionConfig.getLoginInfo(jsessionId); + + if(oauthUser == null || !oauthUser.isValid()) { + SessionConfig.removeLoginInfo(jsessionId); + model.addAttribute("message", "잘못된 접근입니다. 정상적인 방법으로 이용바랍니다."); + model.addAttribute("loginBtnYn", "Y"); + model.addAttribute("memberBtnYn", "Y"); + return "nlib/login/loginMessage"; + } + + //----------------------------------------------- + // 로그인 처리 + //----------------------------------------------- + String loginResult = loginService.loginCouncilSSO(request, councilCd, oauthUser); + + // 정상 SNS 연동 로그인 + if(loginResult == null) { + String mbInfoId = getMbInfoId(request); + cartService.mergeCart(mbInfoId, request, response); + SessionConfig.removeLoginInfo(jsessionId); + // 세션에 설정된 redirect 주소 확인 + return "redirect:" + addParamsToUrl(councilReturnUrl, "fromPage", "login"); + } + + // 휴면계좌 + if(StringUtil.equalsIgnoreCase(loginResult, loginService.WRN_CODE_DORMANT)) { + return "redirect:" + NlibProperty.getString("login.dormant.url"); + } + + // SNS 로그인은 정상적이나, NLIB 시스템에 등록되지 않은 사용자 : 회원가입으로 전환 + model.addAttribute("error", loginResult); + if(StringUtil.equalsIgnoreCase(loginResult, loginService.ERR_CODE_REQ_MEMBERSHIP)) { + SessionConfig.setNewMemberInfo(jsessionId, oauthUser); + SessionConfig.removeLoginInfo(jsessionId); + model.addAttribute("message", "먼저 회원가입하신 후, 이용하여 주시기 바랍니다."); + model.addAttribute("memberBtnYn", "Y"); + return "nlib/login/loginMessage"; + } else if(StringUtil.equalsIgnoreCase(loginResult, loginService.ERR_CODE_REQ_SNSLOGIN)) { + SessionConfig.setNewMemberInfo(jsessionId, oauthUser); + SessionConfig.removeLoginInfo(jsessionId); + model.addAttribute("message", "먼저 로그인할 SNS를 선택하여 로그인 바랍니다."); + model.addAttribute("loginBtnYn", "Y"); + return "nlib/login/loginMessage"; + } + + // 잘못된 접근 또는 기타 오류 + SessionConfig.removeLoginInfo(jsessionId); + model.addAttribute("message", "로그인에 실패하였습니다. 관리자에게 문의바랍니다 : " + loginResult); + return "nlib/login/loginMessage"; + + } + + /** + * 로그아웃 후의 처리를 담당한다. 스프링 시큐리티에서 로그아웃이 수행된 후, 호출된다. + * + * @param req + * @return + */ + @RequestMapping("/login/logout.do") + public String logout(HttpServletRequest req, ModelMap model) { + model.addAttribute("message", "이용해 주셔서 감사드립니다."); + model.addAttribute("loginBtnYn", "Y"); + model.addAttribute("logout", "logout"); + return "nlib/login/loginMessage"; + } + + /** + * 휴면계좌 안내 및 해지 선택 화면을 표출한다. + * + * @param req + * @param error + * @param message + * @param logout + * @param redirectAttrs + * @param paramMap + * @param model + * @param session + * @return + */ + @RequestMapping("/login/activateDormantAccForm.do") + public String activateDormantAccForm( + HttpServletRequest req, + RedirectAttributes redirectAttrs, + @RequestParam Map paramMap, + Model model, + HttpSession session) { + + //---------------------------------------------- + // 지방문화원 사이트에서 접속한 경우, 지방문화원 정보 확인 + //---------------------------------------------- + String councilJsessionId = (String)session.getAttribute("councilJsessionId"); + String councilDnsHost = (String)session.getAttribute("councilDnsHost"); + String councilReturnUrl = (String)session.getAttribute("councilReturnUrl"); + String councilHomeUrl = (String)session.getAttribute("councilHomeUrl"); + String councilCd = (String)session.getAttribute("councilCd"); + String councilNm = (String)session.getAttribute("councilNm"); + + log.debug("activateDormantAccForm > sessionid=" + session.getId()); + log.debug("activateDormantAccForm > councilJsessionId = " + councilJsessionId); + log.debug("activateDormantAccForm > councilDnsHost = " + councilDnsHost); + log.debug("activateDormantAccForm > councilReturnUrl = " + councilReturnUrl); + log.debug("activateDormantAccForm > councilHomeUrl = " + councilHomeUrl); + log.debug("activateDormantAccForm > councilCd = " + councilCd); + log.debug("activateDormantAccForm > councilNm = " + councilNm); + + OAuthUniversalUser oauthUser = SessionConfig.getLoginInfo(session.getId()); + model.addAttribute("oauthUser", oauthUser); + return "nlib/login/activateDormantAccForm"; + } + + /** + * 휴면계좌 안내 및 해지 선택 화면을 표출한다. + * + * @param req + * @param error + * @param message + * @param logout + * @param redirectAttrs + * @param paramMap + * @param model + * @param session + * @return + */ + @RequestMapping("/login/activateDormantAcc.do") + public String activateDormantAcc( + HttpServletRequest req, + @RequestParam Map paramMap, + Model model, + HttpSession session) { + + String mbInfoId = StringUtil.getString(paramMap.get("mbInfoId"), ""); + + //---------------------------------------------- + // 지방문화원 사이트에서 접속한 경우, 지방문화원 정보 확인 + //---------------------------------------------- + String councilDnsHost = (String)session.getAttribute("councilDnsHost"); + String councilReturnUrl = (String)session.getAttribute("councilReturnUrl"); + String councilHomeUrl = (String)session.getAttribute("councilHomeUrl"); + String councilCd = (String)session.getAttribute("councilCd"); + String councilNm = (String)session.getAttribute("councilNm"); + + log.debug("activateDormantAcc > sessionid=" + session.getId()); + log.debug("activateDormantAcc > councilDnsHost = " + councilDnsHost); + log.debug("activateDormantAcc > councilReturnUrl = " + councilReturnUrl); + log.debug("activateDormantAcc > councilHomeUrl = " + councilHomeUrl); + log.debug("activateDormantAcc > councilCd = " + councilCd); + log.debug("activateDormantAcc > councilNm = " + councilNm); + + OAuthUniversalUser oauthUser = SessionConfig.getLoginInfo(session.getId()); + NlibLoginVO loginVO = oauthUser.getNlibVO(); + + if(loginVO == null || !mbInfoId.equals(loginVO.getMbInfoId())) { + model.addAttribute("code", "TIMEOUT"); + model.addAttribute("message", "잘못된 접근입니다. 장시간 대기로 다시 로그인 하신 후, 이용해 주시기 바랍니다."); + return "nlib/login/activateDormantAccForm"; + } + + int ret = loginService.activateDormantAcc(loginVO); + + if(ret < 1) { + model.addAttribute("code", "NO_TARGET"); + model.addAttribute("message", "휴면사용자가 아닙니다. \\n다시 로그인하시거나 관리자에게 문의하여 주시기 바랍니다."); + return "nlib/login/activateDormantAccForm"; + } + + model.addAttribute("oauthUser", oauthUser); + + return "nlib/login/activateDormantAcc"; + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/user/web/MemberController.java b/legacy/nlib/src/main/java/nlib/user/web/MemberController.java new file mode 100644 index 00000000..a79f5187 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/user/web/MemberController.java @@ -0,0 +1,961 @@ + +package nlib.user.web; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +import nlib.util.UUID; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import egovframework.com.ext.oauth.service.OAuthLogin; +import egovframework.com.ext.oauth.service.OAuthUniversalUser; +import egovframework.com.ext.oauth.service.OAuthVO; +import egovframework.rte.fdl.cryptography.EgovPasswordEncoder; +import nlib.cmm.NlibCommonController; +import nlib.cmm.crypto.AriaCrypto; +import nlib.cmm.service.NlibProperty; +import nlib.cmm.session.SessionConfig; +import nlib.col.service.RentService; +import nlib.info.service.InformService; +import nlib.mail.EmailSender; +import nlib.mail.service.EmailVO; +import nlib.user.service.LoginService; +import nlib.user.service.MemberService; +import nlib.user.service.NlibLoginVO; +import nlib.user.service.NlibSmsVO; +import nlib.user.service.UserInfoService; +import nlib.util.StringUtil; + +import nlib.util.EmailUtil; + + +/** + *
+ * @Class Name : MemberController.java
+ * 
+ * @Description : 회원가입 관련 Controller
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 12. JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 7. 12. + * @version 1.0 + * + */ + +@Controller +public class MemberController extends NlibCommonController{ + + //------------------------------------------- + // SNS 연동 환경설정 정보 : context-oauth.xml 참고 + //------------------------------------------- + @Inject + private OAuthVO naverAuthVO; /* 네이버 */ + + @Inject + private OAuthVO googleAuthVO; /* 구글 */ + + @Inject + private OAuthVO kakaoAuthVO; /* 카카오 */ + //------------------------------------------- + + @Resource(name="userInfoService") + private UserInfoService userInfoService; + + @Resource(name = "rentService") + private RentService rentService; + + @Resource(name="memberService") + private MemberService memberService; + + @Resource(name="informService") + private InformService informService; + + @Resource(name="loginService") + private LoginService loginService; + + @Resource(name = "egovEnvPasswordEncoderService") + EgovPasswordEncoder egovPasswordEncoder; + + @Resource(name = "ariaCrypto") + private AriaCrypto ariaCrypto; + + @Resource(name = "emailUtil") + private EmailUtil emailUtil; + + + /* 이메일 메시지 및 템플릿 정보 */ + //템플릿 파일경로 + @Value("#{properties['mailing.sender.membership.signUpTemplate']}") + private String signUpTemplate; + + @Value("#{properties['mailing.sender.membership.pwdTemplate']}") + private String pwdTemplate; + + @Value("#{properties['mailing.sender.membership.certTemplate']}") + private String certTemplate; + + //보내는 사람 이메일주소 + @Value("#{properties['mailing.sender.membership.email']}") + private String senderAddr; + + //보내는 사람 이름 + @Value("#{properties['mailing.sender.membership.name']}") + private String senderName; + + // SMS 보내는 사람 번호 + @Value("#{properties['sms.sender.phone.number']}") + private String senderNumber; + + //hostName(이미지 접근) + @Value("#{properties['host.name']}") + private String hostName; + + //게스트 USERID + @Value("#{properties['guest.userid']}") + private String gUserId; + + //마이페이지 uri + @Value("#{properties['mypage.uri']}") + private String myPageUri; + + @Autowired + private EmailSender emailSender; + + /** + * 약관 동의화면 + * @param req + * @param model + * @return + * @throws Exception + */ + @RequestMapping(value="/member/selectMemberJoiningInfo.do") + public String selectMemberJoiningInfo(HttpServletRequest req,ModelMap model,HttpSession session) throws Exception { + //이용약관 및 개인정보제공동의 + HashMap termRet = informService.selectTermsInfo(NlibProperty.getString("nlib.council.cd")); + HashMap privacyRet = informService.selectPrivacyInfo(NlibProperty.getString("nlib.council.cd")); + + String jsessionId = session.getId(); + OAuthUniversalUser oauthUser = SessionConfig.getNewMemberInfo(jsessionId); + + int count=0; + + //기 가입계정인지 확인 + count = memberService.selectSnsIdCount(oauthUser); + if(count>0) + { + model.addAttribute("message", "이미 가입된 계정입니다. 로그인 후, 이용해 주시기 바랍니다."); + model.addAttribute("loginBtnYn", "Y"); + return "nlib/login/loginMessage"; + } + + model.addAttribute("termTitle", termRet.get("TITLE")); + model.addAttribute("termContent", termRet.get("CONTENT")); + + model.addAttribute("privacyTitle", privacyRet.get("TITLE")); + model.addAttribute("privacyContent", privacyRet.get("CONTENT")); + return "/nlib/member/selectMemberJoiningInfo"; + } + + /** + * 회원가입 폼 + * @exception Exception + */ + @RequestMapping(value="/member/insertMemberInfoForm.do") + public String insertMemberInfoForm(HttpServletRequest request,NlibLoginVO vo,HttpSession session,ModelMap model ) throws Exception{ + String jsessionId = session.getId(); + OAuthUniversalUser oauthUser = SessionConfig.getNewMemberInfo(jsessionId); + + String redirectUrl=""; + + String url = request.getRequestURL().toString(); + String councilHomeUrl=url.replaceAll(request.getRequestURI(), "") + request.getContextPath(); + if(oauthUser == null) + { + model.addAttribute("msg","SNS인증이 정상적이지않습니다. 다시 회원가입을 진행해주세요."); + model.addAttribute("url",NlibProperty.getString("member.new.url")); + return "nlib/cmm/alert"; + } + // 등록된 ID가 있는 지 확인 + if(!(StringUtil.getString(oauthUser.getSnsUserId(),"")== "")) + vo = memberService.selectAlreadySignUpId(oauthUser); + + /* 등록된 ID가 있을때 통합처리 */ + if(vo != null && !StringUtil.getString(vo.getMbInfoId(), "").equals("")) + { + oauthUser.setMbInfoId(vo.getMbInfoId()); + memberService.insertMemberSns(oauthUser); + SessionConfig.setLoginInfo(jsessionId, oauthUser); + + session.setAttribute("councilReturnUrl","/member/accountConsolidationForm.do" );//자동로그인후 이동할페이지 + redirectUrl = councilHomeUrl + NlibProperty.getString("nculture.login.post.login.redirect.uri"); + + vo.setEmail(StringUtil.maskEmail(ariaCrypto.decode(vo.getEmail()))); + vo.setName(StringUtil.maskName(vo.getName())); + oauthUser.setSnsUserId(StringUtil.maskEmail(oauthUser.getSnsUserId())); + model.addAttribute("result",vo); + model.addAttribute("oauthUser",oauthUser); + //통합처리 url + return "redirect:" + redirectUrl; + } + model.addAttribute("loginVO",oauthUser); + return "nlib/member/insertMemberInfoForm"; + } + + /** + * 동일한 핸드폰번호로 가입한 계정있을 시 통합팝업 + * @exception Exception + */ + @RequestMapping(value="/member/selectAlreadySignUpMobilePopup.do") + public String selectAlreadySignUpMobile(NlibLoginVO vo,ModelMap model,HttpSession session,HttpServletRequest request) throws Exception{ + List voList = new ArrayList(); + // 등록된 전화번호가 있는 지 확인 (리스트) + voList = memberService.selectAlreadySignUpMobile(vo); + + vo.setMobileNo(ariaCrypto.decode(vo.getMobileNo())); + + //사용자ID 마스킹처리 + for(int i=0;voList.size()>i;i++) + { + voList.get(i).setEmail(StringUtil.maskEmail(ariaCrypto.decode(voList.get(i).getEmail()))); + voList.get(i).setName(StringUtil.maskName(voList.get(i).getName())); + } + + model.addAttribute("cnt",voList.size()); + model.addAttribute("result",voList); + model.addAttribute("vo",vo); + return "nlib/member/alreadySignUpPopup"; + } + + /** + * 회원가입시 기존계정과 핸드폰번호가 일치할시 sns 계정통합 + * @exception Exception + */ + @RequestMapping(value="/member/snsAccountLink.ajax" , method=RequestMethod.POST) + public @ResponseBody String snsAccountLink(NlibLoginVO vo,HttpServletResponse response,Authentication authentication,ModelMap model,HttpServletRequest request,HttpSession session) throws Exception{ + String jsessionId = session.getId(); + OAuthUniversalUser oauthUser = SessionConfig.getNewMemberInfo(jsessionId); + + if(oauthUser == null) + { + model.addAttribute("msg","SNS인증이 정상적이지않습니다. 다시 회원가입을 진행해주세요."); + model.addAttribute("url",NlibProperty.getString("member.new.url")); + return "nlib/cmm/alert"; + } + + NlibLoginVO loginVO = new NlibLoginVO(); + loginVO.setMbInfoId(vo.getMbInfoId()); + + //사용자 정보를 가져온다. + loginVO = userInfoService.selectMyInfo(loginVO); + + String msg=""; + + String encodedText=null; + encodedText = egovPasswordEncoder.encryptPassword(loginVO.getLoginUserId()+vo.getPassword()); + vo.setPassword(encodedText); + + //암호화된 패스워드 비교 + if(loginVO.getPassword().equals(vo.getPassword())) { + oauthUser.setMbInfoId(vo.getMbInfoId()); + memberService.insertMemberSns(oauthUser); + model.addAttribute("oauthUser",oauthUser); + model.addAttribute("NlibLoginVO",vo); + msg="link"; + }else { + msg="mismatch"; + } + return msg; + } + + /** + * 계정통합후 로그인 + * @exception Exception + */ + @RequestMapping(value="/member/snsAccountLinkLogin.do") + public String snsAccountLinkLogin(NlibLoginVO vo,ModelMap model,HttpSession session,HttpServletRequest request) throws Exception{ + String redirectUrl=""; + + String url = request.getRequestURL().toString(); + String councilHomeUrl=url.replaceAll(request.getRequestURI(), "") + request.getContextPath(); + + String jsessionId = session.getId(); + OAuthUniversalUser oauthUser = SessionConfig.getNewMemberInfo(jsessionId); + + if(oauthUser == null) + { + model.addAttribute("msg","SNS인증이 정상적이지않습니다. 다시 회원가입을 진행해주세요."); + model.addAttribute("url",NlibProperty.getString("member.new.url")); + return "nlib/cmm/alert"; + } + + SessionConfig.setLoginInfo(jsessionId, oauthUser); + session.setAttribute("councilReturnUrl","/member/accountConsolidationForm.do" );//로그인후 이동할페이지 + redirectUrl = councilHomeUrl + NlibProperty.getString("nculture.login.post.login.redirect.uri"); + + return "redirect:" + redirectUrl; + } + + /** + * 계정통합 결과폼 + * @exception Exception + */ + @RequestMapping(value="/member/accountConsolidationForm.do") + public String accountConsolidationForm(NlibLoginVO vo,ModelMap model,Authentication authentication,HttpSession session,HttpServletRequest request) throws Exception{ + //사용자 정보를 가져온다. + NlibLoginVO loginVO = getNlibLoginVO(authentication); + loginVO.setJoinCouncilCd(getCurCouncilCd(request)); + + loginVO = loginService.selectLoginUserInfo(loginVO); + loginVO.setEmail(StringUtil.maskEmail(loginVO.getEmail())); + loginVO.setName(StringUtil.maskName(loginVO.getName())); + + String jsessionId = session.getId(); + OAuthUniversalUser oauthUser = SessionConfig.popNewMemberInfo(jsessionId); + + if(oauthUser == null) + { + model.addAttribute("msg","SNS인증이 정상적이지않습니다. 다시 회원가입을 진행해주세요."); + model.addAttribute("url",NlibProperty.getString("member.new.url")); + return "nlib/cmm/alert"; + } + + model.addAttribute("result",loginVO); + model.addAttribute("oauthUser",oauthUser); + return "/nlib/member/accountConsolidationForm"; + } + /** + * 회원가입 + * @exception Exception + */ + @RequestMapping(value="/member/insertMemberInfo.do") + public String insertMemberInfo(NlibLoginVO vo,ModelMap model,HttpSession session,HttpServletRequest request) throws Exception{ + String redirectUrl=""; + + String url = request.getRequestURL().toString(); + String councilHomeUrl=url.replaceAll(request.getRequestURI(), "") + request.getContextPath(); + String jsessionId = session.getId(); + OAuthUniversalUser oauthUser = SessionConfig.popNewMemberInfo(jsessionId); + if(oauthUser != null) + { + //핸드폰인증시 sns제공 번호와 회원가입폼 번호 비교 + if(!(vo.getMobileNo().equals(oauthUser.getSnsMobileNo()))) + { + if(oauthUser.getNlibVO() == null) + { + model.addAttribute("msg","핸드폰인증이 정상적이지않습니다. 다시 회원가입을 진행해주세요."); + model.addAttribute("url",NlibProperty.getString("member.new.url")); + return "nlib/cmm/alert"; + } + + if( !(vo.getMobileVrfctNo().equals(oauthUser.getNlibVO().getMobileVrfctNo())) + || !(vo.getMobileNo().equals(oauthUser.getNlibVO().getMobileNo())) + || oauthUser.getNlibVO().getMobileVrfctDd() == null) + { + model.addAttribute("msg","핸드폰인증이 정상적이지않습니다. 다시 회원가입을 진행해주세요."); + model.addAttribute("url",NlibProperty.getString("member.new.url")); + return "nlib/cmm/alert"; + } + } + //이메일인증시 sns제공 이메일과 회원가입폼 이메일 비교 + if(!(vo.getEmail().equals(oauthUser.getSnsUserId()))) + { + if(oauthUser.getNlibVO() == null) + { + model.addAttribute("msg","이메일인증이 정상적이지않습니다. 다시 회원가입을 진행해주세요."); + model.addAttribute("url",NlibProperty.getString("member.new.url")); + return "nlib/cmm/alert"; + } + if(!(vo.getEmailVrfctNo().equals(oauthUser.getNlibVO().getEmailVrfctNo())) + || !(vo.getEmail().equals(oauthUser.getNlibVO().getEmail())) + ||oauthUser.getNlibVO().getEmailVrfctDd() == null) + { + model.addAttribute("msg","이메일인증이 정상적이지않습니다. 다시 회원가입을 진행해주세요."); + model.addAttribute("url",NlibProperty.getString("member.new.url")); + return "nlib/cmm/alert"; + } + } + }else { + model.addAttribute("msg","잘못된 접근입니다. \\n장시간 대기로 다시 회원가입을 진행해주세요."); + model.addAttribute("url",NlibProperty.getString("member.new.url")); + return "nlib/cmm/alert"; + } + //문화원코드 + String councilNm = (String)session.getAttribute("councilNm"); + //클라이언트 IP주소 + vo.setIp(getRemoteIP(request)); + + //초기비밀번호 + String initPwd = memberService.createInitPwd(); + vo.setPassword(initPwd); + + //회원정보 insert + memberService.insertMemberInfo(vo); + + //sns 테이블 insert + oauthUser.setMbInfoId(vo.getMbInfoId()); + + memberService.insertMemberSns(oauthUser); + + SessionConfig.setLoginInfo(jsessionId, oauthUser); + session.setAttribute("councilReturnUrl","/member/insertMemberInfoResult.do" );//로그인후 이동할페이지 + redirectUrl = councilHomeUrl + NlibProperty.getString("nculture.login.post.login.redirect.uri"); + + // 결과가 정상이면, 안내 메일 발송 + // > 템플릿파일에서 내용 mailing.sender.membership.signUpTemplate + // > 발송처리 요청 + vo.setEmail(ariaCrypto.decode(vo.getEmail())); + + SimpleDateFormat format = new SimpleDateFormat ("yyyy/MM/dd HH:mm:ss"); + Date date = new Date(); + String time = format.format(date); + + Map replaceContents = new HashMap(); + replaceContents.put("${name}", vo.getName()); + replaceContents.put("${email}", vo.getEmail()); + replaceContents.put("${councilNm}", councilNm); + replaceContents.put("${hostName}", hostName); + replaceContents.put("${time}", time); + replaceContents.put("${password}", initPwd); + emailUtil.sendEmail(vo.getEmail(),senderName +" 회원가입을 축하드립니다.",replaceContents,signUpTemplate); + + return "redirect:" + redirectUrl; + } + + + /** + * 회원가입 결과페이지 + * @param response + * @param authentication + * @param request + * @param session + * @return + * @throws Exception + */ + @RequestMapping(value="/member/insertMemberInfoResult.do") + public String insertMemberInfoResult(HttpServletResponse response,Authentication authentication,HttpServletRequest request,HttpSession session, ModelMap model) throws Exception{ + //사용자 정보를 가져온다. + NlibLoginVO loginVO = getNlibLoginVO(authentication); + if(loginVO == null) { + model.addAttribute("msg","잘못된 접근입니다. \n다시 로그인 하신 후, 이용해 주시기 바랍니다."); + model.addAttribute("url","/"); + return "nlib/cmm/alert"; + } + model.addAttribute("result",loginVO); + return "nlib/member/insertMemberInfoResult"; + } + /** + * 이메일 인증번호 발송 + * @exception Exception + */ + @RequestMapping(value="/member/emailCertNum.ajax" , method=RequestMethod.POST) + public @ResponseBody Map emailCertNum(HttpServletResponse response,Authentication authentication,HttpServletRequest request,HttpSession session) throws Exception{ + String email = request.getParameter("email"); + //회원가입페이지와 정보수정페이지의 프로세스 분기를위해 가져옴 + String pageName = request.getParameter("pageName"); + + Map map = new HashMap(); + + OAuthUniversalUser authUser= new OAuthUniversalUser(); + authUser.setSnsUserId(email); + authUser.setSnsEmail(email); + + String mbInfoId=""; + NlibLoginVO chk = new NlibLoginVO(); + chk = memberService.selectAlreadySignUpId(authUser); + + String jsessionId = session.getId(); + + //사용자 정보를 가져온다. 회원가입페이지라면 null + NlibLoginVO loginVO = getNlibLoginVO(authentication); + mbInfoId= loginVO.getMbInfoId(); + + //중복된 아이디가 있을시(로그인시 본인의 mbInfoId 와 동일한경우는 제외) + if(chk != null && !(chk.getMbInfoId().equals(mbInfoId))) + { + + map.put("msg","이미 사용중인 이메일입니다."); + map.put("emailCertYn","N"); + return map; + } + + //인증번호 생성 + String CertNumber=memberService.numberGen(6,1); + + //내 정보 페이지 + if("myInfo".equals(pageName)) + { + loginVO.setEmailTemp(email); + loginVO.setEmailVrfctNo(CertNumber); + replaceNlibLoginVO(request, loginVO); + }else + { + OAuthUniversalUser oauthUser = SessionConfig.getNewMemberInfo(jsessionId); + + if(oauthUser == null) { + map.put("msg","이메일 발송에 실패하였습니다. \n장시간 대기로 다시 로그인 하신 후, 이용해 주시기 바랍니다."); + map.put("emailCertYn","N"); + return map; + } + + NlibLoginVO vo=oauthUser.getNlibVO(); + //이미 생성된 VO가 없을때 + if(vo == null) + vo= new NlibLoginVO(); + + vo.setEmail(email); + vo.setEmailVrfctNo(CertNumber); + oauthUser.setNlibVO(vo); + SessionConfig.setNewMemberInfo(jsessionId,oauthUser); + + } + + //이메일 발송 + // 결과가 정상이면, 안내 메일 발송 + // > 템플릿파일에서 내용 mailing.sender.membership.certTemplate + // > 발송처리 요청 + Map replaceContents = new HashMap(); + + SimpleDateFormat format = new SimpleDateFormat ("yyyy/MM/dd HH:mm:ss"); + Date date = new Date(); + String time = format.format(date); + + String councilNm = (String)session.getAttribute("councilNm"); + + replaceContents.put("${certNumber}", CertNumber); + replaceContents.put("${time}", time); + replaceContents.put("${hostName}", hostName); + replaceContents.put("${councilNm}", councilNm); + replaceContents.put("${name}", StringUtil.getString(loginVO.getName(),"")); + + String result = emailUtil.sendEmail(email,senderName +" 이메일 인증번호입니다.",replaceContents,certTemplate); + + if(result == "templateFail") + { + map.put("msg","이메일 발송에 실패하였습니다. \n관리자에게 문의하여 주시기 바랍니다."); + map.put("emailCertYn","N"); + return map; + } + + map.put("msg","이메일 인증번호가 발송됐습니다."); + map.put("emailCertYn","Y"); + return map; + } + + /** + * 이메일 인증번호 확인 + * @exception Exception + */ + @RequestMapping(value="/member/emailCertNumChk.ajax" , method=RequestMethod.POST) + public @ResponseBody String emailCertNumChk(HttpServletResponse response,Authentication authentication,HttpServletRequest request,HttpSession session) throws Exception{ + String email = request.getParameter("email"); + String emailVrfctNo = request.getParameter("emailVrfctNo"); + //회원가입페이지와 정보수정페이지의 프로세스 분기를위해 가져옴 + String pageName = request.getParameter("pageName"); + + SimpleDateFormat format = new SimpleDateFormat ( "yyyy년 MM월dd일 HH시mm분ss초"); + Date time = new Date(); + + //내 정보 페이지 + if("myInfo".equals(pageName)) + { + //사용자 정보를 가져온다. 회원가입페이지라면 null + NlibLoginVO loginVO = getNlibLoginVO(authentication); + + //이메일과 인증번호 확인 + if(loginVO.getEmailTemp().equals(email) && loginVO.getEmailVrfctNo().equals(emailVrfctNo)) + { + loginVO.setEmailVrfctDd(format.format(time)); + replaceNlibLoginVO(request, loginVO); + return "true"; + }else { + return "false"; + } + + }else + { + //세션에 저장 + String jsessionId = session.getId(); + OAuthUniversalUser oauthUser = SessionConfig.getNewMemberInfo(jsessionId); + + if(oauthUser == null) + { + return "false"; + } + //이메일과 인증번호 확인 + if(oauthUser.getNlibVO().getEmail().equals(email) && oauthUser.getNlibVO().getEmailVrfctNo().equals(emailVrfctNo)) + { + + NlibLoginVO sessionNlibLoginVO = oauthUser.getNlibVO(); + sessionNlibLoginVO.setEmailVrfctDd(format.format(time)); + oauthUser.setNlibVO(sessionNlibLoginVO); + SessionConfig.setNewMemberInfo(jsessionId,oauthUser); + return "true"; + }else { + return "false"; + } + } + } + + /** + * 핸드폰 인증번호 발송 + * @exception Exception + */ + @RequestMapping(value="/member/mobileCertNum.ajax" , method=RequestMethod.POST) + public @ResponseBody void phoneCertNum(HttpServletResponse response,Authentication authentication,HttpServletRequest request,HttpSession session) throws Exception{ + String mobileNo = request.getParameter("mobileNo"); + + //회원가입페이지와 정보수정페이지의 프로세스 분기를위해 가져옴 + String pageName = request.getParameter("pageName"); + + //인증번호 생성 + String CertNumber=memberService.numberGen(6,1); + + //세션에 저장 + String jsessionId = session.getId(); + + //내 정보 페이지 + if("myInfo".equals(pageName)) + { + NlibLoginVO loginVO = getNlibLoginVO(authentication); + loginVO.setMobileTemp(mobileNo); + loginVO.setMobileVrfctNo(CertNumber); + replaceNlibLoginVO(request, loginVO); + } + else { + OAuthUniversalUser oauthUser = SessionConfig.getNewMemberInfo(jsessionId); + + NlibLoginVO vo=oauthUser.getNlibVO(); + //이미 생성된 VO가 없을때 + if(vo == null) + vo= new NlibLoginVO(); + + vo.setMobileNo(mobileNo); + vo.setMobileVrfctNo(CertNumber); + oauthUser.setNlibVO(vo); + SessionConfig.setNewMemberInfo(jsessionId,oauthUser); + } + + NlibSmsVO smsVO=new NlibSmsVO(); + smsVO.setCmid(UUID.getNlibCommonID("",32)); + smsVO.setDestPhone(mobileNo); + smsVO.setSendPhone(senderNumber); + smsVO.setMsgBody("[한국문화원연합회] 본인확인 인증번호 [" + CertNumber + "]를 입력해주세요."); + // 문자발송 솔루션 + memberService.sendSms(smsVO); + //------------ + } + + /** + * 핸드폰 인증번호 확인 + * @exception Exception + */ + @RequestMapping(value="/member/mobileCertNumChk.ajax" , method=RequestMethod.POST) + public @ResponseBody String mobileCertNumChk(HttpServletResponse response,Authentication authentication,HttpServletRequest request,HttpSession session) throws Exception{ + String mobileNo = request.getParameter("mobileNo"); + String mobileVrfctNo = request.getParameter("mobileVrfctNo"); + //회원가입페이지와 정보수정페이지의 프로세스 분기를위해 가져옴 + String pageName = request.getParameter("pageName"); + + SimpleDateFormat format = new SimpleDateFormat ( "yyyy년 MM월dd일 HH시mm분ss초"); + + Date time = new Date(); + + //내 정보 페이지 + if("myInfo".equals(pageName)) + { + //사용자 정보를 가져온다. 회원가입페이지라면 null + NlibLoginVO loginVO = getNlibLoginVO(authentication); + + //핸드폰번호와 인증번호 확인 + if(loginVO.getMobileTemp().equals(mobileNo) && loginVO.getMobileVrfctNo().equals(mobileVrfctNo)) + { + loginVO.setMobileVrfctDd(format.format(time)); + replaceNlibLoginVO(request, loginVO); + return "true"; + }else { + return "false"; + } + }else { + //세션에 저장 + String jsessionId = session.getId(); + OAuthUniversalUser oauthUser = SessionConfig.getNewMemberInfo(jsessionId); + + if(oauthUser == null) + { + return "false"; + } + + //핸드폰번호와 인증번호 확인 + if(oauthUser.getNlibVO().getMobileNo().equals(mobileNo) && oauthUser.getNlibVO().getMobileVrfctNo().equals(mobileVrfctNo)) + { + NlibLoginVO sessionNlibLoginVO = oauthUser.getNlibVO(); + sessionNlibLoginVO.setMobileVrfctDd(format.format(time)); + oauthUser.setNlibVO(sessionNlibLoginVO); + SessionConfig.setNewMemberInfo(jsessionId,oauthUser); + return "true"; + }else { + return "false"; + } + } + } + + /** + * 회원탈퇴 폼 + * @exception Exception + */ + @Secured("ROLE_USER") + @RequestMapping(value="/member/deleteMembershipForm.do") + public String deleteMembershipForm(HttpServletResponse response,Authentication authentication,HttpServletRequest request,ModelMap model) throws Exception{ + //사용자 정보를 가져온다. + NlibLoginVO loginVO = getNlibLoginVO(authentication); + if(loginVO == null) { + model.addAttribute("msg","잘못된 접근입니다. \n장시간 대기로 다시 로그인 하신 후, 이용해 주시기 바랍니다."); + model.addAttribute("url","/"); + return "nlib/cmm/alert"; + } + loginVO.setJoinCouncilCd(getCurCouncilCd(request)); + + loginVO = loginService.selectLoginUserInfo(loginVO); + //이메일,이름 마스킹 + loginVO.setEmail(StringUtil.maskEmail(loginVO.getEmail())); + loginVO.setName(StringUtil.maskName(loginVO.getName())); + model.addAttribute("loginVO",loginVO); + return "nlib/member/deleteMembershipForm"; + } + + /** + * 회원탈퇴 + * @exception Exception + */ + @RequestMapping(value="/member/deleteMembership.ajax") + public @ResponseBody String deleteMembership(Authentication authentication,HttpServletResponse response,HttpServletRequest request,ModelMap model) throws Exception{ + //사용자 정보를 가져온다. + NlibLoginVO loginVO = getNlibLoginVO(authentication); + String message=""; + + if(loginVO == null) { + model.addAttribute("msg","잘못된 접근입니다. \\n장시간 대기로 다시 로그인 하신 후, 이용해 주시기 바랍니다."); + model.addAttribute("url","/"); + return "nlib/cmm/alert"; + } + + // 대출/방문열람 현황 + Map rentStats = rentService.getRentStats(loginVO.getMbInfoId()); + model.addAttribute("rentStats", rentStats); + + if(Integer.parseInt(rentStats.get("lentCnt")) > 0 || Integer.parseInt(rentStats.get("lentOverCnt")) > 0) { + return message = "nonReturn"; + } + + loginVO.setJoinCouncilCd(getCurCouncilCd(request)); + + loginVO = loginService.selectLoginUserInfo(loginVO); + String password = egovPasswordEncoder.encryptPassword(loginVO.getLoginUserId()+request.getParameter("password").trim()); + + if(loginVO != null && (loginVO.getPassword().equals(password))) + { + //회원탈퇴 + memberService.deleteMembership(loginVO); + + OAuthUniversalUser oAuthVO = new OAuthUniversalUser(); + oAuthVO.setMbInfoId(loginVO.getMbInfoId()); + + //sns 연동해제 + userInfoService.deleteSnsLink(oAuthVO); + + message="delete"; + }else { + message="mismatch"; + } + + return message; + } + + /** + * 비밀번호초기화 폼 + * @exception Exception + */ + @RequestMapping(value="/member/initPasswordFormPopup.do") + public String searchIdForm(NlibLoginVO vo,HttpServletResponse response,HttpServletRequest request,ModelMap model) throws Exception{ + model.addAttribute("loginVO", vo); + return "nlib/member/initPasswordFormPopup"; + } + + /** + * 비밀번호 초기화 + * @exception Exception + */ + @RequestMapping(value="/member/initPassword.ajax") + public @ResponseBody String initPassword(NlibLoginVO vo,HttpSession session,HttpServletResponse response,HttpServletRequest request,ModelMap model) throws Exception{ + String email = vo.getEmail(); + vo.setEmail(""); + int count =0; + //mbinfo를 이용해 조회 + NlibLoginVO loginVO = userInfoService.selectMyInfo(vo); + + //일치하는 이메일이 있는지 확인 + List snsLoginVO = userInfoService.selectSnsSignUpList(vo); + if(email.equals(loginVO.getEmail()) || email.equals(loginVO.getLoginUserId())) + { + count +=1; + } + for(int i = 0; snsLoginVO.size() > i;i++) + { + if(email.equals(snsLoginVO.get(i).getSnsUserId())) + count +=1; + } + + if(count == 0) + { + return "fail"; + } + + String name=""; + + //내 정보 수정시 비밀번호 찾기 , 회원가입시 비밀번호찾기 메일발송시(마스킹) 차별화 + if(vo != null && "alreadySignUpPopup".equals(vo.getPreviousPage()) ) + { + name = vo.getNameTemp(); + }else { + name = loginVO.getName(); + } + + String message = null; + + //비밀번호 초기화 변수 생성 + String initPwd=memberService.createInitPwd(); + + if(loginVO!=null) + { + // 결과가 정상이면, 안내 메일 발송 + // > 템플릿파일에서 내용 mailing.sender.membership.pwdtemplate + // > 발송처리 요청 + + SimpleDateFormat format = new SimpleDateFormat ("yyyy/MM/dd HH:mm:ss"); + Date date = new Date(); + String time = format.format(date); + + String councilNm = (String)session.getAttribute("councilNm"); + + Map replaceContents = new HashMap(); + loginVO.setPassword(egovPasswordEncoder.encryptPassword(loginVO.getLoginUserId()+initPwd)); + replaceContents.put("${initPwd}", initPwd); + replaceContents.put("${time}", time); + replaceContents.put("${hostName}", hostName); + replaceContents.put("${councilNm}", councilNm); + replaceContents.put("${name}", name); + message = emailUtil.sendEmail(email, senderName +" 비밀번호 초기화 안내메일입니다.",replaceContents,pwdTemplate); + if("success".equals(message)) + { + memberService.changePassword(loginVO); + } + }else { + message="fail"; + } + + return message; + } + + /** + * 비밀번호 변경 + * @exception Exception + */ + @RequestMapping(value="/member/changePassword.ajax") + public @ResponseBody String changePassword(Authentication authentication,HttpServletResponse response,HttpServletRequest request,ModelMap model) throws Exception{ + //사용자 정보를 가져온다. + NlibLoginVO loginVO = getNlibLoginVO(authentication); + + String message=""; + + if(loginVO == null) { + message="notLogin"; + return message; + } + + String pattern = "^.*(?=^.{9,}$)(?=.*\\d)(?=.*[a-zA-Z])(?=.*[!@#$%^&+=]).*$"; + + if(!request.getParameter("newPassword").equals(request.getParameter("newPasswordConfirm")) || !Pattern.matches(pattern, request.getParameter("newPassword")) ) + { + message="passwordNoMatch"; + return message; + } + + loginVO.setJoinCouncilCd(getCurCouncilCd(request)); + + loginVO = loginService.selectLoginUserInfo(loginVO); + + String password=egovPasswordEncoder.encryptPassword(loginVO.getLoginUserId()+request.getParameter("password")); + String newPassword=egovPasswordEncoder.encryptPassword(loginVO.getLoginUserId()+request.getParameter("newPassword")); + + if(loginVO!=null && loginVO.getPassword().equals(password)) + { + loginVO.setPassword(newPassword); + loginVO.encodePrivateInfo(); + //암호화된 비밀번호로 수정 + memberService.changePassword(loginVO); + message="success"; + }else { + message="fail"; + } + + return message; + } + //클라이언트 IP 가져오기 + public static String getRemoteIP(HttpServletRequest request){ + String ip = request.getHeader("X-FORWARDED-FOR"); + + //proxy 환경일 경우 + if (ip == null || ip.length() == 0) { + ip = request.getHeader("Proxy-Client-IP"); + } + + //웹로직 서버일 경우 + if (ip == null || ip.length() == 0) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + + if (ip == null || ip.length() == 0) { + ip = request.getRemoteAddr() ; + } + + return ip; + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/user/web/UserInfoController.java b/legacy/nlib/src/main/java/nlib/user/web/UserInfoController.java new file mode 100644 index 00000000..bed04bdf --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/user/web/UserInfoController.java @@ -0,0 +1,380 @@ + +package nlib.user.web; + +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.Resource; +import javax.imageio.ImageIO; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import egovframework.com.ext.oauth.service.OAuthUniversalUser; +import egovframework.rte.fdl.cryptography.EgovPasswordEncoder; +import nlib.cmm.NlibCommonController; +import nlib.cmm.qrcode.QRCodeUtil; +import nlib.col.service.CollectionService; +import nlib.col.service.CollectionVO; +import nlib.col.service.InterestService; +import nlib.col.service.ReadService; +import nlib.col.service.RentService; +import nlib.restful.DataApiResVO; +import nlib.security.SecUserDetailsService; +import nlib.user.service.LoginService; +import nlib.user.service.NlibLoginVO; +import nlib.user.service.UserInfoService; +import nlib.util.StringUtil; + + +/** + *
+ * @Class Name : userInfoController.java
+ * 
+ * @Description : 회원 정보 controller
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 14. JSYOO 최초 생성 + * @ 2021.10. 7. KKN 회원증 조회 기능 추가 + * @ 2021.11. 09. KNKIM 마이페이지 기능 추가 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 7. 14. + * @version 1.0 + * + */ +@Controller +public class UserInfoController extends NlibCommonController { + + private static final Logger log = LoggerFactory.getLogger(UserInfoController.class); + + @Resource(name="userInfoService") + private UserInfoService userInfoService; + + @Resource(name="loginService") + private LoginService loginService; + + @Resource(name = "egovEnvPasswordEncoderService") + EgovPasswordEncoder egovPasswordEncoder; + + @Resource(name = "userDetailsService") + private SecUserDetailsService SecUserDetailsService; + + @Resource(name = "rentService") + private RentService rentService; + + @Resource(name = "readService") + private ReadService readService; + + @Resource(name = "interestService") + private InterestService interestService; + + @Resource(name = "collectionService") + private CollectionService collectionService; + + /** QRCodeService (2021.10.07) */ + @Resource(name = "qrCodeService") + private QRCodeUtil qrCodeService; + + + + //마이페이지 uri + @Value("#{properties['mypage.uri']}") + private String myPageUri; + + /** + * 내 정보 수정 페이지 + * @exception Exception + */ + @Secured("ROLE_USER") + @RequestMapping(value="/userInfo/putMyInfo.do") + public String putMyInfo(NlibLoginVO vo,HttpServletResponse response,HttpServletRequest request,Authentication authentication,ModelMap model) throws Exception{ + //사용자 정보를 가져온다. + NlibLoginVO loginVO = getNlibLoginVO(authentication); + + if(loginVO == null) + { + model.addAttribute("msg","잘못된 접근입니다. \\n장시간 대기로 다시 로그인 하신 후, 이용해 주시기 바랍니다."); + model.addAttribute("url","/userInfo/pwCertMyInfo.do"); + return "nlib/cmm/alert"; + } + + loginVO.setJoinCouncilCd(getCurCouncilCd(request)); + + loginVO = loginService.selectLoginUserInfo(loginVO); + if(loginVO == null) + { + model.addAttribute("msg","비정상적인 접근입니다. \\n관리자에게 문의하여 주시기 바랍니다."); + model.addAttribute("url","/userInfo/pwCertMyInfo.do"); + return "nlib/cmm/alert"; + } + + List snsList = new ArrayList(); + + //sns연동 계정 리스트 + snsList = userInfoService.selectSnsSignUpList(loginVO); + + String encodedText=null; + encodedText = egovPasswordEncoder.encryptPassword(loginVO.getLoginUserId()+vo.getPassword()); + vo.setPassword(encodedText); + + //암호화된 패스워드 비교 + if(loginVO.getPassword().equals(vo.getPassword()) || vo.getPreviousPage().equals("deleteMembershipForm")) { + model.addAttribute("loginVO",loginVO); + model.addAttribute("snsList",snsList); + return "nlib/userInfo/putMyInfo"; + }else { + model.addAttribute("msg","비밀번호가 일치하지 않습니다."); + model.addAttribute("url","/userInfo/pwCertMyInfo.do"); + return "nlib/cmm/alert"; + } + } + + /** + * 내 정보 수정 + * @return + * @exception Exception + */ + @Secured("ROLE_USER") + @RequestMapping(value="/userInfo/updateMyInfo.do" , method=RequestMethod.POST) + public String updateMyInfo(NlibLoginVO vo,Authentication authentication,HttpServletResponse response,HttpServletRequest request,ModelMap model) throws Exception{ + + //사용자 정보를 가져온다. + NlibLoginVO loginVO = getNlibLoginVO(authentication); + + if(loginVO != null) + { + //이메일인증 확인 + if(!(vo.getEmail().equals(loginVO.getEmail()))) + { + if(!(vo.getEmailVrfctNo().equals(loginVO.getEmailVrfctNo())) + ||loginVO.getEmailVrfctDd() == null) + { + model.addAttribute("msg","이메일인증이 정상적이지않습니다."); + model.addAttribute("url",myPageUri); + return "nlib/cmm/alert"; + } + vo.setEmail(loginVO.getEmailTemp()); + } + //핸드폰인증 확인 + if(!(vo.getMobileNo().equals(loginVO.getMobileNo()))) + { + if(!(vo.getMobileVrfctNo().equals(loginVO.getMobileVrfctNo())) + ||loginVO.getMobileVrfctDd() == null) + { + model.addAttribute("msg","핸드폰인증이 정상적이지않습니다."); + model.addAttribute("url",myPageUri); + return "nlib/cmm/alert"; + } + vo.setMobileNo(loginVO.getMobileTemp()); + } + }else { + model.addAttribute("msg","잘못된 접근입니다. \\n장시간 대기로 다시 로그인 진행해주세요."); + model.addAttribute("url","/"); + return "nlib/cmm/alert"; + } + + String encodedText=null; + encodedText = egovPasswordEncoder.encryptPassword(vo.getPassword()); + vo.setPassword(encodedText); + + // 내 정보 수정 + userInfoService.updateMyInfo(vo); + NlibLoginVO sessionVO=(NlibLoginVO) SecUserDetailsService.loadUserByUsername(vo.getLoginUserId()); + + //세션에 수정정보로 재 주입 + replaceNlibLoginVO(request,loginVO); + + model.addAttribute("msg","수정되었습니다."); + model.addAttribute("url",myPageUri); + return "nlib/cmm/alert"; + } + + /** + * 내 정보 수정 전 password 인증 + * @exception Exception + */ + @Secured("ROLE_USER") + @RequestMapping(value="/userInfo/pwCertMyInfo.do") + public String pwCertMyInfo(HttpServletResponse response,HttpServletRequest request,ModelMap model) throws Exception{ + NlibLoginVO loginVO = getNlibLoginVO(request); + + if(loginVO == null) + { + model.addAttribute("msg","잘못된 접근입니다. \\n장시간 대기로 다시 로그인 하신 후, 이용해 주시기 바랍니다."); + model.addAttribute("url","/"); + return "nlib/cmm/alert"; + } + + model.addAttribute("loginVO",loginVO); + return "nlib/userInfo/pwCertMyInfo"; + } + + /** SNS연동을 해지한다. + * @param response + * @param request + * @return + * @return + * @throws Exception + */ + @RequestMapping(value="/userInfo/deleteSnsLink.ajax") + public @ResponseBody void deleteSnsLink(HttpServletResponse response,HttpServletRequest request) throws Exception{ + OAuthUniversalUser oAuthVO = new OAuthUniversalUser(); + oAuthVO.setMbSnsId(request.getParameter("mbSnsId")); + userInfoService.deleteSnsLink(oAuthVO); + + } + + /** + * 회원증 QR코드를 조회한다. + * + * (2021.10.07 KKN 추가) + * + * @param request + * @param model + * @return + */ + @Secured("ROLE_USER") + @RequestMapping(value="/userInfo/getMemberQrcodeFormPopup.do") + public String getMemberQrcodeFormPopup(HttpServletRequest request, ModelMap model) { + + NlibLoginVO loginVO = getNlibLoginVO(request); + log.debug("getMemberQrcode : loginVO=" + loginVO.toString()); + + model.addAttribute("loginVO", loginVO); + + return "nlib/userInfo/getMemberQrcodeFormPopup"; + } + + /** + * 회원정보를 가지고 QR 2D 바코드를 생성하여 이미지(JPG)로 출력한다. + * (Zxing Lib 사용) + * + * (2021.10.07 KKN 추가) + * + * @param request + * @param response + * @return + * @throws Exception + */ + @Secured("ROLE_USER") + @RequestMapping(value="/userInfo/getMemberQrcode.do", produces=MediaType.IMAGE_JPEG_VALUE) + public ResponseEntity getMemberQrcode(HttpServletRequest request, HttpServletResponse response) throws Exception { + + NlibLoginVO loginVO = getNlibLoginVO(request); + + if(loginVO == null || StringUtil.isEmpty(loginVO.getMbInfoId())) { + throw new Exception("잘못된 접근입니다."); + } + + BufferedImage bufferedImage = qrCodeService.generateMemberQrcodeImage(loginVO); + + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ImageIO.write( bufferedImage , "jpg", byteArrayOutputStream); + byte[] bs = byteArrayOutputStream.toByteArray(); + response.setContentLength(bs.length); + + final HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.IMAGE_JPEG); + return new ResponseEntity(bs , headers, HttpStatus.OK); + } + + /** + * 회원의 마이페이지를 출력한다. + * (Zxing Lib 사용) + * + * (2021.10.07 KKN 추가) + * + * @param request + * @param response + * @return + * @throws Exception + */ + @Secured("ROLE_USER") + @RequestMapping(value="/userInfo/getMyHome.do") + public String getMyHome(HttpServletRequest request, ModelMap model) throws Exception { + + NlibLoginVO loginVO = getNlibLoginVO(request); + log.debug("getMemberQrcode : loginVO=" + loginVO.toString()); + + model.addAttribute("loginVO", loginVO); + + // 이전접속정보 + Map lastLogin = null; + List> lastLoginList = userInfoService.getLastLogin(loginVO.getMbInfoId()); + if(lastLoginList == null || lastLoginList.size() < 1) { + lastLogin = new HashMap(); + lastLogin.put("dtStr", "(최초접속)"); + lastLogin.put("dtStr", " "); + } else if(lastLoginList.size() == 1) { + lastLogin = lastLoginList.get(0); + } else { + lastLogin = lastLoginList.get(1); + } + model.addAttribute("lastLogin", lastLogin); + + // 소장자료관 접속현황 (최근 5개) + List> visitedOrgs = userInfoService.getVisitedOrgs(loginVO.getMbInfoId()); + model.addAttribute("visitedOrgs", visitedOrgs); + + // 대출/방문열람 현황 + Map rentStats = rentService.getRentStats(loginVO.getMbInfoId()); + model.addAttribute("rentStats", rentStats); + + CollectionVO searchCollectionVO = new CollectionVO(); + searchCollectionVO.setMbInfoId(loginVO.getMbInfoId()); + searchCollectionVO.setPageSize(5); + + // 관심자료 (최근 5개) + List interestList = interestService.listInterests(searchCollectionVO); + int interestTotalCount = interestService.countListInterests(searchCollectionVO); + + interestList = collectionService.setDetailInfoForList(interestList, searchCollectionVO.getMbInfoId()); + + model.addAttribute("interestList", interestList); + model.addAttribute("interestTotalCount", interestTotalCount); + + // 대출내역 (최근 5개) + // 조회 + // 대출상태구분코드("": 전체, A:신청, B:대출준비완료, C:취소, W:대출중, R0:정상반납, R1:연체반납, P:연체) + DataApiResVO resRentVO = rentService.listRentItems(searchCollectionVO); + List rentList = collectionService.setDetailInfoForHashList(resRentVO.getRecordList(), searchCollectionVO.getMbInfoId()); + model.addAttribute("rentList", rentList); + model.addAttribute("rentTotalCount", resRentVO.getRecordTotCount()); + + // 방문열람내역 (최근 5개) + searchCollectionVO.setReqStatusDivCd(null); + DataApiResVO resReadVO = readService.listReadItems(searchCollectionVO); + List readList = collectionService.setDetailInfoForHashList(resReadVO.getRecordList(), searchCollectionVO.getMbInfoId()); + model.addAttribute("readList", readList); + model.addAttribute("readTotalCount", resReadVO.getRecordTotCount()); + + return "nlib/userInfo/getMyHome"; + } +} \ No newline at end of file diff --git a/legacy/nlib/src/main/java/nlib/util/EmailUtil.java b/legacy/nlib/src/main/java/nlib/util/EmailUtil.java new file mode 100644 index 00000000..e6836be2 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/util/EmailUtil.java @@ -0,0 +1,112 @@ +package nlib.util; + +import java.io.IOException; +import java.io.StringWriter; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import nlib.mail.EmailSender; +import nlib.mail.service.EmailVO; + +/** + *
+ * @Class Name : EmailUtil.java
+ * 
+ * @Description : 이메일 관련 유틸리티 기능 모음 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 16. JSYOo 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 9. 16. + * @version 1.0 + * + */ +@Component("emailUtil") +public class EmailUtil{ + + static Logger log = LoggerFactory.getLogger(EmailUtil.class); + + @Autowired + private EmailSender emailSender; + + + /** 메일발송 + * @param reciverEmail + * @param subject + * @param replaceContents + * @param templateFilePath + * @throws Exception + */ + public String sendEmail(String reciverEmail, String subject, Map replaceContents, String templateFilePath) throws Exception { + EmailVO email = new EmailVO(); + String error=""; + Path path = Paths.get(templateFilePath); + Charset cs = StandardCharsets.UTF_8; + List list = new ArrayList(); + String contents = ""; + + if(!Files.exists(path)) + { + return "templateFail"; + } + + try { + list = Files.readAllLines(path,cs); + }catch(IOException e) { + error=getPrintStackTrace(e); + } + + if(!error.equals("")) + { + log.error(error); + return "templateFail"; + } + for(String readLine : list) { + contents+=readLine; + } + Set set = replaceContents.keySet(); + + Iterator iterator = set.iterator(); + + while(iterator.hasNext()){ + String key = (String)iterator.next(); + contents=contents.replace(key,(CharSequence) replaceContents.get(key)); + } + email.setReciver(reciverEmail); + + email.setSubject(subject); + email.setContent(contents); + emailSender.SendEmail(email); + return "success"; + } + public static String getPrintStackTrace(Exception e) { + + StringWriter errors = new StringWriter(); + log.error("ERROR at EmailUtil.getPrintStackTrace : " + e.toString()); + + return errors.toString(); + + } +} diff --git a/legacy/nlib/src/main/java/nlib/util/FileUtil.java b/legacy/nlib/src/main/java/nlib/util/FileUtil.java new file mode 100644 index 00000000..571e223f --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/util/FileUtil.java @@ -0,0 +1,63 @@ +package nlib.util; + +import egovframework.com.cmm.EgovWebUtil; +import egovframework.com.utl.fcc.service.EgovStringUtil; + +/** + *
+ * @Class Name : FileUtil.java
+ * 
+ * @Description : 파일 처리관련 유틸리티 기능 모음 클래스 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 16. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 16. + * @version 1.0 + * + */ +public class FileUtil extends EgovStringUtil { + + /** + * 경로나 파일명으로 적합한지를 판단한다. + * + * @param path + * @return 적합한 경우, true + */ + public static boolean isValid(String pathOrFilename) { + if(pathOrFilename == null || pathOrFilename.trim().length() == 0) return false; + + if(pathOrFilename.contains("..")) return false; + + return true; + } + + /** + * 경로나 파일명으로 적합한지를 판단한다. + * + * @param path + * @return 부적합한 경우, true + */ + public static boolean isNotValid(String pathOrFilename) { + return !isValid(pathOrFilename); + } + + /** + * 파일 경로 문자열에서 보안 문제가 되는 문자를 제거하여 리턴한다. + * + * @param path + * @return + */ + public static String filePathBlackList(String path) { + return EgovWebUtil.filePathBlackList(path); + } +} diff --git a/legacy/nlib/src/main/java/nlib/util/StringUtil.java b/legacy/nlib/src/main/java/nlib/util/StringUtil.java new file mode 100644 index 00000000..b32c76e6 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/util/StringUtil.java @@ -0,0 +1,527 @@ +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 java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; +import org.owasp.html.HtmlPolicyBuilder; +import org.owasp.html.PolicyFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Predicate; + +import nlib.cmm.service.NlibProperty; + +/** + *
+ * @Class Name : StringUtil.java
+ * 
+ * @Description : 문자열 관련 공통 함수 모음 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 6. 22. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 6. 22. + * @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("nlib.council.dns.host", "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; + } + + /** + * 게시글 제목 등 허용되지 말아야하는 일부 특수문자에 대한 치환 처리하여 리턴 + * + * @param val + * @return + */ + public static String getRemovedQuotesStr(String val) { + + if (isEmpty(val)) return val; + + StringBuffer strBuff = new StringBuffer(); + for (int j = 0; j < val.length(); j++) { + char c = val.charAt(j); + switch (c) { + case '<': + strBuff.append("<"); + break; + case '>': + strBuff.append(">"); + break; + case '&': + strBuff.append("&"); + break; + case '"': + strBuff.append("""); + break; + case '\'': + strBuff.append("'"); + break; + default: + strBuff.append(c); + break; + } + } + + return strBuff.toString(); + } + + + /** + * 날짜 문자열(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 후 리턴
* 변환 실패시 입력값 그대로 리턴
*/ + 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 = { "

","

","
" }; + + 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; + } + + /* + ************************************************************************************************ + * OWASP HTML SANITIZING 관련 : 시작 + ************************************************************************************************ + */ + private static final Pattern ONSITE_URL = Pattern.compile("(?:[\\p{L}\\p{N}\\\\\\.\\#@\\$%\\+&;\\-_~,\\?=/!]+|\\#(\\w)+)"); + private static final Pattern OFFSITE_URL = Pattern.compile("\\s*(?:(?:ht|f)tps?://|mailto:)[\\p{L}\\p{N}]" + + "[\\p{L}\\p{N}\\p{Zs}\\.\\#@\\$%\\+&;:\\-_~,\\?=/!\\(\\)]*+\\s*"); + private static final Pattern EMBED_URL = Pattern.compile("^.*data:image/.*$"); + + private static final Predicate ONSITE_OR_OFFSITE_URL = matchesEither(ONSITE_URL, OFFSITE_URL, EMBED_URL); + + /** + * XSS 등의 공격으로 부터 보안성 유지를 위해서 HTML 허용된 태그와 속성만으로 HTML을 재구성하여 리턴한다. + * + * @param html + * @return + */ + public static String sanitizeHtml(String html) { + + if(isEmpty(html)) return html; + + PolicyFactory policy = new HtmlPolicyBuilder() + .allowAttributes("src", "align", "title").onElements("img") + .allowAttributes("href", "title").onElements("a") + .allowAttributes("class", "height", "width", "style").globally() + .allowUrlProtocols("http","https","mailto","tel","data") + .allowAttributes("src").matching(ONSITE_OR_OFFSITE_URL).onElements("img") + .allowElements( + "a", "label", + "h1", "h2", "h3", "h4", "h5", "h6", + "p", "i", "b", "u", "strong", "em", "small", "big", "pre", "code", + "cite", "samp", "sub", "sup", "strike", "center", "blockquote", + "hr", "br", "col", "font", "span", "div", "img", + "ul", "ol", "li", "dd", "dt", "dl", "tbody", "thead", "tfoot", + "table", "td", "th", "tr", "colgroup", "fieldset", "legend" + ) + .toFactory(); + + return policy.sanitize(html); + } + + private static Predicate matchesEither(final Pattern a, final Pattern b, final Pattern c) { + return new Predicate() { + public boolean apply(String s) { + return a.matcher(s).matches() || b.matcher(s).matches() || c.matcher(s).matches(); + } + }; + } + + /* + ************************************************************************************************ + * OWASP HTML SANITIZING 관련 : 종료 + ************************************************************************************************ + */ + +} diff --git a/legacy/nlib/src/main/java/nlib/util/UUID.java b/legacy/nlib/src/main/java/nlib/util/UUID.java new file mode 100644 index 00000000..b5729118 --- /dev/null +++ b/legacy/nlib/src/main/java/nlib/util/UUID.java @@ -0,0 +1,76 @@ +package nlib.util; + +import egovframework.com.utl.fcc.service.EgovFormBasedUUID; + +/** + *
+ * @Class Name : UUID.java
+ * 
+ * @Description : UUID를 생성한다. 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 13. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 13. + * @version 1.0 + * + */ +public class UUID { + + /** + * 새로운 UUID를 생성하여 리턴한다. + * + * @return + */ + public static String getNewUUID() { + return EgovFormBasedUUID.randomUUID().toString(); + } + + public static String getNewUUIDWithAlphaNum() { + return getNewUUID().toUpperCase().replaceAll("-", ""); + } + + public static String getNlibCommonID(String prefix, int length) { + + String articleID = getNewUUIDWithAlphaNum(); + if(StringUtil.isNotEmpty(prefix)) articleID = prefix + "-" + articleID; + + if(length > 0 && length < articleID.length()) return articleID.substring(0, length); + + return articleID; + } + + public static String getNewAttachFileId() { + //return StringUtil.getTimeStamp("yyyyMMddhhmmss") + getNewUUIDWithAlphaNum(); + return getNlibCommonID("AT", 35); + } + + public static String getNewStreFileNm() { + // NQ202109300311510712 + return "NQ" + StringUtil.getTimeStamp() + getNlibCommonID(null, 5); + } + + public static String getNewFileId() { + // CF-DEA398CA0D0E45BF80077AB3872D5BE7 + return getNlibCommonID("CF", 35); + } + + /** + * 파일용 UUID로 생성한 파일명을 리턴한다. + * + * @return + */ + public static String getPhysicalFileName() { + return "F" + StringUtil.getTimeStamp() + "_" + getNewUUID().replaceAll("-", "").toUpperCase(); + } + +} diff --git a/legacy/nlib/src/main/resources/egovframework/egovProps/globals.properties b/legacy/nlib/src/main/resources/egovframework/egovProps/globals.properties new file mode 100644 index 00000000..428b71b6 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/egovProps/globals.properties @@ -0,0 +1,157 @@ +#----------------------------------------------------------------------- +# +# globals.properties : \uc2dc\uc2a4\ud15c +# +#----------------------------------------------------------------------- +# 1. key = value \uad6c\uc870\uc785\ub2c8\ub2e4. +# 2. key\uac12\uc740 \uacf5\ubc31\ubb38\uc790\ub97c \ud3ec\ud568\ubd88\uac00, value\uac12\uc740 \uacf5\ubc31\ubb38\uc790\ub97c \uac00\ub2a5 +# 3. key\uac12\uc73c\ub85c \ud55c\uae00\uc744 \uc0ac\uc6a9\ubd88\uac00, value\uac12\uc740 \ud55c\uae00\uc0ac\uc6a9\uc774 \uac00\ub2a5 +# 4. \uc904\uc744 \ubc14\uafc0 \ud544\uc694\uac00 \uc788\uc73c\uba74 '\'\ub97c \ub77c\uc778\uc758 \ub05d\uc5d0 \ucd94\uac00(\ub9cc\uc57d '\'\ubb38\uc790\ub97c \uc0ac\uc6a9\ud574\uc57c \ud558\ub294 \uacbd\uc6b0\ub294 '\\'\ub97c \uc0ac\uc6a9) +# 5. Windows\uc5d0\uc11c\uc758 \ub514\ub809\ud1a0\ub9ac \ud45c\uc2dc : '\\' or '/' ('\' \uc0ac\uc6a9\ud558\uba74 \uc548\ub428) +# 6. Unix\uc5d0\uc11c\uc758 \ub514\ub809\ud1a0\ub9ac \ud45c\uc2dc : '/' +# 7. \uc8fc\uc11d\ubb38 \ucc98\ub9ac\ub294 #\uc0ac\uc6a9 +# 8. value\uac12 \ub4a4\uc5d0 \uc2a4\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud558\ub294 \uacbd\uc6b0 \uc11c\ube14\ub9bf\uc5d0\uc11c \ucc38\uc870\ud560\ub54c\ub294 \uc5d0\ub7ec\ubc1c\uc0dd\ud560 \uc218 \uc788\uc73c\ubbc0\ub85c trim()\ud558\uac70\ub098 \ub9c8\uc9c0\ub9c9 \uacf5\ubc31\uc5c6\uc774 properties \uac12\uc744 \uc124\uc815\ud560\uac83 +#----------------------------------------------------------------------- + +# \uc6b4\uc601\uc11c\ubc84 \ud0c0\uc785(WINDOWS, UNIX) +#Globals.OsType = UNIX +Globals.OsType = WINDOWS + +# DB\uc11c\ubc84 \ud0c0\uc785(mysql, oracle, altibase, tibero, cubrid, maria, postgres) - datasource \ubc0f sqlMap \ud30c\uc77c \uc9c0\uc815\uc5d0 \uc0ac\uc6a9\ub428 +#Globals.DbType = mysql +Globals.DbType = maria + +#MariaDB +# \uc0ac\ubb34\uc2e4 \uac1c\ubc1cPC : hosts \ud30c\uc77c\uc5d0 \uc120 \ub4f1\ub85d \ud544\uc694 : 210.181.197.70 nlib-db.nculture.org +# HOME \uac1c\uc778PC : hosts \ud30c\uc77c\uc5d0 \uc120 \ub4f1\ub85d \ud544\uc694 : 127.0.0.1 nlib-db.nculture.org +# [\ub85c\uceecPC DB\uc124\uc815] +# > create database uac_cltr_db; +# > create user 'uac_cltr' identified by 'uac_cltr'; +# > grant all privileges on uac_cltr_db.* to 'uac_cltr'; +# > flush privileges; +Globals.maria.DriverClassName=org.mariadb.jdbc.Driver +Globals.maria.Url=jdbc:mariadb://210.181.197.70:3306/uac_cltr_db +Globals.maria.UserName = uac_cltr +Globals.maria.Password = ENC(79UHzZdkigwDg939vEgnjcPYfRYHh88y) + +# \uad8c\ud55c \uc778\uc99d\ubc29\uc2dd(dummy, session, security) - \uc0ac\uc6a9\uc790\uc758 \ub85c\uadf8\uc778\uc2dc \uc778\uc99d \ubc29\uc2dd\uc744 \uacb0\uc815\ud568 +# dummy : \ub354\ubbf8 \ubc29\uc2dd\uc73c\ub85c \uc0ac\uc6a9\uc790 \uad8c\ud55c\uc744 \uc778\uc99d\ud568 +# session : \uc138\uc158 \ubc29\uc2dd\uc73c\ub85c \uc0ac\uc6a9\uc790 \uad8c\ud55c\uc744 \uc778\uc99d\ud568 +# security : spring security \ubc29\uc2dd\uc73c\ub85c \uc0ac\uc6a9\uc790 \uad8c\ud55c\uc744 \uc778\uc99d\ud568 +Globals.Auth = security + +# MainPage Setting +#Globals.MainPage = /EgovContent.do + + +# \ub85c\uadf8\uc778 \uc778\uc99d \uc81c\ud55c(login authentication limit) +# (\uc0ac\uc6a9 \uc5ec\ubd80 \uc124\uc815\uac12 : true, false) +Globals.login.Lock = true +# -\uc778\uc99d \uc81c\uc2dc\ub3c4 \ud69f\uc218 +Globals.login.LockCount = 5 + +#\ud1b5\ud569\uba54\uc778\uba54\ub274 +#Globals.MainPage = /sym/mnu/mpm/EgovMainMenuHome.do + +# G4C \uc5f0\uacb0\uc6a9 IP (localhost) +#Globals.LocalIp = 127.0.0.2 + +# \ud658\uacbd\ud30c\uc77c \uc704\uce58 +Globals.ShellFilePath = globals.properties +Globals.ServerConfPath = conf/server.properties +Globals.ClientConfPath = conf/client.properties +Globals.FileFormatPath = conf/format.properties +Globals.GPKIConfPath = conf/gpki.properties +Globals.ConfPath = conf +Globals.MailRequestPath = mail/request/ +Globals.MailRResponsePath = mail/response/ +Globals.SMEConfigPath = conf/SMEConfig.properties + +# \ud658\uacbd\ud30c\uc77c \uc704\uce58 (jeus) +#Globals.ShellFilePath = globals.properties +#Globals.ServerConfPath = conf/server.properties +#Globals.ClientConfPath = conf/client.properties +#Globals.FileFormatPath = conf/format.properties +#Globals.GPKIConfPath = conf/gpki.properties +#Globals.ConfPath = conf +#Globals.fileStorePath = +#Globals.MailRequestPath = mail/request/ +#Globals.MailRResponsePath = mail/response/ +#Globals.SMEConfigPath = conf/SMEConfig.properties +#Globals.SynchrnServerPath = tmp/upload/ + +# WINDOWS\uc6a9 \uc258\ud30c\uc77c \uc815\ubcf4 +SHELL.WINDOWS.getHostName = prg/sh_001.bat +SHELL.WINDOWS.getDrctryByOwner = prg/getDrctryByOwner.bat +SHELL.WINDOWS.getDrctryOwner = prg/getDrctryOwner.bat +SHELL.WINDOWS.moveDrctry = prg/moveDrctry.bat +SHELL.WINDOWS.compileSchema = prg/compileSchema.bat +SHELL.WINDOWS.getDiskAttrb = prg/getDiskAttrb.bat +SHELL.WINDOWS.getDiskCpcty = prg/getDiskCpcty.bat +SHELL.WINDOWS.getDiskExst = prg/getDiskExst.bat + +# UNIX\uc6a9 \uc258\ud30c\uc77c \uc815\ubcf4 - \uac1c\ubc1cwas jeus\uc5d0\uc11c \uc0ac\uc6a9\ud560\ub54c \uae30\uc900 +SHELL.UNIX.getHostName = prg/sh_001.sh +SHELL.UNIX.getDrctryByOwner = prg/getDrctryByOwner.sh +SHELL.UNIX.getDrctryOwner = prg/getDrctryOwner.sh +SHELL.UNIX.getDrctryAccess = prg/getDrctryAccess.sh +SHELL.UNIX.getMountLc = prg/getMountLc.sh +SHELL.UNIX.getDiskName = prg/getNetWorkInfo.sh +SHELL.UNIX.moveDrctry = prg/moveDrctry.sh +SHELL.UNIX.compileSchema = prg/compileSchema.sh +SHELL.UNIX.getDiskAttrb = prg/getDiskAttrb.sh +SHELL.UNIX.getDiskCpcty = prg/getDiskCpcty.sh +SHELL.UNIX.getDiskExst = prg/getDiskExst.sh +SHELL.UNIX.getProcInfo = prg/getProcInfo.sh + +# LINUX\uc6a9 \uc258\ud30c\uc77c \uc815\ubcf4 + +# \uc5f0\uacc4 +# \uae30\uad00\ucf54\ub4dc\uc218\uc2e0\uc6a9(\uacbd\ub85c \uc124\uc815\uc740 \ubc18\ub4dc\uc2dc \uc808\ub300\uacbd\ub85c\ub97c \uc0ac\uc6a9\ud574\uc57c\ud568.) +#CNTC.INSTTCODE.DIR.rcv = D:/tmp/test/rcv/ +#CNTC.INSTTCODE.DIR.rcvold = D:/tmp/test/rcvold/ +#CNTC.INSTTCODE.DIR.bin = D:/tmp/test/bin/ +# +#CNTC.INSTTCODE.CMD.edircv = gcc_edircv.bat +#CNTC.INSTTCODE.CMD.edircvmsg = gcc_edircvmsg.bat +# +#CNTC.INSTTCODE.INFO.userid = USERID +#CNTC.INSTTCODE.INFO.userpw = ****** + +# \ud30c\uc77c \uc5c5\ub85c\ub4dc \uacbd\ub85c(\uacbd\ub85c \uc124\uc815\uc740 \ubc18\ub4dc\uc2dc \uc808\ub300\uacbd\ub85c\ub97c \uc0ac\uc6a9\ud574\uc57c\ud568, \uacbd\ub85c \ub4a4\uc5d0 /\ub97c \ubd99\uc5ec \uc8fc\uc5b4\uc57c\ud568.) +Globals.fileStorePath = C:/egovframework/upload/ +# \uc5c5\ub85c\ub4dc URL \uacbd\ub85c \uc554\ud638\ud654 KEY +#Globals.filePath.Encryption.key = 10\uc790\ub9ac\uc774\uc0c1,\uc54c\ud30c\ubcb3 \ubc0f \uc22b\uc790 \ubc0f \ud2b9\uc218\uae30\ud638 \ud63c\uc6a9\ud558\uc5ec \ud0a4\ub97c \uc9c0\uc815\ud55c\ub2e4. +# \ud30c\uc77c \ud655\uc7a5\uc790 \ud654\uc774\ud2b8\ub9ac\uc2a4\ud2b8(\ud5c8\uc6a9\ubaa9\ub85d) : \ud30c\uc77c \ud655\uc7a5\uc790\ub97c (.)\uacfc \ud568\uaed8 \uc5f0\uc774\uc5b4\uc11c \uc0ac\uc6a9\ud568. +Globals.fileUpload.Extensions = .gif.jpg.jpeg.png +Globals.fileDownload.Extensions = .gif.jpg.jpeg.png + +# \ud30c\uc77c \ub3d9\uae30\ud654 \ucef4\ud3ec\ub10c\ud2b8\uc5d0\uc11c \uc0ac\uc6a9\ud560 \ud30c\uc77c \uc5c5\ub85c\ub4dc \uacbd\ub85c(\uacbd\ub85c \uc124\uc815\uc740 \ubc18\ub4dc\uc2dc \uc808\ub300\uacbd\ub85c\ub97c \uc0ac\uc6a9\ud574\uc57c\ud568, \uacbd\ub85c \ub4a4\uc5d0 /\ub97c \ubd99\uc5ec \uc8fc\uc5b4\uc57c\ud568.) +Globals.SynchrnServerPath = C:/egovframework/upload/Synch/ + +# for JFile properties +system.uploadpath = C:/egovframework/upload/ +no.image.url = /resources/jfile/swfupload/images/no_img.gif +ftp.server.ip = 127.0.0.1 +ftp.user.id = test +ftp.user.password = test + +# Social(Facebook, Oauth \ucef4\ud3ec\ub10c\ud2b8 \uc0ac\uc6a9\uc2dc \ud65c\uc6a9) +facebook.appId = +facebook.appSecret = +twitter.consumerKey = +twitter.consumerSecret = + +#LDAP\uc870\uc9c1\ub3c4\uad00\ub9ac \ucef4\ud3ec\ub10c\ud2b8 \uc0ac\uc6a9\uc2dc LDAP\uc11c\ubc84\uc124\uc815\uc815\ubcf4 \ud544\uc694 +ldap.url = ldap://localhost:10389 +ldap.rootDn = c=kr +ldap.username = uid=admin,ou=system +ldap.password = secret + +#\uc57d\ub3c4\uad00\ub9ac Kakao \uac1c\ubc1c\uc790 appkey \ubc1c\uae09 \ubc1b\uc544 \ub4f1\ub85d\ud574\uc11c \uae30\uc785 (\uce74\uce74\uc624\uac1c\ubc1c Dev \uc571\uad00\ub9ac \ub0b4\uc5d0\uc11c \ub3c4\uba54\uc778 \ub4f1\ub85d \ud544\uc694) +roughMap.appkey = b0fdac4f718d71a02d796f8fe3e12987 + +#\uba54\uc77c \uacc4\uc815 \uc815\ubcf4 +system.notification.email.sender = teachteam02@gmail.com +system.notification.email.sender.password = ENC(AlvwMj7hcqcIZYJiU/RvSABIRl0WmVMzqIPecTeH2Uw=) +system.notification.email.sender.name = \ud55c\uad6d\ubb38\ud654\uc6d0\uc5f0\ud569\ud68c diff --git a/legacy/nlib/src/main/resources/egovframework/egovProps/globals.properties.opr b/legacy/nlib/src/main/resources/egovframework/egovProps/globals.properties.opr new file mode 100644 index 00000000..250221db --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/egovProps/globals.properties.opr @@ -0,0 +1,157 @@ +#----------------------------------------------------------------------- +# +# globals.properties : 시스템 +# +#----------------------------------------------------------------------- +# 1. key = value 구조입니다. +# 2. key값은 공백문자를 포함불가, value값은 공백문자를 가능 +# 3. key값으로 한글을 사용불가, value값은 한글사용이 가능 +# 4. 줄을 바꿀 필요가 있으면 '\'를 라인의 끝에 추가(만약 '\'문자를 사용해야 하는 경우는 '\\'를 사용) +# 5. Windows에서의 디렉토리 표시 : '\\' or '/' ('\' 사용하면 안됨) +# 6. Unix에서의 디렉토리 표시 : '/' +# 7. 주석문 처리는 #사용 +# 8. value값 뒤에 스페이스가 존재하는 경우 서블릿에서 참조할때는 에러발생할 수 있으므로 trim()하거나 마지막 공백없이 properties 값을 설정할것 +#----------------------------------------------------------------------- + +# 운영서버 타입(WINDOWS, UNIX) +#Globals.OsType = UNIX +Globals.OsType = WINDOWS + +# DB서버 타입(mysql, oracle, altibase, tibero, cubrid, maria, postgres) - datasource 및 sqlMap 파일 지정에 사용됨 +#Globals.DbType = mysql +Globals.DbType = maria + +#MariaDB +# 사무실 개발PC : hosts 파일에 선 등록 필요 : 210.181.197.70 nlib-db.nculture.org +# HOME 개인PC : hosts 파일에 선 등록 필요 : 127.0.0.1 nlib-db.nculture.org +# [로컬PC DB설정] +# > create database uac_cltr_db; +# > create user 'uac_cltr' identified by 'uac_cltr'; +# > grant all privileges on uac_cltr_db.* to 'uac_cltr'; +# > flush privileges; +Globals.maria.DriverClassName=org.mariadb.jdbc.Driver +Globals.maria.Url=jdbc:mariadb://10.10.10.237:3306/uac_cltr_db +Globals.maria.UserName = uac_cltr +Globals.maria.Password = uac_cltr + +# 권한 인증방식(dummy, session, security) - 사용자의 로그인시 인증 방식을 결정함 +# dummy : 더미 방식으로 사용자 권한을 인증함 +# session : 세션 방식으로 사용자 권한을 인증함 +# security : spring security 방식으로 사용자 권한을 인증함 +Globals.Auth = security + +# MainPage Setting +#Globals.MainPage = /EgovContent.do + + +# 로그인 인증 제한(login authentication limit) +# (사용 여부 설정값 : true, false) +Globals.login.Lock = true +# -인증 제시도 횟수 +Globals.login.LockCount = 5 + +#통합메인메뉴 +#Globals.MainPage = /sym/mnu/mpm/EgovMainMenuHome.do + +# G4C 연결용 IP (localhost) +#Globals.LocalIp = 127.0.0.2 + +# 환경파일 위치 +Globals.ShellFilePath = globals.properties +Globals.ServerConfPath = conf/server.properties +Globals.ClientConfPath = conf/client.properties +Globals.FileFormatPath = conf/format.properties +Globals.GPKIConfPath = conf/gpki.properties +Globals.ConfPath = conf +Globals.MailRequestPath = mail/request/ +Globals.MailRResponsePath = mail/response/ +Globals.SMEConfigPath = conf/SMEConfig.properties + +# 환경파일 위치 (jeus) +#Globals.ShellFilePath = globals.properties +#Globals.ServerConfPath = conf/server.properties +#Globals.ClientConfPath = conf/client.properties +#Globals.FileFormatPath = conf/format.properties +#Globals.GPKIConfPath = conf/gpki.properties +#Globals.ConfPath = conf +#Globals.fileStorePath = +#Globals.MailRequestPath = mail/request/ +#Globals.MailRResponsePath = mail/response/ +#Globals.SMEConfigPath = conf/SMEConfig.properties +#Globals.SynchrnServerPath = tmp/upload/ + +# WINDOWS용 쉘파일 정보 +SHELL.WINDOWS.getHostName = prg/sh_001.bat +SHELL.WINDOWS.getDrctryByOwner = prg/getDrctryByOwner.bat +SHELL.WINDOWS.getDrctryOwner = prg/getDrctryOwner.bat +SHELL.WINDOWS.moveDrctry = prg/moveDrctry.bat +SHELL.WINDOWS.compileSchema = prg/compileSchema.bat +SHELL.WINDOWS.getDiskAttrb = prg/getDiskAttrb.bat +SHELL.WINDOWS.getDiskCpcty = prg/getDiskCpcty.bat +SHELL.WINDOWS.getDiskExst = prg/getDiskExst.bat + +# UNIX용 쉘파일 정보 - 개발was jeus에서 사용할때 기준 +SHELL.UNIX.getHostName = prg/sh_001.sh +SHELL.UNIX.getDrctryByOwner = prg/getDrctryByOwner.sh +SHELL.UNIX.getDrctryOwner = prg/getDrctryOwner.sh +SHELL.UNIX.getDrctryAccess = prg/getDrctryAccess.sh +SHELL.UNIX.getMountLc = prg/getMountLc.sh +SHELL.UNIX.getDiskName = prg/getNetWorkInfo.sh +SHELL.UNIX.moveDrctry = prg/moveDrctry.sh +SHELL.UNIX.compileSchema = prg/compileSchema.sh +SHELL.UNIX.getDiskAttrb = prg/getDiskAttrb.sh +SHELL.UNIX.getDiskCpcty = prg/getDiskCpcty.sh +SHELL.UNIX.getDiskExst = prg/getDiskExst.sh +SHELL.UNIX.getProcInfo = prg/getProcInfo.sh + +# LINUX용 쉘파일 정보 + +# 연계 +# 기관코드수신용(경로 설정은 반드시 절대경로를 사용해야함.) +#CNTC.INSTTCODE.DIR.rcv = D:/tmp/test/rcv/ +#CNTC.INSTTCODE.DIR.rcvold = D:/tmp/test/rcvold/ +#CNTC.INSTTCODE.DIR.bin = D:/tmp/test/bin/ +# +#CNTC.INSTTCODE.CMD.edircv = gcc_edircv.bat +#CNTC.INSTTCODE.CMD.edircvmsg = gcc_edircvmsg.bat +# +#CNTC.INSTTCODE.INFO.userid = USERID +#CNTC.INSTTCODE.INFO.userpw = ****** + +# 파일 업로드 경로(경로 설정은 반드시 절대경로를 사용해야함, 경로 뒤에 /를 붙여 주어야함.) +Globals.fileStorePath = C:/egovframework/upload/ +# 업로드 URL 경로 암호화 KEY +#Globals.filePath.Encryption.key = 10자리이상,알파벳 및 숫자 및 특수기호 혼용하여 키를 지정한다. +# 파일 확장자 화이트리스트(허용목록) : 파일 확장자를 (.)과 함께 연이어서 사용함. +Globals.fileUpload.Extensions = .gif.jpg.jpeg.png +Globals.fileDownload.Extensions = .gif.jpg.jpeg.png + +# 파일 동기화 컴포넌트에서 사용할 파일 업로드 경로(경로 설정은 반드시 절대경로를 사용해야함, 경로 뒤에 /를 붙여 주어야함.) +Globals.SynchrnServerPath = C:/egovframework/upload/Synch/ + +# for JFile properties +system.uploadpath = C:/egovframework/upload/ +no.image.url = /resources/jfile/swfupload/images/no_img.gif +ftp.server.ip = 127.0.0.1 +ftp.user.id = test +ftp.user.password = test + +# Social(Facebook, Oauth 컴포넌트 사용시 활용) +facebook.appId = +facebook.appSecret = +twitter.consumerKey = +twitter.consumerSecret = + +#LDAP조직도관리 컴포넌트 사용시 LDAP서버설정정보 필요 +ldap.url = ldap://localhost:10389 +ldap.rootDn = c=kr +ldap.username = uid=admin,ou=system +ldap.password = secret + +#약도관리 Kakao 개발자 appkey 발급 받아 등록해서 기입 (카카오개발 Dev 앱관리 내에서 도메인 등록 필요) +roughMap.appkey = b0fdac4f718d71a02d796f8fe3e12987 + +#메일 계정 정보 +system.notification.email.sender = teachteam02@gmail.com +system.notification.email.sender.password = djhohubeosfspiek +system.notification.email.sender.name = 한국문화원연합회 diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/config/mapper-config.xml b/legacy/nlib/src/main/resources/egovframework/mapper/config/mapper-config.xml new file mode 100644 index 00000000..4eca5610 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/config/mapper-config.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/bbs/AncmntDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/bbs/AncmntDAO_SQL.xml new file mode 100644 index 00000000..98884cc4 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/bbs/AncmntDAO_SQL.xml @@ -0,0 +1,103 @@ + + + + + + + + + + AND S.TITLE LIKE CONCAT('%', #{escapeSearchKeyword}, '%') + + + + + AND IFNULL(CONVERT(S.CONTENT_LBL USING UTF8),'') LIKE CONCAT('%', #{escapeSearchKeyword}, '%') + + + AND IFNULL(S.DELETE_YN, 'N') = 'N' + + + + + + + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/bbs/AttachFileDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/bbs/AttachFileDAO_SQL.xml new file mode 100644 index 00000000..1acc2ec4 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/bbs/AttachFileDAO_SQL.xml @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + INSERT INTO BD_FILE ( + ATTACH_FILE_ID + , REG_DD + , USE_AT + ) VALUES ( + #{attachFileId} + , NOW() + , 'Y' + ) + ON DUPLICATE KEY + UPDATE USE_AT = 'Y'; + + + + + SELECT IFNULL(MAX(FILE_SN) + 1, 1) + FROM BD_FILEDETAIL + WHERE ATTACH_FILE_ID = #{attachFileId} + + INSERT INTO BD_FILEDETAIL ( + ATTACH_FILE_ID + , FILE_SN + , FILE_STRE_PATH + , STRE_FILE_NM + , ORIGNL_FILE_NM + , FILE_EXT + , FILE_SIZE + , USE_AT + ) VALUES ( + #{attachFileId} + , IFNULL(#{fileSn}, 1) + , #{fileStrePath} + , #{streFileNm} + , #{orignlFileNm} + , #{fileExt} + , #{fileSize} + , 'Y' + ) + + + + UPDATE BD_FILE SET USE_AT = 'N' + WHERE ATTACH_FILE_ID = #{attachFileId} + AND IFNULL(USE_AT, 'Y') = 'Y' + + + + UPDATE BD_FILEDETAIL SET USE_AT = 'N' + WHERE ATTACH_FILE_ID = #{attachFileId} + AND IFNULL(USE_AT, 'Y') = 'Y' + + + + UPDATE BD_FILEDETAIL SET USE_AT = 'N' + WHERE ATTACH_FILE_ID = #{attachFileId} + AND FILE_SN = #{fileSn} + + + diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/bbs/FaqDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/bbs/FaqDAO_SQL.xml new file mode 100644 index 00000000..7ad87a63 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/bbs/FaqDAO_SQL.xml @@ -0,0 +1,115 @@ + + + + + + + + + + AND S.TITLE LIKE CONCAT('%', #{escapeSearchKeyword}, '%') + + + + + AND CONCAT(IFNULL(CONVERT(S.CONTENT_LBL USING UTF8),''), IFNULL(CONVERT(S.ANSWER_LBL USING UTF8),'')) LIKE CONCAT('%', #{escapeSearchKeyword}, '%') + + + + AND S.QUESTION_TYPE = #{searchQuestionType} + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/bbs/QnaDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/bbs/QnaDAO_SQL.xml new file mode 100644 index 00000000..8919e066 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/bbs/QnaDAO_SQL.xml @@ -0,0 +1,205 @@ + + + + + + + + + + AND S.TITLE LIKE CONCAT('%', #{escapeSearchKeyword}, '%') + + + + + AND CONCAT(IFNULL(CONVERT(S.CONTENT_LBL USING UTF8),''), IFNULL(CONVERT(S.ANSWER_LBL USING UTF8),'')) LIKE CONCAT('%', #{escapeSearchKeyword}, '%') + + + + AND S.REG_ID = #{searchMbInfoId} + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/cmm/CodeDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/cmm/CodeDAO_SQL.xml new file mode 100644 index 00000000..ac5cd420 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/cmm/CodeDAO_SQL.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/cmm/MainDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/cmm/MainDAO_SQL.xml new file mode 100644 index 00000000..589afb3a --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/cmm/MainDAO_SQL.xml @@ -0,0 +1,241 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/cmm/NotificationDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/cmm/NotificationDAO_SQL.xml new file mode 100644 index 00000000..524c5c92 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/cmm/NotificationDAO_SQL.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/CartDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/CartDAO_SQL.xml new file mode 100644 index 00000000..89de712f --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/CartDAO_SQL.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/CollectionDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/CollectionDAO_SQL.xml new file mode 100644 index 00000000..37e5115d --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/CollectionDAO_SQL.xml @@ -0,0 +1,155 @@ + + + + + + + + INSERT INTO MB_VIEW_LOG( + MNG_ORG_CD + , MASTER_ID + , MB_INFO_ID + , REG_DD + ) VALUES ( + #{mngOrgCd} + , #{masterId} + , #{mbInfoId} + , SYSDATE() + ) + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/InterestDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/InterestDAO_SQL.xml new file mode 100644 index 00000000..326f248b --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/InterestDAO_SQL.xml @@ -0,0 +1,109 @@ + + + + + + + + + + /* CollectionDAO.deleteInterests 관심자료 삭제 */ + UPDATE + MB_INTEREST + SET + USE_YN="N" + WHERE 1=1 + AND MASTER_ID = #{masterId} + AND MB_INFO_ID = #{mbInfoId} + + + + /* CollectionDAO.insertInterest 관심자료 추가 */ + + SELECT IFNULL(MAX(MB_INTEREST_ID)+1,1) FROM MB_INTEREST; + + INSERT INTO + MB_INTEREST + VALUES + (#{mbInterestId},#{mbInfoId},#{masterId},NOW(),"Y"); + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/ReadDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/ReadDAO_SQL.xml new file mode 100644 index 00000000..0026496c --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/ReadDAO_SQL.xml @@ -0,0 +1,46 @@ + + + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/RentDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/RentDAO_SQL.xml new file mode 100644 index 00000000..e552d611 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/RentDAO_SQL.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/RisDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/RisDAO_SQL.xml new file mode 100644 index 00000000..c94c2e6f --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/col/RisDAO_SQL.xml @@ -0,0 +1,36 @@ + + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/info/InformDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/info/InformDAO_SQL.xml new file mode 100644 index 00000000..1cb817ea --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/info/InformDAO_SQL.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/user/DAO명_SQL.xml 파일명규칙.txt b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/user/DAO명_SQL.xml 파일명규칙.txt new file mode 100644 index 00000000..32b0798c --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/user/DAO명_SQL.xml 파일명규칙.txt @@ -0,0 +1 @@ +DAO명_SQL.xml 파일명규칙 diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/user/LoginDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/user/LoginDAO_SQL.xml new file mode 100644 index 00000000..7eab38c3 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/user/LoginDAO_SQL.xml @@ -0,0 +1,107 @@ + + + + + + + + + + UPDATE UAC_CLTR_DB.MB_INFO A /* 사용자정보 */ + SET A.STATUS = 'S' /* 정상 */ + , A.DMT_PROC_DD = NULL + , A.MOD_ID = #{mbInfoId} + , A.MOD_DD = NOW() + WHERE MB_INFO_ID = #{mbInfoId} + AND A.STATUS = 'P' /* 휴면 */ + + + + UPDATE UAC_CLTR_DB.MB_INFO A /* 사용자정보 */ + SET A.IP = #{ip} + , A.LAST_ACCESS_DD = NOW() + , A.MOD_ID = #{mbInfoId} + , A.MOD_DD = NOW() + WHERE MB_INFO_ID = #{mbInfoId} + + + + INSERT INTO SM_ACC_LOG /* 접속로그 */ + ( USER_ID + , USER_NM + , DEPT_SEQ + , DEPT_NM + , ACC_IP + , LOGIN_SUCS_YN + , ACC_DATE + , SYS_DIV + ) VALUES ( + #{mbInfoId} + ,#{name} + ,#{joinCouncilCd} + ,#{joinCouncilNm} + ,#{ip} + ,'Y' + ,NOW() + ,'02' /* 2021.10.05 추가 (소장자료관) */ + ) + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/user/MemberDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/user/MemberDAO_SQL.xml new file mode 100644 index 00000000..d59defd9 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/user/MemberDAO_SQL.xml @@ -0,0 +1,219 @@ + + + + + + + SELECT + IFNULL(CONCAT(LEFT(MAX(MB_INFO_ID),2),LPAD(RIGHT(MAX(MB_INFO_ID),9)+1,9,0)),'M1000000001') AS mbInfoId + ,IFNULL( + ( + SELECT + CAST(MAX(MB_NO)+1 AS CHAR(6)) + FROM + MB_INFO + WHERE MB_NO LIKE CONCAT(DATE_FORMAT(NOW(),'%y'),'%') + ) + ,CONCAT(DATE_FORMAT(NOW(),'%y'),'0001')) AS mbNo + FROM + MB_INFO + + INSERT INTO + MB_INFO + ( + MB_INFO_ID + ,LOGIN_USER_ID + ,NAME + ,PASSWORD + ,EMAIL + ,BIRTHDAY + ,GENDER + ,MOBILE_NO + ,ZIP_CODE + ,ADDRESS + ,ADDRESS_DETAIL + ,REG_ID + ,REG_DD + ,MOD_ID + ,MOD_DD + ,STATUS + ,JOIN_DATE + ,MOBILE_VRFCT_NO + ,MOBILE_VRFCT_DD + ,IP + ,LAST_ACCESS_DD + ,INFO_RECV_EMAIL_YN + ,INFO_RECV_SMS_YN + ,MKT_RECV_EMAIL_YN + ,MKT_RECV_SMS_YN + ,MB_NO + ) + VALUES + ( + #{mbInfoId} + ,#{loginUserId} + ,#{name} + ,#{password} + ,#{email} + ,#{birthday} + ,#{gender} + ,#{mobileNo} + ,#{zipCode} + ,#{address} + ,#{addressDetail} + ,#{mbInfoId} + ,NOW() + ,#{mbInfoId} + ,NOW() + ,'S' + ,DATE_FORMAT(CURDATE(), '%Y%m%d') + ,#{mobileVrfctNo} + ,STR_TO_DATE(#{mobileVrfctDd},'%Y-%m-%d %H:%i:%S') + ,#{ip} + ,NOW() + ,#{infoRecvEmailYn} + ,#{infoRecvSmsYn} + ,#{mktRecvEmailYn} + ,#{mktRecvSmsYn} + ,#{mbNo} + ) + + + + + UPDATE + MB_INFO + SET + PASSWORD=#{password} + ,MOD_ID = #{mbInfoId} + ,MOD_DD = NOW() + WHERE 1=1 + AND MB_INFO_ID = #{mbInfoId} + + + + + + + + + + + INSERT INTO + MB_SNS + ( + MB_INFO_ID + ,SNS_TYPE + ,SNS_ID + ,SNS_NAME + ,SNS_NICK_NAME + ,SNS_USER_ID + ,SNS_GENDER + ,SNS_BIRTHDAY + ,SNS_EMAIL + ,SNS_MOBILE_NO + ,REG_DD + ,UNLINK_DD + ) + VALUES + ( + #{mbInfoId} + ,#{snsType} + ,#{snsId} + ,#{snsName} + ,#{snsNickName} + ,#{snsUserId} + ,#{snsGender} + ,#{snsBirthday} + ,#{snsEmail} + ,#{snsMobileNo} + ,NOW() + ,NULL + ); + + + + + + + + + /* deleteMembership */ + UPDATE + MB_INFO + SET + LEAVE_SITE_DATE = DATE_FORMAT(CURDATE(), '%Y%m%d') + ,LOGIN_USER_ID= CONCAT(#{loginUserId},'-',#{mbInfoId}) + ,STATUS = "D" + ,BIRTHDAY = NULL + ,ZIP_CODE = NULL + ,ADDRESS = NULL + ,ADDRESS_DETAIL = NULL + ,GENDER = NULL + ,MOBILE_NO = "-" + ,EMAIL = "-" + ,PASSWORD = "-" + WHERE 1=1 + AND MB_INFO_ID = #{mbInfoId} + + + + + /* MemberDAO.sendSms */ + INSERT INTO biz_msg + ( CMID + , REQUEST_TIME + , SEND_TIME + , DEST_PHONE + , SEND_PHONE + , MSG_BODY + , NATION_CODE) + VALUES (#{cmid}, NOW(), NOW(), #{destPhone}, #{sendPhone},#{msgBody},'82') + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/user/SecUserDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/user/SecUserDAO_SQL.xml new file mode 100644 index 00000000..0874ecce --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/user/SecUserDAO_SQL.xml @@ -0,0 +1,39 @@ + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/mapper/nlib/user/UserInfoDAO_SQL.xml b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/user/UserInfoDAO_SQL.xml new file mode 100644 index 00000000..cd797b75 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/mapper/nlib/user/UserInfoDAO_SQL.xml @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /* updateMyInfo */ + UPDATE + MB_INFO + SET + NAME=#{name} + ,BIRTHDAY=#{birthday} + ,MOBILE_NO=#{mobileNo} + ,ZIP_CODE=#{zipCode} + ,ADDRESS=#{address} + ,EMAIL=#{email} + ,ADDRESS_DETAIL=#{addressDetail} + ,GENDER=#{gender} + ,MOD_ID=#{mbInfoId} + ,MOD_DD=NOW() + ,INFO_RECV_SMS_YN=#{infoRecvSmsYn} + ,INFO_RECV_EMAIL_YN=#{infoRecvEmailYn} + ,MKT_RECV_SMS_YN=#{mktRecvSmsYn} + ,MKT_RECV_EMAIL_YN=#{mktRecvEmailYn} + WHERE 1=1 + AND MB_INFO_ID=#{mbInfoId} + + + + + UPDATE + MB_SNS + SET + UNLINK_DD = NOW() + ,SNS_ID = '-' + ,SNS_NAME = NULL + ,SNS_NICK_NAME = NULL + ,SNS_USER_ID = NULL + ,SNS_GENDER = NULL + ,SNS_BIRTHDAY = NULL + ,SNS_EMAIL = NULL + ,SNS_MOBILE_NO = NULL + WHERE 1=1 + + AND MB_SNS_ID = #{mbSnsId}; + + + AND MB_INFO_ID = #{mbInfoId}; + + + + + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/message/message-common.properties b/legacy/nlib/src/main/resources/egovframework/message/message-common.properties new file mode 100644 index 00000000..50313a44 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/message/message-common.properties @@ -0,0 +1,212 @@ + +############################################################################################ +# nLib +############################################################################################ +nlib.title=\uc628\ub77c\uc778\uc790\ub8cc\ub300\ucd9c\uc2dc\uc2a4\ud15c + + +############################################################################################ + +fail.common.msg=\uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4! +fail.common.sql=sql \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4! error code: {0}, error msg: {1} +info.nodata.msg=\ud574\ub2f9 \ub370\uc774\ud130\uac00 \uc5c6\uc2b5\ub2c8\ub2e4. + +#UI Common resource# +table.num=\ubc88\ud638 +table.regdate=\ub4f1\ub85d\uc77c +table.reger=\ub4f1\ub85d\uc790 +table.select=\uc120\ud0dd +title.html=egovframe common component +title.detail=\uc0c1\uc138\uc870\ud68c +title.inquire=\uc870\ud68c +title.update=\uc218\uc815 +title.create=\ub4f1\ub85d +title.delete=\uc0ad\uc81c +title.save=\uc800\uc7a5 +title.list=\ubaa9\ub85d +title.searchCondition=\uac80\uc0c9\uc870\uac74 +title.search=\uac80\uc0c9\uc5b4 +title.reply=\ub2f5\uae00 +title.scrap=\uc2a4\ud06c\ub7a9 +title.comment=\ub313\uae00 +title.attachedFileSelect=\ud30c\uc77c\uc120\ud0dd +title.attachedFileDelete=\ud30c\uc77c\uc0ad\uc81c +title.link=\ub9c1\ud06c +title.management=\uad00\ub9ac +title.all=\uc804\uccb4 + +input.select=\uc120\ud0dd\ud558\uc138\uc694 +input.cSelect=\uc120\ud0dd +input.input=\uc785\ub825 +input.button=\ubc84\ud2bc +input.selectAll.title=\uc804\uccb4\uc120\ud0dd\uccb4\ud06c\ubc15\uc2a4 +input.yes=\uc608 +input.no=\uc544\ub2c8\uc624 + +select.searchCondition=\uc870\ud68c\uc870\uac74 \uc120\ud0dd + +button.select=\uc120\ud0dd +button.search=\uac80\uc0c9 +button.use=\uc0ac\uc6a9 +button.notUsed=\uc0ac\uc6a9\uc911\uc9c0 +button.inquire=\uc870\ud68c +button.update=\uc218\uc815 +button.create=\ub4f1\ub85d +button.delete=\uc0ad\uc81c +button.deleteDatabase=\uc644\uc804\uc0ad\uc81c +button.close=\ub2eb\uae30 +button.save=\uc800\uc7a5 +button.list=\ubaa9\ub85d +button.reset=\ucde8\uc18c +button.passwordUpdate=\uc554\ud638\ubcc0\uacbd +button.subscribe=\uac00\uc785\uc2e0\uccad +button.realname=\uc2e4\uba85\ud655\uc778 +button.moveToGpin=GPIN\uc2e4\uba85\ud655\uc778\uc73c\ub85c \uc774\ub3d9 +button.moveToIhidnum=\uc8fc\ubbfc\ub4f1\ub85d\ubc88\ud638 \uc2e4\uba85\ud655\uc778\uc73c\ub85c \uc774\ub3d9 +button.agree=\ub3d9\uc758 +button.disagree=\ube44\ub3d9\uc758 +button.possible=\uac00\ub2a5 +button.impossible=\ubd88\uac00\ub2a5 +button.qnaregist=Q&A\ub4f1\ub85d +button.cnsltregist=\uc0c1\ub2f4\ub4f1\ub85d +button.preview=\ubbf8\ub9ac\ubcf4\uae30 +button.next=\ub2e4\uc74c +button.add=\ubc14\ub85c\ucd94\uac00 +button.confirm=\ud655\uc778 +button.back = \ub4a4\ub85c +button.yes = \uc608 +button.no = \uc544\ub2c8\uc624 +button.home = \ud648 +button.user = \uc0ac\uc6a9\uc790\uc9c0\uc6d0 +button.cop = \ud611\uc5c5 +button.wrkstart = \ucd9c\uadfc +button.wrkend = \ud1f4\uadfc +button.reply = \ub2f5\uae00 +button.scrap = \uc2a4\ud06c\ub7a9 +button.comment = \ub313\uae00 +button.excel = \uc5d1\uc140 +button.init=\ucd08\uae30\ud654 +button.acknowledgment=\uc2b9\uc778 +button.cancelAcknowledgment=\uc2b9\uc778\ucde8\uc18c +button.bulkUpload=\uc77c\uad04\ub4f1\ub85d +button.log = \ub85c\uadf8 +button.set = \uc124\uc815 +button.move = \uc774\ub3d9 + +#UI Common Message# +common.noScriptTitle.msg=\uc790\ubc14\uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc9c0\uc6d0\ud558\uc9c0 \uc54a\ub294 \ube0c\ub77c\uc6b0\uc800\uc5d0\uc11c\ub294 \uc77c\ubd80 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uc2e4 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +common.searchCondition.msg=\uc774 \ub808\uc774\uc544\uc6c3\uc740 \ud558\ub2e8 \uc815\ubcf4\ub97c \ub300\ud55c \uac80\uc0c9 \uc815\ubcf4\ub85c \uad6c\uc131\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4. + +common.summary.list={0}\uc758 \ub0b4\uc5ed\uc5d0 \ub300\ud55c \ubaa9\ub85d\uc744 \ucd9c\ub825\ud569\ub2c8\ub2e4. +common.summary.regist={0}\uc758 \ub4f1\ub85d \uac00\ub2a5\ud55c \ub0b4\uc6a9\uc744 \uc785\ub825\ud558\uc5ec \ub4f1\ub85d \ubc84\ud2bc\uc744 \ud074\ub9ad\ud558\uc5ec \ub4f1\ub85d\ud55c\ub2e4. +common.summary.update={0}\uc758 \ub4f1\ub85d \uac00\ub2a5\ud55c \ub0b4\uc6a9\uc744 \uc785\ub825\ud558\uc5ec \ub4f1\ub85d \ubc84\ud2bc\uc744 \ud074\ub9ad\ud558\uc5ec \uc218\uc815\ud55c\ub2e4. +common.summary.inqire={0}\uc758 \ub0b4\uc5ed\uc5d0 \ub300\ud55c \uc0c1\uc138\uc870\ud68c \ub0b4\uc5ed\uc744 \ucd9c\ub825\ud569\ub2c8\ub2e4. + +common.save.msg=\uc800\uc7a5\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? +common.regist.msg=\ub4f1\ub85d\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? +common.delete.msg=\uc0ad\uc81c\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? +common.update.msg=\uc218\uc815\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? +common.nodata.msg=\uc790\ub8cc\uac00 \uc5c6\uc2b5\ub2c8\ub2e4. \ub2e4\ub978 \uac80\uc0c9\uc870\uac74\uc744 \uc120\ud0dd\ud574\uc8fc\uc138\uc694 +common.required.msg=(\uc740)\ub294 \ud544\uc218\uc785\ub825\ud56d\ubaa9\uc785\ub2c8\ub2e4. +common.acknowledgement.msg=\uc2b9\uc778\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? +common.acknowledgementcancel.msg=\uc2b9\uc778\ucde8\uc18c\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? +common.nocomment.msg=\ub313\uae00\uc774 \uc5c6\uc2b5\ub2c8\ub2e4. +common.noguest.msg=\uc791\uc131\ub41c \ubc29\uba85\ub85d\uc774 \uc5c6\uc2b5\ub2c8\ub2e4. + +success.request.msg = \uc694\uccad\ucc98\ub9ac\uac00 \uc131\uacf5\uc801\uc73c\ub85c \uc218\ud589\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +success.common.select=\uc815\uc0c1\uc801\uc73c\ub85c \uc870\ud68c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +success.common.insert=\uc815\uc0c1\uc801\uc73c\ub85c \ub4f1\ub85d\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +success.common.update=\uc815\uc0c1\uc801\uc73c\ub85c \uc218\uc815\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +success.common.delete=\uc815\uc0c1\uc801\uc73c\ub85c \uc0ad\uc81c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. + +common.imposbl.fileupload = \ub354 \uc774\uc0c1 \ud30c\uc77c\uc744 \ucca8\ubd80\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +common.isConfmDe.msg=\uc2b9\uc778\uc77c\uc790\ub97c \ud655\uc778 \ubc14\ub78d\ub2c8\ub2e4. +common.isExist.msg = \uc774\ubbf8 \uc874\uc7ac\ud558\uac70\ub098 \uacfc\uac70\uc5d0 \ub4f1\ub85d\uc774 \ub418\uc5c8\ub358 \uc0c1\ud0dc\uc785\ub2c8\ub2e4. + +fail.common.insert = \uc0dd\uc131\uc774 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4. +fail.common.update = \uc218\uc815\uc774 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4. +fail.common.delete = \uc0ad\uc81c\uac00 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4. +fail.common.delete.upperMenuExist = \ucc38\uc870\ub418\ub294 \uba54\ub274\uac00 \uc788\uc5b4 \uc0ad\uc81c\uac00 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4. +fail.common.select = \uc870\ud68c\uc5d0 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4. +fail.common.login = \ub85c\uadf8\uc778 \uc815\ubcf4\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +fail.common.loginIncorrect = {0}\ud68c \uc774\uc0c1 \ub85c\uadf8\uc778 \uc811\uc18d\uc774 \uc2dc\ub3c4 \ub418\uc5b4 \uacc4\uc815\uc774 \uc7a0\uaca8\uc2b5\ub2c8\ub2e4! +fail.common.login.password = \ud328\uc2a4\uc6cc\ub4dc \uc790\ub9ac \uc218\uac00 \uc77c\uce58 \ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.(8\uc790\ub9ac \uc774\uc0c1 20\uc790\ub9ac \uc774\ud558) +fail.common.idsearch = \uc544\uc774\ub514\ub97c \ucc3e\uc744\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +fail.common.pwsearch = \ube44\ubc00\ubc88\ud638\ub97c \ucc3e\uc744\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +fail.request.msg = \uc694\uccad\ucc98\ub9ac\ub97c \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4. +fail.common.login.ip = \ub4f1\ub85d\ub41c IP\uac00 \uc544\ub2c8\ubbc0\ub85c \ub85c\uadf8\uc778\uc774 \uac70\ubd80\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +fail.request.msg = \ucc98\ub9ac\uc911 \uc624\ub958\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.\uad00\ub9ac\uc790\uc5d0\uac8c \ubb38\uc758\ud574\uc8fc\uc138\uc694. + +#UI User Message# +fail.user.passwordUpdate1=\ud604\uc7ac \ube44\ubc00\ubc88\ud638\uac00 \ub9de\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +fail.user.passwordUpdate2=\ube44\ubc00\ubc88\ud638\uc640 \ube44\ubc00\ubc88\ud638 \ud655\uc778\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +info.user.rlnmCnfirm=\uc8fc\ubbfc\ub4f1\ub85d\ubc88\ud638\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc2e4\uba85\ud655\uc778\uc744 \ud558\uc2ed\uc2dc\uc624. +success.user.rlnmCnfirm=\ud589\uc815\uc548\uc804\ubd80\uc758 \uc8fc\ubbfc\ub4f1\ub85d\uc790\ub8cc\uc640 \uc77c\uce58\ud569\ub2c8\ub2e4. +fail.user.rlnmCnfirm=\ud589\uc815\uc548\uc804\ubd80\uc758 \uc8fc\ubbfc\ub4f1\ub85d\uc790\ub8cc\uc640 \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +fail.user.connectFail=\uc2dc\uc2a4\ud15c \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.(\uc778\uc99d\uc11c\ubc84 \uc5f0\uacb0 \uc2e4\ud328) +info.user.rlnmPinCnfirm=\uacf5\uacf5 \uc544\uc774\ud540 \uc544\uc774\ub514\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc2e4\uba85\ud655\uc778\uc744 \ud558\uc2ed\uc2dc\uc624. +success.user.rlnmPinCnfirm=\uacf5\uacf5\uc544\uc774\ud540\uc758 \ub4f1\ub85d\uc790\ub8cc\uc640 \uc77c\uce58\ud569\ub2c8\ub2e4. +fail.user.rlnmPinCnfirm=\uacf5\uacf5\uc544\uc774\ud540\uc758 \ub4f1\ub85d\uc790\ub8cc\uc640 \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. + +#Vlidator Errors# +errors.prefix=
+errors.suffix=

+ +errors.required={0}\uc740(\ub294) \ud544\uc218 \uc785\ub825\uac12\uc785\ub2c8\ub2e4. +errors.minlength={0}\uc740(\ub294) {1}\uc790 \uc774\uc0c1 \uc785\ub825\ud574\uc57c \ud569\ub2c8\ub2e4. +errors.maxlength={0}\uc740(\ub294) {1}\uc790 \uc774\uc0c1 \uc785\ub825\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +errors.invalid={0}\uc740(\ub294) \uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uac12\uc785\ub2c8\ub2e4. +errors.minInteger={0}\uc740(\ub294) \uc720\ud6a8\ud55c \uac12\uc774 \uc544\ub2d9\ub2c8\ub2e4. 1 \uc774\uc0c1\uc758 \uac12\uc744 \uc785\ub825\ud574\uc57c \ud569\ub2c8\ub2e4. +errors.byte={0}\uc740(\ub294) byte\ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +errors.short={0}\uc740(\ub294) short\ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +errors.integer={0}\uc740(\ub294) integer \ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +errors.long={0}\uc740(\ub294) long \ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +errors.float={0}\uc740(\ub294) float \ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +errors.double={0}\uc740(\ub294) double \ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. + +errors.date={0}\uc740(\ub294) \ub0a0\uc9dc \uc720\ud615\uc774 \uc544\ub2d9\ub2c8\ub2e4. +errors.range={0}\uc740(\ub294) {1}\uacfc {2} \uc0ac\uc774\uc758 \uac12\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +errors.creditcard={0}\uc740(\ub294) \uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uc2e0\uc6a9\uce74\ub4dc \ubc88\ud638\uc785\ub2c8\ub2e4. +errors.email={0}\uc740(\ub294) \uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uc774\uba54\uc77c \uc8fc\uc18c\uc785\ub2c8\ub2e4. + +errors.ihidnum=\uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uc8fc\ubbfc\ub4f1\ub85d\ubc88\ud638\uc785\ub2c8\ub2e4. +errors.korean={0}\uc740(\ub294) \ud55c\uae00\uc744 \uc785\ub825\ud558\uc154\uc57c \ud569\ub2c8\ub2e4. +errors.ip=\uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 IP\uc8fc\uc18c\uc785\ub2c8\ub2e4. +errors.english={0}\uc740(\ub294) \uc601\ubb38\ub9cc \uc0ac\uc6a9\ud558\uc2e4\uc218 \uc788\uc2b5\ub2c8\ub2e4. +errors.notKorean={0}\uc740(\ub294) \ud55c\uae00\uc744 \uc0ac\uc6a9\ud558\uc2e4\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. + +errors.password1={0}\uc740(\ub294) 8~20\uc790 \ub0b4\uc5d0\uc11c \uc785\ub825\ud574\uc57c \ud569\ub2c8\ub2e4. +errors.password2={0}\uc740(\ub294) \ud55c\uae00,\ud2b9\uc218\ubb38\uc790,\ub744\uc5b4\uc4f0\uae30\ub294 \ud5c8\uc6a9\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +errors.password3={0}\uc740(\ub294) \uc21c\ucc28\uc801\uc778 \uc22b\uc790\ub97c 4\uac1c\uc774\uc0c1 \uc5f0\uc18d\ud574\uc11c \uc0ac\uc6a9\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +errors.password4={0}\uc740(\ub294) \ubc18\ubcf5\ub418\ub294 \ubb38\uc790\ub098 \uc22b\uc790\ub97c 4\uac1c\uc774\uc0c1 \uc5f0\uc18d\ud574\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. + +error.security.runtime.error = error + +#Xss Errors# +errors.xss.checkerUser=\ud574\ub2f9 \uae30\ub2a5\uc5d0 \ub300\ud55c \uc0ac\uc6a9 \ubc0f \ucc98\ub9ac \uad8c\ud55c\uc774 \uc5c6\uc2b5\ub2c8\ub2e4. + +#File Upload / Download +errors.file.extension=\uc9c0\uc6d0\ub418\ub294 \ud30c\uc77c\uc720\ud615\uc774 \uc544\ub2d9\ub2c8\ub2e4. +errors.file.transfer=\ud30c\uc77c\uc804\uc1a1\uc911 \uc624\ub958\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4. +success.file.transfer=\ud30c\uc77c\uc804\uc1a1\uc774 \uc644\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4. + +# image name # +image.search=btn_form_search.gif +image.errorBg=error + + +#EgovUnitContent(\ub85c\uadf8\uc778 \ud6c4 \ud398\uc774\uc9c0)# +comCmm.unitContent.1=\uacf5\ud1b5\ucef4\ud3ec\ub10c\ud2b8 +comCmm.unitContent.2=\ub2d8 \ud658\uc601\ud569\ub2c8\ub2e4. +comCmm.unitContent.3=\ub85c\uadf8\uc544\uc6c3 +comCmm.unitContent.4=\uc2e4\ud589 \uc2dc \uc624\ub958 \uc0ac\ud56d\uc774 \uc788\uc73c\uc2dc\uba74 \ud45c\uc900\ud504\ub808\uc784\uc6cc\ud06c\uc13c\ud130\ub85c \uc5f0\ub77d\ud558\uc2dc\uae30 \ubc14\ub78d\ub2c8\ub2e4. +comCmm.unitContent.5=\ud654\uba74 \uc124\uba85 +comCmm.unitContent.6=\uc67c\ucabd \uba54\ub274\ub294 \uba54\ub274\uc640 \uad00\ub828\ub41c \ucef4\ud3ec\ub10c\ud2b8(\uba54\ub274\uad00\ub9ac, \uc0ac\uc774\ud2b8\ub9f5 \ub4f1)\ub4e4\uc758 \uc601\ud5a5\uc744 \ubc1b\uc9c0 \uc54a\uc73c\uba70, +comCmm.unitContent.7=\uac01 \ucef4\ud3ec\ub10c\ud2b8\ub97c \uc27d\uac8c \ucc3e\uc544\ubcfc \uc218 \uc788\ub294 \ubc14\ub85c \uac00\uae30 \ub9c1\ud06c\ud398\uc774\uc9c0\uc785\ub2c8\ub2e4. +comCmm.unitContent.8=\ucef4\ud3ec\ub10c\ud2b8 \uc124\uce58 \ud6c4 \uc124\uce58\ub41c \ucef4\ud3ec\ub10c\ud2b8\ub4e4\uc744 IncludedInfo annotation\uc744 \ud1b5\ud574 \ucc3e\uc544\ub0b8 \ud6c4 +comCmm.unitContent.9=\ud654\uba74\uc5d0 \ud45c\uc2dc\ud560 \uc815\ubcf4\ub97c \ucc98\ub9ac\ud558\ub294 Controller \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4. +comCmm.unitContent.10=\uac1c\ubc1c \uc2dc \uba54\ub274 \uad6c\uc870\uac00 \uc7a1\ud788\uae30 \uc804\uc5d0 \ubc30\ud3ec \ud30c\uc77c\ub4e4\uc5d0 \ud3ec\ud568\ub41c \uacf5\ud1b5 \ucef4\ud3ec\ub10c\ud2b8\ub4e4\uc758 \ubaa9\ub85d\uc131 \ud654\uba74\uc5d0 URL\uc744 \uc81c\uacf5\ud558\uc5ec +comCmm.unitContent.11=\uac1c\ubc1c\uc790\uac00 \ud3b8\ub9ac\ud558\uac8c \ud65c\uc6a9\ud560 \uc218 \uc788\ub3c4\ub85d \uc791\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +comCmm.unitContent.12=\uc6b4\uc601 \uc2dc\uc5d0 \ubcf8 \ucee8\ud2b8\ub864\uc744 \uc0ac\uc6a9\ud558\uc5ec \uba54\ub274\ub97c \uad6c\uc131\ud558\ub294 \uacbd\uc6b0, +comCmm.unitContent.13=\uc131\ub2a5 \ubb38\uc81c\ub97c \uc77c\uc73c\ud0a4\uac70\ub098 \uc0ac\uc6a9\uc790\ubcc4 \uba54\ub274 \uad6c\uc131\uc5d0 \uc624\ub958\ub97c \ubc1c\uc0dd\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 +comCmm.unitContent.14=\uc2e4 \uc6b4\uc601 \uc2dc\uc5d0\ub294 \uc0ad\uc81c\ud574\uc11c \ubc30\ud3ec\ud558\ub294 \uac83\uc744 \uad8c\uc7a5\ud574 \ub4dc\ub9bd\ub2c8\ub2e4. \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/message/message-common_en.properties b/legacy/nlib/src/main/resources/egovframework/message/message-common_en.properties new file mode 100644 index 00000000..8c35c85a --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/message/message-common_en.properties @@ -0,0 +1,213 @@ + +############################################################################################ +# nLib +############################################################################################ +nlib.title=\uc628\ub77c\uc778\uc790\ub8cc\ub300\ucd9c\uc2dc\uc2a4\ud15c + +############################################################################################ + + + +fail.common.msg=error ocurred! +fail.common.sql=sql error ocurred! error code: {0}, error msg: {1} +info.nodata.msg=no data found. + +#UI Common resource# +table.num=num. +table.regdate=reg.date +table.reger=registrant +table.select=select +title.html=egovframe common component +title.detail=Detail Inquiry +title.inquire=Inquire +title.update=Modify +title.create=Create +title.delete=Delete +title.save=Save +title.list=List +title.searchCondition=search condition +title.search=keyword +title.reply=reply +title.scrap=scrap +title.comment=comment +title.attachedFileSelect=attached file +title.attachedFileDelete=attached file delete +title.link=link +title.management=Management +title.all=All + +input.select=Select +input.cSelect=Select +input.input=input +input.button=button +input.selectAll.title=Checkbox select all +input.yes=Yes +input.no=No + +select.searchCondition=select condition select + +button.select=select +button.search=Search +button.use=use +button.notUsed=Not used +button.inquire=inquire +button.update=update +button.create=create +button.delete=delete +button.deleteDatabase=Wiping +button.close=close +button.save=save +button.list=list +button.reset=reset +button.passwordUpdate=password update +button.subscribe=subscribe +button.realname=realname confirm +button.moveToGpin=move to gpin confirm +button.moveToIhidnum=move to ihidnum confirm +button.agree=agree +button.disagree=disagree +button.possible=possible +button.impossible=impossible +button.qnaregist=Q&A create +button.cnsltregist=Counsel create +button.preview=preview +button.next=nexut +button.add=add it now +button.confirm=confirm +button.back =back +button.yes =yes +button.no =no +button.home =home +button.user =user support +button.cop =cooperation +button.wrkstart = work start +button.wrkend = work end +button.reply = reply +button.scrap = scrap +button.comment = comment +button.excel = excel +button.init=init +button.acknowledgment=acknowledgment +button.cancelAcknowledgment=cancel acknowledgment +button.bulkUpload=bulk upload +button.log = log +button.set = set +button.move = move + +#UI Common Message# +common.noScriptTitle.msg=I can't use all functions in browser JavaScript is not supported. +common.searchCondition.msg=This layout is a lower information searches made up of information. + +common.summary.list={0} A list of the details of the output. +common.summary.regist={0} Registered by typing the possible contents of registers by clicking the button. +common.summary.update={0} Registered by typing the possible content of modification by clicking the button. +common.summary.inqire={0} Full inquiry details about the details of the output. + +common.save.msg=confirm save? +common.regist.msg=confirm regist? +common.delete.msg=confirm delete? +common.update.msg=confirm update? +common.nodata.msg=There is no data. please choose another seach keyword +common.required.msg=is required field +common.acknowledgement.msg=confirm acknowledgement? +common.acknowledgementcancel.msg=confirm acknowledgement cancel? +common.nocomment.msg=There is no comment. +common.noguest.msg=There is no guest notice. + +success.request.msg=you're request successfully done +success.common.select=successfully selected +success.common.insert=successfully inserted +success.common.update=successfully updated +success.common.delete=successfully deleted + +common.imposbl.fileupload = cannot upload files +common.isConfmDe.msg=Please check the approval date box +common.isExist.msg = already exist + +fail.common.insert = fail to insert. +fail.common.update = fail to update +fail.common.delete = fail to delete +fail.common.delete.upperMenuExist = fail to delete[upperMenuId foreign key error] +fail.common.select = fail to select +fail.common.login = login information is not correct +fail.common.loginIncorrect = login in more than {0} account will be locked! +fail.common.login.password = password information is not correct(password digit should be 8 to 20) +fail.common.idsearch = can not find id +fail.common.pwsearch = can not find password +fail.request.msg = Failed to handle the request +fail.common.login.ip = Login is refused because it is not a registered IP. + +#UI User Message# +fail.user.passwordUpdate1=current password is not correct +fail.user.passwordUpdate2=password confirm is not correct +info.user.rlnmCnfirm=realname confirm ready +success.user.rlnmCnfirm=it is realname +fail.user.rlnmCnfirm=it is not realname +fail.user.connectFail=connection fail +info.user.rlnmPinCnfirm=Using the i-PIN ID, please check your real name +success.user.rlnmPinCnfirm=Consistent with the registration data of the i-PIN +fail.user.rlnmPinCnfirm=i-PIN does not match the registered data + +#Vlidator Errors# +errors.prefix=
+errors.suffix=

+ +errors.required={0} is required. +errors.minlength={0} can not be less than {1} characters. +errors.maxlength={0} can not be greater than {1} characters. +errors.invalid={0} is invalid. + +errors.byte={0} must be a byte. +errors.short={0} must be a short. +errors.integer={0} must be an integer. +errors.long={0} must be a long. +errors.float={0} must be a float. +errors.double={0} must be a double. + +errors.date={0} is not a date. +errors.range={0} is not in the range {1} through {2}. +errors.creditcard={0} is an invalid credit card number. +errors.email={0} is an invalid e-mail address. + +errors.ihidnum=Is not a valid Social Security number +errors.korean={0} should be entered with their Korean +errors.ip=Invalid IP address. +errors.english={0}is an invalid English character. +errors.notKorean={0} should not be entered with their Korean + +errors.password1={0} must be entered within 8 to 20 characters. +errors.password2={0} is Korean, special characters, spaces are not allowed. +errors.password3={0} can not be used continuously for more than four sequential digits. +errors.password4={0} can not be used continuously for more than 4 letters or numbers that are repeated. + +error.security.runtime.error = error + +#Xss Errors# +errors.xss.checkerUser=There is no use and disposal authority for its capabilities. + +#File Upload / Download +errors.file.extension=It is not a supported file type. +errors.file.transfer=An error occurred during file transfer. +success.file.transfer=The file transfer is complete. + + +# image name # +image.search=btn_form_search.gif +image.errorBg=error + + +#EgovUnitContent(\ub85c\uadf8\uc778 \ud6c4 \ud398\uc774\uc9c0)# +comCmm.unitContent.1=\uacf5\ud1b5\ucef4\ud3ec\ub10c\ud2b8 +comCmm.unitContent.2=\ub2d8 \ud658\uc601\ud569\ub2c8\ub2e4. +comCmm.unitContent.3=\ub85c\uadf8\uc544\uc6c3 +comCmm.unitContent.4=\uc2e4\ud589 \uc2dc \uc624\ub958 \uc0ac\ud56d\uc774 \uc788\uc73c\uc2dc\uba74 \ud45c\uc900\ud504\ub808\uc784\uc6cc\ud06c\uc13c\ud130\ub85c \uc5f0\ub77d\ud558\uc2dc\uae30 \ubc14\ub78d\ub2c8\ub2e4. +comCmm.unitContent.5=\ud654\uba74 \uc124\uba85 +comCmm.unitContent.6=\uc67c\ucabd \uba54\ub274\ub294 \uba54\ub274\uc640 \uad00\ub828\ub41c \ucef4\ud3ec\ub10c\ud2b8(\uba54\ub274\uad00\ub9ac, \uc0ac\uc774\ud2b8\ub9f5 \ub4f1)\ub4e4\uc758 \uc601\ud5a5\uc744 \ubc1b\uc9c0 \uc54a\uc73c\uba70, +comCmm.unitContent.7=\uac01 \ucef4\ud3ec\ub10c\ud2b8\ub97c \uc27d\uac8c \ucc3e\uc544\ubcfc \uc218 \uc788\ub294 \ubc14\ub85c \uac00\uae30 \ub9c1\ud06c\ud398\uc774\uc9c0\uc785\ub2c8\ub2e4. +comCmm.unitContent.8=\ucef4\ud3ec\ub10c\ud2b8 \uc124\uce58 \ud6c4 \uc124\uce58\ub41c \ucef4\ud3ec\ub10c\ud2b8\ub4e4\uc744 IncludedInfo annotation\uc744 \ud1b5\ud574 \ucc3e\uc544\ub0b8 \ud6c4 +comCmm.unitContent.9=\ud654\uba74\uc5d0 \ud45c\uc2dc\ud560 \uc815\ubcf4\ub97c \ucc98\ub9ac\ud558\ub294 Controller \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4. +comCmm.unitContent.10=\uac1c\ubc1c \uc2dc \uba54\ub274 \uad6c\uc870\uac00 \uc7a1\ud788\uae30 \uc804\uc5d0 \ubc30\ud3ec \ud30c\uc77c\ub4e4\uc5d0 \ud3ec\ud568\ub41c \uacf5\ud1b5 \ucef4\ud3ec\ub10c\ud2b8\ub4e4\uc758 \ubaa9\ub85d\uc131 \ud654\uba74\uc5d0 URL\uc744 \uc81c\uacf5\ud558\uc5ec +comCmm.unitContent.11=\uac1c\ubc1c\uc790\uac00 \ud3b8\ub9ac\ud558\uac8c \ud65c\uc6a9\ud560 \uc218 \uc788\ub3c4\ub85d \uc791\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +comCmm.unitContent.12=\uc6b4\uc601 \uc2dc\uc5d0 \ubcf8 \ucee8\ud2b8\ub864\uc744 \uc0ac\uc6a9\ud558\uc5ec \uba54\ub274\ub97c \uad6c\uc131\ud558\ub294 \uacbd\uc6b0, +comCmm.unitContent.13=\uc131\ub2a5 \ubb38\uc81c\ub97c \uc77c\uc73c\ud0a4\uac70\ub098 \uc0ac\uc6a9\uc790\ubcc4 \uba54\ub274 \uad6c\uc131\uc5d0 \uc624\ub958\ub97c \ubc1c\uc0dd\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 +comCmm.unitContent.14=\uc2e4 \uc6b4\uc601 \uc2dc\uc5d0\ub294 \uc0ad\uc81c\ud574\uc11c \ubc30\ud3ec\ud558\ub294 \uac83\uc744 \uad8c\uc7a5\ud574 \ub4dc\ub9bd\ub2c8\ub2e4. \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/message/message-common_ko.properties b/legacy/nlib/src/main/resources/egovframework/message/message-common_ko.properties new file mode 100644 index 00000000..bfa24986 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/message/message-common_ko.properties @@ -0,0 +1,212 @@ + +############################################################################################ +# nLib +############################################################################################ +nlib.title=\uc628\ub77c\uc778\uc790\ub8cc\ub300\ucd9c\uc2dc\uc2a4\ud15c + +############################################################################################ + + +fail.common.msg=\uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4! +fail.common.sql=sql \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4! error code: {0}, error msg: {1} +info.nodata.msg=\ud574\ub2f9 \ub370\uc774\ud130\uac00 \uc5c6\uc2b5\ub2c8\ub2e4. + +#UI Common resource# +table.num=\ubc88\ud638 +table.regdate=\ub4f1\ub85d\uc77c +table.reger=\ub4f1\ub85d\uc790 +table.select=\uc120\ud0dd +title.html=egovframe common component +title.detail=\uc0c1\uc138\uc870\ud68c +title.inquire=\uc870\ud68c +title.update=\uc218\uc815 +title.create=\ub4f1\ub85d +title.delete=\uc0ad\uc81c +title.save=\uc800\uc7a5 +title.list=\ubaa9\ub85d +title.searchCondition=\uac80\uc0c9\uc870\uac74 +title.search=\uac80\uc0c9\uc5b4 +title.reply=\ub2f5\uae00 +title.scrap=\uc2a4\ud06c\ub7a9 +title.comment=\ub313\uae00 +title.attachedFileSelect=\ud30c\uc77c\uc120\ud0dd +title.attachedFileDelete=\ud30c\uc77c\uc0ad\uc81c +title.link=\ub9c1\ud06c +title.management=\uad00\ub9ac +title.all=\uc804\uccb4 + +input.select=\uc120\ud0dd\ud558\uc138\uc694 +input.cSelect=\uc120\ud0dd +input.input=\uc785\ub825 +input.button=\ubc84\ud2bc +input.selectAll.title=\uc804\uccb4\uc120\ud0dd\uccb4\ud06c\ubc15\uc2a4 +input.yes=\uc608 +input.no=\uc544\ub2c8\uc624 + +select.searchCondition=\uc870\ud68c\uc870\uac74 \uc120\ud0dd + +button.select=\uc120\ud0dd +button.search=\uac80\uc0c9 +button.use=\uc0ac\uc6a9 +button.notUsed=\uc0ac\uc6a9\uc911\uc9c0 +button.inquire=\uc870\ud68c +button.update=\uc218\uc815 +button.create=\ub4f1\ub85d +button.delete=\uc0ad\uc81c +button.deleteDatabase=\uc644\uc804\uc0ad\uc81c +button.close=\ub2eb\uae30 +button.save=\uc800\uc7a5 +button.list=\ubaa9\ub85d +button.reset=\ucde8\uc18c +button.passwordUpdate=\uc554\ud638\ubcc0\uacbd +button.subscribe=\uac00\uc785\uc2e0\uccad +button.realname=\uc2e4\uba85\ud655\uc778 +button.moveToGpin=GPIN\uc2e4\uba85\ud655\uc778\uc73c\ub85c \uc774\ub3d9 +button.moveToIhidnum=\uc8fc\ubbfc\ub4f1\ub85d\ubc88\ud638 \uc2e4\uba85\ud655\uc778\uc73c\ub85c \uc774\ub3d9 +button.agree=\ub3d9\uc758 +button.disagree=\ube44\ub3d9\uc758 +button.possible=\uac00\ub2a5 +button.impossible=\ubd88\uac00\ub2a5 +button.qnaregist=Q&A\ub4f1\ub85d +button.cnsltregist=\uc0c1\ub2f4\ub4f1\ub85d +button.preview=\ubbf8\ub9ac\ubcf4\uae30 +button.next=\ub2e4\uc74c +button.add=\ubc14\ub85c\ucd94\uac00 +button.confirm=\ud655\uc778 +button.back = \ub4a4\ub85c +button.yes = \uc608 +button.no = \uc544\ub2c8\uc624 +button.home = \ud648 +button.user = \uc0ac\uc6a9\uc790\uc9c0\uc6d0 +button.cop = \ud611\uc5c5 +button.wrkstart = \ucd9c\uadfc +button.wrkend = \ud1f4\uadfc +button.reply = \ub2f5\uae00 +button.scrap = \uc2a4\ud06c\ub7a9 +button.comment = \ub313\uae00 +button.excel = \uc5d1\uc140 +button.init=\ucd08\uae30\ud654 +button.acknowledgment=\uc2b9\uc778 +button.cancelAcknowledgment=\uc2b9\uc778\ucde8\uc18c +button.bulkUpload=\uc77c\uad04\ub4f1\ub85d +button.log = \ub85c\uadf8 +button.set = \uc124\uc815 +button.move = \uc774\ub3d9 + +#UI Common Message# +common.noScriptTitle.msg=\uc790\ubc14\uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc9c0\uc6d0\ud558\uc9c0 \uc54a\ub294 \ube0c\ub77c\uc6b0\uc800\uc5d0\uc11c\ub294 \uc77c\ubd80 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uc2e4 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +common.searchCondition.msg=\uc774 \ub808\uc774\uc544\uc6c3\uc740 \ud558\ub2e8 \uc815\ubcf4\ub97c \ub300\ud55c \uac80\uc0c9 \uc815\ubcf4\ub85c \uad6c\uc131\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4. + +common.summary.list={0}\uc758 \ub0b4\uc5ed\uc5d0 \ub300\ud55c \ubaa9\ub85d\uc744 \ucd9c\ub825\ud569\ub2c8\ub2e4. +common.summary.regist={0}\uc758 \ub4f1\ub85d \uac00\ub2a5\ud55c \ub0b4\uc6a9\uc744 \uc785\ub825\ud558\uc5ec \ub4f1\ub85d \ubc84\ud2bc\uc744 \ud074\ub9ad\ud558\uc5ec \ub4f1\ub85d\ud55c\ub2e4. +common.summary.update={0}\uc758 \ub4f1\ub85d \uac00\ub2a5\ud55c \ub0b4\uc6a9\uc744 \uc785\ub825\ud558\uc5ec \ub4f1\ub85d \ubc84\ud2bc\uc744 \ud074\ub9ad\ud558\uc5ec \uc218\uc815\ud55c\ub2e4. +common.summary.inqire={0}\uc758 \ub0b4\uc5ed\uc5d0 \ub300\ud55c \uc0c1\uc138\uc870\ud68c \ub0b4\uc5ed\uc744 \ucd9c\ub825\ud569\ub2c8\ub2e4. + +common.save.msg=\uc800\uc7a5\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? +common.regist.msg=\ub4f1\ub85d\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? +common.delete.msg=\uc0ad\uc81c\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? +common.update.msg=\uc218\uc815\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? +common.nodata.msg=\uc790\ub8cc\uac00 \uc5c6\uc2b5\ub2c8\ub2e4. \ub2e4\ub978 \uac80\uc0c9\uc870\uac74\uc744 \uc120\ud0dd\ud574\uc8fc\uc138\uc694 +common.required.msg=(\uc740)\ub294 \ud544\uc218\uc785\ub825\ud56d\ubaa9\uc785\ub2c8\ub2e4. +common.acknowledgement.msg=\uc2b9\uc778\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? +common.acknowledgementcancel.msg=\uc2b9\uc778\ucde8\uc18c\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? +common.nocomment.msg=\ub313\uae00\uc774 \uc5c6\uc2b5\ub2c8\ub2e4. +common.noguest.msg=\uc791\uc131\ub41c \ubc29\uba85\ub85d\uc774 \uc5c6\uc2b5\ub2c8\ub2e4. + +success.request.msg = \uc694\uccad\ucc98\ub9ac\uac00 \uc131\uacf5\uc801\uc73c\ub85c \uc218\ud589\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +success.common.select=\uc815\uc0c1\uc801\uc73c\ub85c \uc870\ud68c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +success.common.insert=\uc815\uc0c1\uc801\uc73c\ub85c \ub4f1\ub85d\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +success.common.update=\uc815\uc0c1\uc801\uc73c\ub85c \uc218\uc815\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +success.common.delete=\uc815\uc0c1\uc801\uc73c\ub85c \uc0ad\uc81c\ub418\uc5c8\uc2b5\ub2c8\ub2e4. + +common.imposbl.fileupload = \ub354 \uc774\uc0c1 \ud30c\uc77c\uc744 \ucca8\ubd80\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +common.isConfmDe.msg=\uc2b9\uc778\uc77c\uc790\ub97c \ud655\uc778 \ubc14\ub78d\ub2c8\ub2e4. +common.isExist.msg = \uc774\ubbf8 \uc874\uc7ac\ud558\uac70\ub098 \uacfc\uac70\uc5d0 \ub4f1\ub85d\uc774 \ub418\uc5c8\ub358 \uc0c1\ud0dc\uc785\ub2c8\ub2e4. + +fail.common.insert = \uc0dd\uc131\uc774 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4. +fail.common.update = \uc218\uc815\uc774 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4. +fail.common.delete = \uc0ad\uc81c\uac00 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4. +fail.common.delete.upperMenuExist = \ucc38\uc870\ub418\ub294 \uba54\ub274\uac00 \uc788\uc5b4 \uc0ad\uc81c\uac00 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4. +fail.common.select = \uc870\ud68c\uc5d0 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4. +fail.common.login = \ub85c\uadf8\uc778 \uc815\ubcf4\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +fail.common.loginIncorrect = {0}\ud68c \uc774\uc0c1 \ub85c\uadf8\uc778 \uc811\uc18d\uc774 \uc2dc\ub3c4 \ub418\uc5b4 \uacc4\uc815\uc774 \uc7a0\uaca8\uc2b5\ub2c8\ub2e4! +fail.common.login.password = \ud328\uc2a4\uc6cc\ub4dc \uc790\ub9ac \uc218\uac00 \uc77c\uce58 \ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.(8\uc790\ub9ac \uc774\uc0c1 20\uc790\ub9ac \uc774\ud558) +fail.common.idsearch = \uc544\uc774\ub514\ub97c \ucc3e\uc744\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +fail.common.pwsearch = \ube44\ubc00\ubc88\ud638\ub97c \ucc3e\uc744\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +fail.request.msg = \uc694\uccad\ucc98\ub9ac\ub97c \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4. +fail.common.login.ip = \ub4f1\ub85d\ub41c IP\uac00 \uc544\ub2c8\ubbc0\ub85c \ub85c\uadf8\uc778\uc774 \uac70\ubd80\ub418\uc5c8\uc2b5\ub2c8\ub2e4. + +#UI User Message# +fail.user.passwordUpdate1=\ud604\uc7ac \ube44\ubc00\ubc88\ud638\uac00 \ub9de\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +fail.user.passwordUpdate2=\ube44\ubc00\ubc88\ud638\uc640 \ube44\ubc00\ubc88\ud638 \ud655\uc778\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +info.user.rlnmCnfirm=\uc8fc\ubbfc\ub4f1\ub85d\ubc88\ud638\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc2e4\uba85\ud655\uc778\uc744 \ud558\uc2ed\uc2dc\uc624. +success.user.rlnmCnfirm=\ud589\uc815\uc548\uc804\ubd80\uc758 \uc8fc\ubbfc\ub4f1\ub85d\uc790\ub8cc\uc640 \uc77c\uce58\ud569\ub2c8\ub2e4. +fail.user.rlnmCnfirm=\ud589\uc815\uc548\uc804\ubd80\uc758 \uc8fc\ubbfc\ub4f1\ub85d\uc790\ub8cc\uc640 \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +fail.user.connectFail=\uc2dc\uc2a4\ud15c \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.(\uc778\uc99d\uc11c\ubc84 \uc5f0\uacb0 \uc2e4\ud328) +info.user.rlnmPinCnfirm=\uacf5\uacf5 \uc544\uc774\ud540 \uc544\uc774\ub514\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc2e4\uba85\ud655\uc778\uc744 \ud558\uc2ed\uc2dc\uc624. +success.user.rlnmPinCnfirm=\uacf5\uacf5\uc544\uc774\ud540\uc758 \ub4f1\ub85d\uc790\ub8cc\uc640 \uc77c\uce58\ud569\ub2c8\ub2e4. +fail.user.rlnmPinCnfirm=\uacf5\uacf5\uc544\uc774\ud540\uc758 \ub4f1\ub85d\uc790\ub8cc\uc640 \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. + +#Vlidator Errors# +errors.prefix=
+errors.suffix=

+ +errors.required={0}\uc740(\ub294) \ud544\uc218 \uc785\ub825\uac12\uc785\ub2c8\ub2e4. +errors.minlength={0}\uc740(\ub294) {1}\uc790 \uc774\uc0c1 \uc785\ub825\ud574\uc57c \ud569\ub2c8\ub2e4. +errors.maxlength={0}\uc740(\ub294) {1}\uc790 \uc774\uc0c1 \uc785\ub825\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +errors.invalid={0}\uc740(\ub294) \uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uac12\uc785\ub2c8\ub2e4. +errors.minInteger={0}\uc740(\ub294) \uc720\ud6a8\ud55c \uac12\uc774 \uc544\ub2d9\ub2c8\ub2e4. 1 \uc774\uc0c1\uc758 \uac12\uc744 \uc785\ub825\ud574\uc57c \ud569\ub2c8\ub2e4. +errors.byte={0}\uc740(\ub294) byte\ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +errors.short={0}\uc740(\ub294) short\ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +errors.integer={0}\uc740(\ub294) integer \ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +errors.long={0}\uc740(\ub294) long \ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +errors.float={0}\uc740(\ub294) float \ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +errors.double={0}\uc740(\ub294) double \ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. + +errors.date={0}\uc740(\ub294) \ub0a0\uc9dc \uc720\ud615\uc774 \uc544\ub2d9\ub2c8\ub2e4. +errors.range={0}\uc740(\ub294) {1}\uacfc {2} \uc0ac\uc774\uc758 \uac12\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4. +errors.creditcard={0}\uc740(\ub294) \uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uc2e0\uc6a9\uce74\ub4dc \ubc88\ud638\uc785\ub2c8\ub2e4. +errors.email={0}\uc740(\ub294) \uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uc774\uba54\uc77c \uc8fc\uc18c\uc785\ub2c8\ub2e4. + +errors.ihidnum=\uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uc8fc\ubbfc\ub4f1\ub85d\ubc88\ud638\uc785\ub2c8\ub2e4. +errors.korean={0}\uc740(\ub294) \ud55c\uae00\uc744 \uc785\ub825\ud558\uc154\uc57c \ud569\ub2c8\ub2e4. +errors.ip=\uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 IP\uc8fc\uc18c\uc785\ub2c8\ub2e4. +errors.english={0}\uc740(\ub294) \uc601\ubb38\ub9cc \uc0ac\uc6a9\ud558\uc2e4\uc218 \uc788\uc2b5\ub2c8\ub2e4. +errors.notKorean={0}\uc740(\ub294) \ud55c\uae00\uc744 \uc0ac\uc6a9\ud558\uc2e4\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. + +errors.password1={0}\uc740(\ub294) 8~20\uc790 \ub0b4\uc5d0\uc11c \uc785\ub825\ud574\uc57c \ud569\ub2c8\ub2e4. +errors.password2={0}\uc740(\ub294) \ud55c\uae00,\ud2b9\uc218\ubb38\uc790,\ub744\uc5b4\uc4f0\uae30\ub294 \ud5c8\uc6a9\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. +errors.password3={0}\uc740(\ub294) \uc21c\ucc28\uc801\uc778 \uc22b\uc790\ub97c 4\uac1c\uc774\uc0c1 \uc5f0\uc18d\ud574\uc11c \uc0ac\uc6a9\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4. +errors.password4={0}\uc740(\ub294) \ubc18\ubcf5\ub418\ub294 \ubb38\uc790\ub098 \uc22b\uc790\ub97c 4\uac1c\uc774\uc0c1 \uc5f0\uc18d\ud574\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. + +error.security.runtime.error = error + +#Xss Errors# +errors.xss.checkerUser=\ud574\ub2f9 \uae30\ub2a5\uc5d0 \ub300\ud55c \uc0ac\uc6a9 \ubc0f \ucc98\ub9ac \uad8c\ud55c\uc774 \uc5c6\uc2b5\ub2c8\ub2e4. + +#File Upload / Download +errors.file.extension=\uc9c0\uc6d0\ub418\ub294 \ud30c\uc77c\uc720\ud615\uc774 \uc544\ub2d9\ub2c8\ub2e4. +errors.file.transfer=\ud30c\uc77c\uc804\uc1a1\uc911 \uc624\ub958\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4. +success.file.transfer=\ud30c\uc77c\uc804\uc1a1\uc774 \uc644\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4. + + +# image name # +image.search=btn_form_search.gif +image.errorBg=error + + +#EgovUnitContent(\ub85c\uadf8\uc778 \ud6c4 \ud398\uc774\uc9c0)# +comCmm.unitContent.1=\uacf5\ud1b5\ucef4\ud3ec\ub10c\ud2b8 +comCmm.unitContent.2=\ub2d8 \ud658\uc601\ud569\ub2c8\ub2e4. +comCmm.unitContent.3=\ub85c\uadf8\uc544\uc6c3 +comCmm.unitContent.4=\uc2e4\ud589 \uc2dc \uc624\ub958 \uc0ac\ud56d\uc774 \uc788\uc73c\uc2dc\uba74 \ud45c\uc900\ud504\ub808\uc784\uc6cc\ud06c\uc13c\ud130\ub85c \uc5f0\ub77d\ud558\uc2dc\uae30 \ubc14\ub78d\ub2c8\ub2e4. +comCmm.unitContent.5=\ud654\uba74 \uc124\uba85 +comCmm.unitContent.6=\uc67c\ucabd \uba54\ub274\ub294 \uba54\ub274\uc640 \uad00\ub828\ub41c \ucef4\ud3ec\ub10c\ud2b8(\uba54\ub274\uad00\ub9ac, \uc0ac\uc774\ud2b8\ub9f5 \ub4f1)\ub4e4\uc758 \uc601\ud5a5\uc744 \ubc1b\uc9c0 \uc54a\uc73c\uba70, +comCmm.unitContent.7=\uac01 \ucef4\ud3ec\ub10c\ud2b8\ub97c \uc27d\uac8c \ucc3e\uc544\ubcfc \uc218 \uc788\ub294 \ubc14\ub85c \uac00\uae30 \ub9c1\ud06c\ud398\uc774\uc9c0\uc785\ub2c8\ub2e4. +comCmm.unitContent.8=\ucef4\ud3ec\ub10c\ud2b8 \uc124\uce58 \ud6c4 \uc124\uce58\ub41c \ucef4\ud3ec\ub10c\ud2b8\ub4e4\uc744 IncludedInfo annotation\uc744 \ud1b5\ud574 \ucc3e\uc544\ub0b8 \ud6c4 +comCmm.unitContent.9=\ud654\uba74\uc5d0 \ud45c\uc2dc\ud560 \uc815\ubcf4\ub97c \ucc98\ub9ac\ud558\ub294 Controller \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4. +comCmm.unitContent.10=\uac1c\ubc1c \uc2dc \uba54\ub274 \uad6c\uc870\uac00 \uc7a1\ud788\uae30 \uc804\uc5d0 \ubc30\ud3ec \ud30c\uc77c\ub4e4\uc5d0 \ud3ec\ud568\ub41c \uacf5\ud1b5 \ucef4\ud3ec\ub10c\ud2b8\ub4e4\uc758 \ubaa9\ub85d\uc131 \ud654\uba74\uc5d0 URL\uc744 \uc81c\uacf5\ud558\uc5ec +comCmm.unitContent.11=\uac1c\ubc1c\uc790\uac00 \ud3b8\ub9ac\ud558\uac8c \ud65c\uc6a9\ud560 \uc218 \uc788\ub3c4\ub85d \uc791\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4. +comCmm.unitContent.12=\uc6b4\uc601 \uc2dc\uc5d0 \ubcf8 \ucee8\ud2b8\ub864\uc744 \uc0ac\uc6a9\ud558\uc5ec \uba54\ub274\ub97c \uad6c\uc131\ud558\ub294 \uacbd\uc6b0, +comCmm.unitContent.13=\uc131\ub2a5 \ubb38\uc81c\ub97c \uc77c\uc73c\ud0a4\uac70\ub098 \uc0ac\uc6a9\uc790\ubcc4 \uba54\ub274 \uad6c\uc131\uc5d0 \uc624\ub958\ub97c \ubc1c\uc0dd\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 +comCmm.unitContent.14=\uc2e4 \uc6b4\uc601 \uc2dc\uc5d0\ub294 \uc0ad\uc81c\ud574\uc11c \ubc30\ud3ec\ud558\ub294 \uac83\uc744 \uad8c\uc7a5\ud574 \ub4dc\ub9bd\ub2c8\ub2e4. \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/spring/context-aspect.xml b/legacy/nlib/src/main/resources/egovframework/spring/context-aspect.xml new file mode 100644 index 00000000..497183e1 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/spring/context-aspect.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + **service.impl.* + + + + + + + + + + + + + + + + **service.impl.* + + + + + + + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/spring/context-common.xml b/legacy/nlib/src/main/resources/egovframework/spring/context-common.xml new file mode 100644 index 00000000..dac0d6a4 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/spring/context-common.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + classpath:/egovframework/message/message-common + classpath:/egovframework/rte/fdl/idgnr/messages/idgnr + classpath:/egovframework/rte/fdl/property/messages/properties + + + + 60 + + + + + + + + + + + + + + + + + + * + + + + + + + + + + + + + + + + + + + + + + + + + + + classpath:/egovframework/egovProps/globals.properties + + + + + + + + + + + + + diff --git a/legacy/nlib/src/main/resources/egovframework/spring/context-crypto.xml b/legacy/nlib/src/main/resources/egovframework/spring/context-crypto.xml new file mode 100644 index 00000000..e6b37859 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/spring/context-crypto.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/spring/context-datasource.xml b/legacy/nlib/src/main/resources/egovframework/spring/context-datasource.xml new file mode 100644 index 00000000..c65d8681 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/spring/context-datasource.xml @@ -0,0 +1,48 @@ + + + + + + + classpath:/egovframework/egovProps/globals.properties + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/legacy/nlib/src/main/resources/egovframework/spring/context-mail.xml b/legacy/nlib/src/main/resources/egovframework/spring/context-mail.xml new file mode 100644 index 00000000..de49cfb1 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/spring/context-mail.xml @@ -0,0 +1,31 @@ + + + + + + + + + true + true + true + smtp.gmail.com + TLSv1.2 + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/spring/context-mapper.xml b/legacy/nlib/src/main/resources/egovframework/spring/context-mapper.xml new file mode 100644 index 00000000..c38599a1 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/spring/context-mapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + classpath:/egovframework/mapper/nlib/**/*.xml + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/egovframework/spring/context-oauth.xml b/legacy/nlib/src/main/resources/egovframework/spring/context-oauth.xml new file mode 100644 index 00000000..0d62d862 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/spring/context-oauth.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/legacy/nlib/src/main/resources/egovframework/spring/context-oauth.xml.opr b/legacy/nlib/src/main/resources/egovframework/spring/context-oauth.xml.opr new file mode 100644 index 00000000..35da4f89 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/spring/context-oauth.xml.opr @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/legacy/nlib/src/main/resources/egovframework/spring/context-properties.xml b/legacy/nlib/src/main/resources/egovframework/spring/context-properties.xml new file mode 100644 index 00000000..6e7b1091 --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/spring/context-properties.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/legacy/nlib/src/main/resources/egovframework/spring/context-validator.xml b/legacy/nlib/src/main/resources/egovframework/spring/context-validator.xml new file mode 100644 index 00000000..f128f50f --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/spring/context-validator.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/legacy/nlib/src/main/resources/egovframework/spring/context-whitelist.xml b/legacy/nlib/src/main/resources/egovframework/spring/context-whitelist.xml new file mode 100644 index 00000000..482e299b --- /dev/null +++ b/legacy/nlib/src/main/resources/egovframework/spring/context-whitelist.xml @@ -0,0 +1,35 @@ + + + + + + /egovframework/com/sym/mnu/stm/EgovSiteMap + /cmm/sym/mpm/EgovSiteMap + /egovframework/com/main_bottom + + + + + + + comthtrsmrcvmntrngloginfo + comtczip + + + + + /uss/umt/EgovMberSbscrbView.do + /uss/umt/EgovEntrprsMberSbscrbView.do + /uss/olh/qna/QnaCnRegistView.do + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/resources/log4j2.xml b/legacy/nlib/src/main/resources/log4j2.xml new file mode 100644 index 00000000..0c391df1 --- /dev/null +++ b/legacy/nlib/src/main/resources/log4j2.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/legacy/nlib/src/main/resources/nlib/nlib.properties b/legacy/nlib/src/main/resources/nlib/nlib.properties new file mode 100644 index 00000000..41910734 --- /dev/null +++ b/legacy/nlib/src/main/resources/nlib/nlib.properties @@ -0,0 +1,256 @@ +#----------------------------------------------------------------------- +# nlib.properties : \uc628\ub77c\uc778\uc790\ub8cc\ub300\ucd9c\uad00\ub9ac\uc2dc\uc2a4\ud15c +# +# @\ud504\ub85c\uc81d\ud2b8\uba85: \uc9c0\ubc29\ubb38\ud654\uc6d0 \ud1b5\ud569\uc790\ub8cc\uad00\ub9ac\uc2dc\uc2a4\ud15c \uad6c\ucd95\uc0ac\uc5c5 (2021) +#----------------------------------------------------------------------- +# 1. key = value \uad6c\uc870\uc785\ub2c8\ub2e4. +# 2. key\uac12\uc740 \uacf5\ubc31\ubb38\uc790\ub97c \ud3ec\ud568\ubd88\uac00, value\uac12\uc740 \uacf5\ubc31\ubb38\uc790\ub97c \uac00\ub2a5 +# 3. key\uac12\uc73c\ub85c \ud55c\uae00\uc744 \uc0ac\uc6a9\ubd88\uac00, value\uac12\uc740 \ud55c\uae00\uc0ac\uc6a9\uc774 \uac00\ub2a5 +# 4. \uc904\uc744 \ubc14\uafc0 \ud544\uc694\uac00 \uc788\uc73c\uba74 '\'\ub97c \ub77c\uc778\uc758 \ub05d\uc5d0 \ucd94\uac00(\ub9cc\uc57d '\'\ubb38\uc790\ub97c \uc0ac\uc6a9\ud574\uc57c \ud558\ub294 \uacbd\uc6b0\ub294 '\\'\ub97c \uc0ac\uc6a9) +# 5. Windows\uc5d0\uc11c\uc758 \ub514\ub809\ud1a0\ub9ac \ud45c\uc2dc : '\\' or '/' ('\' \uc0ac\uc6a9\ud558\uba74 \uc548\ub428) +# 6. Unix\uc5d0\uc11c\uc758 \ub514\ub809\ud1a0\ub9ac \ud45c\uc2dc : '/' +# 7. \uc8fc\uc11d\ubb38 \ucc98\ub9ac\ub294 #\uc0ac\uc6a9 +# 8. value\uac12 \ub4a4\uc5d0 \uc2a4\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud558\ub294 \uacbd\uc6b0 \uc11c\ube14\ub9bf\uc5d0\uc11c \ucc38\uc870\ud560\ub54c\ub294 \uc5d0\ub7ec\ubc1c\uc0dd\ud560 \uc218 \uc788\uc73c\ubbc0\ub85c trim()\ud558\uac70\ub098 \ub9c8\uc9c0\ub9c9 \uacf5\ubc31\uc5c6\uc774 properties \uac12\uc744 \uc124\uc815\ud560\uac83 +#----------------------------------------------------------------------- + +# \uba54\uc778\ud648\ud398\uc774\uc9c0 URI +home.uri = /index.do + +# \ub9c8\uc774\ud398\uc774\uc9c0 URI +mypage.uri = /index.do + +# \ub85c\uceec\ud638\uc2a4\ud2b8 \uc801\uc6a9 \ud638\uc2a4\ud2b8\uba85 +domain.host.localhost = nlib-dev + +#---------------------------------------- +# \ub85c\uadf8\uc778/\ud68c\uc6d0\uac00\uc785\uad00\ub828 URL \uc815\ubcf4 +#---------------------------------------- +member.new.url = /login/memberSnsForm.do + +# \ub85c\uadf8\uc778 \ub610\ub294 \uad8c\ud55c\uc5c6\ub294 \uacbd\uc6b0, \ub85c\uadf8\uc778\uc73c\ub85c \uc804\ud658\ucc98\ub9ac\ub418\uc5b4 \uc811\uc18d\ub418\ub294 \ucd5c\ucd08 \uc8fc\uc18c +login.url = /login/loginForm.do + +# \ub85c\uadf8\uc778 \ubb38\uc81c \ubc1c\uc0dd \uc2dc, \ub2e4\uc2dc \ub9ac\ub2e4\uc774\ub809\ud2b8\ub420 \uc8fc\uc18c +login.back.url = /login/loginGuide.do + +# \ud734\uba74\uacc4\uc88c \ud574\uc9c0\uc548\ub0b4 \uc8fc\uc18c +login.dormant.url = /login/activateDormantAccForm.do + +# \uc9c0\ubc29\ubb38\ud654\uc6d0\uc5d0\uc11c \uc811\uc18d\uc2dc \ub9ac\ub2e4\uc774\ub809\ud2b8\ub420 \ub85c\uadf8\uc778\ud654\uba74 URL \uc815\ubcf4 +nculture.login.redirect.uri = /login/loginForm.do + +# SNS\uc0ac\uc6a9\uc790 \uc778\uc99d \ubc0f \ucf5c\ubc31 \ucc98\ub9ac \ud6c4, \ud574\ub2f9 \uc9c0\ubc29\ubb38\ud654\uc6d0\uc73c\ub85c \uc774\ub3d9\ud558\uc5ec \ud6c4\ucc98\ub9ac\ub420 URL : \ub85c\uadf8\uc778\uc6a9 +nculture.login.post.login.redirect.uri = /login/loginCouncilSSO.do + +# SNS\uc0ac\uc6a9\uc790 \uc778\uc99d \ubc0f \ucf5c\ubc31 \ucc98\ub9ac \ud6c4, \ud574\ub2f9 \uc9c0\ubc29\ubb38\ud654\uc6d0\uc73c\ub85c \uc774\ub3d9\ud558\uc5ec \ud6c4\ucc98\ub9ac\ub420 URL : \ud68c\uc6d0\uac00\uc785\uc6a9 +nculture.login.post.member.redirect.uri = /member/selectMemberJoiningInfo.do + +# \uc9c0\ubc29\ubb38\ud654\uc6d0\uc5d0\uc11c \uc811\uc18d\uc2dc \ub9ac\ub2e4\uc774\ub809\ud2b8\ub420 \ud68c\uc6d0\uac00\uc785\ud654\uba74 URL \uc815\ubcf4 +nculture.member.redirect.uri = /login/memberSnsForm.do + +#---------------------------------------- +# NLIB \uc9c0\ubc29\ubb38\ud654\uc6d0\uc815\ubcf4 +#---------------------------------------- +# \uacf5\ud1b5 \uc9c0\ubc29\ubb38\ud654\uc6d0\uc815\ubcf4 \ucf54\ub4dc +nlib.council.cd = KCCF +nlib.council.nm = \uc9c0\ubc29\ubb38\ud654\uc6d0 + +# \uac1c\ubc1c\uc11c\ubc84 +nlib.council.dns.host = nlib-dev +# \uc6b4\uc601\uc11c\ubc84 +#nlib.council.dns.host = nlib + + + +#---------------------------------------- +# DataAPI \uc811\uc18d\uc815\ubcf4 +#---------------------------------------- +# \uac1c\ubc1c\uc11c\ubc84 +dataapi.server.ip = 210.181.197.70 +dataapi.server.port = 8080 +dataapi.server.protocol = http + +# \uc6b4\uc601\uc11c\ubc84 +#dataapi.server.ip = 10.10.10.230 +#dataapi.server.port = 8080 +#dataapi.server.protocol = http + +# Aria \uc54c\uace0\ub9ac\uc998 +crypto.aria.defaultKey = gdyYs/IZqY86VcWhT8emCYfqY1ahw2vtLG+/FzNqtrQ= + +#---------------------------------------- +# \ubaa9\ub85d \ud398\uc774\uc9d5 +#---------------------------------------- +list.paging.page.size = 10 + + +#---------------------------------------- +# \uba54\uc778\ud654\uba74 \uae30\ubcf8 \ubc30\ub108 +#---------------------------------------- +# \uba54\uc778\ud654\uba74 \uae30\ubcf8 \ubc30\ub108 \uc704\uce58 +# \ub85c\uceec\uc11c\ubc84 +#main.banner.img.path = C:/iams/workspace/nlib/src/main/webapp/WEB-INF/template/images/bg-mainbanner.jpg +# \uac1c\ubc1c\uc11c\ubc84 +main.banner.img.path = /apps/tomcat/apache-tomcat-8.5.46_nlib/webapps/nlib/WEB-INF/template/images/bg-mainbanner.jpg +# \uc6b4\uc601\uc11c\ubc84 +#main.banner.img.path = /kccf/webapps/nlibhome/WEB-INF/template/images/bg-mainbanner.jpg + + +#---------------------------------------- +# Q&A \ucca8\ubd80\ud30c\uc77c \uc5c5\ub85c\ub4dc \uad00\ub828 +#---------------------------------------- + +# \ucca8\ubd80\ud30c\uc77c \ucd5c\uc0c1\uc704 \uc704\uce58 + +# \ub85c\uceecPC +#fileupload.base.path = C:/iams/workspace/nlib/data/fileupload +# \uac1c\ubc1c\uc11c\ubc84 +fileupload.base.path = /nfs_nas_dev/uac/nlib +# \uc6b4\uc601\uc11c\ubc84 +#fileupload.base.path = /nfs_nas/uac/nlib + +# \ubb3b\uace0\ub2f5\ud558\uae30 \uac8c\uc2dc\ud310 \uc11c\ube0c\uc704\uce58 : \ucca8\ubd80\ud30c\uc77c \ucd5c\uc0c1\uc704 \uc704\uce58 \uc774\ud558\uc758 \uc704\uce58 \uc815\ubcf4\ub97c \uc124\uc815 +fileupload.bbs.qna.subpath = /qna + +# \ucd5c\ub300 \ud30c\uc77c \ud06c\uae30 (MB) +fileupload.max.mbsize = 10 +# \ucd5c\ub300 \ud30c\uc77c \uac1c\uc218 +fileupload.max.files = 5 +# \ud30c\uc77c \uc5c5\ub85c\ub4dc \uac00\ub2a5 \ud655\uc7a5\uc790 +fileupload.acceptable.ext = .jpg,.jpe,.jpge,.bmp,.gif,.png,.hwp,.hwpx,.pdf,.xls,.xlsx,.ppt,.pptx,.doc,.docx,.txt + + +#---------------------------------------- +# \uc774\uba54\uc77c \ud15c\ud50c\ub9bf \uacbd\ub85c +#---------------------------------------- +# \ub85c\uceec\uc11c\ubc84 +#mailing.sender.membership.signUpTemplate = C:/iams/workspace/nlib/src/main/webapp/WEB-INF/template/mail/signUp_mail_template.html +#mailing.sender.membership.pwdTemplate = C:/iams/workspace/nlib/src/main/webapp/WEB-INF/template/mail/pwd_mail_template.html +#mailing.sender.membership.certTemplate = C:/iams/workspace/nlib/src/main/webapp/WEB-INF/template/mail/cert_mail_template.html + +# \uac1c\ubc1c\uc11c\ubc84 +mailing.sender.membership.signUpTemplate = /apps/tomcat/apache-tomcat-8.5.46_nlib/webapps/nlib/WEB-INF/template/mail/signUp_mail_template.html +mailing.sender.membership.pwdTemplate = /apps/tomcat/apache-tomcat-8.5.46_nlib/webapps/nlib/WEB-INF/template/mail/pwd_mail_template.html +mailing.sender.membership.certTemplate = /apps/tomcat/apache-tomcat-8.5.46_nlib/webapps/nlib/WEB-INF/template/mail/cert_mail_template.html + +# \uc6b4\uc601\uc11c\ubc84 +#mailing.sender.membership.signUpTemplate = /kccf/webapps/nlibhome/WEB-INF/template/mail/signUp_mail_template.html +#mailing.sender.membership.pwdTemplate = /kccf/webapps/nlibhome/WEB-INF/template/mail/pwd_mail_template.html +#mailing.sender.membership.certTemplate = /kccf/webapps/nlibhome/WEB-INF/template/mail/cert_mail_template.html + +#\uba54\uc77c \uc774\ubbf8\uc9c0 \uacbd\ub85c\uc6a9 \ub3c4\uba54\uc778 URL +# \uac1c\ubc1c\uc11c\ubc84 +host.name = https://nlib-dev.nculture.org +# \uc6b4\uc601\uc11c\ubc84 +#host.name = https://nlib.nculture.org + +#\uba54\uc77c \ubcf4\ub0b4\ub294 \uc8fc\uc18c +mailing.sender.membership.email = no-reply@nlib.org + +#\uba54\uc77c \ubcf4\ub0b4\ub294\uc0ac\ub78c \uc774\ub984 +mailing.sender.membership.name = [\ud55c\uad6d\ubb38\ud654\uc6d0\uc5f0\ud569\ud68c] + +#SMS \ubcf4\ub0b4\ub294\uc0ac\ub78c \ubc88\ud638 +sms.sender.phone.number = 027042322 +#---------------------------------------- +# \uac80\uc0c9\uc5d4\uc9c4 +#---------------------------------------- +# \uac1c\ubc1c\uc11c\ubc84 +search.searchIp = 210.181.197.67 +search.searchPort = 7800 +search.protocol = http + +# \uc6b4\uc601\uc11c\ubc84 +#search.searchIp = 10.10.10.138 +#search.searchPort = 7800 +#search.protocol = http + + +#---------------------------------------- +# SNS SSO \ucc98\ub9ac URL \uc815\ubcf4 (\ud074\ub77c\uc774\uc5b8\ud2b8 \uc124\uc815\uc815\ubcf4 : context-oauth.xml \ucc38\uc870) +#---------------------------------------- +# \ub124\uc774\ubc84 +oauth2.client.provider.naver.name = NAVER +oauth2.client.provider.naver.authorization-uri = https://nid.naver.com/oauth2.0/authorize +oauth2.client.provider.naver.token-uri = https://nid.naver.com/oauth2.0/token?grant_type=authorization_code +oauth2.client.provider.naver.user-info-uri = https://openapi.naver.com/v1/nid/me +oauth2.client.provider.naver.user-name-attribute = response + +# \uad6c\uae00 +oauth2.client.provider.google.name = GOOGLE +oauth2.client.provider.google.user-info-uri = https://openidconnect.googleapis.com/v1/userinfo + +# \uce74\uce74\uc624 +oauth2.client.provider.kakao.name = KAKAO +oauth2.client.provider.kakao.authorization-uri = https://kauth.kakao.com/oauth/authorize +oauth2.client.provider.kakao.token-uri = https://kauth.kakao.com/oauth/token?client_id= +oauth2.client.provider.kakao.user-info-uri = https://kapi.kakao.com/v2/user/me + +#---------------------------------------- +# \uc190\ub2d8\uc815\ubcf4 +#---------------------------------------- +guest.userid = GUEST + +#---------------------------------------- +# \uc0ac\uc6a9\uc790\uad8c\ud55c\uba85 +#---------------------------------------- +# \uc77c\ubc18\uc0ac\uc6a9\uc790 +auth.role.user = ROLE_USER +# \uad00\ub9ac\uc790 +auth.role.admin = ROLE_ADMIN +# \uc2dc\uc2a4\ud15c\uad00\ub9ac\uc790 +auth.role.system = ROLE_SYSTEM + + +#---------------------------------------- +# \uce74\ud2b8 \uad00\ub828 +#---------------------------------------- +# \ubbf8\ub85c\uadf8\uc778 \uc0ac\uc6a9\uc790\uc758 \uce74\ud2b8\uc815\ubcf4\uac00 \uc800\uc7a5\ub418\ub294 \ucfe0\ud0a4 \uc124\uc815 \ub3c4\uba54\uc778 +cart.cookie.domain = nculture.org +# \ubbf8\ub85c\uadf8\uc778 \uc0ac\uc6a9\uc790\uc758 \uce74\ud2b8\uc815\ubcf4\uac00 \uc800\uc7a5\ub418\ub294 \ucfe0\ud0a4\uba85 +cart.cookie.name = _NLIB_CART_COOKIE +cart.cookie.path = / + + +#---------------------------------------- +# \uc378\ub124\uc77c \uae30\ubcf8 \uc774\ubbf8\uc9c0 (\uc378\ub124\uc77c \uc5c6\uc74c) +#---------------------------------------- +thumbnail.image.url.small = /images/thumbnail/noimage-s.jpg +thumbnail.image.url.middle = /images/thumbnail/noimage-m.jpg +thumbnail.image.url.big = /images/thumbnail/noimage-b.jpg + +# \uac1c\ubc1c\uc11c\ubc84 +thumbnail.image.url.prefix = https://iams-dev.nculture.org/uac +# \uc6b4\uc601\uc11c\ubc84 +#thumbnail.image.url.prefix = https://archive.nculture.org/uac + + +#---------------------------------------- +# \ub2e8\ucd95URL +#---------------------------------------- +# \uac1c\ubc1c\uc11c\ubc84 +shorturl.api = https://local-dev.nculture.org/yourls-api.php?signature=d48a5ab90c +# \uc6b4\uc601\uc11c\ubc84 +#shorturl.api = https://local.nculture.org/yourls-api.php?signature=6882eb3237 + + +#---------------------------------------- +# \uc6d0\ubb38\ubcf4\uae30 +#---------------------------------------- +# \uc6d0\ubb38\ubcf4\uae30 (PDF) +# \uac1c\ubc1c\uc11c\ubc84 +pdf.url = https://port-dev.nculture.org/npdfView.do?npdf=N +# \uc6b4\uc601\uc11c\ubc84 +#pdf.url = https://www.nculture.org/npdfView.do?npdf=I + +# \uc6d0\ubb38\ubcf4\uae30 (IMAGE) +# \uac1c\ubc1c\uc11c\ubc84 +image.url = https://port-dev.nculture.org/cmm/nImageView.do?nimage=N +# \uc6b4\uc601\uc11c\ubc84 +#image.url = https://www.nculture.org/cmm/nImageView.do?nimage=N + +# \uc6d0\ubb38\ubcf4\uae30 (VIDEO) +# \uac1c\ubc1c\uc11c\ubc84 +video.url = https://port-dev.nculture.org/cmm/nvodView.do?nvod=N +# \uc6b4\uc601\uc11c\ubc84 +#video.url = https://www..nculture.org/nvodView.do?nvod=I diff --git a/legacy/nlib/src/main/resources/nlib/nlib.properties.opr b/legacy/nlib/src/main/resources/nlib/nlib.properties.opr new file mode 100644 index 00000000..6f45a957 --- /dev/null +++ b/legacy/nlib/src/main/resources/nlib/nlib.properties.opr @@ -0,0 +1,256 @@ +#----------------------------------------------------------------------- +# nlib.properties : \uc628\ub77c\uc778\uc790\ub8cc\ub300\ucd9c\uad00\ub9ac\uc2dc\uc2a4\ud15c +# +# @\ud504\ub85c\uc81d\ud2b8\uba85: \uc9c0\ubc29\ubb38\ud654\uc6d0 \ud1b5\ud569\uc790\ub8cc\uad00\ub9ac\uc2dc\uc2a4\ud15c \uad6c\ucd95\uc0ac\uc5c5 (2021) +#----------------------------------------------------------------------- +# 1. key = value \uad6c\uc870\uc785\ub2c8\ub2e4. +# 2. key\uac12\uc740 \uacf5\ubc31\ubb38\uc790\ub97c \ud3ec\ud568\ubd88\uac00, value\uac12\uc740 \uacf5\ubc31\ubb38\uc790\ub97c \uac00\ub2a5 +# 3. key\uac12\uc73c\ub85c \ud55c\uae00\uc744 \uc0ac\uc6a9\ubd88\uac00, value\uac12\uc740 \ud55c\uae00\uc0ac\uc6a9\uc774 \uac00\ub2a5 +# 4. \uc904\uc744 \ubc14\uafc0 \ud544\uc694\uac00 \uc788\uc73c\uba74 '\'\ub97c \ub77c\uc778\uc758 \ub05d\uc5d0 \ucd94\uac00(\ub9cc\uc57d '\'\ubb38\uc790\ub97c \uc0ac\uc6a9\ud574\uc57c \ud558\ub294 \uacbd\uc6b0\ub294 '\\'\ub97c \uc0ac\uc6a9) +# 5. Windows\uc5d0\uc11c\uc758 \ub514\ub809\ud1a0\ub9ac \ud45c\uc2dc : '\\' or '/' ('\' \uc0ac\uc6a9\ud558\uba74 \uc548\ub428) +# 6. Unix\uc5d0\uc11c\uc758 \ub514\ub809\ud1a0\ub9ac \ud45c\uc2dc : '/' +# 7. \uc8fc\uc11d\ubb38 \ucc98\ub9ac\ub294 #\uc0ac\uc6a9 +# 8. value\uac12 \ub4a4\uc5d0 \uc2a4\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud558\ub294 \uacbd\uc6b0 \uc11c\ube14\ub9bf\uc5d0\uc11c \ucc38\uc870\ud560\ub54c\ub294 \uc5d0\ub7ec\ubc1c\uc0dd\ud560 \uc218 \uc788\uc73c\ubbc0\ub85c trim()\ud558\uac70\ub098 \ub9c8\uc9c0\ub9c9 \uacf5\ubc31\uc5c6\uc774 properties \uac12\uc744 \uc124\uc815\ud560\uac83 +#----------------------------------------------------------------------- + +# \uba54\uc778\ud648\ud398\uc774\uc9c0 URI +home.uri = /index.do + +# \ub9c8\uc774\ud398\uc774\uc9c0 URI +mypage.uri = /index.do + +# \ub85c\uceec\ud638\uc2a4\ud2b8 \uc801\uc6a9 \ud638\uc2a4\ud2b8\uba85 +domain.host.localhost = nlib-dev + +#---------------------------------------- +# \ub85c\uadf8\uc778/\ud68c\uc6d0\uac00\uc785\uad00\ub828 URL \uc815\ubcf4 +#---------------------------------------- +member.new.url = /login/memberSnsForm.do + +# \ub85c\uadf8\uc778 \ub610\ub294 \uad8c\ud55c\uc5c6\ub294 \uacbd\uc6b0, \ub85c\uadf8\uc778\uc73c\ub85c \uc804\ud658\ucc98\ub9ac\ub418\uc5b4 \uc811\uc18d\ub418\ub294 \ucd5c\ucd08 \uc8fc\uc18c +login.url = /login/loginForm.do + +# \ub85c\uadf8\uc778 \ubb38\uc81c \ubc1c\uc0dd \uc2dc, \ub2e4\uc2dc \ub9ac\ub2e4\uc774\ub809\ud2b8\ub420 \uc8fc\uc18c +login.back.url = /login/loginGuide.do + +# \ud734\uba74\uacc4\uc88c \ud574\uc9c0\uc548\ub0b4 \uc8fc\uc18c +login.dormant.url = /login/activateDormantAccForm.do + +# \uc9c0\ubc29\ubb38\ud654\uc6d0\uc5d0\uc11c \uc811\uc18d\uc2dc \ub9ac\ub2e4\uc774\ub809\ud2b8\ub420 \ub85c\uadf8\uc778\ud654\uba74 URL \uc815\ubcf4 +nculture.login.redirect.uri = /login/loginForm.do + +# SNS\uc0ac\uc6a9\uc790 \uc778\uc99d \ubc0f \ucf5c\ubc31 \ucc98\ub9ac \ud6c4, \ud574\ub2f9 \uc9c0\ubc29\ubb38\ud654\uc6d0\uc73c\ub85c \uc774\ub3d9\ud558\uc5ec \ud6c4\ucc98\ub9ac\ub420 URL : \ub85c\uadf8\uc778\uc6a9 +nculture.login.post.login.redirect.uri = /login/loginCouncilSSO.do + +# SNS\uc0ac\uc6a9\uc790 \uc778\uc99d \ubc0f \ucf5c\ubc31 \ucc98\ub9ac \ud6c4, \ud574\ub2f9 \uc9c0\ubc29\ubb38\ud654\uc6d0\uc73c\ub85c \uc774\ub3d9\ud558\uc5ec \ud6c4\ucc98\ub9ac\ub420 URL : \ud68c\uc6d0\uac00\uc785\uc6a9 +nculture.login.post.member.redirect.uri = /member/selectMemberJoiningInfo.do + +# \uc9c0\ubc29\ubb38\ud654\uc6d0\uc5d0\uc11c \uc811\uc18d\uc2dc \ub9ac\ub2e4\uc774\ub809\ud2b8\ub420 \ud68c\uc6d0\uac00\uc785\ud654\uba74 URL \uc815\ubcf4 +nculture.member.redirect.uri = /login/memberSnsForm.do + +#---------------------------------------- +# NLIB \uc9c0\ubc29\ubb38\ud654\uc6d0\uc815\ubcf4 +#---------------------------------------- +# \uacf5\ud1b5 \uc9c0\ubc29\ubb38\ud654\uc6d0\uc815\ubcf4 \ucf54\ub4dc +nlib.council.cd = KCCF +nlib.council.nm = \uc9c0\ubc29\ubb38\ud654\uc6d0 + +# \uac1c\ubc1c\uc11c\ubc84 +#nlib.council.dns.host = nlib-dev +# \uc6b4\uc601\uc11c\ubc84 +nlib.council.dns.host = nlib + + + +#---------------------------------------- +# DataAPI \uc811\uc18d\uc815\ubcf4 +#---------------------------------------- +# \uac1c\ubc1c\uc11c\ubc84 +#dataapi.server.ip = 210.181.197.70 +#dataapi.server.port = 8080 +#dataapi.server.protocol = http + +# \uc6b4\uc601\uc11c\ubc84 +dataapi.server.ip = 10.10.10.230 +dataapi.server.port = 8080 +dataapi.server.protocol = http + +# Aria \uc54c\uace0\ub9ac\uc998 +crypto.aria.defaultKey = gdyYs/IZqY86VcWhT8emCYfqY1ahw2vtLG+/FzNqtrQ= + +#---------------------------------------- +# \ubaa9\ub85d \ud398\uc774\uc9d5 +#---------------------------------------- +list.paging.page.size = 10 + + +#---------------------------------------- +# \uba54\uc778\ud654\uba74 \uae30\ubcf8 \ubc30\ub108 +#---------------------------------------- +# \uba54\uc778\ud654\uba74 \uae30\ubcf8 \ubc30\ub108 \uc704\uce58 +# \ub85c\uceec\uc11c\ubc84 +#main.banner.img.path = C:/iams/workspace/nlib/src/main/webapp/WEB-INF/template/images/bg-mainbanner.jpg +# \uac1c\ubc1c\uc11c\ubc84 +#main.banner.img.path = /apps/tomcat/apache-tomcat-8.5.46_nlib/webapps/nlib/WEB-INF/template/images/bg-mainbanner.jpg +# \uc6b4\uc601\uc11c\ubc84 +main.banner.img.path = /kccf/webapps/nlibhome/WEB-INF/template/images/bg-mainbanner.jpg + + +#---------------------------------------- +# Q&A \ucca8\ubd80\ud30c\uc77c \uc5c5\ub85c\ub4dc \uad00\ub828 +#---------------------------------------- + +# \ucca8\ubd80\ud30c\uc77c \ucd5c\uc0c1\uc704 \uc704\uce58 + +# \ub85c\uceecPC +#fileupload.base.path = C:/iams/workspace/nlib/data/fileupload +# \uac1c\ubc1c\uc11c\ubc84 +#fileupload.base.path = /nfs_nas_dev/uac/nlib +# \uc6b4\uc601\uc11c\ubc84 +fileupload.base.path = /nfs_nas/uac/nlib + +# \ubb3b\uace0\ub2f5\ud558\uae30 \uac8c\uc2dc\ud310 \uc11c\ube0c\uc704\uce58 : \ucca8\ubd80\ud30c\uc77c \ucd5c\uc0c1\uc704 \uc704\uce58 \uc774\ud558\uc758 \uc704\uce58 \uc815\ubcf4\ub97c \uc124\uc815 +fileupload.bbs.qna.subpath = /qna + +# \ucd5c\ub300 \ud30c\uc77c \ud06c\uae30 (MB) +fileupload.max.mbsize = 10 +# \ucd5c\ub300 \ud30c\uc77c \uac1c\uc218 +fileupload.max.files = 5 +# \ud30c\uc77c \uc5c5\ub85c\ub4dc \uac00\ub2a5 \ud655\uc7a5\uc790 +fileupload.acceptable.ext = .jpg,.jpe,.jpge,.bmp,.gif,.png,.hwp,.hwpx,.pdf,.xls,.xlsx,.ppt,.pptx,.doc,.docx,.txt + + +#---------------------------------------- +# \uc774\uba54\uc77c \ud15c\ud50c\ub9bf \uacbd\ub85c +#---------------------------------------- +# \ub85c\uceec\uc11c\ubc84 +#mailing.sender.membership.signUpTemplate = C:/iams/workspace/nlib/src/main/webapp/WEB-INF/template/mail/signUp_mail_template.html +#mailing.sender.membership.pwdTemplate = C:/iams/workspace/nlib/src/main/webapp/WEB-INF/template/mail/pwd_mail_template.html +#mailing.sender.membership.certTemplate = C:/iams/workspace/nlib/src/main/webapp/WEB-INF/template/mail/cert_mail_template.html + +# \uac1c\ubc1c\uc11c\ubc84 +#mailing.sender.membership.signUpTemplate = /apps/tomcat/apache-tomcat-8.5.46_nlib/webapps/nlib/WEB-INF/template/mail/signUp_mail_template.html +#mailing.sender.membership.pwdTemplate = /apps/tomcat/apache-tomcat-8.5.46_nlib/webapps/nlib/WEB-INF/template/mail/pwd_mail_template.html +#mailing.sender.membership.certTemplate = /apps/tomcat/apache-tomcat-8.5.46_nlib/webapps/nlib/WEB-INF/template/mail/cert_mail_template.html + +# \uc6b4\uc601\uc11c\ubc84 +mailing.sender.membership.signUpTemplate = /kccf/webapps/nlibhome/WEB-INF/template/mail/signUp_mail_template.html +mailing.sender.membership.pwdTemplate = /kccf/webapps/nlibhome/WEB-INF/template/mail/pwd_mail_template.html +mailing.sender.membership.certTemplate = /kccf/webapps/nlibhome/WEB-INF/template/mail/cert_mail_template.html + +#\uba54\uc77c \uc774\ubbf8\uc9c0 \uacbd\ub85c\uc6a9 \ub3c4\uba54\uc778 URL +# \uac1c\ubc1c\uc11c\ubc84 +#host.name = https://nlib-dev.nculture.org +# \uc6b4\uc601\uc11c\ubc84 +host.name = https://nlib.nculture.org + +#\uba54\uc77c \ubcf4\ub0b4\ub294 \uc8fc\uc18c +mailing.sender.membership.email = no-reply@nlib.org + +#\uba54\uc77c \ubcf4\ub0b4\ub294\uc0ac\ub78c \uc774\ub984 +mailing.sender.membership.name = [\ud55c\uad6d\ubb38\ud654\uc6d0\uc5f0\ud569\ud68c] + +#SMS \ubcf4\ub0b4\ub294\uc0ac\ub78c \ubc88\ud638 +sms.sender.phone.number = 027042322 +#---------------------------------------- +# \uac80\uc0c9\uc5d4\uc9c4 +#---------------------------------------- +# \uac1c\ubc1c\uc11c\ubc84 +#search.searchIp = 210.181.197.67 +#search.searchPort = 7800 +#search.protocol = http + +# \uc6b4\uc601\uc11c\ubc84 +search.searchIp = 10.10.10.138 +search.searchPort = 7800 +search.protocol = http + + +#---------------------------------------- +# SNS SSO \ucc98\ub9ac URL \uc815\ubcf4 (\ud074\ub77c\uc774\uc5b8\ud2b8 \uc124\uc815\uc815\ubcf4 : context-oauth.xml \ucc38\uc870) +#---------------------------------------- +# \ub124\uc774\ubc84 +oauth2.client.provider.naver.name = NAVER +oauth2.client.provider.naver.authorization-uri = https://nid.naver.com/oauth2.0/authorize +oauth2.client.provider.naver.token-uri = https://nid.naver.com/oauth2.0/token?grant_type=authorization_code +oauth2.client.provider.naver.user-info-uri = https://openapi.naver.com/v1/nid/me +oauth2.client.provider.naver.user-name-attribute = response + +# \uad6c\uae00 +oauth2.client.provider.google.name = GOOGLE +oauth2.client.provider.google.user-info-uri = https://openidconnect.googleapis.com/v1/userinfo + +# \uce74\uce74\uc624 +oauth2.client.provider.kakao.name = KAKAO +oauth2.client.provider.kakao.authorization-uri = https://kauth.kakao.com/oauth/authorize +oauth2.client.provider.kakao.token-uri = https://kauth.kakao.com/oauth/token?client_id= +oauth2.client.provider.kakao.user-info-uri = https://kapi.kakao.com/v2/user/me + +#---------------------------------------- +# \uc190\ub2d8\uc815\ubcf4 +#---------------------------------------- +guest.userid = GUEST + +#---------------------------------------- +# \uc0ac\uc6a9\uc790\uad8c\ud55c\uba85 +#---------------------------------------- +# \uc77c\ubc18\uc0ac\uc6a9\uc790 +auth.role.user = ROLE_USER +# \uad00\ub9ac\uc790 +auth.role.admin = ROLE_ADMIN +# \uc2dc\uc2a4\ud15c\uad00\ub9ac\uc790 +auth.role.system = ROLE_SYSTEM + + +#---------------------------------------- +# \uce74\ud2b8 \uad00\ub828 +#---------------------------------------- +# \ubbf8\ub85c\uadf8\uc778 \uc0ac\uc6a9\uc790\uc758 \uce74\ud2b8\uc815\ubcf4\uac00 \uc800\uc7a5\ub418\ub294 \ucfe0\ud0a4 \uc124\uc815 \ub3c4\uba54\uc778 +cart.cookie.domain = nculture.org +# \ubbf8\ub85c\uadf8\uc778 \uc0ac\uc6a9\uc790\uc758 \uce74\ud2b8\uc815\ubcf4\uac00 \uc800\uc7a5\ub418\ub294 \ucfe0\ud0a4\uba85 +cart.cookie.name = _NLIB_CART_COOKIE +cart.cookie.path = / + + +#---------------------------------------- +# \uc378\ub124\uc77c \uae30\ubcf8 \uc774\ubbf8\uc9c0 (\uc378\ub124\uc77c \uc5c6\uc74c) +#---------------------------------------- +thumbnail.image.url.small = /images/thumbnail/noimage-s.jpg +thumbnail.image.url.middle = /images/thumbnail/noimage-m.jpg +thumbnail.image.url.big = /images/thumbnail/noimage-b.jpg + +# \uac1c\ubc1c\uc11c\ubc84 +#thumbnail.image.url.prefix = https://iams-dev.nculture.org/uac +# \uc6b4\uc601\uc11c\ubc84 +thumbnail.image.url.prefix = https://archive.nculture.org/uac + + +#---------------------------------------- +# \ub2e8\ucd95URL +#---------------------------------------- +# \uac1c\ubc1c\uc11c\ubc84 +#shorturl.api = https://local-dev.nculture.org/yourls-api.php?signature=d48a5ab90c +# \uc6b4\uc601\uc11c\ubc84 +shorturl.api = https://local.nculture.org/yourls-api.php?signature=6882eb3237 + + +#---------------------------------------- +# \uc6d0\ubb38\ubcf4\uae30 +#---------------------------------------- +# \uc6d0\ubb38\ubcf4\uae30 (PDF) +# \uac1c\ubc1c\uc11c\ubc84 +#pdf.url = https://port-dev.nculture.org/npdfView.do?npdf=N +# \uc6b4\uc601\uc11c\ubc84 +pdf.url = https://www.nculture.org/npdfView.do?npdf=N + +# \uc6d0\ubb38\ubcf4\uae30 (IMAGE) +# \uac1c\ubc1c\uc11c\ubc84 +#image.url = https://port-dev.nculture.org/cmm/nImageView.do?nimage=N +# \uc6b4\uc601\uc11c\ubc84 +image.url = https://www.nculture.org/cmm/nImageView.do?nimage=N + +# \uc6d0\ubb38\ubcf4\uae30 (VIDEO) +# \uac1c\ubc1c\uc11c\ubc84 +#video.url = https://port-dev.nculture.org/cmm/nvodView.do?nvod=N +# \uc6b4\uc601\uc11c\ubc84 +video.url = https://www.nculture.org/cmm/nvodView.do?nvod=N diff --git a/legacy/nlib/src/main/webapp/META-INF/MANIFEST.MF b/legacy/nlib/src/main/webapp/META-INF/MANIFEST.MF new file mode 100644 index 00000000..ccee5e2b --- /dev/null +++ b/legacy/nlib/src/main/webapp/META-INF/MANIFEST.MF @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +Built-By: scale +Build-Jdk: 1.8.0_201 +Created-By: Maven Integration for Eclipse + diff --git a/legacy/nlib/src/main/webapp/META-INF/maven/nlib/nlib/pom.properties b/legacy/nlib/src/main/webapp/META-INF/maven/nlib/nlib/pom.properties new file mode 100644 index 00000000..dcb4dd98 --- /dev/null +++ b/legacy/nlib/src/main/webapp/META-INF/maven/nlib/nlib/pom.properties @@ -0,0 +1,7 @@ +#Generated by Maven Integration for Eclipse +#Wed Feb 19 14:00:08 KST 2025 +version=1.0.0 +groupId=nlib +m2e.projectName=iams.nlib +m2e.projectLocation=D\:\\iams\\workspace\\iams.nlib +artifactId=nlib diff --git a/legacy/nlib/src/main/webapp/META-INF/maven/nlib/nlib/pom.xml b/legacy/nlib/src/main/webapp/META-INF/maven/nlib/nlib/pom.xml new file mode 100644 index 00000000..1bc8bf0c --- /dev/null +++ b/legacy/nlib/src/main/webapp/META-INF/maven/nlib/nlib/pom.xml @@ -0,0 +1,636 @@ + + + 4.0.0 + nlib + nlib + war + 1.0.0 + nlib + http://www.egovframe.go.kr + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + 4.3.16.RELEASE + 3.8.0 + 4.2.5.RELEASE + 1.7.2 + 2.15.0 + + + + + mvn2 + http://repo1.maven.org/maven2/ + + true + + + true + + + + egovframe + http://www.egovframe.go.kr/maven/ + + true + + + false + + + + egovframe2 + http://maven.egovframe.kr:8080/maven/ + + true + + + false + + + + + + + + egovframework.rte + egovframework.rte.ptl.mvc + ${egovframework.rte.version} + + + commons-logging + commons-logging + + + + + egovframework.rte + egovframework.rte.psl.dataaccess + ${egovframework.rte.version} + + + egovframework.rte + egovframework.rte.fdl.idgnr + ${egovframework.rte.version} + + + egovframework.rte + egovframework.rte.fdl.property + ${egovframework.rte.version} + + + egovframework.rte + egovframework.rte.fdl.security + ${egovframework.rte.version} + + + + javax.servlet + servlet-api + provided + 2.5 + + + + javax.servlet + jstl + 1.2 + + + + taglibs + standard + 1.1.2 + + + + org.antlr + antlr + 3.5 + + + + commons-codec + commons-codec + 1.9 + + + + egovframework.rte + egovframework.rte.fdl.crypto + ${egovframework.rte.version} + + + + org.apache.poi + poi + 5.0.0 + + + org.apache.poi + poi-ooxml + 3.9 + + + commons-httpclient + commons-httpclient + 3.1 + + + + org.springframework + spring-core + ${spring.maven.artifact.version} + + + + org.springframework + spring-expression + ${spring.maven.artifact.version} + + + + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.slf4j + jcl-over-slf4j + ${slf4j.version} + runtime + + + org.slf4j + slf4j-log4j12 + ${slf4j.version} + runtime + + + org.apache.logging.log4j + log4j-core + ${log4j.version} + + + + + commons-fileupload + commons-fileupload + 1.3.1 + + + + + + + org.springframework.webflow + spring-faces + 2.4.1.RELEASE + + + org.springframework.security + spring-security-web + ${spring-security.version} + + + org.springframework.security + spring-security-core + ${spring-security.version} + + + org.springframework.security + spring-security-config + ${spring-security.version} + + + org.springframework.security + spring-security-taglibs + ${spring-security.version} + + + + + com.ibm.icu + icu4j + 53.1 + + + + + + org.jasypt + jasypt-spring3 + 1.9.2 + + + + com.googlecode.json-simple + json-simple + 1.1.1 + + + + org.apache.httpcomponents + httpcore + 4.4.6 + + + org.apache.httpcomponents + httpclient + 4.5.3 + + + + com.google.zxing + core + 3.3.0 + + + com.google.zxing + javase + 3.3.0 + + + + + org.apache.tiles + tiles-extras + 3.0.8 + + + org.apache.tiles + tiles-servlet + 3.0.8 + + + org.apache.tiles + tiles-jsp + 3.0.8 + + + + + com.fasterxml.jackson.core + jackson-core + 2.12.1 + + + com.fasterxml.jackson.core + jackson-annotations + 2.12.1 + + + com.fasterxml.jackson.core + jackson-databind + 2.12.1 + + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + 2.12.1 + + + + + org.springframework + spring-jdbc + ${spring.maven.artifact.version} + + + org.mariadb.jdbc + mariadb-java-client + 2.2.5 + + + commons-dbcp + commons-dbcp + 1.4 + + + org.lazyluke + log4jdbc-remix + 0.2.7 + + + org.projectlombok + lombok + 1.18.20 + provided + + + + + com.google.code.gson + gson + 2.8.7 + + + org.json + json + 20201115 + + + + + com.github.scribejava + scribejava-apis + + 8.3.1 + + + + + com.github.scribejava + scribejava-core + 8.3.1 + + + + org.springframework.social + spring-social-core + 1.1.4.RELEASE + + + org.springframework.social + spring-social-web + 1.1.4.RELEASE + + + org.apache.commons + commons-lang3 + 3.3.2 + + + + + com.googlecode.owasp-java-html-sanitizer + owasp-java-html-sanitizer + 20211018.2 + + + + + + install + ${basedir}/target + ${artifactId}-${version} + + + + org.apache.tomcat.maven + tomcat7-maven-plugin + 2.2 + + 80 + / + + -Xms256m -Xmx768m -XX:MaxPermSize=256m + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + UTF-8 + + + + org.codehaus.mojo + hibernate3-maven-plugin + 2.1 + + + + hbm2ddl + annotationconfiguration + + + + + + org.hsqldb + hsqldb + 2.3.2 + + + + + + org.codehaus.mojo + emma-maven-plugin + 1.0-alpha-3 + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.1 + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + once + xml + + **/Abstract*.java + **/*Suite.java + + + **/*Test.java + + + + + org.codehaus.mojo + emma-maven-plugin + true + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + + + ${basedir}/target/site + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.7 + + + sunlink + + javadoc + + true + + + http://docs.oracle.com/javase/6/docs/api/ + + + + + + + + org.codehaus.mojo + emma-maven-plugin + true + + + org.codehaus.mojo + surefire-report-maven-plugin + true + + + + report-only + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + 128m + 512m + ${encoding} + ${encoding} + ${encoding} + + + + + org.apache.maven.plugins + maven-jxr-plugin + + ${encoding} + ${encoding} + true + apidocs + + + + + + + + + + + opr + + opr + nlibhome + + + ${profile.final.name} + + + org.apache.maven.plugins + maven-war-plugin + 2.4 + + + + + + css/, favicon/, fonts/, images/, js/, index.html + + + + + maven-antrun-plugin + + + test + + run + + + + + + + + + + + + + + + + + + + + + + + maven-assembly-plugin + 2.2-beta-5 + + + + src/main/assembly/static-contents.xml + + + + + make-assembly + package + + single + + + + + + + + + + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/config/egovframework/springmvc/dispatcher-servlet.xml b/legacy/nlib/src/main/webapp/WEB-INF/config/egovframework/springmvc/dispatcher-servlet.xml new file mode 100644 index 00000000..c7230247 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/config/egovframework/springmvc/dispatcher-servlet.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /WEB-INF/tiles/tiles-layout.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/WEB-INF/config/egovframework/validator/validator-rules.xml b/legacy/nlib/src/main/webapp/WEB-INF/config/egovframework/validator/validator-rules.xml new file mode 100644 index 00000000..6b696a68 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/config/egovframework/validator/validator-rules.xml @@ -0,0 +1,1222 @@ + + + + + + + + + + = 0) { + value = field.options[si].value; + } + } else if (field.type == 'radio' || field.type == 'checkbox') { + if (field.checked) { + value = field.value; + } + } else { + value = field.value; + } + if (trim(value).length == 0) { + if ((i == 0) && (field.type != 'hidden')) { + focusField = field; + } + fields[i++] = oRequired[x][1]; + isValid = false; + } + } else if (field.type == "select-multiple") { + var numOptions = field.options.length; + lastSelected=-1; + for(loop=numOptions-1;loop>=0;loop--) { + if(field.options[loop].selected) { + lastSelected = loop; + value = field.options[loop].value; + break; + } + } + if(lastSelected < 0 || trim(value).length == 0) { + if(i == 0) { + focusField = field; + } + fields[i++] = oRequired[x][1]; + isValid=false; + } + } else if ((field.length > 0) && (field[0].type == 'radio' || field[0].type == 'checkbox')) { + isChecked=-1; + for (loop=0;loop < field.length;loop++) { + if (field[loop].checked) { + isChecked=loop; + break; // only one needs to be checked + } + } + if (isChecked < 0) { + if (i == 0) { + focusField = field[0]; + } + fields[i++] = oRequired[x][1]; + isValid=false; + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return isValid; + } + + // Trim whitespace from left and right sides of s. + function trim(s) { + return s.replace( /^\s*/, "" ).replace( /\s*$/, "" ); + } + + ]]> + + + + + + + + + + + + 0) && (field.value.length < iMin)) { + if (i == 0) { + focusField = field; + } + fields[i++] = oMinLength[x][1]; + isValid = false; + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return isValid; + }]]> + + + + + + + + iMax) { + if (i == 0) { + focusField = field; + } + fields[i++] = oMaxLength[x][1]; + isValid = false; + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return isValid; + }]]> + + + + + + + + 0)) { + + if (!matchPattern(field.value, oMasked[x][2]("mask"))) { + if (i == 0) { + focusField = field; + } + fields[i++] = oMasked[x][1]; + isValid = false; + } + } + } + + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return isValid; + } + + function matchPattern(value, mask) { + return mask.exec(value); + }]]> + + + + + + + + = 0) { + value = field.options[si].value; + } + } else { + value = field.value; + } + + if (value.length > 0) { + if (!isAllDigits(value)) { + bValid = false; + if (i == 0) { + focusField = field; + } + fields[i++] = oByte[x][1]; + + } else { + + var iValue = parseInt(value); + if (isNaN(iValue) || !(iValue >= -128 && iValue <= 127)) { + if (i == 0) { + focusField = field; + } + fields[i++] = oByte[x][1]; + bValid = false; + } + } + } + + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return bValid; + }]]> + + + + + + + + = 0) { + value = field.options[si].value; + } + } else { + value = field.value; + } + + if (value.length > 0) { + if (!isAllDigits(value)) { + bValid = false; + if (i == 0) { + focusField = field; + } + fields[i++] = oShort[x][1]; + + } else { + + var iValue = parseInt(value); + if (isNaN(iValue) || !(iValue >= -32768 && iValue <= 32767)) { + if (i == 0) { + focusField = field; + } + fields[i++] = oShort[x][1]; + bValid = false; + } + } + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return bValid; + }]]> + + + + + + + + = 0) { + value = field.options[si].value; + } + } else { + value = field.value; + } + + if (value.length > 0) { + + if (!isAllDigits(value)) { + bValid = false; + if (i == 0) { + focusField = field; + } + fields[i++] = oInteger[x][1]; + + } else { + var iValue = parseInt(value); + if (isNaN(iValue) || !(iValue >= -2147483648 && iValue <= 2147483647)) { + if (i == 0) { + focusField = field; + } + fields[i++] = oInteger[x][1]; + bValid = false; + } + } + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return bValid; + } + + function isAllDigits(argvalue) { + argvalue = argvalue.toString(); + var validChars = "0123456789"; + var startFrom = 0; + if (argvalue.substring(0, 2) == "0x") { + validChars = "0123456789abcdefABCDEF"; + startFrom = 2; + } else if (argvalue.charAt(0) == "0") { + validChars = "01234567"; + startFrom = 1; + } else if (argvalue.charAt(0) == "-") { + startFrom = 1; + } + + for (var n = startFrom; n < argvalue.length; n++) { + if (validChars.indexOf(argvalue.substring(n, n+1)) == -1) return false; + } + return true; + }]]> + + + + + + + + + + + = 0) { + value = field.options[si].value; + } + } else { + value = field.value; + } + + if (value.length > 0) { + // remove '.' before checking digits + var tempArray = value.split('.'); + var joinedString= tempArray.join(''); + + if (!isAllDigits(joinedString)) { + bValid = false; + if (i == 0) { + focusField = field; + } + fields[i++] = oFloat[x][1]; + + } else { + var iValue = parseFloat(value); + if (isNaN(iValue)) { + if (i == 0) { + focusField = field; + } + fields[i++] = oFloat[x][1]; + bValid = false; + } + } + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return bValid; + }]]> + + + + + + + + + + + 0) && + (datePattern.length > 0)) { + var MONTH = "MM"; + var DAY = "dd"; + var YEAR = "yyyy"; + var orderMonth = datePattern.indexOf(MONTH); + var orderDay = datePattern.indexOf(DAY); + var orderYear = datePattern.indexOf(YEAR); + if ((orderDay < orderYear && orderDay > orderMonth)) { + var iDelim1 = orderMonth + MONTH.length; + var iDelim2 = orderDay + DAY.length; + var delim1 = datePattern.substring(iDelim1, iDelim1 + 1); + var delim2 = datePattern.substring(iDelim2, iDelim2 + 1); + if (iDelim1 == orderDay && iDelim2 == orderYear) { + dateRegexp = new RegExp("^(\\d{2})(\\d{2})(\\d{4})$"); + } else if (iDelim1 == orderDay) { + dateRegexp = new RegExp("^(\\d{2})(\\d{2})[" + delim2 + "](\\d{4})$"); + } else if (iDelim2 == orderYear) { + dateRegexp = new RegExp("^(\\d{2})[" + delim1 + "](\\d{2})(\\d{4})$"); + } else { + dateRegexp = new RegExp("^(\\d{2})[" + delim1 + "](\\d{2})[" + delim2 + "](\\d{4})$"); + } + var matched = dateRegexp.exec(value); + if(matched != null) { + if (!isValidDate(matched[2], matched[1], matched[3])) { + if (i == 0) { + focusField = form[oDate[x][0]]; + } + fields[i++] = oDate[x][1]; + bValid = false; + } + } else { + if (i == 0) { + focusField = form[oDate[x][0]]; + } + fields[i++] = oDate[x][1]; + bValid = false; + } + } else if ((orderMonth < orderYear && orderMonth > orderDay)) { + var iDelim1 = orderDay + DAY.length; + var iDelim2 = orderMonth + MONTH.length; + var delim1 = datePattern.substring(iDelim1, iDelim1 + 1); + var delim2 = datePattern.substring(iDelim2, iDelim2 + 1); + if (iDelim1 == orderMonth && iDelim2 == orderYear) { + dateRegexp = new RegExp("^(\\d{2})(\\d{2})(\\d{4})$"); + } else if (iDelim1 == orderMonth) { + dateRegexp = new RegExp("^(\\d{2})(\\d{2})[" + delim2 + "](\\d{4})$"); + } else if (iDelim2 == orderYear) { + dateRegexp = new RegExp("^(\\d{2})[" + delim1 + "](\\d{2})(\\d{4})$"); + } else { + dateRegexp = new RegExp("^(\\d{2})[" + delim1 + "](\\d{2})[" + delim2 + "](\\d{4})$"); + } + var matched = dateRegexp.exec(value); + if(matched != null) { + if (!isValidDate(matched[1], matched[2], matched[3])) { + if (i == 0) { + focusField = form[oDate[x][0]]; + } + fields[i++] = oDate[x][1]; + bValid = false; + } + } else { + if (i == 0) { + focusField = form[oDate[x][0]]; + } + fields[i++] = oDate[x][1]; + bValid = false; + } + } else if ((orderMonth > orderYear && orderMonth < orderDay)) { + var iDelim1 = orderYear + YEAR.length; + var iDelim2 = orderMonth + MONTH.length; + var delim1 = datePattern.substring(iDelim1, iDelim1 + 1); + var delim2 = datePattern.substring(iDelim2, iDelim2 + 1); + if (iDelim1 == orderMonth && iDelim2 == orderDay) { + dateRegexp = new RegExp("^(\\d{4})(\\d{2})(\\d{2})$"); + } else if (iDelim1 == orderMonth) { + dateRegexp = new RegExp("^(\\d{4})(\\d{2})[" + delim2 + "](\\d{2})$"); + } else if (iDelim2 == orderDay) { + dateRegexp = new RegExp("^(\\d{4})[" + delim1 + "](\\d{2})(\\d{2})$"); + } else { + dateRegexp = new RegExp("^(\\d{4})[" + delim1 + "](\\d{2})[" + delim2 + "](\\d{2})$"); + } + var matched = dateRegexp.exec(value); + if(matched != null) { + if (!isValidDate(matched[3], matched[2], matched[1])) { + if (i == 0) { + focusField = form[oDate[x][0]]; + } + fields[i++] = oDate[x][1]; + bValid = false; + } + } else { + if (i == 0) { + focusField = form[oDate[x][0]]; + } + fields[i++] = oDate[x][1]; + bValid = false; + } + } else { + if (i == 0) { + focusField = form[oDate[x][0]]; + } + fields[i++] = oDate[x][1]; + bValid = false; + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return bValid; + } + + function isValidDate(day, month, year) { + if (month < 1 || month > 12) { + return false; + } + if (day < 1 || day > 31) { + return false; + } + if ((month == 4 || month == 6 || month == 9 || month == 11) && + (day == 31)) { + return false; + } + if (month == 2) { + var leap = (year % 4 == 0 && + (year % 100 != 0 || year % 400 == 0)); + if (day>29 || (day == 29 && !leap)) { + return false; + } + } + return true; + }]]> + + + + + + + + + + + + + + + 0)) { + + var iMin = parseInt(oRange[x][2]("min")); + var iMax = parseInt(oRange[x][2]("max")); + var iValue = parseInt(field.value); + if (!(iValue >= iMin && iValue <= iMax)) { + if (i == 0) { + focusField = field; + } + fields[i++] = oRange[x][1]; + isValid = false; + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return isValid; + }]]> + + + + + + + 0)) { + + var fMin = parseFloat(oRange[x][2]("min")); + var fMax = parseFloat(oRange[x][2]("max")); + var fValue = parseFloat(field.value); + if (!(fValue >= fMin && fValue <= fMax)) { + if (i == 0) { + focusField = field; + } + fields[i++] = oRange[x][1]; + isValid = false; + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return isValid; + }]]> + + + + + + + 0)) { + if (!luhnCheck(form[oCreditCard[x][0]].value)) { + if (i == 0) { + focusField = form[oCreditCard[x][0]]; + } + fields[i++] = oCreditCard[x][1]; + bValid = false; + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return bValid; + } + + /** + * Reference: http://www.ling.nwu.edu/~sburke/pub/luhn_lib.pl + */ + function luhnCheck(cardNumber) { + if (isLuhnNum(cardNumber)) { + var no_digit = cardNumber.length; + var oddoeven = no_digit & 1; + var sum = 0; + for (var count = 0; count < no_digit; count++) { + var digit = parseInt(cardNumber.charAt(count)); + if (!((count & 1) ^ oddoeven)) { + digit *= 2; + if (digit > 9) digit -= 9; + }; + sum += digit; + }; + if (sum == 0) return false; + if (sum % 10 == 0) return true; + }; + return false; + } + + function isLuhnNum(argvalue) { + argvalue = argvalue.toString(); + if (argvalue.length == 0) { + return false; + } + for (var n = 0; n < argvalue.length; n++) { + if ((argvalue.substring(n, n+1) < "0") || + (argvalue.substring(n,n+1) > "9")) { + return false; + } + } + return true; + }]]> + + + + + + + + 0)) { + if (!checkEmail(form[oEmail[x][0]].value)) { + if (i == 0) { + focusField = form[oEmail[x][0]]; + } + fields[i++] = oEmail[x][1]; + bValid = false; + } + } + } + if (fields.length > 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return bValid; + } + + /** + * Reference: Sandeep V. Tamhankar (stamhankar@hotmail.com), + * http://javascript.internet.com + */ + function checkEmail(emailStr) { + if (emailStr.length == 0) { + return true; + } + var emailPat=/^(.+)@(.+)$/; + var specialChars="\\(\\)<>@,;:\\\\\\\"\\.\\[\\]"; + var validChars="\[^\\s" + specialChars + "\]"; + var quotedUser="(\"[^\"]*\")"; + var ipDomainPat=/^(\d{1,3})[.](\d{1,3})[.](\d{1,3})[.](\d{1,3})$/; + var atom=validChars + '+'; + var word="(" + atom + "|" + quotedUser + ")"; + var userPat=new RegExp("^" + word + "(\\." + word + ")*$"); + var domainPat=new RegExp("^" + atom + "(\\." + atom + ")*$"); + var matchArray=emailStr.match(emailPat); + if (matchArray == null) { + return false; + } + var user=matchArray[1]; + var domain=matchArray[2]; + if (user.match(userPat) == null) { + return false; + } + var IPArray = domain.match(ipDomainPat); + if (IPArray != null) { + for (var i = 1; i <= 4; i++) { + if (IPArray[i] > 255) { + return false; + } + } + return true; + } + var domainArray=domain.match(domainPat); + if (domainArray == null) { + return false; + } + var atomPat=new RegExp(atom,"g"); + var domArr=domain.match(atomPat); + var len=domArr.length; + if ((domArr[domArr.length-1].length < 2) || + (domArr[domArr.length-1].length > 3)) { + return false; + } + if (len < 2) { + return false; + } + return true; + }]]> + + + + + + + 0) { + alert(fields.join('\n')); + } + return bValid; + } + + /** + * Reference: JS Guide + * http://jsguide.net/ver2/articles/frame.php?artnum=002 + */ + function checkIhIdNum(ihidnum){ + + fmt = /^\d{6}[1234]\d{6}$/; + if(!fmt.test(ihidnum)){ + return false; + } + + birthYear = (ihidnum.charAt(7) <= "2") ? "19" : "20"; + birthYear += ihidnum.substr(0, 2); + birthMonth = ihidnum.substr(2, 2) - 1; + birthDate = ihidnum.substr(4, 2); + birth = new Date(birthYear, birthMonth, birthDate); + + if( birth.getYear() % 100 != ihidnum.substr(0, 2) || + birth.getMonth() != birthMonth || + birth.getDate() != birthDate) { + return false; + } + + var arrDivide = [2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5]; + var checkdigit = 0; + for(var i=0;i + + + + 0) { + focusField.focus(); + alert(fields.join('\n')); + } + return bValid; + } + + function checkKorean(koreanStr){ + for(var i=0;i + + + + + + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/config/egovframework/validator/validator.xml b/legacy/nlib/src/main/webapp/WEB-INF/config/egovframework/validator/validator.xml new file mode 100644 index 00000000..453fa362 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/config/egovframework/validator/validator.xml @@ -0,0 +1,22 @@ + + + + + + +
+ + + + + + + + + +
+
+ +
\ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/insertQnaForm.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/insertQnaForm.jsp new file mode 100644 index 00000000..7b7526c8 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/insertQnaForm.jsp @@ -0,0 +1,394 @@ +<% +/** + *
+ * @Class Name : insertQnaForm.jsp
+ * 
+ * @Description : 묻고답하기 등록화면을 표출한다. 
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 13. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 13. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> + + +Q&A + + + 수정 + + + 등록 + + + + + + + + + + + + + + + +
+

Q&A 섹션영역

+
+
+
+
    +
  • HOME
  • +
  • 고객지원
  • +
  • +
+
+

+
+
+
+
+
+ +
+
+
+

* 표시는 필수 입력 항목입니다.

+
+
+ Q&A 작성 + + + + + + + + +
+
    +
  • +
    제목 *
    +
    + +
    +
  • +
  • +
    + checked /> + +
    +
  • +
  • +
    답변메일 수신여부
    +
    + checked /> + +
    +
  • +
  • +
    내용 *
    +
    + +
    +
  • +
+
+
+
+ +
+
    +
  • +
    첨부파일
    +
    +
    +
    + +
    최대 5개까지 (개당 10MB 이내)
    + +
    +
    +
    +
  • +
+
+
+ + +
+
+
+
+ +
+
+
+ + +
+ + + + + +
+ + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/listAncmnts.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/listAncmnts.jsp new file mode 100644 index 00000000..361315c9 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/listAncmnts.jsp @@ -0,0 +1,260 @@ +<% +/** + *
+ * @Class Name : listAncmnts.jsp
+ * 
+ * @Description : 공지사항 목록 화면을 표출한다.
+ * 
+ * 
+ * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
+ *
+ * 
+ * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 13. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 9. 13. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> + +공지사항 + + + + + +
+

공지사항 섹션영역

+
+
+
+
    +
  • HOME
  • +
  • 고객지원
  • +
  • +
+
+

+
+
+
+
+
+ +
+
+
+ + +
+ +
+ + + + + + + + + + + + + + + + +
공지사항 목록 표 – NO, 제목, 등록자, 등록일, 첨부로 구성
NO제목등록자등록일첨부
+
+ +
    +
    + +
    + +
    +
    +
    + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/listFaqs.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/listFaqs.jsp new file mode 100644 index 00000000..385ce468 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/listFaqs.jsp @@ -0,0 +1,322 @@ +<% +/** + *
    + * @Class Name : listFaqs.jsp
    + * 
    + * @Description : 자주하는질문 목록 화면을 표출한다.
    + * 
    + * 
    + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
    + *
    + * 
    + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 15. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 9. 15. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> + +FAQ + + + + +
    +

    섹션영역

    +
    +
    +
    +
      +
    • HOME
    • +
    • 고객지원
    • +
    • +
    +
    +

    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    + + + + + + +
    +
    0
    + +
    + +
    +
    + +
    +
    + + + +
    +
    +
    +
    +
    + +
    +
    + +
    +
      + +
    +
    + +
      + +
      +
      +
      + +
      +
      +
      +
      + + +
      + + + + + +
      + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/listQnas.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/listQnas.jsp new file mode 100644 index 00000000..c8858456 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/listQnas.jsp @@ -0,0 +1,316 @@ +<% +/** + *
      + * @Class Name : listQnas.jsp
      + * 
      + * @Description : 묻고답하기 목록 화면을 표출한다.
      + * 
      + * 
      + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
      + *
      + * 
      + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 16. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 9. 16. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> +<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%> + +Q&A + + + + +
      +

      섹션영역

      +
      +
      +
      +
        +
      • HOME
      • +
      • 고객지원
      • +
      • +
      +
      +

      +
      +
      +
      +
      +
      +
      +
      + +
      +
      +
      +
      +
      0
      + +
      + +
      +
      + + + +
      +
      + + + +
      +
      + + + + + + + +
      +
      +
      + +
      +
      + +
      +
      + +
      + + + + + + + + + + + + + + + + +
      Q&A 목록 표 – NO, 제목, 등록자, 등록일, 답변으로 구성
      NO제목등록자등록일답변
      +
      + +
      + +
      + +
        + +
        + +
        + +
        + +
        +
        + +
        +
        +
        +
        diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/selectAncmntArticle.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/selectAncmntArticle.jsp new file mode 100644 index 00000000..70dcb329 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/selectAncmntArticle.jsp @@ -0,0 +1,163 @@ +<% +/** + *
        + * @Class Name : selectAncmntArticle.jsp
        + * 
        + * @Description : 공지사항 상세내용을 조회한다.
        + * 
        + * 
        + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
        + *
        + * 
        + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 14. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 9. 14. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> + +공지사항 - 상세조회 + + + + + +
        +

        공지사항 보기 섹션영역

        +
        +
        +
        +
          +
        • HOME
        • +
        • 고객지원
        • +
        • +
        +
        +

        +
        +
        +
        +
        +
        + +
        +
        +
        +
        +

        공지 +

        + + + + +
        + + + +
        + <% + // 파일정보 : 저장파일ID=원파일명 + %> + +
        + 파일 아이콘 + + +
        +
        +
        +
        + +
        +
        +
        + +
        +
        +
          + +
        +
        + +
        +
        +
        + +
        +
        +
        + + +
        + + + + + +
        + + +
        + + + + + + +
        \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/selectQnaArticle.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/selectQnaArticle.jsp new file mode 100644 index 00000000..be7e05a3 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/bbs/selectQnaArticle.jsp @@ -0,0 +1,209 @@ +<% +/** + *
        + * @Class Name : selectQnaArticle.jsp
        + * 
        + * @Description : 묻고답하기 상세내용을 조회한다.
        + * 
        + * 
        + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
        + *
        + * 
        + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 16. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 9. 16. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> + +Q&A + + + + +
        +

        Q&A 섹션영역

        +
        +
        +
        +
          +
        • HOME
        • +
        • 고객지원
        • +
        • +
        +
        +

        +
        +
        +
        +
        +
        + +
        +
        +
        +
        +

        + + 답변완료 + + + 자물쇠 아이콘 + + +

        + + + + +
        + + +
        + <% + // 파일정보 : 저장파일ID=원파일명 + %> + +
        + 파일 + + +
        +
        +
        +
        + +
        +
        +
        +

        + +

        +
        +
        + +
        +
        + 답변 + +
        +
        +

        +
        +
        +
        +
        +
        +
        + + + + + +
        +
        + +
        +
        +
        +
        +
        + +
        +
        +
        + + + +
        + + + + + + + +
        + + +
        + + + + + +
        \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cart/listCartItems.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cart/listCartItems.jsp new file mode 100644 index 00000000..95d555a8 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cart/listCartItems.jsp @@ -0,0 +1,448 @@ +<% +/** + *
        + * @Class Name : listCartItems.jsp
        + * 
        + * @Description : 카트 목록을 조회한다.
        + * 
        + * 
        + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
        + *
        + * 
        + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 10. 08 KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 10. 08. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> +<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%> +카트 + + +
        + + + + + + + +
        +

        카트 섹션영역

        +
        +
        +
        +
          +
        • HOME
        • +
        • 카트
        • +
        +
        +

        카트

        +
        +
        +
        +
        +
        +
        +
        + + +
        +
        +
        +
        + + + + + + + + + + + +
        + + + + + +

        +
        +
        +
        + + + 전체선택 (0/0) +
        +
        자료정보
        +
        이용상태
        +
        반납예정일
        +
        대출
        +
        방문열람
        +
        선택삭제
        +
        + + + + + + + +
        +
        +
        +
        + 썸네일 + + + + 즐겨찾기 아이콘 + 즐겨찾기 아이콘 + + + + + 즐겨찾기 아이콘 + 즐겨찾기 아이콘 + + + +
        +
        + + 온라인열람 + + + + 대출 + + + + 방문열람 + + +
        +
        +
        +
        poss imposs">

        +
        +
        poss imposs">
        +
        poss imposs">
        +
        + + + + +
        + + + + + +
        +
        +
        +
        자료정보
        +
        이용상태
        +
        반납예정일
        +
        대출
        +
        방문열람
        +
        +
        + 자료가 없습니다. +
        +
        +
        + + +
        +
        + + + + + + + + + +
        +
        + + + + + + + + +
        +
        +
        + +
        + +
        +
        + +
        + + +
        +
        +
        + +
        + +
        + + + + + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/Modal.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/Modal.jsp new file mode 100644 index 00000000..6c008381 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/Modal.jsp @@ -0,0 +1,57 @@ +<% + /** + * @Class Name : EgovModal.jsp + * @Description : 모달 JSP + * @Modification Information + * @ + * @ 수정일 수정자 수정내용 + * @ ------- -------- --------------------------- + * @ 2016.07.13 장동한 최초 생성 + * + * @author 2016 표준프레임워크유지보수 개발팀 장동한 + * @since 2016.07.13 + * @version 1.0 + * @see + * + */ +%> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ page import="egovframework.com.cmm.EgovWebUtil" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui"%> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<% + String sScriptYn = request.getParameter("scriptYn") == null ? "" : (String)request.getParameter("scriptYn"); + String sModelName = request.getParameter("modalName") == null ? "" : (String)request.getParameter("modalName"); +%> +<%if(sScriptYn.equals("Y")){ %> + + +<%} %> + + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/alert.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/alert.jsp new file mode 100644 index 00000000..bbef8053 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/alert.jsp @@ -0,0 +1,17 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + +alertPage + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/common.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/common.jsp new file mode 100644 index 00000000..936e8f9f --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/common.jsp @@ -0,0 +1,29 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%> + +결과코드 : +
        +메시지 : + + 

        + + +
        +
        + + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/accessDenied.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/accessDenied.jsp new file mode 100644 index 00000000..27b9f317 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/accessDenied.jsp @@ -0,0 +1,38 @@ +<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> + + + + + +<spring:message code="title.html"/> + + + + +
        +

        +
        + +

        + +
        +
        +
        +

        +


        + +
        +
        +
        +
        +
        + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/bizException.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/bizException.jsp new file mode 100644 index 00000000..577e08ab --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/bizException.jsp @@ -0,0 +1,39 @@ +<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> + + + + + +<spring:message code="title.html"/> + + + + + +
        +

        +
        + +


        + +
        +
        +
        +

        +


        + +
        +
        +
        +
        +
        + + + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/dataAccessFailure.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/dataAccessFailure.jsp new file mode 100644 index 00000000..a8c2694e --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/dataAccessFailure.jsp @@ -0,0 +1,39 @@ +<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> + + + + + +<spring:message code="title.html"/> + + + + + +
        +

        +
        + +


        + +
        +
        +
        +

        +


        + +
        +
        +
        +
        +
        + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/egovXssException.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/egovXssException.jsp new file mode 100644 index 00000000..d879e9e5 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/egovXssException.jsp @@ -0,0 +1,38 @@ +<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> + + + + +<spring:message code="title.html"/> + + + + + +
        +

        +
        + +

        User authorization Error

        + +
        +
        +
        +

        ${exception.message}

        +


        + +
        +
        +
        +
        +
        + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/error.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/error.jsp new file mode 100644 index 00000000..6751f4b8 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/error.jsp @@ -0,0 +1,39 @@ +<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> + + + + + +<spring:message code="title.html"/> + + + + + +
        +

        +
        + +


        + +
        +
        +
        +

        +


        + +
        +
        +
        +
        +
        + + + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/httpSessionException.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/httpSessionException.jsp new file mode 100644 index 00000000..dc84807d --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/error/httpSessionException.jsp @@ -0,0 +1,39 @@ +<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> + + + + + +<spring:message code="title.html"/> + + + + + +
        +

        +
        + +


        + +
        +
        +
        +

        +


        + +
        +
        +
        +
        +
        + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/fms/EgovFileList.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/fms/EgovFileList.jsp new file mode 100644 index 00000000..c2a3222c --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/fms/EgovFileList.jsp @@ -0,0 +1,150 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> + +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui"%> +<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +<% + +/** + * @Class Name : EgovFileList.jsp + * @Description : 파일 목록화면 + * @Modification Information + * @ + * @ 수정일 수정자 수정내용 + * @ ---------- ------ --------------------------- + * @ 2009.03.26 이삼섭 최초 생성 + * 2011.07.20 옥찬우 Tag id속성 추가( Line : 68 ) + * 2018.09.11 신용호 불필요한 function 삭제 - fn_egov_multi_selector_update_delete + * + * @author 공통서비스 개발팀 이삼섭 + * @since 2009.03.26 + * @version 1.0 + * @see + * + */ +%> + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +  [ byte] + ','','egov_file_view_table_tr_${status.count}');" alt=""> + + + ','')"> +  [ byte] + + + + +
        + +
        + +
        diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/fms/EgovImgFileList.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/fms/EgovImgFileList.jsp new file mode 100644 index 00000000..331c0d3a --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/fms/EgovImgFileList.jsp @@ -0,0 +1,39 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui"%> +<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +<% + /** + * @Class Name : EgovImgFileList.jsp + * @Description : 이미지 파일 조회화면 + * @Modification Information + * @ + * @ 수정일 수정자 수정내용 + * @ ------- -------- --------------------------- + * @ 2009.03.31 이삼섭 최초 생성 + * + * @author 공통서비스 개발팀 이삼섭 + * @since 2009.03.31 + * @version 1.0 + * @see + * + */ +%> +이미지파일목록 + + + + + + + + + + + + + +
        + ?atchFileId=&fileSn=' width="640" alt="해당파일이미지"/> +
        diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/footerSubPart.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/footerSubPart.jsp new file mode 100644 index 00000000..2418974c --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/footerSubPart.jsp @@ -0,0 +1,12 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> + + + + + + + +
        검색결과가 없습니다.
        +
        \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/headerSubPart.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/headerSubPart.jsp new file mode 100644 index 00000000..2d38cdea --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/headerSubPart.jsp @@ -0,0 +1,95 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%> + +<% +String councilCd = (String)session.getAttribute("councilCd"); +String councilNm = (String)session.getAttribute("councilNm"); +%> + + +

        헤더영역

        +
        + +

        소장자료관

        + + + + +
        +

        검색

        +
        +
        + +
        + 검색 +
        + + +
        +
        + + + +
        +
        +
        +
        +
        + +
        + +
        +
        + + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/home.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/home.jsp new file mode 100644 index 00000000..6e941227 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/home.jsp @@ -0,0 +1,727 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%> + + + + +
        +

        배너 섹션영역

        +
        + + + +
        +

        검색

        +
        +
        + +
        + 검색 +
        +
        + + +
        +
        + + + +
        +
        +
        +
        +
        + + +
        +
        + + + +
        +

        문화원픽 섹션영역

        +
        +
        +

        문화원's Pick

        +

        추천하는 자료를 만나보세요!

        + + +
        +
        + + + +
        +
        +
        <c:out value='${itemPick.title }'/> 표지
        + +
        +
        + +
        + +
        +
        +
        + +
        +
        +
        +
        +
        + + + + +
        +

        인기자료 섹션영역

        +
        +

        인기 자료

        +

        이런 인기자료들이 있어요!

        +
        + +
        +
        +
        +
          + +
        • +
          +
          + +
          +
          +

          주제분야-

          +

          생산기관-

          +

          생산년도-

          +
          +
        • +
          +
        + +
        +
        +
        + +
        +
        +
        +
        + + + +
        +

        온라인자료관 섹션영역

        +
        +

        온라인 자료관

        +

        문화원 전자자료를 온라인으로 간편하게 열람해보세요!

        + +
        +
        + + +
        +
        +
        +
        + <c:out value='${itemOnline.title }'/> 표지 +
        + +
          +
        • 자료유형-
        • +
        • 주제분야-
        • +
        • 생산기관-
        • +
        • 생산년도-
        • +
        + +
        +
        +
        +
        +
        +
        +
        +
        +
        + +
        + +
        +
        +
        + + + +
        +

        키워드 섹션영역

        +
        +
        +

        AI 추천 키워드

        +

        어떤 자료들을 소장 중인지 키워드로 살펴보세요!

        +
          + +
        • # +
        • +
          +
        +
        +
        +
        +
        + + +
        +

        커뮤니티 섹션영역

        + +
        + + +
        +

        중간배너 섹션영역

        +
        +
        +

        회원가입만 하면 발급되는
        간편 온라인 회원증!

        +

        문화원 소장자료관 회원가입 시 해당 문화원에서
        사용할 수 있는 온라인 회원증이 발급됩니다.

        +
        +
        +
        + + + + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/listNotifications.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/listNotifications.jsp new file mode 100644 index 00000000..25db2ccd --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/listNotifications.jsp @@ -0,0 +1,239 @@ +<% +/** + *
        + * @Class Name : lisNotifications.jsp
        + * 
        + * @Description : 알림 목록을 조회한다.
        + * 
        + * 
        + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
        + *
        + * 
        + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 6. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 9. 6. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> + +알림 + + + + +
        +

        알림 섹션영역

        +
        +
        +
        +
          +
        • HOME
        • +
        • +
        +
        +

        +
        +
        +
        +
        +
        +
        +
        + 0 +
        +

        - 최근 한달동안 발송된 알림 내역만 보관됩니다.

        +
        +
        + +
        +
        +
          + +
        +
        +
          +
          + +
          +
          +
          +
          + +
          + + + +
          + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/validator.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/validator.jsp new file mode 100644 index 00000000..5fd6058f --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/cmm/validator.jsp @@ -0,0 +1,4 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ page language="java" contentType="application/javascript" pageEncoding="UTF-8"%> +<%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/collection/listInterests.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/collection/listInterests.jsp new file mode 100644 index 00000000..f2f9fabb --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/collection/listInterests.jsp @@ -0,0 +1,377 @@ +<% +/** + *
          + * @Class Name : listInterests.jsp
          + * 
          + * @Description : 관심 자료를 조회한다.
          + * 
          + * 
          + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
          + *
          + * 
          + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 28. JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 7. 28. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> + +관심자료 + + + + +
          +

          섹션영역

          +
          +
          +
          +
            +
          • HOME
          • +
          • 마이페이지
          • +
          • +
          +
          +

          관심자료

          +
          +
          +
          +
          +
          +
          +
          + + + +
          + 0 +
          +
          + +
          +
          +
          +
          +
          +
          +
            +
            +
            + + +
            +
            +
            +
            +
            +
            +
            +
            \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/collection/searchItemDetail.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/collection/searchItemDetail.jsp new file mode 100644 index 00000000..dcf556e4 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/collection/searchItemDetail.jsp @@ -0,0 +1,680 @@ +<%@page import="nlib.cmm.NlibCommonController"%> +<% +/** + *
            + * @Class Name : selectItemDetail.jsp
            + * 
            + * @Description : 소장자료 상세내용을 조회한다.
            + * 
            + * 
            + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
            + *
            + * 
            + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 30. JSYOO 최초 생성 + * @ 2021.10. 28. KNKIM 대출예약, 방문열람신청, 카트담기 연결 처리 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 7. 30. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> + + + +
            + +
            +
            + + + + + + + + + + + + + + + + + + + + + + + + + +

            소장자료 상세페이지 섹션영역

            +
            +
            +
            + +
            +
            +
            + + 온라인열람 + + + 대출 + + + 방문열람 + + + 기타 + +
            +
            + +
            +
            +
            +
            + + + + + + + + + + + +
            +
            + +
            +
            " alt="">
            +
            + +
            +
            +
            +
              +
            • + 자료유형 + + + + + + + > + + + + + - + + + + +
            • +
            • + 연대 + + 년부터 + 까지 + - + +
            • +
            • + 주제분야 + + + + + + + > + + + + + - + + + + +
            • +
            • + 생산기관 + - +
            • +
            • + 테마 + - +
            • +
            • + 시대 + - +
            • +
            • + 생산년도 + - +
            • + +
            • + 저자 + - +
            • +
            • + 출판사 + - +
            • +
            • + 발간유형 + - +
            • +
            • + 발간매체 + - +
            • +
            • + 청구기호 + - +
            • +
              + +
            • + 문서번호 + - +
            • +
              + +
            • + 매체 + - +
            • +
            • + 규격 + - +
            • +
                +
              • + 미디어 설명 +
                +
                + - + +
                + +
                +
              • +
              +
                +
              • + 미디어 부가설명 +
                +
                + - + +
                + +
                +
              • +
              +
              + +
            • + 미디어 유형 + - +
            • +
            • + 재생시간 + - +
            • +
            • + 재생화질상태 + - +
            • +
                +
              • + 미디어 설명 +
                +
                + - + +
                + +
                +
              • +
              +
                +
              • + 미디어 부가설명 +
                +
                + - + +
                + +
                +
              • +
              +
              + +
            • + 도면/지도유형 + - +
            • +
            • + 위치(주소) + - +
            • +
              + +
            • + 박물유형 + - +
            • +
            • + 박물형태 + - +
            • +
            • + 재질 + - +
            • +
              +
            +
            +
            + + + + + + + + +
            + +
            + 키워드 + + + +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            이용상태
            +
            +
            +
            +
            +
            반납예정일
            +
            + + + + - + + + + + + +
            +
            +
            +
            +
            대출
            +
            + 신청가능 + 예약가능 + 신청/예약불가 +
            +
            +
            +
            +
            방문열람
            +
            + 신청가능 + 신청불가 +
            +
            +
            +
            +

            - 자료의 이용상태, 대출가능여부, 방문열람가능여부를 꼭 확인하신 후 이용해주시길 바랍니다.

            +

            - 다른 지방문화원 소장자료관 이용자들을 위해 꼭 필요한 자료만 예약한 후, 가능한 날짜에 예약 및 이용 부탁드립니다.

            +
            +
            + + +
            +
            +

            목차정보

            + +
            +
            +

            +
            +
            +
            + +
            +
            + +
            +
            +

            함께 볼만한자료

            +
            +
            + +
            +
            +
            +
            +
            +
            +

            자료유형- >

            +

            주제분야- >

            +

            생산기관-

            +

            생산년도-

            +
            +
            +
            +
            +
            +
            +
            + +
            + +
            +
            +
            +
            + +
            + +
            +
            +

            이 자료와 유사한자료

            +

            , 에 있습니다

            +
            +
            + +
            +
            + +
            +
            +
            +
            + +
            + +
              +
            • 주제유형-
            • +
            • 주제분야-
            • +
            • 생산기관-
            • +
            • 생산년도-
            • +
            +
            +
            +
            +
            +
            +
            +
            +
            +
            + +
            + +
            +
            +
            +
            + +
            +
            +
            +
            +
            +
            + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/collection/searchList.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/collection/searchList.jsp new file mode 100644 index 00000000..f6c99549 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/collection/searchList.jsp @@ -0,0 +1,542 @@ +<% + /** + *
            +     * @Class Name : searchList.jsp
            +     *
            +     * @Description : 소장 자료를 조회한다.
            +     *
            +     *
            +     * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
            +     *
            +     * 
            + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 10. 13. JSYOO 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 10. 13. + * @version 1.0 + * + */ +%> +<%@ page language="java" contentType="text/html; charset=UTF-8"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui"%> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> +<%@ taglib prefix="validator" + uri="http://www.springmodules.org/tags/commons-validator"%> + +소장 자료 + + + + + + + + +소장자료 + + + +
            + + + + + + + + + + + + + + + + + +
            +

            섹션영역

            +
            +
            +
            +
              +
            • HOME
            • +
            • +
            +
            +

            소장자료

            +
            +
            +
            +
            +
            +
            + +
            +
            +
            + 검색결과 필터 + 닫기 아이콘 +
            +
            +

            검색필터

            + +
            +
            +
              +
            +
            +
            +
            +
            +

            자료유형

            +
            +
            +
              + +
            • +
              on"> +
              + checked="checked" /> + +
              +
              +
                + + +
              • +
                checked="checked" /> + +
                +
              • +
                +
                +
              +
            • +
              +
            +
            + +
            +
            +
            +

            주제분야

            + +
            +
            +
              + + + +
            • +
              on"> +
              checked="checked"/>
              +
              +
                + + +
              • checked="checked"/>
              • +
                +
                +
              +
            • + +
              +
              +
            +
            + +
            + +
            +
            +

            생산년도

            +
            +
            +
              +
            • + +
            • +
            • + + ~ +
            • +
            • + +
            • +
            +
            + +
            + +
            +
            +

            생산기관

            +
            +
            +
              + +
            • +
              +
              checked="checked"/>
              +
              +
            • +
              +
            +
            + +
            + +
            +
            +
            + +
            +
            + + +
            + + + '' 에 대한 검색결과는 총 + 건 입니다. + + + + + + +
            + +
            + + +
            +
            + + style="display:none;" placeholder="검색어를 입력하세요." value="" maxlength="50" /> + + style="display:none;" placeholder="결과내재검색" value="" maxlength="50" /> + + +
            +
            +
            + +
            +
            +
            + +
            +
            +
            +
            자료정보
            +
            이용
            +
            + +
            +
            +
            <c:out value='${result.title}'/> + + + + + + +
            +
            + + 온라인열람 + + + 대출 + + + 방문열람 + + + 기타 + +
            +
            +
            +
            + 자료유형 : - > + 주제분야 : - > + 생산기관 : - + 생산년도 : - +
            +
            +
            +

            + + 대출신청 가능 + + + 대출예약 가능 + + + 대출신청/예약 불가 + +
            + + 방문열람신청 가능 + + + 방문열람신청 불가 + +

            + + + + +
            +
            +
            + +
            +
            +

            느낌표 아이콘

            +

            검색된 결과가 없습니다

            +

            지역N문화에서 더 많은 자료를 확인하세요!

            +

            +
            +
            +
            +
            +
            + +
              +
            + +
            +
            +
            +
            +
            + +
            +
            +
            +
            +
            \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/inform/selectGreeting.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/inform/selectGreeting.jsp new file mode 100644 index 00000000..566f0cd7 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/inform/selectGreeting.jsp @@ -0,0 +1,85 @@ +<% +/** + *
            + * @Class Name : selectGreeting.jsp
            + * 
            + * @Description : 인사말 조회 
            + * 
            + * 
            + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
            + *
            + * 
            + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 27. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 27. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> + +<% +String councilCd = (String)session.getAttribute("councilCd"); +String councilNm = (String)session.getAttribute("councilNm"); +%> + +인사말 + + + +
            + +

            섹션영역

            +
            +
            +
            +
              +
            • HOME
            • +
            • 자료관안내
            • +
            • +
            +
            +

            +
            +
            +
            +
            +
            +
            + + +
            +

            소장자료관을 방문하신 여러분,
            진심으로 환영합니다.

            +
            +
            + + + + +
            +
            +
            +
            +
            + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/inform/selectNCultureLocationInfo.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/inform/selectNCultureLocationInfo.jsp new file mode 100644 index 00000000..e3801b0d --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/inform/selectNCultureLocationInfo.jsp @@ -0,0 +1,168 @@ +<% +/** + *
            + * @Class Name : selectNCultureLocationInfo.jsp
            + * 
            + * @Description : 찾아오시는길 조회 
            + * 
            + * 
            + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
            + *
            + * 
            + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 27. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 27. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %><%@taglib prefix="spring" uri="http://www.springframework.org/tags"%> + +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> +찾아오시는길 + + + +
            +

            섹션영역

            +
            +
            +
            +
              +
            • HOME
            • +
            • 자료관안내
            • +
            • +
            +
            +

            찾아오시는

            +
            +
            +
            +
            +
            +
            +

            오시는 길

            +
            +
            + +
            +
            +
            + + + +
            +
            +

            +

            주소

            +

            ()

            +
            +
            +

            +

            운영시간

            +

            월요일~금요일 / 오전 ~ 오후

            +

            매주 토요일, 일요일 휴관

            +
            +
            +

            +

            전화

            +

            +
            +
            +

            +

            팩스

            +

            +
            +
            +
            +
            +
            + +
            +
            +
            + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/inform/selectNCultureOperationInfo.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/inform/selectNCultureOperationInfo.jsp new file mode 100644 index 00000000..c59de9a6 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/inform/selectNCultureOperationInfo.jsp @@ -0,0 +1,104 @@ +<% +/** + *
            + * @Class Name : selectNCultureOperationInfo.jsp
            + * 
            + * @Description : 이용안내 조회 
            + * 
            + * 
            + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
            + *
            + * 
            + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 27. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 27. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> +이용안내 + + +
            +

            섹션영역

            +
            +
            +
            +
              +
            • HOME
            • +
            • 자료관안내
            • +
            • +
            +
            +

            이용안내

            +
            +
            +
            +
            +
            +
            + + +
            +
            +
            +
            + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/inform/selectPrivacyInfo.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/inform/selectPrivacyInfo.jsp new file mode 100644 index 00000000..25da45af --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/inform/selectPrivacyInfo.jsp @@ -0,0 +1,65 @@ +<% +/** + *
            + * @Class Name : selectPrivacyInfo.jsp
            + * 
            + * @Description : 개인정보처리방침 조회 
            + * 
            + * 
            + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
            + *
            + * 
            + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 27. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 27. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> + +개인정보처리방침 + + +
            +

            개인정보처리방침 섹션영역

            +
            +
            +
            +
              +
            • HOME
            • +
            • +
            +
            +

            개인정보처리방침

            +
            +
            +
            +
            +
            +
            +
            +

            <소장자료관> 개인정보 처리방침

            +

            <소장자료관>은 회원의 자유와 권리 보호를 위해 「개인정보 보호법」 및 관계 법령이 정한 바를 준수하며, 적법하게 개인정보를 처리하고 안전하게 관리하고 있습니다.
            이에 「개인정보 보호법」 제30조에 따라 회원에게 개인정보 처리에 관한 절차 및 기준을 안내하고, 이와 관련한 고충을 신속하고 원활하게 처리할 수 있도록 다음과 같이 개인정보 처리방침을 수립·공개합니다.

            +
            +
            + +
            +
            +
            +
            +
            + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/inform/selectTermsInfo.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/inform/selectTermsInfo.jsp new file mode 100644 index 00000000..8c8f38ac --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/inform/selectTermsInfo.jsp @@ -0,0 +1,65 @@ +<% +/** + *
            + * @Class Name : selectTermsInfo.jsp
            + * 
            + * @Description : 이용약관 조회 
            + * 
            + * 
            + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
            + *
            + * 
            + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 27. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 7. 27. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %> + +이용약관 + + +
            +

            이용약관 섹션영역

            +
            +
            +
            +
              +
            • HOME
            • +
            • +
            +
            +

            이용약관

            +
            +
            +
            +
            +
            +
            +
            +

            지방문화원 소장자료관 이용약관

            +

            한국문화원연합회(이하 ‘연합회’라 한다)는 개인정보 보호법 제30조에 따라 정보주체의 개인정보를 보호하고 이와 관련한 고충을 신속하고 원활하게 처리할 수 있도록 하기 위하여 다음과 같이 개인정보 처리지침을 수립·공개합니다.

            +
            +
            + +
            +
            +
            +
            +
            + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/activateDormantAcc.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/activateDormantAcc.jsp new file mode 100644 index 00000000..cca2d93f --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/activateDormantAcc.jsp @@ -0,0 +1,77 @@ +<% +/** + *
            + * @Class Name : activateDormantAccForm.jsp
            + * 
            + * @Description : 휴면계좌 해지안내 및 확인 화면 
            + * 
            + * 
            + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
            + *
            + * 
            + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 1. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 9. 1. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%> +휴면계정 해제 + + + + +
            +

            휴면계정 섹션영역

            +
            +
            +
            자물쇠 아이콘
            +

            +
            +
            +
            + +
            + +
            +
            +

            회원님의 계정이 정상적으로 휴면 해제되었습니다.

            +
            +
            + +

            [로그인]을 클릭하여 로그인을 계속 진행해 주시기 바랍니다.

            +
            + +

            +
            +
            +
            + 로그인 +
            +
            +
            +
            +
            +
            +
            + + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/activateDormantAccForm.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/activateDormantAccForm.jsp new file mode 100644 index 00000000..877faae0 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/activateDormantAccForm.jsp @@ -0,0 +1,77 @@ +<% +/** + *
            + * @Class Name : activateDormantAccForm.jsp
            + * 
            + * @Description : 휴면계좌 해지안내 및 확인 화면 
            + * 
            + * 
            + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
            + *
            + * 
            + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 9. 1. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 9. 1. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%> +휴면계정 안내 + + + + +
            +

            휴면계정 섹션영역

            +
            +
            +
            자물쇠 아이콘
            +

            +
            +
            +
            +
            + +
            +
            +

            회원님의 계정은 현재 휴면 상태입니다.
            서비스 이용을 원하신다면 지금 바로 휴면을 해제하세요!

            +

            회원님의 정보를 안전하게 보호하기 위하여 일정 기간동안 이용내역이 없는 경우
            휴면 상태로 계정을 전환하여 보관하는 정책을 실시하고 있습니다.

            +
            +
            + +

            휴면 상태의 회원의 경우 서비스 이용이 제한되며,
            [휴면해제] 버튼을 통해 휴면해제 가능합니다.

            +
            + +

            +
            +
            + +
            +
            +
            +
            +
            +
            + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/loginForm.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/loginForm.jsp new file mode 100644 index 00000000..256bef6d --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/loginForm.jsp @@ -0,0 +1,75 @@ +<% +/** + *
            + * @Class Name : loginForm.jsp
            + * 
            + * @Description : 로그인폼
            + * 
            + * 
            + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
            + *
            + * 
            + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 12. JSYOO 최초 생성 + * @ 2021.10. 20. KNKIM 퍼블리쉬 템플릿 적용 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 10. 20. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%> +로그인 + + + +
            +

            로그인 섹션영역

            +
            +
            +
            자물쇠 아이콘
            + +

            로그인 안내

            +
            + +

            로그인 후, 이용해 주시기 바랍니다.

            +
            +
            +
            +
            + + +
            +

            로그인할 때 이용할 SNS를 선택하세요!

            +

             

            +

            회원가입하고 대출/열람 서비스를 이용해보세요!

            + +
            + +
            +
            +
            +
            + + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/loginFormPopup.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/loginFormPopup.jsp new file mode 100644 index 00000000..57e50bb5 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/loginFormPopup.jsp @@ -0,0 +1,63 @@ +<% +/** + *
            + * @Class Name : loginFormPopup.jsp
            + * 
            + * @Description : 로그인 SNS 연동 선택 팝업 화면
            + * 
            + * 
            + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
            + *
            + * 
            + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 7. 12. JSYOO 최초 생성 + * @ 2021.10. 20. KNKIM 퍼블리쉬 템플릿 적용 작업 및 팝업 형태로 변경 + * + * + * @author 이씨플라자 * DIGITALSHIP JSYOO + * @since 2021. 10. 20. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%> +통합 로그인 + + + + +
            +

            지방문화원 소장자료관

            +

            +
            +
            +
            + +
            +
            +
            +
            +

            회원가입하고 대출/열람 서비스를 이용해보세요!

            +

            회원가입

            +
            + +
            +
            + diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/loginMessage.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/loginMessage.jsp new file mode 100644 index 00000000..6f567d07 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/loginMessage.jsp @@ -0,0 +1,82 @@ +<% +/** + *
            + * @Class Name : loginMessage.jsp
            + * 
            + * @Description : 로그인/회원가입 처리 과정 중 문제 발생에 따른 안내 화면  
            + * 
            + * 
            + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
            + *
            + * 
            + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 10. 21. KNKIM 최초생성 + + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 10. 21. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui"%> +<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +안내 + + + +
            +

            안내 섹션영역

            +
            +
            +
            자물쇠 아이콘
            + +

            로그인 및 회원가입 안내

            +
            + +

            로그인 안내

            +
            +
            +
            +
            +
            +
            +

            +
            + +
            +

            위의 안내 메시지를 확인하신 후, 다시 로그인하시거나 회원가입을 진행해 주시기 바랍니다.

            +
            +
            +
            + 홈으로 +   +   + + 로그인 + +   +   + + + 회원가입 + +
            +
            +
            +
            +
            +
            + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/loginPreSet.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/loginPreSet.jsp new file mode 100644 index 00000000..71b29816 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/loginPreSet.jsp @@ -0,0 +1,70 @@ +<% +/** + *
            + * @Class Name : loginPreSet.jsp
            + * 
            + * @Description : 로그인폼 사전 처리 페이지 이동 
            + * 
            + * 
            + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
            + *
            + * 
            + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 10.13. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 10.13. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%> + +처리중입니다 + + + + +
            + +
            + +
            + +

            로그인 섹션영역

            +
            +
            +
            +
              +
            • HOME
            • +
            • 로그인
            • +
            +
            +

            로그인

            +
            +
            +
            +
            +
            +
            +
            +

            처리중입니다. 잠시만 기다려 주시기 바랍니다.

            +
            +
            +
            +
            +
            diff --git a/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/loginPreSetPopup.jsp b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/loginPreSetPopup.jsp new file mode 100644 index 00000000..f4ba4f47 --- /dev/null +++ b/legacy/nlib/src/main/webapp/WEB-INF/jsp/nlib/login/loginPreSetPopup.jsp @@ -0,0 +1,85 @@ +<% +/** + *
            + * @Class Name : loginPreSet.jsp
            + * 
            + * @Description : 로그인폼 사전 처리 페이지 이동 
            + * 
            + * 
            + * @프로젝트명: 지방문화원 통합자료관리시스템 구축사업 (2021)
            + *
            + * 
            + * + * @ ------------ -------- --------------------------- + * @ 수정일 수정자 수정내용 + * @ ------------ -------- --------------------------- + * @ 2021. 10.13. KNKIM 최초 생성 + * + * + * @author 이씨플라자 * DIGITALSHIP KNKIM + * @since 2021. 10.13. + * @version 1.0 + * + */ + %> +<%@ page language="java" contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui" %> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%> +처리중입니다 + +
            +

            지방문화원 소장자료관

            +

            통합 로그인

            +
            +
            +
            + '+ + '
            ', + + srcAction: 'iframe_src', + + // we don't care and support only one default type of URL by default + patterns: { + youtube: { + index: 'youtube.com', + id: 'v=', + src: '//www.youtube.com/embed/%id%?autoplay=1' + }, + vimeo: { + index: 'vimeo.com/', + id: '/', + src: '//player.vimeo.com/video/%id%?autoplay=1' + }, + gmaps: { + index: '//maps.google.', + src: '%id%&output=embed' + } + } + }, + + proto: { + initIframe: function() { + mfp.types.push(IFRAME_NS); + + _mfpOn('BeforeChange', function(e, prevType, newType) { + if(prevType !== newType) { + if(prevType === IFRAME_NS) { + _fixIframeBugs(); // iframe if removed + } else if(newType === IFRAME_NS) { + _fixIframeBugs(true); // iframe is showing + } + }// else { + // iframe source is switched, don't do anything + //} + }); + + _mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() { + _fixIframeBugs(); + }); + }, + + getIframe: function(item, template) { + var embedSrc = item.src; + var iframeSt = mfp.st.iframe; + + $.each(iframeSt.patterns, function() { + if(embedSrc.indexOf( this.index ) > -1) { + if(this.id) { + if(typeof this.id === 'string') { + embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length); + } else { + embedSrc = this.id.call( this, embedSrc ); + } + } + embedSrc = this.src.replace('%id%', embedSrc ); + return false; // break; + } + }); + + var dataObj = {}; + if(iframeSt.srcAction) { + dataObj[iframeSt.srcAction] = embedSrc; + } + mfp._parseMarkup(template, dataObj, item); + + mfp.updateStatus('ready'); + + return template; + } + } +}); + + + +/*>>iframe*/ + +/*>>gallery*/ +/** + * Get looped index depending on number of slides + */ +var _getLoopedId = function(index) { + var numSlides = mfp.items.length; + if(index > numSlides - 1) { + return index - numSlides; + } else if(index < 0) { + return numSlides + index; + } + return index; + }, + _replaceCurrTotal = function(text, curr, total) { + return text.replace(/%curr%/gi, curr + 1).replace(/%total%/gi, total); + }; + +$.magnificPopup.registerModule('gallery', { + + options: { + enabled: false, + arrowMarkup: '', + preload: [0,2], + navigateByImgClick: true, + arrows: true, + + tPrev: 'Previous (Left arrow key)', + tNext: 'Next (Right arrow key)', + tCounter: '%curr% of %total%' + }, + + proto: { + initGallery: function() { + + var gSt = mfp.st.gallery, + ns = '.mfp-gallery', + supportsFastClick = Boolean($.fn.mfpFastClick); + + mfp.direction = true; // true - next, false - prev + + if(!gSt || !gSt.enabled ) return false; + + _wrapClasses += ' mfp-gallery'; + + _mfpOn(OPEN_EVENT+ns, function() { + + if(gSt.navigateByImgClick) { + mfp.wrap.on('click'+ns, '.mfp-img', function() { + if(mfp.items.length > 1) { + mfp.next(); + return false; + } + }); + } + + _document.on('keydown'+ns, function(e) { + if (e.keyCode === 37) { + //mfp.prev(); + } else if (e.keyCode === 39) { + //mfp.next(); + } + }); + }); + + _mfpOn('UpdateStatus'+ns, function(e, data) { + if(data.text) { + data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length); + } + }); + + _mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) { + var l = mfp.items.length; + values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : ''; + }); + + _mfpOn('BuildControls' + ns, function() { + if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) { + var markup = gSt.arrowMarkup, + arrowLeft = mfp.arrowLeft = $( markup.replace(/%title%/gi, gSt.tPrev).replace(/%dir%/gi, 'left') ).addClass(PREVENT_CLOSE_CLASS), + arrowRight = mfp.arrowRight = $( markup.replace(/%title%/gi, gSt.tNext).replace(/%dir%/gi, 'right') ).addClass(PREVENT_CLOSE_CLASS); + + var eName = supportsFastClick ? 'mfpFastClick' : 'click'; + arrowLeft[eName](function() { + mfp.prev(); + }); + arrowRight[eName](function() { + mfp.next(); + }); + + // Polyfill for :before and :after (adds elements with classes mfp-a and mfp-b) + if(mfp.isIE7) { + _getEl('b', arrowLeft[0], false, true); + _getEl('a', arrowLeft[0], false, true); + _getEl('b', arrowRight[0], false, true); + _getEl('a', arrowRight[0], false, true); + } + + mfp.container.append(arrowLeft.add(arrowRight)); + } + }); + + _mfpOn(CHANGE_EVENT+ns, function() { + if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout); + + mfp._preloadTimeout = setTimeout(function() { + mfp.preloadNearbyImages(); + mfp._preloadTimeout = null; + }, 16); + }); + + + _mfpOn(CLOSE_EVENT+ns, function() { + _document.off(ns); + mfp.wrap.off('click'+ns); + + if(mfp.arrowLeft && supportsFastClick) { + mfp.arrowLeft.add(mfp.arrowRight).destroyMfpFastClick(); + } + mfp.arrowRight = mfp.arrowLeft = null; + }); + + }, + next: function() { + mfp.direction = true; + mfp.index = _getLoopedId(mfp.index + 1); + mfp.updateItemHTML(); + }, + prev: function() { + mfp.direction = false; + mfp.index = _getLoopedId(mfp.index - 1); + mfp.updateItemHTML(); + }, + goTo: function(newIndex) { + mfp.direction = (newIndex >= mfp.index); + mfp.index = newIndex; + mfp.updateItemHTML(); + }, + preloadNearbyImages: function() { + var p = mfp.st.gallery.preload, + preloadBefore = Math.min(p[0], mfp.items.length), + preloadAfter = Math.min(p[1], mfp.items.length), + i; + + for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) { + mfp._preloadItem(mfp.index+i); + } + for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) { + mfp._preloadItem(mfp.index-i); + } + }, + _preloadItem: function(index) { + index = _getLoopedId(index); + + if(mfp.items[index].preloaded) { + return; + } + + var item = mfp.items[index]; + if(!item.parsed) { + item = mfp.parseEl( index ); + } + + _mfpTrigger('LazyLoad', item); + + if(item.type === 'image') { + item.img = $('').on('load.mfploader', function() { + item.hasSize = true; + }).on('error.mfploader', function() { + item.hasSize = true; + item.loadError = true; + _mfpTrigger('LazyLoadError', item); + }).attr('src', item.src); + } + + + item.preloaded = true; + } + } +}); + +/* +Touch Support that might be implemented some day + +addSwipeGesture: function() { + var startX, + moved, + multipleTouches; + + return; + + var namespace = '.mfp', + addEventNames = function(pref, down, move, up, cancel) { + mfp._tStart = pref + down + namespace; + mfp._tMove = pref + move + namespace; + mfp._tEnd = pref + up + namespace; + mfp._tCancel = pref + cancel + namespace; + }; + + if(window.navigator.msPointerEnabled) { + addEventNames('MSPointer', 'Down', 'Move', 'Up', 'Cancel'); + } else if('ontouchstart' in window) { + addEventNames('touch', 'start', 'move', 'end', 'cancel'); + } else { + return; + } + _window.on(mfp._tStart, function(e) { + var oE = e.originalEvent; + multipleTouches = moved = false; + startX = oE.pageX || oE.changedTouches[0].pageX; + }).on(mfp._tMove, function(e) { + if(e.originalEvent.touches.length > 1) { + multipleTouches = e.originalEvent.touches.length; + } else { + //e.preventDefault(); + moved = true; + } + }).on(mfp._tEnd + ' ' + mfp._tCancel, function(e) { + if(moved && !multipleTouches) { + var oE = e.originalEvent, + diff = startX - (oE.pageX || oE.changedTouches[0].pageX); + + if(diff > 20) { + mfp.next(); + } else if(diff < -20) { + mfp.prev(); + } + } + }); +}, +*/ + + +/*>>gallery*/ + +/*>>retina*/ + +var RETINA_NS = 'retina'; + +$.magnificPopup.registerModule(RETINA_NS, { + options: { + replaceSrc: function(item) { + return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; }); + }, + ratio: 1 // Function or number. Set to 1 to disable. + }, + proto: { + initRetina: function() { + if(window.devicePixelRatio > 1) { + + var st = mfp.st.retina, + ratio = st.ratio; + + ratio = !isNaN(ratio) ? ratio : ratio(); + + if(ratio > 1) { + _mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) { + item.img.css({ + 'max-width': item.img[0].naturalWidth / ratio, + 'width': '100%' + }); + }); + _mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) { + item.src = st.replaceSrc(item, ratio); + }); + } + } + + } + } +}); + +/*>>retina*/ + +/*>>fastclick*/ +/** + * FastClick event implementation. (removes 300ms delay on touch devices) + * Based on https://developers.google.com/mobile/articles/fast_buttons + * + * You may use it outside the Magnific Popup by calling just: + * + * $('.your-el').mfpFastClick(function() { + * console.log('Clicked!'); + * }); + * + * To unbind: + * $('.your-el').destroyMfpFastClick(); + * + * + * Note that it's a very basic and simple implementation, it blocks ghost click on the same element where it was bound. + * If you need something more advanced, use plugin by FT Labs https://github.com/ftlabs/fastclick + * + */ + +(function() { + var ghostClickDelay = 1000, + supportsTouch = 'ontouchstart' in window, + unbindTouchMove = function() { + _window.off('touchmove'+ns+' touchend'+ns); + }, + eName = 'mfpFastClick', + ns = '.'+eName; + + + // As Zepto.js doesn't have an easy way to add custom events (like jQuery), so we implement it in this way + $.fn.mfpFastClick = function(callback) { + + return $(this).each(function() { + + var elem = $(this), + lock; + + if( supportsTouch ) { + + var timeout, + startX, + startY, + pointerMoved, + point, + numPointers; + + elem.on('touchstart' + ns, function(e) { + pointerMoved = false; + numPointers = 1; + + point = e.originalEvent ? e.originalEvent.touches[0] : e.touches[0]; + startX = point.clientX; + startY = point.clientY; + + _window.on('touchmove'+ns, function(e) { + point = e.originalEvent ? e.originalEvent.touches : e.touches; + numPointers = point.length; + point = point[0]; + if (Math.abs(point.clientX - startX) > 10 || + Math.abs(point.clientY - startY) > 10) { + pointerMoved = true; + unbindTouchMove(); + } + }).on('touchend'+ns, function(e) { + unbindTouchMove(); + if(pointerMoved || numPointers > 1) { + return; + } + lock = true; + e.preventDefault(); + clearTimeout(timeout); + timeout = setTimeout(function() { + lock = false; + }, ghostClickDelay); + callback(); + }); + }); + + } + + elem.on('click' + ns, function() { + if(!lock) { + callback(); + } + }); + }); + }; + + $.fn.destroyMfpFastClick = function() { + $(this).off('touchstart' + ns + ' click' + ns); + if(supportsTouch) _window.off('touchmove'+ns+' touchend'+ns); + }; +})(); + +/*>>fastclick*/ + _checkInstance(); })(window.jQuery || window.Zepto); \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/js/jquery.mousewheel.js b/legacy/nlib/src/main/webapp/js/jquery.mousewheel.js new file mode 100644 index 00000000..c2c94b46 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/jquery.mousewheel.js @@ -0,0 +1,221 @@ +/*! + * jQuery Mousewheel 3.1.13 + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + */ + +(function (factory) { + if ( typeof define === 'function' && define.amd ) { + // AMD. Register as an anonymous module. + define(['jquery'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS style for Browserify + module.exports = factory; + } else { + // Browser globals + factory(jQuery); + } +}(function ($) { + + var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'], + toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ? + ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'], + slice = Array.prototype.slice, + nullLowestDeltaTimeout, lowestDelta; + + if ( $.event.fixHooks ) { + for ( var i = toFix.length; i; ) { + $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks; + } + } + + var special = $.event.special.mousewheel = { + version: '3.1.12', + + setup: function() { + if ( this.addEventListener ) { + for ( var i = toBind.length; i; ) { + this.addEventListener( toBind[--i], handler, false ); + } + } else { + this.onmousewheel = handler; + } + // Store the line height and page height for this particular element + $.data(this, 'mousewheel-line-height', special.getLineHeight(this)); + $.data(this, 'mousewheel-page-height', special.getPageHeight(this)); + }, + + teardown: function() { + if ( this.removeEventListener ) { + for ( var i = toBind.length; i; ) { + this.removeEventListener( toBind[--i], handler, false ); + } + } else { + this.onmousewheel = null; + } + // Clean up the data we added to the element + $.removeData(this, 'mousewheel-line-height'); + $.removeData(this, 'mousewheel-page-height'); + }, + + getLineHeight: function(elem) { + var $elem = $(elem), + $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent'](); + if (!$parent.length) { + $parent = $('body'); + } + return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16; + }, + + getPageHeight: function(elem) { + return $(elem).height(); + }, + + settings: { + adjustOldDeltas: true, // see shouldAdjustOldDeltas() below + normalizeOffset: true // calls getBoundingClientRect for each event + } + }; + + $.fn.extend({ + mousewheel: function(fn) { + return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel'); + }, + + unmousewheel: function(fn) { + return this.unbind('mousewheel', fn); + } + }); + + + function handler(event) { + var orgEvent = event || window.event, + args = slice.call(arguments, 1), + delta = 0, + deltaX = 0, + deltaY = 0, + absDelta = 0, + offsetX = 0, + offsetY = 0; + event = $.event.fix(orgEvent); + event.type = 'mousewheel'; + + // Old school scrollwheel delta + if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; } + if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; } + if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; } + if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; } + + // Firefox < 17 horizontal scrolling related to DOMMouseScroll event + if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) { + deltaX = deltaY * -1; + deltaY = 0; + } + + // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy + delta = deltaY === 0 ? deltaX : deltaY; + + // New school wheel delta (wheel event) + if ( 'deltaY' in orgEvent ) { + deltaY = orgEvent.deltaY * -1; + delta = deltaY; + } + if ( 'deltaX' in orgEvent ) { + deltaX = orgEvent.deltaX; + if ( deltaY === 0 ) { delta = deltaX * -1; } + } + + // No change actually happened, no reason to go any further + if ( deltaY === 0 && deltaX === 0 ) { return; } + + // Need to convert lines and pages to pixels if we aren't already in pixels + // There are three delta modes: + // * deltaMode 0 is by pixels, nothing to do + // * deltaMode 1 is by lines + // * deltaMode 2 is by pages + if ( orgEvent.deltaMode === 1 ) { + var lineHeight = $.data(this, 'mousewheel-line-height'); + delta *= lineHeight; + deltaY *= lineHeight; + deltaX *= lineHeight; + } else if ( orgEvent.deltaMode === 2 ) { + var pageHeight = $.data(this, 'mousewheel-page-height'); + delta *= pageHeight; + deltaY *= pageHeight; + deltaX *= pageHeight; + } + + // Store lowest absolute delta to normalize the delta values + absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) ); + + if ( !lowestDelta || absDelta < lowestDelta ) { + lowestDelta = absDelta; + + // Adjust older deltas if necessary + if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) { + lowestDelta /= 40; + } + } + + // Adjust older deltas if necessary + if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) { + // Divide all the things by 40! + delta /= 40; + deltaX /= 40; + deltaY /= 40; + } + + // Get a whole, normalized value for the deltas + delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta); + deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta); + deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta); + + // Normalise offsetX and offsetY properties + if ( special.settings.normalizeOffset && this.getBoundingClientRect ) { + var boundingRect = this.getBoundingClientRect(); + offsetX = event.clientX - boundingRect.left; + offsetY = event.clientY - boundingRect.top; + } + + // Add information to the event object + event.deltaX = deltaX; + event.deltaY = deltaY; + event.deltaFactor = lowestDelta; + event.offsetX = offsetX; + event.offsetY = offsetY; + // Go ahead and set deltaMode to 0 since we converted to pixels + // Although this is a little odd since we overwrite the deltaX/Y + // properties with normalized deltas. + event.deltaMode = 0; + + // Add event and delta to the front of the arguments + args.unshift(event, delta, deltaX, deltaY); + + // Clearout lowestDelta after sometime to better + // handle multiple device types that give different + // a different lowestDelta + // Ex: trackpad = 3 and mouse wheel = 120 + if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); } + nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200); + + return ($.event.dispatch || $.event.handle).apply(this, args); + } + + function nullLowestDelta() { + lowestDelta = null; + } + + function shouldAdjustOldDeltas(orgEvent, absDelta) { + // If this is an older event and the delta is divisable by 120, + // then we are assuming that the browser is treating this as an + // older mouse wheel event and that we should divide the deltas + // by 40 to try and get a more usable deltaFactor. + // Side note, this actually impacts the reported scroll distance + // in older browsers and can cause scrolling to be slower than native. + // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false. + return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0; + } + +})); \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/js/jquery/jquery.js b/legacy/nlib/src/main/webapp/js/jquery/jquery.js new file mode 100644 index 00000000..fc6c299b --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/jquery/jquery.js @@ -0,0 +1,10881 @@ +/*! + * jQuery JavaScript Library v3.6.0 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2021-03-02T17:08Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 + // Plus for old WebKit, typeof returns "function" for HTML collections + // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) + return typeof obj === "function" && typeof obj.nodeType !== "number" && + typeof obj.item !== "function"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.6.0", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), + function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); + } ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.6 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2021-02-16 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem && elem.namespaceURI, + docElem = elem && ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +} +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the primary Deferred + primary = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + primary.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( primary.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return primary.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject ); + } + + return primary.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
            " ], + col: [ 2, "", "
            " ], + tr: [ 2, "", "
            " ], + td: [ 3, "", "
            " ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + + // Support: Chrome 86+ + // In Chrome, if an element having a focusout handler is blurred by + // clicking outside of it, it invokes the handler synchronously. If + // that handler calls `.remove()` on the element, the data is cleared, + // leaving `result` undefined. We need to guard against this. + return result && result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + which: true +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + // Suppress native focus or blur as it's already being fired + // in leverageNative. + _default: function() { + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + // + // Support: Firefox 70+ + // Only Firefox includes border widths + // in computed dimensions. (gh-4529) + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate"; + tr.style.cssText = "border:1px solid"; + + // Support: Chrome 86+ + // Height set through cssText does not get applied. + // Computed height then comes back as 0. + tr.style.height = "1px"; + trChild.style.height = "9px"; + + // Support: Android 8 Chrome 86+ + // In our bodyBackground.html iframe, + // display for all div elements is set to "inline", + // which causes a problem only in Android 8 Chrome 86. + // Ensuring the div is display: block + // gets around this issue. + trChild.style.display = "block"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) + + parseInt( trStyle.borderTopWidth, 10 ) + + parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml, parserErrorElem; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) {} + + parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; + if ( !xml || parserErrorElem ) { + jQuery.error( "Invalid XML: " + ( + parserErrorElem ? + jQuery.map( parserErrorElem.childNodes, function( el ) { + return el.textContent; + } ).join( "\n" ) : + data + ) ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ).filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ).map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + +originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script but not if jsonp + if ( !isSuccess && + jQuery.inArray( "script", s.dataTypes ) > -1 && + jQuery.inArray( "json", s.dataTypes ) < 0 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + +
            + + +

            + + + + +

            +
            + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin.html b/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin.html new file mode 100644 index 00000000..f15cfe27 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin.html @@ -0,0 +1,786 @@ + + + + + + +네이버 :: Smart Editor 2 ™ + + + + + + + + + + + + +
            +
            글쓰기영역으로 바로가기 +
            + +
            +
              +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +
              + +
            • + +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +
              + +
            • +
              +
            • + +
            • + +
            • + +
            • + +
            • + + + +
            • + +
            • + + + +
            • + +
            • + +
            • +
              +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +

              직접 입력

              + + + + + +
              + +
              +
              +
              +
              + +
            • +
              +
            • + + + +
            • +
              + + +
            • + +
              +
              +
              +
                +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              +

              + +

              +
              +
              +
              + +
            • + +
            • + + +
              +
              +
              +
              + 칸수 지정 +
              +
              +
              + + +
              +
              +
              + + +
              +
              + + + + + + + + + + + + + + + + + + + +
                  
                  
                  
              +
              +
              + 속성직접입력 +
              +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              + + +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              +
              + 표스타일 +
              +
              +
              + + + +
              +
              +
              +

              + +

              + +
              + +
              +
              +
              + + +
            • + +
            • + + +
              +
              +
              + +

              찾기/바꾸기

              +
                +
              • +
              • +
              +
              +
              +
              +
              +

              + +

              +
              + + +
              +
              +
              + + +
            • +
            +
            + +
            + + + + + +
            + +
            + + + + + + + + + +
            + + +
            + + +
            + + + + +
            + + +
            + + +
            +
            + + +
            + +
              +
            • +
            • +
            • +
            +
            + +
            + + + +
            +
            + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin_en_US.html b/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin_en_US.html new file mode 100644 index 00000000..dc8583e9 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin_en_US.html @@ -0,0 +1,786 @@ + + + + + + +네이버 :: Smart Editor 2 ™ + + + + + + + + + + + + +
            +
            글쓰기영역으로 바로가기 +
            + +
            +
              +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +
              + +
            • + +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +
              + +
            • +
              +
            • + +
            • + +
            • + +
            • + +
            • + + + +
            • + +
            • + + + +
            • + +
            • + +
            • +
              +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +

              Enter

              + + + + + +
              + +
              +
              +
              +
              + +
            • +
              +
            • + + + +
            • +
              + + +
            • + +
              +
              +
              +
                +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              +

              + +

              +
              +
              +
              + +
            • + +
            • + + +
              +
              +
              +
              + Designate Number of Blanks +
              +
              +
              + + +
              +
              +
              + + +
              +
              + + + + + + + + + + + + + + + + + + + +
                  
                  
                  
              +
              +
              + Enter Attributes +
              +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              + + +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              +
              + Table Style +
              +
              +
              + + + +
              +
              +
              +

              + +

              + +
              + +
              +
              +
              + + +
            • + +
            • + + +
              +
              +
              + +

              Find/Change

              +
                +
              • +
              • +
              +
              +
              +
              +
              +

              + +

              +
              + + +
              +
              +
              + + +
            • +
            +
            + +
            + + + + + +
            + +
            + + + + + + + + + +
            + + +
            + + +
            + + + + +
            + + +
            + + +
            +
            + + +
            + +
              +
            • +
            • +
            • +
            +
            + +
            + + + +
            +
            + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin_ja_JP.html b/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin_ja_JP.html new file mode 100644 index 00000000..68ecd69e --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin_ja_JP.html @@ -0,0 +1,786 @@ + + + + + + +네이버 :: Smart Editor 2 ™ + + + + + + + + + + + + +
            +
            글쓰기영역으로 바로가기 +
            + +
            +
              +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +
              + +
            • + +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +
              + +
            • +
              +
            • + +
            • + +
            • + +
            • + +
            • + + + +
            • + +
            • + + + +
            • + +
            • + +
            • +
              +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +

              直接入力

              + + + + + +
              + +
              +
              +
              +
              + +
            • +
              +
            • + + + +
            • +
              + + +
            • + +
              +
              +
              +
                +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              +

              + +

              +
              +
              +
              + +
            • + +
            • + + +
              +
              +
              +
              + セル数指定 +
              +
              +
              + + +
              +
              +
              + + +
              +
              + + + + + + + + + + + + + + + + + + + +
                  
                  
                  
              +
              +
              + プロパティ直接入力 +
              +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              + + +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              +
              + 表スタイル +
              +
              +
              + + + +
              +
              +
              +

              + +

              + +
              + +
              +
              +
              + + +
            • + +
            • + + +
              +
              +
              + +

              検索/置換

              +
                +
              • +
              • +
              +
              +
              +
              +
              +

              + +

              +
              + + +
              +
              +
              + + +
            • +
            +
            + +
            + + + + + +
            + +
            + + + + + + + + + +
            + + +
            + + +
            + + + + +
            + + +
            + + +
            +
            + + +
            + +
              +
            • +
            • +
            • +
            +
            + +
            + + + +
            +
            + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin_ko_KR.html b/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin_ko_KR.html new file mode 100644 index 00000000..91f433f7 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin_ko_KR.html @@ -0,0 +1,786 @@ + + + + + + +네이버 :: Smart Editor 2 ™ + + + + + + + + + + + + +
            +
            글쓰기영역으로 바로가기 +
            + +
            +
              +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +
              + +
            • + +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +
              + +
            • +
              +
            • + +
            • + +
            • + +
            • + +
            • + + + +
            • + +
            • + + + +
            • + +
            • + +
            • +
              +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +

              직접 입력

              + + + + + +
              + +
              +
              +
              +
              + +
            • +
              +
            • + + + +
            • +
              + + +
            • + +
              +
              +
              +
                +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              +

              + +

              +
              +
              +
              + +
            • + +
            • + + +
              +
              +
              +
              + 칸수 지정 +
              +
              +
              + + +
              +
              +
              + + +
              +
              + + + + + + + + + + + + + + + + + + + +
                  
                  
                  
              +
              +
              + 속성직접입력 +
              +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              + + +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              +
              + 표스타일 +
              +
              +
              + + + +
              +
              +
              +

              + +

              + +
              + +
              +
              +
              + + +
            • + +
            • + + +
              +
              +
              + +

              찾기/바꾸기

              +
                +
              • +
              • +
              +
              +
              +
              +
              +

              + +

              +
              + + +
              +
              +
              + + +
            • +
            +
            + +
            + + + + + +
            + +
            + + + + + + + + + +
            + + +
            + + +
            + + + + +
            + + +
            + + +
            +
            + + +
            + +
              +
            • +
            • +
            • +
            +
            + +
            + + + +
            +
            + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin_zh_CN.html b/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin_zh_CN.html new file mode 100644 index 00000000..4328e9d1 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin_zh_CN.html @@ -0,0 +1,786 @@ + + + + + + +네이버 :: Smart Editor 2 ™ + + + + + + + + + + + + +
            +
            글쓰기영역으로 바로가기 +
            + +
            +
              +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +
              + +
            • + +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +
              + +
            • +
              +
            • + +
            • + +
            • + +
            • + +
            • + + + +
            • + +
            • + + + +
            • + +
            • + +
            • +
              +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +

              直接输入

              + + + + + +
              + +
              +
              +
              +
              + +
            • +
              +
            • + + + +
            • +
              + + +
            • + +
              +
              +
              +
                +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              +

              + +

              +
              +
              +
              + +
            • + +
            • + + +
              +
              +
              +
              + 指定格数 +
              +
              +
              + + +
              +
              +
              + + +
              +
              + + + + + + + + + + + + + + + + + + + +
                  
                  
                  
              +
              +
              + 直接输入属性 +
              +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              + + +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              +
              + 表格 +
              +
              +
              + + + +
              +
              +
              +

              + +

              + +
              + +
              +
              +
              + + +
            • + +
            • + + +
              +
              +
              + +

              查找/改变

              +
                +
              • +
              • +
              +
              +
              +
              +
              +

              + +

              +
              + + +
              +
              +
              + + +
            • +
            +
            + +
            + + + + + +
            + +
            + + + + + + + + + +
            + + +
            + + +
            + + + + +
            + + +
            + + +
            +
            + + +
            + +
              +
            • +
            • +
            • +
            +
            + +
            + + + +
            +
            + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin_zh_TW.html b/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin_zh_TW.html new file mode 100644 index 00000000..d7cff675 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/SmartEditor2Skin_zh_TW.html @@ -0,0 +1,786 @@ + + + + + + +네이버 :: Smart Editor 2 ™ + + + + + + + + + + + + +
            +
            글쓰기영역으로 바로가기 +
            + +
            +
              +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +
              + +
            • + +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +
              + +
            • +
              +
            • + +
            • + +
            • + +
            • + +
            • + + + +
            • + +
            • + + + +
            • + +
            • + +
            • +
              +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +

              直接輸入

              + + + + + +
              + +
              +
              +
              +
              + +
            • +
              +
            • + + + +
            • +
              + + +
            • + +
              +
              +
              +
                +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              +

              + +

              +
              +
              +
              + +
            • + +
            • + + +
              +
              +
              +
              + 指定間數 +
              +
              +
              + + +
              +
              +
              + + +
              +
              + + + + + + + + + + + + + + + + + + + +
                  
                  
                  
              +
              +
              + 直接輸入屬性 +
              +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              + + +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              +
              + 表格形式 +
              +
              +
              + + + +
              +
              +
              +

              + +

              + +
              + +
              +
              +
              + + +
            • + +
            • + + +
              +
              +
              + +

              查詢/改變

              +
                +
              • +
              • +
              +
              +
              +
              +
              +

              + +

              +
              + + +
              +
              +
              + + +
            • +
            +
            + +
            + + + + + +
            + +
            + + + + + + + + + +
            + + +
            + + +
            + + + + +
            + + +
            + + +
            +
            + + +
            + +
              +
            • +
            • +
            • +
            +
            + +
            + + + +
            +
            + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/en_US/smart_editor2.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/en_US/smart_editor2.css new file mode 100644 index 00000000..9d7c4703 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/en_US/smart_editor2.css @@ -0,0 +1,192 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* COMMON */ +body,#smart_editor2,#smart_editor2 p,#smart_editor2 h1,#smart_editor2 h2,#smart_editor2 h3,#smart_editor2 h4,#smart_editor2 h5,#smart_editor2 h6,#smart_editor2 ul,#smart_editor2 ol,#smart_editor2 li,#smart_editor2 dl,#smart_editor2 dt,#smart_editor2 dd,#smart_editor2 table,#smart_editor2 th,#smart_editor2 td,#smart_editor2 form,#smart_editor2 fieldset,#smart_editor2 legend,#smart_editor2 input,#smart_editor2 textarea,#smart_editor2 button,#smart_editor2 select{margin:0;padding:0} +#smart_editor2,#smart_editor2 h1,#smart_editor2 h2,#smart_editor2 h3,#smart_editor2 h4,#smart_editor2 h5,#smart_editor2 h6,#smart_editor2 input,#smart_editor2 textarea,#smart_editor2 select,#smart_editor2 table,#smart_editor2 button{font-family:'돋움',Dotum,Helvetica,sans-serif;font-size:12px;color:#666} +#smart_editor2 span,#smart_editor2 em{font-size:12px} +#smart_editor2 em,#smart_editor2 address{font-style:normal} +#smart_editor2 img,#smart_editor2 fieldset{border:0} +#smart_editor2 hr{display:none} +#smart_editor2 ol,#smart_editor2 ul{list-style:none} +#smart_editor2 button{border:0;background:none;font-size:11px;vertical-align:top;cursor:pointer} +#smart_editor2 button span,#smart_editor2 button em{visibility:hidden;overflow:hidden;position:absolute;top:0;font-size:0;line-height:0} +#smart_editor2 legend,#smart_editor2 .blind{visibility:hidden;overflow:hidden;position:absolute;width:0;height:0;font-size:0;line-height:0} +#smart_editor2 .input_ty1{height:14px;margin:0;padding:4px 2px 0 4px;border:1px solid #c7c7c7;font-size:11px;color:#666} +#smart_editor2 a:link,#smart_editor2 a:visited,#smart_editor2 a:active,#smart_editor2 a:focus{color:#666;text-decoration:none} +#smart_editor2 a:hover{color:#666;text-decoration:underline} +/* LAYOUT */ +#smart_editor2 .se2_header{margin:10px 0 29px 0} +#smart_editor2 .se2_bi{float:left;width:93px;height:20px;margin:0;padding:0;background:url("../../img/en_US/btn_set.png?160622") -343px -358px no-repeat;font-size:0;line-height:0;text-indent:-10000px;vertical-align:middle} +#smart_editor2 .se2_allhelp{display:inline-block;width:18px;height:18px;padding:0;background:url("../../img/en_US/btn_set.png?160622") -437px -358px no-repeat;font-size:0;line-height:0;text-indent:-10000px;vertical-align:middle} +#smart_editor2 #smart_editor2_content{position:relative;border:1px solid #b5b5b5} +#smart_editor2 .se2_tool{overflow:visible;position:relative;z-index:25} +/* EDITINGAREA */ +#smart_editor2 .se2_input_area{position:relative;z-index:22;height:400px;margin:0;padding:0;*zoom:1} +#smart_editor2 .se2_input_wysiwyg,#smart_editor2 .se2_input_syntax{display:block;overflow:auto;width:100%;height:100%;margin:0;*margin:-1px 0 0 0;border:0} +/* EDITINGMODE */ +#smart_editor2 .se2_conversion_mode{position:relative;height:15px;padding-top:1px;border-top:1px solid #b5b5b5;background:url("../../img/icon_set.gif?141007") 0 -896px repeat-x} +#smart_editor2 .se2_inputarea_controller{display:block;clear:both;position:relative;width:100%;height:15px;background:url("../../img/icon_set.gif?141007") center -47px no-repeat;text-align:center;cursor:n-resize} +#smart_editor2 .se2_inputarea_controller span{display:block;visibility:visible;height:15px;font-size:0;line-height:0;color:#fff;white-space:nowrap} +#smart_editor2 .ly_controller{display:block;position:absolute;bottom:2px;left:50%;width:287px;margin-left:-148px;padding:8px 0 7px 9px;border:1px solid #827f7c;background:#fffdef} +#smart_editor2 .ly_controller p{color:#666;font-size:11px;letter-spacing:-1px;line-height:11px} +#smart_editor2 .ly_controller .bt_clse,#smart_editor2 .ly_controller .ic_arr{position:absolute;background:url("../../img/ico_extend.png") no-repeat} +#smart_editor2 .ly_controller .bt_clse{top:5px;right:4px;width:14px;height:15px;background-position:1px -43px} +#smart_editor2 .ly_controller .ic_arr{top:25px;left:50%;width:10px;height:6px;margin-left:-5px;background-position:0 -65px} +#smart_editor2 .se2_converter{float:left;position:absolute;top:-1px;right:3px;z-index:20} +#smart_editor2 .se2_converter li{float:left} +#smart_editor2 .se2_converter .se2_to_editor{width:59px;height:15px;background:url("../../img/en_US/btn_set.png?160622") 0 -85px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .se2_to_html{width:59px;height:15px;background:url("../../img/en_US/btn_set.png?160622") -59px -70px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .se2_to_text{width:60px;height:15px;background:url("../../img/en_US/btn_set.png?160622") -417px -466px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .active .se2_to_editor{width:59px;height:15px;background:url("../../img/en_US/btn_set.png?160622") 0 -70px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .active .se2_to_html{width:59px;height:15px;background:url("../../img/en_US/btn_set.png?160622") -59px -85px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .active .se2_to_text{width:60px;height:15px;background:url("../../img/en_US/btn_set.png?160622") -417px -481px no-repeat;vertical-align:top} +/* EDITINGAREA_HTMLSRC */ +#smart_editor2 .off .ico_btn,#smart_editor2 .off .se2_more,#smart_editor2 .off .se2_more2,#smart_editor2 .off .se2_font_family,#smart_editor2 .off .se2_font_size,#smart_editor2 .off .se2_bold,#smart_editor2 .off .se2_underline,#smart_editor2 .off .se2_italic,#smart_editor2 .off .se2_tdel,#smart_editor2 .off .se2_fcolor,#smart_editor2 .off .se2_fcolor_more,#smart_editor2 .off .se2_bgcolor,#smart_editor2 .off .se2_bgcolor_more,#smart_editor2 .off .se2_left,#smart_editor2 .off .se2_center,#smart_editor2 .off .se2_right,#smart_editor2 .off .se2_justify,#smart_editor2 .off .se2_ol,#smart_editor2 .off .se2_ul,#smart_editor2 .off .se2_indent,#smart_editor2 .off .se2_outdent,#smart_editor2 .off .se2_lineheight,#smart_editor2 .off .se2_del_style,#smart_editor2 .off .se2_blockquote,#smart_editor2 .off .se2_summary,#smart_editor2 .off .se2_footnote,#smart_editor2 .off .se2_url,#smart_editor2 .off .se2_emoticon,#smart_editor2 .off .se2_character,#smart_editor2 .off .se2_table,#smart_editor2 .off .se2_find,#smart_editor2 .off .se2_spelling,#smart_editor2 .off .se2_sup,#smart_editor2 .off .se2_sub,#smart_editor2 .off .se2_text_tool_more,#smart_editor2 .off .se2_new,#smart_editor2 .off .selected_color,#smart_editor2 .off .se2_lineSticker{-ms-filter:alpha(opacity=50);opacity:.5;cursor:default;filter:alpha(opacity=50)} +/* LAYER */ +#smart_editor2 .se2_text_tool .se2_layer{display:none;float:left;position:absolute;top:20px;left:0;z-index:50;margin:0;padding:0;border:1px solid #bcbbbb;background:#fafafa} +#smart_editor2 .se2_text_tool li.active{z-index:50} +#smart_editor2 .se2_text_tool .active .se2_layer{display:block} +#smart_editor2 .se2_text_tool .active li .se2_layer{display:none} +#smart_editor2 .se2_text_tool .active .active .se2_layer{display:block} +#smart_editor2 .se2_text_tool .se2_layer .se2_in_layer{float:left;margin:0;padding:0;border:1px solid #fff;background:#fafafa} +#smart_editor2 .se2_content_loading{display:none;z-index:10;position:absolute;top:0;left:0;width:100%;height:100%;text-align:center} +#smart_editor2 .se2_content_loading img{position:absolute;top:50%;left:50%;margin:-27px 0 0 -27px} +#smart_editor2 .se2_alert_wrap{display:none;z-index:20;position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;text-align:center} +#smart_editor2 .se2_alert_wrap.active{display:block} +#smart_editor2 .se2_alert_wrap .dimmed{position:absolute;top:0;left:0;width:100%;height:100%;background:#000;opacity:0.4;filter:alpha(opacity=40)} +#smart_editor2 .se2_alert_wrap .ie_cover{position:absolute;top:0;left:0;width:100%;height:100%;background:#fff;opacity:0;filter:alpha(opacity=0)} +#smart_editor2 .se2_alert_wrap .va_line{display:inline-block;height:100%;vertical-align:middle;*zoom:1} +#smart_editor2 .se2_alert_wrap .se2_alert_content{z-index:10;position:relative;display:inline-block;*display:inline;*zoom:1;border:1px solid #727272;background:#fff;padding:26px 33px 22px;vertical-align:middle} +#smart_editor2 .se2_alert_wrap .se2_alert_content{margin-top:47px} +#smart_editor2 .se2_alert_wrap .txt1{color:#333;line-height:18px} +#smart_editor2 .se2_alert_wrap .txt2{margin-top:3px;color:#999} +#smart_editor2 .se2_alert_wrap .btn_close,#smart_editor2 .se2_alert_btns button{background:url("../../img/en_US/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_alert_wrap .btn_close{z-index:10;position:absolute;top:7px;right:7px;width:11px;height:11px;background-position:-122px -32px;text-indent:-5000px} +#smart_editor2 .se2_alert_btns{margin-top:19px} +#smart_editor2 .se2_alert_btns button{display:inline;float:none;width:48px;height:27px} +#smart_editor2 .se2_alert_btns button + button{margin-left:10px} +#smart_editor2 .se2_alert_btns .se2_confirm{background-position:-369px -434px} +#smart_editor2 .se2_alert_btns .se2_cancel{background-position:-419px -434px} +/* TEXT_TOOLBAR */ +#smart_editor2 .se2_text_tool{position:relative;clear:both;z-index:30;padding:4px 0 4px 3px;background:#f4f4f4 url("../../img/bg_text_tool.gif") 0 0 repeat-x;border-bottom:1px solid #b5b5b5;*zoom:1} +#smart_editor2 .se2_text_tool:after{content:"";display:block;clear:both} +#smart_editor2 .se2_text_tool ul{float:left;display:inline;margin-right:3px;padding-left:1px;white-space:nowrap} +#smart_editor2 .se2_text_tool li{_display:inline;float:left;position:relative;z-index:30} +#smart_editor2 .se2_text_tool button,#smart_editor2 .se2_multy .se2_icon{width:21px;height:21px;background:url("../../img/en_US/text_tool_set.png?140317") no-repeat;vertical-align:top} +#smart_editor2 .se2_text_tool .se2_font_type{position:relative} +#smart_editor2 .se2_text_tool .se2_font_type li{margin-left:3px} +#smart_editor2 .se2_text_tool .se2_font_type button{text-align:left} +#smart_editor2 .se2_text_tool .se2_font_type button.se2_font_family span,#smart_editor2 .se2_text_tool .se2_font_type button.se2_font_size span{display:inline-block;visibility:visible;position:static;width:52px;height:20px;padding:0 0 0 6px;font-size:12px;line-height:20px;*line-height:22px;color:#333;*zoom:1} +#smart_editor2 .se2_text_tool .se2_multy{position:absolute;top:0;right:0;padding-left:0;margin-right:0;white-space:nowrap;border-left:1px solid #e0dedf} +#smart_editor2 .se2_text_tool .se2_multy .se2_mn{float:left;white-space:nowrap} +#smart_editor2 .se2_text_tool .se2_multy button{background-image:none} +#smart_editor2 .se2_text_tool .se2_multy .se2_photo{width:55px} +#smart_editor2 .se2_text_tool .se2_multy .se2_map{width:47px} +#smart_editor2 .se2_text_tool .se2_multy .se2_icon{display:inline-block;visibility:visible;overflow:visible;position:static;width:16px;height:29px;margin:-1px 2px 0 -1px;background-position:0 -132px;line-height:30px;vertical-align:top} +#smart_editor2 .se2_text_tool .se2_multy button,#smart_editor2 .se2_text_tool .se2_multy button span{height:29px;line-height:29px} +#smart_editor2 .se2_text_tool .se2_map .se2_icon{background-position:-29px -132px} +#smart_editor2 .se2_text_tool button span.se2_mntxt{display:inline-block;visibility:visible;overflow:visible;_overflow-y:hidden;position:relative;*margin-right:-1px;width:auto;height:29px;font-weight:normal;font-size:11px;line-height:30px;*line-height:29px;_line-height:30px;color:#444;letter-spacing:-1px;vertical-align:top} +#smart_editor2 .se2_text_tool .se2_multy .se2_photo{margin-right:1px} +#smart_editor2 .se2_text_tool .se2_multy .hover .ico_btn{background:#e8e8e8} +#smart_editor2 .se2_text_tool .se2_multy .se2_mn.hover{background:#e0dedf} +/* TEXT_TOOLBAR : ROUNDING */ +#smart_editor2 ul li.first_child button span.tool_bg, #smart_editor2 ul li.last_child button span.tool_bg, #smart_editor2 ul li.single_child button span.tool_bg{visibility:visible;height:21px} +#smart_editor2 ul li.first_child button span.tool_bg{left:-1px;width:3px;background:url("../../img/bg_button_left.gif?20121228") no-repeat} +#smart_editor2 ul li.last_child button span.tool_bg{right:0px;_right:-1px;width:2px;background:url("../../img/bg_button_right.gif") no-repeat} +#smart_editor2 ul li.single_child{padding-right:1px} +#smart_editor2 ul li.single_child button span.tool_bg{left:0;background:url("../../img/bg_button.gif?20121228") no-repeat;width:22px} +#smart_editor2 div.se2_text_tool ul li.hover button span.tool_bg{background-position:0 -21px} +#smart_editor2 div.se2_text_tool ul li.active button span.tool_bg, #smart_editor2 div.se2_text_tool ul li.active li.active button span.tool_bg{background-position:0 -42px} +#smart_editor2 div.se2_text_tool ul li.active li button span.tool_bg{background-position:0 0} +/* TEXT_TOOLBAR : SUB_MENU */ +#smart_editor2 .se2_sub_text_tool{display:none;position:absolute;top:20px;left:0;z-index:40;width:auto;height:29px;padding:0 4px 0 0;border:1px solid #b5b5b5;border-top:1px solid #9a9a9a;background:#f4f4f4} +#smart_editor2 .active .se2_sub_text_tool{display:block} +#smart_editor2 .se2_sub_text_tool ul{float:left;height:25px;margin:0;padding:4px 0 0 4px} +/* TEXT_TOOLBAR : SUB_MENU_SIZE */ +#smart_editor2 .se2_sub_step1{width:88px} +#smart_editor2 .se2_sub_step2{width:199px} +#smart_editor2 .se2_sub_step2_1{width:178px} +/* TEXT_TOOLBAR : BUTTON */ +#smart_editor2 .se2_text_tool .se2_font_family{width:70px;height:21px;background-position:0 -10px} +#smart_editor2 .se2_text_tool .hover .se2_font_family{background-position:0 -72px} +#smart_editor2 .se2_text_tool .active .se2_font_family{background-position:0 -103px} +#smart_editor2 .se2_text_tool .se2_font_size{width:45px;height:21px;background-position:-70px -10px} +#smart_editor2 .se2_text_tool .hover .se2_font_size{background-position:-70px -72px} +#smart_editor2 .se2_text_tool .active .se2_font_size{background-position:-70px -103px} +#smart_editor2 .se2_text_tool .se2_bold{background-position:-115px -10px} +#smart_editor2 .se2_text_tool .hover .se2_bold{background-position:-115px -72px} +#smart_editor2 .se2_text_tool .active .se2_bold{background-position:-115px -103px} +#smart_editor2 .se2_text_tool .se2_underline{background-position:-136px -10px} +#smart_editor2 .se2_text_tool .hover .se2_underline{background-position:-136px -72px} +#smart_editor2 .se2_text_tool .active .se2_underline{background-position:-136px -103px} +#smart_editor2 .se2_text_tool .se2_italic{background-position:-157px -10px} +#smart_editor2 .se2_text_tool .hover .se2_italic{background-position:-157px -72px} +#smart_editor2 .se2_text_tool .active .se2_italic{background-position:-157px -103px} +#smart_editor2 .se2_text_tool .se2_tdel{background-position:-178px -10px} +#smart_editor2 .se2_text_tool .hover .se2_tdel{background-position:-178px -72px} +#smart_editor2 .se2_text_tool .active .se2_tdel{background-position:-178px -103px} +#smart_editor2 .se2_text_tool .se2_fcolor{position:relative;background-position:-199px -10px} +#smart_editor2 .se2_text_tool .hover .se2_fcolor{background-position:-199px -72px} +#smart_editor2 .se2_text_tool .active .se2_fcolor{background-position:-199px -103px} +#smart_editor2 .se2_text_tool .se2_fcolor_more{background-position:-220px -10px;width:10px} +#smart_editor2 .se2_text_tool .hover .se2_fcolor_more{background-position:-220px -72px} +#smart_editor2 .se2_text_tool .active .se2_fcolor_more{background-position:-220px -103px} +#smart_editor2 .se2_text_tool .selected_color{position:absolute;top:14px;left:5px;width:11px;height:3px;font-size:0} +#smart_editor2 .se2_text_tool .se2_ol,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_ol{background-position:-345px -10px} +#smart_editor2 .se2_text_tool .se2_ul,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_ul{background-position:-366px -10px} +#smart_editor2 .se2_text_tool .hover .se2_ol,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_ol{background-position:-345px -72px} +#smart_editor2 .se2_text_tool .hover .se2_ul,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_ul{background-position:-366px -72px} +#smart_editor2 .se2_text_tool .active .se2_ol,#smart_editor2 .se2_text_tool .active .active .se2_ol{background-position:-345px -103px} +#smart_editor2 .se2_text_tool .active .se2_ul,#smart_editor2 .se2_text_tool .active .active .se2_ul{background-position:-366px -103px} +#smart_editor2 .se2_text_tool .se2_indent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_indent{background-position:-408px -10px} +#smart_editor2 .se2_text_tool .se2_outdent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_outdent{background-position:-387px -10px} +#smart_editor2 .se2_text_tool .hover .se2_indent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_indent{background-position:-408px -72px} +#smart_editor2 .se2_text_tool .hover .se2_outdent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_outdent{background-position:-387px -72px} +#smart_editor2 .se2_text_tool .active .se2_indent,#smart_editor2 .se2_text_tool .active .active .se2_indent{background-position:-408px -103px} +#smart_editor2 .se2_text_tool .active .se2_outdent,#smart_editor2 .se2_text_tool .active .active .se2_outdent{background-position:-387px -103px} +#smart_editor2 .se2_text_tool .se2_lineheight{background-position:-429px -10px} +#smart_editor2 .se2_text_tool .hover .se2_lineheight{background-position:-429px -72px} +#smart_editor2 .se2_text_tool .active .se2_lineheight{background-position:-429px -103px} +#smart_editor2 .se2_text_tool .se2_url{background-position:-513px -10px} +#smart_editor2 .se2_text_tool .hover .se2_url{background-position:-513px -72px} +#smart_editor2 .se2_text_tool .active .se2_url{background-position:-513px -103px} +#smart_editor2 .se2_text_tool .se2_bgcolor{position:relative;background-position:-230px -10px} +#smart_editor2 .se2_text_tool .hover .se2_bgcolor{background-position:-230px -72px} +#smart_editor2 .se2_text_tool .active .se2_bgcolor{background-position:-230px -103px} +#smart_editor2 .se2_text_tool .se2_bgcolor_more{background-position:-251px -10px;width:10px} +#smart_editor2 .se2_text_tool .hover .se2_bgcolor_more{background-position:-251px -72px} +#smart_editor2 .se2_text_tool .active .se2_bgcolor_more{background-position:-251px -103px} +#smart_editor2 .se2_text_tool .se2_left{background-position:-261px -10px} +#smart_editor2 .se2_text_tool .hover .se2_left{background-position:-261px -72px} +#smart_editor2 .se2_text_tool .active .se2_left{background-position:-261px -103px} +#smart_editor2 .se2_text_tool .se2_center{background-position:-282px -10px} +#smart_editor2 .se2_text_tool .hover .se2_center{background-position:-282px -72px} +#smart_editor2 .se2_text_tool .active .se2_center{background-position:-282px -103px} +#smart_editor2 .se2_text_tool .se2_right{background-position:-303px -10px} +#smart_editor2 .se2_text_tool .hover .se2_right{background-position:-303px -72px} +#smart_editor2 .se2_text_tool .active .se2_right{background-position:-303px -103px} +#smart_editor2 .se2_text_tool .se2_justify{background-position:-324px -10px} +#smart_editor2 .se2_text_tool .hover .se2_justify{background-position:-324px -72px} +#smart_editor2 .se2_text_tool .active .se2_justify{background-position:-324px -103px} +#smart_editor2 .se2_text_tool .se2_blockquote{background-position:-471px -10px} +#smart_editor2 .se2_text_tool .hover .se2_blockquote{background-position:-471px -72px} +#smart_editor2 .se2_text_tool .active .se2_blockquote{background-position:-471px -103px} +#smart_editor2 .se2_text_tool .se2_character{background-position:-555px -10px} +#smart_editor2 .se2_text_tool .hover .se2_character{background-position:-555px -72px} +#smart_editor2 .se2_text_tool .active .se2_character{background-position:-555px -103px} +#smart_editor2 .se2_text_tool .se2_table{background-position:-576px -10px} +#smart_editor2 .se2_text_tool .hover .se2_table{background-position:-576px -72px} +#smart_editor2 .se2_text_tool .active .se2_table{background-position:-576px -103px} +#smart_editor2 .se2_text_tool .se2_find{background-position:-597px -10px} +#smart_editor2 .se2_text_tool .hover .se2_find{background-position:-597px -72px} +#smart_editor2 .se2_text_tool .active .se2_find{background-position:-597px -103px} +#smart_editor2 .se2_text_tool .se2_sup{background-position:-660px -10px} +#smart_editor2 .se2_text_tool .hover .se2_sup{background-position:-660px -72px} +#smart_editor2 .se2_text_tool .active .se2_sup{background-position:-660px -103px} +#smart_editor2 .se2_text_tool .se2_sub{background-position:-681px -10px} +#smart_editor2 .se2_text_tool .hover .se2_sub{background-position:-681px -72px} +#smart_editor2 .se2_text_tool .active .se2_sub{background-position:-681px -103px} +#smart_editor2 .se2_text_tool .se2_text_tool_more{background-position:0 -41px;width:13px} +#smart_editor2 .se2_text_tool .se2_text_tool_more span.tool_bg{background:none} +#smart_editor2 .se2_text_tool .hover .se2_text_tool_more{background-position:-13px -41px} +#smart_editor2 .se2_text_tool .active .se2_text_tool_more{background-position:-26px -41px} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/en_US/smart_editor2_in.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/en_US/smart_editor2_in.css new file mode 100644 index 00000000..fdecc092 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/en_US/smart_editor2_in.css @@ -0,0 +1,24 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* COMMON */ +body,.se2_inputarea{margin:0;padding:0;font-family:'돋움',Dotum,Helvetica,Sans-serif;font-size:12px;line-height:1.5} +/* body,.se2_inputarea,.se2_inputarea th,.se2_inputarea td{margin:0;padding:0;font-family:'돋움',Dotum,Helvetica,Sans-serif;font-size:12px;line-height:1.5;color:#666} */ +.se2_inputarea p,.se2_inputarea br{margin:0;padding:0} +.se2_inputarea{margin:15px;word-wrap:break-word;*word-wrap:normal;*word-break:break-all} +.se2_inputarea td{word-break:break-all} +.se2_inputarea_890{width:741px;margin:20px 0 10px 64px} +.se2_inputarea_698{width:548px;margin:20px 0 10px 64px} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + .se2_inputarea td:empty:after,.se2_inputarea td > p:empty:after{content:"\00A0";line-height:1} +} +/* TEXT_TOOLBAR : QUOTE */ +.se2_quote1{margin:0 0 30px 20px;padding:0 8px;border-left:2px solid #ccc;color:#888} +.se2_quote2{margin:0 0 30px 13px;padding:0 8px 0 16px;background:url("../../img/bg_quote2.gif") 0 3px no-repeat;color:#888} +.se2_quote3{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #ccc;color:#888} +.se2_quote4{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #66b246;color:#888} +.se2_quote5{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #ccc;background:#fafafa;color:#888} +.se2_quote6{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #e5e5e5;color:#888} +.se2_quote7{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #66b246;color:#888} +.se2_quote8{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #e5e5e5;background:#fafafa;color:#888} +.se2_quote9{margin:0 0 30px;padding:12px 10px 11px;border:2px solid #e5e5e5;color:#888} +.se2_quote10{margin:0 0 30px;padding:12px 10px 11px;border:2px solid #e5e5e5;background:#fafafa;color:#888} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/en_US/smart_editor2_items.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/en_US/smart_editor2_items.css new file mode 100644 index 00000000..96d7d8cd --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/en_US/smart_editor2_items.css @@ -0,0 +1,447 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* TEXT_TOOLBAR : FONTNAME */ +#smart_editor2 .se2_tool .se2_l_font_fam{width:184px;margin:0;padding:0} +#smart_editor2 .se2_tool .se2_l_font_fam li{display:block;width:184px;height:21px;margin:0;padding:0;color:#333;cursor:pointer} +#smart_editor2 .se2_l_font_fam .hover,#smart_editor2 .se2_l_font_fam .active{background:#ebebeb} +#smart_editor2 .se2_l_font_fam button{width:182px;height:21px;margin:0;padding:2px 0 2px 0px;background:none;text-align:left} +#smart_editor2 .se2_l_font_fam button span{display:block;visibility:visible;overflow:visible;position:relative;top:auto;left:auto;width:auto;height:auto;margin:0 0 0 4px;padding:0;font-size:12px;line-height:normal;color:#333} +#smart_editor2 .se2_l_font_fam button span span{display:inline;visibility:visible;overflow:visible;width:auto;height:auto;margin:0 0 0 4px;font-family:Verdana;font-size:12px;line-height:14px;color:#888} +#smart_editor2 .se2_l_font_fam button span em{visibility:visible;overflow:auto;position:static;width:auto;height:auto;margin-right:-4px;font-size:12px;color:#888} +#smart_editor2 .se2_l_font_fam .se2_division{width:162px;height:2px !important;margin:1px 0 1px 0px;border:0;background:url("../../img/bg_line1.gif") 0 0 repeat-x;font-size:0;cursor:default} +/* TEXT_TOOLBAR : FONTSIZE */ +#smart_editor2 .se2_tool .se2_l_font_size{width:302px;margin:0;padding:0} +#smart_editor2 .se2_tool .se2_l_font_size li{width:302px;margin:0;padding:0;color:#333;cursor:pointer} +#smart_editor2 .se2_l_font_size .hover,#smart_editor2 .se2_l_font_size .active{background:#ebebeb} +#smart_editor2 .se2_l_font_size button{width:300px;height:auto;margin:0;padding:2px 0 1px 0px;*padding:4px 0 1px 0px;background:none;text-align:left} +#smart_editor2 .se2_l_font_size button span{display:block;visibility:visible;overflow:visible;position:relative;top:auto;left:auto;width:auto;height:auto;margin:0 0 0 4px;padding:0;line-height:normal;color:#373737;letter-spacing:0px} +#smart_editor2 .se2_l_font_size button span span{display:inline;margin:0 0 0 5px;padding:0} +#smart_editor2 .se2_l_font_size span em{visibility:visible;overflow:auto;position:static;width:auto;height:auto;color:#888} +/* TEXT_TOOLBAR : FONTCOLOR */ +#smart_editor2 .se2_palette{float:left;position:relative;width:225px;margin:0;padding:11px 0 10px 0} +#smart_editor2 .se2_palette .se2_pick_color{_display:inline;float:left;clear:both;width:205px;margin:0 0 0 11px;padding:0} +#smart_editor2 .se2_palette .se2_pick_color li{float:left;width:12px;height:12px;margin:0;padding:0} +#smart_editor2 .se2_palette .se2_pick_color li button{width:11px;height:11px;border:0} +#smart_editor2 .se2_palette .se2_pick_color li button span{display:block;visibility:visible;overflow:visible;position:absolute;top:1px;left:1px;width:11px;height:11px} +#smart_editor2 .se2_palette .se2_pick_color li button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0} +#smart_editor2 .se2_palette .se2_pick_color .hover button,#smart_editor2 .se2_palette .se2_pick_color .active button{width:11px;height:11px;border:1px solid #666} +#smart_editor2 .se2_palette .se2_pick_color .hover span,#smart_editor2 .se2_palette .se2_pick_color .active span{width:7px;height:7px;border:1px solid #fff} +#smart_editor2 .se2_palette .se2_view_more{_display:inline;float:left;width:46px;height:23px;margin:1px 0 0 1px;background:url("../../img/en_US/btn_set.png?160622") 0 -47px no-repeat} +#smart_editor2 .se2_palette .se2_view_more2{_display:inline;float:left;width:46px;height:23px;margin:1px 0 0 1px;background:url("../../img/en_US/btn_set.png?160622") 0 -24px no-repeat} +#smart_editor2 .se2_palette h4{_display:inline;float:left;width:203px;margin:9px 0 0 11px;padding:10px 0 4px 0;background:url("../../img/bg_line1.gif") repeat-x;font-weight:normal;font-size:12px;line-height:14px;color:#333;letter-spacing:-1px} +#smart_editor2 .se2_palette2{float:left;_float:none;width:214px;margin:9px 0 0 0;padding:11px 0 0 11px;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_palette2 .se2_color_set{float:left} +#smart_editor2 .se2_palette2 .se2_selected_color{_display:inline;float:left;width:83px;height:18px;margin:0;border:1px solid #c7c7c7;background:#fff} +#smart_editor2 .se2_palette2 .se2_selected_color span{_display:inline;float:left;width:79px;height:14px;margin:2px} +#smart_editor2 .se2_palette2 .input_ty1{_display:inline;float:left;width:67px;height:16px;margin:0 3px 0 3px;padding:2px 2px 0 4px;font-family:tahoma;font-size:11px} +#smart_editor2 .se2_palette2 button.se2_btn_insert{float:left;width:35px;height:21px;margin-left:2px;padding:0;background:url("../../img/en_US/btn_set.png?160622") -83px 0 no-repeat} +#smart_editor2 .se2_gradation1{float:left;_float:none;width:201px;height:128px;margin:4px 0 0 0;border:1px solid #c7c7c7;cursor:crosshair} +#smart_editor2 .se2_gradation2{float:left;_float:none;width:201px;height:10px;margin:4px 0 1px 0;border:1px solid #c7c7c7;cursor:crosshair} +/* TEXT_TOOLBAR : BGCOLOR */ +#smart_editor2 .se2_palette_bgcolor{width:225px;margin:11px 0 0;padding:0} +#smart_editor2 .se2_palette_bgcolor .se2_background{width:205px;margin:0 11px 0 11px} +#smart_editor2 .se2_palette_bgcolor .se2_background li{width:68px;height:20px} +#smart_editor2 .se2_palette_bgcolor .se2_background button{width:67px;height:19px;border:0} +#smart_editor2 .se2_palette_bgcolor .se2_background span{left:0;display:block;visibility:visible;overflow:visible;width:65px;height:17px;padding:0} +#smart_editor2 .se2_palette_bgcolor .se2_background span span{display:block;visibility:visible;overflow:visible;width:64px;height:16px;padding:3px 0 0 3px;font-size:11px;line-height:14px;text-align:left} +#smart_editor2 .se2_palette_bgcolor .se2_background .hover span{width:65px;height:17px;border:1px solid #666} +#smart_editor2 .se2_palette_bgcolor .se2_background .hover span span{width:62px;height:14px;padding:1px 0 0 1px;border:1px solid #fff} +/* TEXT_TOOLBAR : LINEHEIGHT */ +#smart_editor2 .se2_l_line_height{width:107px;margin:0;padding:0} +#smart_editor2 .se2_l_line_height li{width:107px;margin:0;padding:0;border-top:0;border-bottom:0;color:#333;cursor:pointer} +#smart_editor2 .se2_l_line_height .hover{background:#ebebeb} +#smart_editor2 .se2_l_line_height button{width:105px;height:19px;margin:0;padding:3px 0 2px 0px;background:none;text-align:left} +#smart_editor2 .se2_l_line_height button span{visibility:visible;overflow:visible;position:relative;width:auto;height:auto;margin:0;padding:0 0 0 15px;font-size:12px;line-height:normal;color:#373737} +#smart_editor2 .se2_l_line_height li button.active span{background:url("../../img/icon_set.gif?141007") 5px -30px no-repeat} +#smart_editor2 .se2_l_line_height_user{clear:both;width:83px;margin:5px 0 0 12px;padding:10px 0 0 0;_padding:11px 0 0 0;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_l_line_height_user h3{margin:0 0 4px 0;_margin:0 0 2px -1px;padding:0;line-height:14px;color:#000;letter-spacing:-1px} +#smart_editor2 .se2_l_line_height_user .bx_input{display:block;position:relative;width:83px} +#smart_editor2 .se2_l_line_height_user .btn_up{position:absolute;top:2px;*top:3px;left:68px;width:13px;height:8px;background:url("../../img/en_US/btn_set.png?160622") -86px -54px no-repeat} +#smart_editor2 .se2_l_line_height_user .btn_down{position:absolute;top:10px;*top:11px;left:68px;width:13px;height:8px;background:url("../../img/en_US/btn_set.png?160622") -86px -62px no-repeat} +#smart_editor2 .se2_l_line_height_user .btn_area{margin:5px 0 10px 0} +#smart_editor2 .se2_tool .btn_area .se2_btn_apply3{width:41px;height:24px;background:url("../../img/en_US/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_tool .btn_area .se2_btn_cancel3{width:42px;height:24px;margin-left:3px;background:url("../../img/en_US/btn_set.png?160622") -41px 0 no-repeat} +/* TEXT_TOOLBAR : QUOTE */ +#smart_editor2 .se2_quote{width:425px;height:56px} +#smart_editor2 .se2_quote ul{_display:inline;float:left;margin:11px 0 0 9px;padding:0} +#smart_editor2 .se2_quote li{_display:inline;float:left;margin:0 0 0 2px;padding:0} +#smart_editor2 .se2_quote button{width:34px;height:34px;margin:0;padding:0;background:url("../../img/en_US/btn_set.png?160622") no-repeat;cursor:pointer} +#smart_editor2 .se2_quote button span{left:0;display:block;visibility:visible;overflow:visible;width:32px;height:32px;margin:0;padding:0;border:1px solid #c7c7c7} +#smart_editor2 .se2_quote button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0} +#smart_editor2 .se2_quote .se2_quote1{background-position:1px -375px} +#smart_editor2 .se2_quote .se2_quote2{background-position:-32px -375px} +#smart_editor2 .se2_quote .se2_quote3{background-position:-65px -375px} +#smart_editor2 .se2_quote .se2_quote4{background-position:-98px -375px} +#smart_editor2 .se2_quote .se2_quote5{background-position:-131px -375px} +#smart_editor2 .se2_quote .se2_quote6{background-position:-164px -375px} +#smart_editor2 .se2_quote .se2_quote7{background-position:-197px -375px} +#smart_editor2 .se2_quote .se2_quote8{background-position:-230px -375px} +#smart_editor2 .se2_quote .se2_quote9{background-position:-263px -375px} +#smart_editor2 .se2_quote .se2_quote10{background-position:-296px -375px} +#smart_editor2 .se2_quote .hover button span,#smart_editor2 .se2_quote .active button span{width:30px;height:30px;margin:0;padding:0;border:2px solid #44b525} +#smart_editor2 .se2_quote .hover button span span,#smart_editor2 .se2_quote .active button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0} +#smart_editor2 .se2_quote .se2_cancel2{float:left;width:40px;height:35px;margin:11px 0 0 5px;background:url("../../img/en_US/btn_set.png?160622") -46px -24px no-repeat} +#smart_editor2 .se2_quote .se2_cancel2 span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0} +/* TEXT_TOOLBAR : HYPERLINK */ +#smart_editor2 .se2_url2{width:281px;padding:11px 11px 6px 11px;color:#666} +#smart_editor2 .se2_url2 .input_ty1{display:block;width:185px;height:16px;margin:0 5px 5px 0;*margin:-1px 5px 5px 0;padding:5px 2px 0 4px} +#smart_editor2 .se2_url2 .se2_url_new{width:15px;height:15px;margin:-1px 3px 1px -1px;*margin:-2px 3px 2px -1px;vertical-align:middle} +#smart_editor2 .se2_url2 label{font-size:11px;line-height:14px;vertical-align:middle} +#smart_editor2 .se2_url2 .se2_apply{position:absolute;top:13px;right:51px;width:41px;height:24px;margin:-1px 3px 1px 0;background:url("../../img/en_US/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_url2 .se2_cancel{position:absolute;top:13px;right:6px;width:42px;height:24px;margin:-1px 3px 1px 0;background:url("../../img/en_US/btn_set.png?160622") -41px 0 no-repeat} +/* TEXT_TOOLBAR : SCHARACTER */ +#smart_editor2 .se2_bx_character{width:553px;height:272px;margin:0;padding:0;background:url("../../img/bx_set_110302.gif") 9px -1230px no-repeat} +#smart_editor2 .se2_bx_character .se2_char_tab{_display:inline;float:left;position:relative;width:527px;margin:11px 10px 200px 11px;padding:0 0 0 1px} +#smart_editor2 .se2_bx_character .se2_char_tab li{position:static;margin:0 0 0 -1px;padding:0} +#smart_editor2 .se2_bx_character .se2_char1{width:93px;height:26px;background:url("../../img/en_US/btn_set.png?160622") 0 -812px no-repeat} +#smart_editor2 .se2_bx_character .se2_char2{width:104px;height:26px;background:url("../../img/en_US/btn_set.png?160622") -92px -812px no-repeat} +#smart_editor2 .se2_bx_character .se2_char3{width:121px;height:26px;background:url("../../img/en_US/btn_set.png?160622") -195px -812px no-repeat} +#smart_editor2 .se2_bx_character .se2_char4{width:55px;height:26px;background:url("../../img/en_US/btn_set.png?160622") -315px -812px no-repeat} +#smart_editor2 .se2_bx_character .se2_char5{width:86px;height:26px;background:url("../../img/en_US/btn_set.png?160622") -369px -812px no-repeat} +#smart_editor2 .se2_bx_character .se2_char6{width:73px;height:26px;background:url("../../img/en_US/btn_set.png?160622") -454px -812px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char1{width:93px;height:26px;background:url("../../img/en_US/btn_set.png?160622") 0 -838px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char2{width:104px;height:26px;background:url("../../img/en_US/btn_set.png?160622") -92px -838px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char3{width:121px;height:26px;background:url("../../img/en_US/btn_set.png?160622") -195px -838px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char4{width:55px;height:26px;background:url("../../img/en_US/btn_set.png?160622") -315px -838px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char5{width:86px;height:26px;background:url("../../img/en_US/btn_set.png?160622") -369px -838px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char6{width:73px;height:26px;background:url("../../img/en_US/btn_set.png?160622") -454px -838px no-repeat} +#smart_editor2 .se2_bx_character .se2_s_character{display:none;position:absolute;top:26px;left:0;width:532px;height:194px;margin:0;padding:0} +#smart_editor2 .se2_bx_character .active .se2_s_character{display:block} +#smart_editor2 .se2_bx_character .se2_s_character ul{float:left;width:506px;height:172px;margin:0;padding:9px 0 0 11px} +#smart_editor2 .se2_bx_character .se2_s_character li{_display:inline;float:left;position:relative;width:20px;height:18px;margin:0 0 1px 1px;background:#fff} +#smart_editor2 .se2_bx_character .se2_s_character button{width:20px;height:18px;margin:0;padding:2px;background:none} +#smart_editor2 .se2_bx_character .se2_s_character .hover,#smart_editor2 .se2_bx_character .se2_s_character .active{background:url("../../img/en_US/btn_set.png?160622") -446px -274px no-repeat} +#smart_editor2 .se2_bx_character .se2_s_character button span{left:0;display:block;visibility:visible;overflow:visible;width:14px;height:16px;margin:3px 0 0 3px;border:0;background:none;font-size:12px;line-height:normal} +#smart_editor2 .se2_apply_character{clear:both;position:relative;padding:0 0 0 11px} +#smart_editor2 .se2_apply_character label{margin:0 3px 0 0;font-size:12px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_apply_character .input_ty1{width:364px;height:17px;margin:-1px 5px 1px 0;padding:4px 0 0 5px;font-size:12px;color:#666;letter-spacing:0;vertical-align:middle} +#smart_editor2 .se2_apply_character .se2_confirm{width:41px;height:24px;margin-right:3px;background:url("../../img/en_US/btn_set.png?160622") no-repeat;vertical-align:middle} +#smart_editor2 .se2_apply_character .se2_cancel{width:42px;height:24px;background:url("../../img/en_US/btn_set.png?160622") -41px 0 no-repeat;vertical-align:middle} +/* TEXT_TOOLBAR : TABLECREATOR */ +#smart_editor2 .se2_table_set{position:relative;width:166px;margin:3px 11px 0 11px;padding:8px 0 0 0} +#smart_editor2 .se2_table_set .se2_cell_num{float:left;width:73px} +#smart_editor2 .se2_table_set .se2_cell_num dt{float:left;clear:both;width:30px;height:23px;margin:0;padding:0} +#smart_editor2 .se2_table_set .se2_cell_num dt label{display:block;margin:5px 0 0 0;font-size:11px;color:#666} +#smart_editor2 .se2_table_set .se2_cell_num dd{float:left;position:relative;width:42px;height:23px;margin:0;padding:0} +#smart_editor2 .se2_table_set .se2_cell_num .input_ty2{display:block;width:20px;height:16px;*margin:-1px 0 0 0;padding:2px 19px 0 0px;border:1px solid #c7c7c7;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666;text-align:right;*direction:rtl} +#smart_editor2 .se2_table_set .se2_cell_num .input_ty2::-ms-clear{display:none} +#smart_editor2 .se2_table_set .se2_pre_table{float:right;width:91px;height:43px;background:#c7c7c7;border-spacing:1px} +#smart_editor2 .se2_table_set .se2_pre_table tr{background:#fff} +#smart_editor2 .se2_table_set .se2_pre_table td{font-size:0;line-height:0} +#smart_editor2 .se2_table_set .se2_add{position:absolute;top:2px;right:3px;width:13px;height:8px;background:url("../../img/en_US/btn_set.png?160622") -86px -54px no-repeat} +#smart_editor2 .se2_table_set .se2_del{position:absolute;top:10px;right:3px;width:13px;height:8px;background:url("../../img/en_US/btn_set.png?160622") -86px -62px no-repeat} +/* TEXT_TOOLBAR : TABLEEDITOR */ +#smart_editor2 .se2_table_set .se2_t_proper1{float:left;width:166px;margin:7px 0 0 0;padding:10px 0 5px;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_table_set .se2_t_proper1 dt{width:166px;margin:0 0 6px 0} +#smart_editor2 .se2_table_set .se2_t_proper1 dd{width:166px} +#smart_editor2 .se2_table_set .se2_t_proper1 dt input{width:15px;height:15px;margin:-1px 3px 1px 0;_margin:-2px 3px 2px 0;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper1 dt label{font-weight:bold;font-size:11px;color:#666;letter-spacing:-1px;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper1_1{float:left;position:relative;z-index:59;width:166px;margin:1px 0 0 0} +#smart_editor2 .se2_table_set .se2_t_proper1_2{z-index:54;margin:0} +#smart_editor2 .se2_table_set .se2_t_proper1_3{z-index:53;margin:0} +#smart_editor2 .se2_table_set .se2_t_proper1_4{z-index:52;margin:0} +#smart_editor2 .se2_table_set .se2_t_proper1_1 dt{_display:inline;float:left;clear:both;width:66px;height:22px;margin:1px 0 0 18px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 dt label{display:block;margin:4px 0 0 0;font-weight:normal;font-size:11px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 dd{float:left;position:relative;width:82px;height:23px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .input_ty1{width:72px;height:16px;*margin:-1px 0 0 0;padding:2px 2px 0 6px;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .input_ty3{float:left;width:49px;height:16px;margin:0 3px 0 0;padding:2px 4px 0 4px;border:1px solid #c7c7c7;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_add{top:2px;right:2px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_del{top:10px;right:2px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_color_set .input_ty1{_display:inline;float:left;width:67px;height:16px;margin:0 3px 0 3px;padding:2px 2px 0 4px;font-family:tahoma,verdana,times New Roman;font-size:11px} +#smart_editor2 .se2_select_ty1{position:relative;width:80px;height:18px;border:1px solid #c7c7c7;background:#fff;font-size:11px;line-height:14px;text-align:left} +#smart_editor2 .se2_select_ty1 span{float:left;width:54px;height:18px;margin:0 0 0 5px;font-size:11px;line-height:14px;color:#666} +#smart_editor2 .se2_select_ty1 .se2_b_style0{position:relative;top:3px;left:-3px;white-space:nowrap} +#smart_editor2 .se2_select_ty1 .se2_b_style1{height:15px;margin:3px 0 0 4px;font-size:11px;line-height:14px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_select_ty1 .se2_b_style2{background:url("../../img/bg_set.gif") 0 -50px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style3{background:url("../../img/bg_set.gif") 0 -68px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style4{background:url("../../img/bg_set.gif") 0 -85px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style5{background:url("../../img/bg_set.gif") 0 -103px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style6{background:url("../../img/bg_set.gif") 0 -121px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style7{background:url("../../img/bg_set.gif") 0 -139px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_view_more{position:absolute;top:1px;right:1px;width:13px;height:16px;background:url("../../img/en_US/btn_set.png?160622") -112px -54px no-repeat} +#smart_editor2 .se2_select_ty1 .se2_view_more2{position:absolute;top:1px;right:1px;width:13px;height:16px;background:url("../../img/en_US/btn_set.png?160622") -99px -54px no-repeat} +/* TEXT_TOOLBAR : TABLEEDITOR > BORDER */ +#smart_editor2 .se2_table_set .se2_b_t_b1{border-top:1px solid #b1b1b1} +#smart_editor2 .se2_layer_b_style{position:absolute;top:20px;right:0px;width:80px;padding-bottom:1px;border:1px solid #c7c7c7;border-top:1px solid #a8a8a8;background:#fff} +#smart_editor2 .se2_layer_b_style ul{width:80px;margin:0;padding:1px 0 0 0} +#smart_editor2 .se2_layer_b_style li{width:80px;height:18px;margin:0;padding:0} +#smart_editor2 .se2_layer_b_style .hover,#smart_editor2 .se2_layer_b_style .active{background:#ebebeb} +#smart_editor2 .se2_layer_b_style button{width:80px;height:18px;background:none} +#smart_editor2 .se2_layer_b_style button span{left:0;display:block;visibility:visible;overflow:visible;width:71px;height:18px;margin:0 0 0 5px;font-size:11px;line-height:15px;text-align:left} +#smart_editor2 .se2_layer_b_style button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0} +#smart_editor2 .se2_layer_b_style .se2_b_style1 span{margin:3px 0 0 4px;font-size:11px;line-height:14px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_layer_b_style .se2_b_style2 span{background:url("../../img/bg_set.gif") 0 -50px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style3 span{background:url("../../img/bg_set.gif") 0 -68px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style4 span{background:url("../../img/bg_set.gif") 0 -86px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style5 span{background:url("../../img/bg_set.gif") 0 -103px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style6 span{background:url("../../img/bg_set.gif") 0 -121px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style7 span{background:url("../../img/bg_set.gif") 0 -139px repeat-x} +/* TEXT_TOOLBAR : TABLEEDITOR > COLOR */ +#smart_editor2 .se2_pre_color{float:left;width:18px;height:18px;border:1px solid #c7c7c7} +#smart_editor2 .se2_pre_color button{float:left;width:14px;height:14px;margin:2px 0 0 2px;padding:0} +#smart_editor2 .se2_pre_color button span{overflow:hidden;position:absolute;top:-10000px;left:-10000px;z-index:-100;width:0;height:0} +/* TEXT_TOOLBAR : TABLEEDITOR > DIMMED */ +#smart_editor2 .se2_table_set .se2_t_dim1{clear:both;position:absolute;top:71px;left:16px;z-index:60;width:157px;height:118px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_table_set .se2_t_dim2{position:absolute;top:116px;left:16px;z-index:55;width:157px;height:45px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_table_set .se2_t_dim3{clear:both;position:absolute;top:192px;left:16px;z-index:51;width:157px;height:39px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +/* TEXT_TOOLBAR : TABLEEDITOR > STYLE PREVIEW */ +#smart_editor2 .se2_table_set .se2_t_proper2{float:left;position:relative;z-index:50;width:166px;margin:2px 0 0 0} +#smart_editor2 .se2_table_set .se2_t_proper2 dt{float:left;width:84px;height:33px;margin:4px 0 0 0} +#smart_editor2 .se2_table_set .se2_t_proper2 dt input{width:15px;height:15px;margin:-1px 3px 1px 0;_margin:-2px 3px 2px 0;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper2 dt label{font-weight:bold;font-size:11px;color:#666;letter-spacing:-1px;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper2 dd{float:left;width:66px;height:33px} +#smart_editor2 .se2_select_ty2{position:relative;width:65px;height:31px;border:1px solid #c7c7c7;background:#fff;font-size:11px;line-height:14px;text-align:left} +#smart_editor2 .se2_select_ty2 span{float:left;width:45px;height:25px;margin:3px 0 0 3px;background:url("../../img/en_US/btn_set.png?160622") repeat-x} +#smart_editor2 .se2_select_ty2 .se2_t_style1{background-position:0 -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style2{background-position:-46px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style3{background-position:-92px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style4{background-position:-138px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style5{background-position:-184px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style6{background-position:-230px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style7{background-position:-276px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style8{background-position:-322px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style9{background-position:0 -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style10{background-position:-46px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style11{background-position:-92px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style12{background-position:-138px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style13{background-position:-184px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style14{background-position:-230px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style15{background-position:-276px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style16{background-position:-322px -436px} +#smart_editor2 .se2_select_ty2 .se2_view_more{position:absolute;top:1px;right:1px;_right:0px;width:13px !important;height:29px !important;background:url("../../img/en_US/btn_set.png?160622") -357px -48px no-repeat !important} +#smart_editor2 .se2_select_ty2 .se2_view_more2{position:absolute;top:1px;right:1px;_right:0px;width:13px !important;height:29px !important;background:url("../../img/en_US/btn_set.png?160622") -344px -48px no-repeat !important} +#smart_editor2 .se2_select_ty2 .se2_view_more span{display:none} +/* TEXT_TOOLBAR : TABLEEDITOR > STYLE */ +#smart_editor2 .se2_layer_t_style{position:absolute;top:33px;right:15px;width:208px;border:1px solid #c7c7c7;border-top:1px solid #a8a8a8;background:#fff} +#smart_editor2 .se2_layer_t_style ul{width:204px;height:126px;margin:1px 2px;padding:1px 0 0 0;background:#fff} +#smart_editor2 .se2_layer_t_style li{_display:inline;float:left;width:45px;height:25px;margin:1px;padding:1px;border:1px solid #fff} +#smart_editor2 .se2_layer_t_style .hover,#smart_editor2 .se2_layer_t_style .active{border:1px solid #666;background:#fff} +#smart_editor2 .se2_layer_t_style button{width:45px;height:25px;background:url("../../img/en_US/btn_set.png?160622") repeat-x !important} +#smart_editor2 .se2_layer_t_style .se2_t_style1{background-position:0 -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style2{background-position:-46px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style3{background-position:-92px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style4{background-position:-138px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style5{background-position:-184px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style6{background-position:-230px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style7{background-position:-276px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style8{background-position:-322px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style9{background-position:0 -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style10{background-position:-46px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style11{background-position:-92px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style12{background-position:-138px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style13{background-position:-184px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style14{background-position:-230px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style15{background-position:-276px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style16{background-position:-322px -436px !important} +#smart_editor2 .se2_table_set .se2_btn_area{float:left;width:166px;margin:6px 0 0 0;padding:12px 0 8px 0;background:url("../../img/bg_line1.gif") repeat-x;text-align:center} +#smart_editor2 .se2_table_set button.se2_apply{width:41px;height:24px;margin-right:3px;background:url("../../img/en_US/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_table_set button.se2_cancel{width:42px;height:24px;background:url("../../img/en_US/btn_set.png?160622") -41px 0 no-repeat} +#smart_editor2 .se2_table_set .se2_rd{width:14px;height:14px;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_celltit{font-size:11px;font-size:11px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_table_set dt label.se2_celltit{display:inline} +/* TEXT_TOOLBAR : FINDREPLACE */ +#smart_editor2 .se2_bx_find_revise{position:relative;width:255px;margin:0;padding:0} +#smart_editor2 .se2_bx_find_revise .se2_close{position:absolute;top:5px;right:8px;width:20px;height:20px;background:url("../../img/en_US/btn_set.png?160622") -484px -45px no-repeat} +#smart_editor2 .se2_bx_find_revise h3{margin:0;padding:10px 0 13px 10px;background:url("../../img/bg_find_h3.gif") 0 -1px repeat-x;font-size:12px;line-height:14px;letter-spacing:-1px} +#smart_editor2 .se2_bx_find_revise ul{position:relative;margin:8px 0 0 0;padding:0 0 0 12px} +#smart_editor2 .se2_bx_find_revise ul li{_display:inline;float:left;position:static;margin:0 0 0 -1px;padding:0} +#smart_editor2 .se2_bx_find_revise .se2_tabfind{width:117px;height:26px;background:url("../../img/en_US/btn_set.png?160622") 0 -100px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_tabrevise{width:117px;height:26px;background:url("../../img/en_US/btn_set.png?160622") -116px -100px no-repeat} +#smart_editor2 .se2_bx_find_revise .active .se2_tabfind{width:117px;height:26px;background:url("../../img/en_US/btn_set.png?160622") 0 -126px no-repeat} +#smart_editor2 .se2_bx_find_revise .active .se2_tabrevise{width:117px;height:26px;background:url("../../img/en_US/btn_set.png?160622") -116px -126px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_in_bx_find dl{_display:inline;float:left;width:223px;margin:0 0 0 9px;padding:7px 0 13px 14px;background:url("../../img/bx_set_110302.gif") -289px -1518px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_in_bx_revise dl{_display:inline;float:left;width:223px;margin:0 0 0 9px;padding:7px 0 13px 14px;background:url("../../img/bx_set_110302.gif") -289px -1619px no-repeat} +#smart_editor2 .se2_bx_find_revise dt{_display:inline;float:left;clear:both;width:59px;margin:1px 0 2px 0} +#smart_editor2 .se2_bx_find_revise dd{float:left;margin:0 0 2px 0} +#smart_editor2 .se2_bx_find_revise label{float:left;padding:5px 0 0 0;font-size:11px;color:#666;letter-spacing:-2px} +#smart_editor2 .se2_bx_find_revise input{float:left;width:145px;height:12px;margin:1px 0 0 0;padding:3px 2px 3px 4px;font-size:12px;color:#666} +#smart_editor2 .se2_bx_find_revise .se2_find_btns{float:left;clear:both;width:255px;padding:8px 0 10px 0;text-align:center} +#smart_editor2 .se2_bx_find_revise .se2_find_next{width:65px;height:24px;margin:0 3px 0 0;background:url("../../img/en_US/btn_set.png?160622") -180px -48px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_find_next2{width:61px;height:24px;margin:0 3px 0 0;background:url("../../img/en_US/btn_set.png?160622") -180px -24px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_revise1{width:54px;height:24px;margin:0 3px 0 0;background:url("../../img/en_US/btn_set.png?160622") -245px -48px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_revise2{width:67px;height:24px;margin:0 3px 0 0;background:url("../../img/en_US/btn_set.png?160622") -245px -24px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_cancel{width:42px;height:24px;background:url("../../img/en_US/btn_set.png?160622") -41px 0 no-repeat} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE */ +#smart_editor2 .se2_qmax{position:absolute;width:18px;height:18px;background:url("../../img/en_US/btn_set.png?160622") -339px -169px no-repeat} +#smart_editor2 .se2_qeditor{position:absolute;top:0;left:0;width:273px;margin:0;padding:0;border:1px solid #c7c7c7;border-right:1px solid #ababab;border-bottom:1px solid #ababab;background:#fafafa} +#smart_editor2 .se2_qeditor label,#smart_editor2 .se2_qeditor span,#smart_editor2 .se2_qeditor dt{font-size:11px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_qbar{position:relative;width:273px;height:11px;background:url("../../img/bx_set_110302.gif") 0 -731px no-repeat} +#smart_editor2 .se2_qbar .se2_qmini{position:absolute;top:-1px;right:0;*right:-1px;_right:-3px;width:18px;height:14px;background:url("../../img/en_US/btn_set.png?160622") -315px -170px no-repeat} +#smart_editor2 .se2_qbar .se2_qmini button{width:20px;height:14px;margin-top:-1px} +#smart_editor2 .se2_qeditor .se2_qbody0{float:left;border:1px solid #fefefe} +#smart_editor2 .se2_qeditor .se2_qbody{position:relative;z-index:90;width:264px;padding:4px 0 0 7px} +#smart_editor2 .se2_qeditor .se2_qe1{overflow:hidden;width:264px} +#smart_editor2 .se2_qeditor .se2_qe1 dt{float:left;width:27px;height:18px;padding:4px 0 0 0} +#smart_editor2 .se2_qeditor .se2_qe1 dd{float:left;width:95px;height:22px;margin-right:8px} +#smart_editor2 .se2_qeditor .se2_addrow{width:40px;height:19px;background:url("../../img/en_US/btn_set.png?160622") no-repeat -385px -49px} +#smart_editor2 .se2_qeditor .se2_addcol{width:55px;height:19px;background:url("../../img/en_US/btn_set.png?160622") no-repeat -425px -49px} +#smart_editor2 .se2_qeditor .se2_seprow{width:40px;height:19px;background:url("../../img/en_US/btn_set.png?160622") no-repeat -385px -68px} +#smart_editor2 .se2_qeditor .se2_sepcol{width:55px;height:19px;background:url("../../img/en_US/btn_set.png?160622") no-repeat -425px -68px} +#smart_editor2 .se2_qeditor .se2_delrow{width:40px;height:19px;background:url("../../img/en_US/btn_set.png?160622") no-repeat -385px -106px} +#smart_editor2 .se2_qeditor .se2_delcol{width:55px;height:19px;background:url("../../img/en_US/btn_set.png?160622") no-repeat -425px -106px} +#smart_editor2 .se2_qeditor .se2_merrow{width:76px;height:19px;background:url("../../img/en_US/btn_set.png?160622") no-repeat -385px -125px} +#smart_editor2 .se2_qeditor .se2_mercol{width:76px;height:19px;background:url("../../img/en_US/btn_set.png?160622") no-repeat -425px -125px} +#smart_editor2 .se2_qeditor .se2_seprow_off{width:40px;height:19px;background:url("../../img/en_US/btn_set.png?160622") no-repeat -385px -87px} +#smart_editor2 .se2_qeditor .se2_sepcol_off{width:55px;height:19px;background:url("../../img/en_US/btn_set.png?160622") no-repeat -425px -87px} +#smart_editor2 .se2_qeditor .se2_merrow_off{width:76px;height:19px;background:url("../../img/en_US/btn_set.png?160622") no-repeat -385px -144px} +#smart_editor2 .se2_qeditor .se2_mercol_off{width:76px;height:19px;background:url("../../img/en_US/btn_set.png?160622") no-repeat -425px -144px} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND */ +#smart_editor2 .se2_qeditor .se2_qe2{_display:inline;float:left;position:relative;z-index:100;width:255px;margin:2px 0 0 1px;padding:7px 0 0 0;background:url("../../img/bg_line1.gif") repeat-x;zoom:1} +#smart_editor2 .se2_qeditor .se2_qe2_1 dt{float:left;width:83px;padding:3px 0 0 0} +#smart_editor2 .se2_qeditor .se2_qe2_1 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qeditor .se2_qe2_1 dd{float:left;position:relative;zoom:1} +#smart_editor2 .se2_qeditor .se2_qe2_3{padding:7px 0 6px 0} +/* My글양식 없을때 */ +#smart_editor2 .se2_qeditor .se2_qe2_2{position:relative;_position:absolute} +#smart_editor2 .se2_qeditor .se2_qe2_2 dt{float:left;width:50px;padding:3px 0 0 13px} +#smart_editor2 .se2_qeditor .se2_qe2_2 dt input{width:15px;height:15px;margin:-1px 2px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qeditor .se2_qe2_2 dd{float:left} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > STYLE */ +#smart_editor2 .se2_table_set .se2_qbody .se2_t_proper2{float:left;*float:none;position:static;width:256px;margin:5px 0 0 1px} +#smart_editor2 .se2_qeditor .se2_qe3 dt{float:left;width:83px;padding:0} +#smart_editor2 .se2_qeditor .se2_qe3 dt label{font-weight:normal} +#smart_editor2 .se2_qeditor .se2_qe3 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qeditor .se2_qe3 dd .se2_qe3_table{position:relative} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND PREWVIEW */ +#smart_editor2 .se2_qeditor .se2_pre_color{float:left;width:18px;height:18px;border:1px solid #c7c7c7} +#smart_editor2 .se2_qeditor .se2_pre_color button{float:left;width:14px;height:14px;margin:2px 0 0 2px;padding:0} +#smart_editor2 .se2_qeditor .se2_pre_color button span{overflow:hidden;position:absolute;top:-10000px;left:-10000px;z-index:-100;width:0;height:0} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND LAYER */ +#smart_editor2 .se2_qeditor .se2_layer{float:left;clear:both;position:absolute;top:20px;left:0;margin:0;padding:0;border:1px solid #c7c7c7;border-top:1px solid #9a9a9a;background:#fafafa} +#smart_editor2 .se2_qeditor .se2_layer .se2_in_layer{float:left;margin:0;padding:0;border:1px solid #fff;background:#fafafa} +#smart_editor2 .se2_qeditor .se2_layer button{vertical-align:top} +#smart_editor2 .se2_qeditor .se2_layer .se2_pick_color li{position:relative} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND IMAGE */ +#smart_editor2 .se2_qeditor .se2_pre_bgimg{float:left;width:14px;height:14px;padding:2px;border:1px solid #c7c7c7} +#smart_editor2 .se2_qeditor .se2_qe2_2 button{width:16px;height:16px;background:url("../../img/en_US/btn_set.png?160622") 0 -261px no-repeat} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND IMAGE LAYER */ +#smart_editor2 .se2_cellimg_set{_display:inline;float:left;width:136px;margin:4px 3px 0 4px;padding-bottom:4px} +#smart_editor2 .se2_cellimg_set li{_display:inline;float:left;width:16px;height:16px;margin:0 1px 1px 0} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg0{background-position:-255px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg1{background-position:0 -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg2{background-position:-17px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg3{background-position:-34px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg4{background-position:-51px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg5{background-position:-68px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg6{background-position:-85px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg7{background-position:-102px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg8{background-position:-119px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg9{background-position:-136px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg10{background-position:-153px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg11{background-position:-170px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg12{background-position:-187px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg13{background-position:-204px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg14{background-position:-221px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg15{background-position:-238px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg16{background-position:-255px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg17{background-position:0 -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg18{background-position:-17px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg19{background-position:-34px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg20{background-position:-51px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg21{background-position:-68px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg22{background-position:-85px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg23{background-position:-102px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg24{background-position:-119px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg25{background-position:-136px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg26{background-position:-153px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg27{background-position:-170px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg28{background-position:-187px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg29{background-position:-204px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg30{background-position:-221px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg31{background-position:-238px -278px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg button{width:14px;height:14px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg1{background-position:-1px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg2{background-position:-18px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg3{background-position:-35px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg4{background-position:-52px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg5{background-position:-69px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg6{background-position:-86px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg7{background-position:-103px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg8{background-position:-120px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg9{background-position:-137px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg10{background-position:-154px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg11{background-position:-171px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg12{background-position:-188px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg13{background-position:-205px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg14{background-position:-222px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg15{background-position:-239px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg16{background-position:-256px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg17{background-position:-1px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg18{background-position:-18px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg19{background-position:-35px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg20{background-position:-52px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg21{background-position:-69px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg22{background-position:-86px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg23{background-position:-103px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg24{background-position:-120px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg25{background-position:-137px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg26{background-position:-154px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg27{background-position:-171px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg28{background-position:-188px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg29{background-position:-205px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg30{background-position:-222px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg31{background-position:-239px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg32{background-position:-256px -279px} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > MY REVIEW */ +#smart_editor2 .se2_btn_area{_display:inline;float:left;clear:both;width:166px;margin:5px 0 0 1px;padding:7px 0 6px 0;background:url("../../img/bg_line1.gif") repeat-x;text-align:center} +#smart_editor2 .se2_btn_area .se2_btn_save{width:97px;height:21px;background:url("../../img/en_US/btn_set.png?160622") -369px -163px no-repeat} +/* TEXT_TOOLBAR : QUICKEDITOR_IMAGE */ +#smart_editor2 .se2_qe10{width:166px;margin:0;*margin:-2px 0 0 0} +#smart_editor2 .se2_qe10 label{margin:0 1px 0 0;vertical-align:middle} +#smart_editor2 .se2_qe10 .se2_sheight{margin-left:4px} +#smart_editor2 .se2_qe10 .input_ty1{width:30px;height:13px;margin:0 0 1px 1px;padding:3px 4px 0 1px;font-size:11px;letter-spacing:0;text-align:right;vertical-align:middle} +#smart_editor2 .se2_qe10 .se2_sreset{width:41px;height:19px;margin-left:3px;background:url("../../img/en_US/btn_set.png?160622") -401px -184px no-repeat;vertical-align:middle} +#smart_editor2 .se2_qe10_1{margin-top:4px;padding:10px 0 3px;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_qe10_1 input{width:15px;height:15px;margin:-1px 3px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qe11{float:left;width:166px;margin:4px 0 0 0;padding:7px 0 2px 0;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_qe11_1{float:left;width:99px} +#smart_editor2 .se2_qe11_1 dt{float:left;width:56px;height:15px;padding:5px 0 0 0} +#smart_editor2 .se2_qe11_1 dd{float:left;position:relative;width:38px;height:20px} +#smart_editor2 .se2_qe11_1 .input_ty1{display:block;width:29px;height:15px;margin:0;*margin:-1px 0 1px 0;padding:3px 1px 0 5px;font-size:11px;letter-spacing:0;text-align:left} +#smart_editor2 .se2_qe11_1 .se2_add{position:absolute;top:2px;right:3px;width:13px;height:8px;background:url("../../img/en_US/btn_set.png?160622") -86px -54px no-repeat} +#smart_editor2 .se2_qe11_1 .se2_del{position:absolute;top:10px;right:3px;width:13px;height:8px;background:url("../../img/en_US/btn_set.png?160622") -86px -62px no-repeat} +#smart_editor2 .se2_qe11_2{float:left;width:67px} +#smart_editor2 .se2_qe11_2 dt{float:left;width:47px;margin:5px 0 0 0} +#smart_editor2 .se2_qe11_2 dd{float:left;position:relative;width:20px} +#smart_editor2 .se2_qe12{float:left;width:166px;margin:3px 0 0 0;padding:7px 0 0 0;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_qe12 dt{float:left;margin:5px 4px 0 0} +#smart_editor2 .se2_qe12 dd{float:left;padding:0 0 6px 0} +#smart_editor2 .se2_qe12 .se2_align0{float:left;width:19px;height:21px;background:url("../../img/en_US/btn_set.png?160622") -276px -121px no-repeat} +#smart_editor2 .se2_qe12 .se2_align1{float:left;width:19px;height:21px;background:url("../../img/en_US/btn_set.png?160622") -295px -121px no-repeat} +#smart_editor2 .se2_qe12 .se2_align2{float:left;width:20px;height:21px;background:url("../../img/en_US/btn_set.png?160622") -314px -121px no-repeat} +#smart_editor2 .se2_qe13{position:relative;z-index:10;zoom:1} +#smart_editor2 .se2_qe13 dt{float:left;width:62px;padding:3px 0 0} +#smart_editor2 .se2_qe13 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle;zoom:1} +#smart_editor2 .se2_qe13 dt .se2_qdim2{width:32px} +#smart_editor2 .se2_qe13 dd .se2_select_ty1{width:38px} +#smart_editor2 .se2_qe13 dd .se2_select_ty1 span{width:15px} +#smart_editor2 .se2_qe13 dd .input_ty1{width:20px} +#smart_editor2 .se2_qe13 dd .se2_palette2 .input_ty1{width:67px} +#smart_editor2 .se2_qe13 .se2_add{*top:3px} +#smart_editor2 .se2_qe13 .se2_del{*top:11px} +#smart_editor2 .se2_qe13 .se2_layer_b_style{right:-2px;_right:0} +#smart_editor2 .se2_qe13 .se2_layer_b_style li span{width:auto;margin:0 4px 0 5px;padding-top:2px} +#smart_editor2 .se2_qe13 dd{_display:inline;float:left;position:relative;width:29px;margin-right:5px;_margin-right:3px;zoom:1} +#smart_editor2 .se2_qe13 dd .se2_palette h4{margin-top:9px;font-family:dotum;font-size:12px} +#smart_editor2 .se2_qe13 dd.dd_type{width:38px} +#smart_editor2 .se2_qe13 dd.dd_type2{width:37px;margin-right:3px} +#smart_editor2 .se2_qe13 dd.dd_type2 .input_ty1{width:29px} +#smart_editor2 .se2_qe13 dd.dd_type2 button{right:2px;_right:1px} +#smart_editor2 .se2_qe13 dd.dd_type3{width:20px;margin:0} +#smart_editor2 .se2_qe13_v1{_display:inline;float:left;margin:2px 0 1px} +#smart_editor2 .se2_qe13_v1 dt{padding:4px 0 0 1px} +#smart_editor2 .se2_qe13_v2{_display:inline;float:left;position:relative;z-index:100;width:165px;margin:4px 0 0 1px;zoom:1} +#smart_editor2 .se2_qe13_v2 dd{width:18px;margin:0} +#smart_editor2 .se2_qeditor .se2_qdim1{clear:both;position:absolute;top:25px;left:160px;width:76px;height:23px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim2{clear:both;position:absolute;top:55px;left:24px;z-index:110;width:92px;height:22px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim3{clear:both;position:absolute;top:55px;left:118px;z-index:110;width:56px;height:22px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim4{clear:both;position:absolute;top:81px;left:23px;z-index:35;width:140px;height:35px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim5{clear:both;position:absolute;top:31px;left:106px;width:68px;height:26px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim6c{clear:both;position:absolute;top:25px;left:34px;width:40px;height:23px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim6r{clear:both;position:absolute;top:25px;left:74px;width:57px;height:23px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_highedit{float:right;width:56px;height:21px;margin:-27px 8px 0 0;background:url("../../img/en_US/btn_set.png?160622") -329px -142px no-repeat} +#smart_editor2 .se2_qeditor .se2_qdim7{clear:both;position:absolute;top:55px;left:24px;z-index:110;width:150px;height:48px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim8{clear:both;position:absolute;top:105px;left:24px;z-index:110;width:150px;height:37px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim9{clear:both;position:absolute;top:55px;left:111px;z-index:110;width:65px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim10{clear:both;position:absolute;top:55px;left:100px;z-index:110;width:77px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim11{clear:both;position:absolute;top:55px;left:65px;z-index:110;width:115px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/en_US/smart_editor2_out.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/en_US/smart_editor2_out.css new file mode 100644 index 00000000..0baf3770 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/en_US/smart_editor2_out.css @@ -0,0 +1,12 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* COMMON */ +.se2_outputarea, .se2_outputarea th, .se2_outputarea td{margin:0;padding:0;color:#666;font-size:12px;font-family:'돋움',Dotum,'굴림',Gulim,Helvetica,Sans-serif;line-height:1.5} +.se2_outputarea p{margin:0;padding:0} +.se2_outputarea a:hover{text-decoration:underline} +.se2_outputarea a:link{color:#0000ff} +.se2_outputarea ul{margin:0 0 0 40px;padding:0} +.se2_outputarea ul li{margin:0;list-style-type:disc;padding:0} +.se2_outputarea ul ul li{list-style-type:circle} +.se2_outputarea ul ul ul li{list-style-type:square} +.se2_outputarea img, .se2_outputarea fieldset{border:0} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/ja_JP/smart_editor2.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/ja_JP/smart_editor2.css new file mode 100644 index 00000000..739b6bf2 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/ja_JP/smart_editor2.css @@ -0,0 +1,190 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* COMMON */ +body,#smart_editor2,#smart_editor2 p,#smart_editor2 h1,#smart_editor2 h2,#smart_editor2 h3,#smart_editor2 h4,#smart_editor2 h5,#smart_editor2 h6,#smart_editor2 ul,#smart_editor2 ol,#smart_editor2 li,#smart_editor2 dl,#smart_editor2 dt,#smart_editor2 dd,#smart_editor2 table,#smart_editor2 th,#smart_editor2 td,#smart_editor2 form,#smart_editor2 fieldset,#smart_editor2 legend,#smart_editor2 input,#smart_editor2 textarea,#smart_editor2 button,#smart_editor2 select{margin:0;padding:0} +#smart_editor2,#smart_editor2 h1,#smart_editor2 h2,#smart_editor2 h3,#smart_editor2 h4,#smart_editor2 h5,#smart_editor2 h6,#smart_editor2 input,#smart_editor2 textarea,#smart_editor2 select,#smart_editor2 table,#smart_editor2 button{font-family:'돋움',Dotum,Helvetica,sans-serif;font-size:12px;color:#666} +#smart_editor2 span,#smart_editor2 em{font-size:12px} +#smart_editor2 em,#smart_editor2 address{font-style:normal} +#smart_editor2 img,#smart_editor2 fieldset{border:0} +#smart_editor2 hr{display:none} +#smart_editor2 ol,#smart_editor2 ul{list-style:none} +#smart_editor2 button{border:0;background:none;font-size:11px;vertical-align:top;cursor:pointer} +#smart_editor2 button span,#smart_editor2 button em{visibility:hidden;overflow:hidden;position:absolute;top:0;font-size:0;line-height:0} +#smart_editor2 legend,#smart_editor2 .blind{visibility:hidden;overflow:hidden;position:absolute;width:0;height:0;font-size:0;line-height:0} +#smart_editor2 .input_ty1{height:14px;margin:0;padding:4px 2px 0 4px;border:1px solid #c7c7c7;font-size:11px;color:#666} +#smart_editor2 a:link,#smart_editor2 a:visited,#smart_editor2 a:active,#smart_editor2 a:focus{color:#666;text-decoration:none} +#smart_editor2 a:hover{color:#666;text-decoration:underline} +/* LAYOUT */ +#smart_editor2 .se2_header{margin:10px 0 29px 0} +#smart_editor2 .se2_bi{float:left;width:93px;height:20px;margin:0;padding:0;background:url("../../img/ja_JP/btn_set.png?160622") -343px -358px no-repeat;font-size:0;line-height:0;text-indent:-10000px;vertical-align:middle} +#smart_editor2 .se2_allhelp{display:inline-block;width:18px;height:18px;padding:0;background:url("../../img/ja_JP/btn_set.png?160622") -437px -358px no-repeat;font-size:0;line-height:0;text-indent:-10000px;vertical-align:middle} +#smart_editor2 #smart_editor2_content{position:relative;border:1px solid #b5b5b5} +#smart_editor2 .se2_tool{overflow:visible;position:relative;z-index:25} +/* EDITINGAREA */ +#smart_editor2 .se2_input_area{position:relative;z-index:22;height:400px;margin:0;padding:0;*zoom:1} +#smart_editor2 .se2_input_wysiwyg,#smart_editor2 .se2_input_syntax{display:block;overflow:auto;width:100%;height:100%;margin:0;*margin:-1px 0 0 0;border:0} +/* EDITINGMODE */ +#smart_editor2 .se2_conversion_mode{position:relative;height:15px;padding-top:1px;border-top:1px solid #b5b5b5;background:url("../../img/icon_set.gif?141007") 0 -896px repeat-x} +#smart_editor2 .se2_inputarea_controller{display:block;clear:both;position:relative;width:100%;height:15px;background:url("../../img/icon_set.gif?141007") center -47px no-repeat;text-align:center;cursor:n-resize} +#smart_editor2 .se2_inputarea_controller span{display:block;visibility:visible;height:15px;font-size:0;line-height:0;color:#fff;white-space:nowrap} +#smart_editor2 .ly_controller{display:block;position:absolute;bottom:2px;left:50%;width:287px;margin-left:-148px;padding:8px 0 7px 9px;border:1px solid #827f7c;background:#fffdef} +#smart_editor2 .ly_controller p{color:#666;font-size:11px;letter-spacing:-1px;line-height:11px} +#smart_editor2 .ly_controller .bt_clse,#smart_editor2 .ly_controller .ic_arr{position:absolute;background:url("../../img/ico_extend.png") no-repeat} +#smart_editor2 .ly_controller .bt_clse{top:5px;right:4px;width:14px;height:15px;background-position:1px -43px} +#smart_editor2 .ly_controller .ic_arr{top:25px;left:50%;width:10px;height:6px;margin-left:-5px;background-position:0 -65px} +#smart_editor2 .se2_converter{float:left;position:absolute;top:-1px;right:3px;z-index:20} +#smart_editor2 .se2_converter li{float:left} +#smart_editor2 .se2_converter .se2_to_editor{width:59px;height:15px;background:url("../../img/ja_JP/btn_set.png?160622") 0 -85px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .se2_to_html{width:59px;height:15px;background:url("../../img/ja_JP/btn_set.png?160622") -59px -70px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .se2_to_text{width:60px;height:15px;background:url("../../img/ja_JP/btn_set.png?160622") -417px -466px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .active .se2_to_editor{width:59px;height:15px;background:url("../../img/ja_JP/btn_set.png?160622") 0 -70px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .active .se2_to_html{width:59px;height:15px;background:url("../../img/ja_JP/btn_set.png?160622") -59px -85px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .active .se2_to_text{width:60px;height:15px;background:url("../../img/ja_JP/btn_set.png?160622") -417px -481px no-repeat;vertical-align:top} +/* EDITINGAREA_HTMLSRC */ +#smart_editor2 .off .ico_btn,#smart_editor2 .off .se2_more,#smart_editor2 .off .se2_more2,#smart_editor2 .off .se2_font_family,#smart_editor2 .off .se2_font_size,#smart_editor2 .off .se2_bold,#smart_editor2 .off .se2_underline,#smart_editor2 .off .se2_italic,#smart_editor2 .off .se2_tdel,#smart_editor2 .off .se2_fcolor,#smart_editor2 .off .se2_fcolor_more,#smart_editor2 .off .se2_bgcolor,#smart_editor2 .off .se2_bgcolor_more,#smart_editor2 .off .se2_left,#smart_editor2 .off .se2_center,#smart_editor2 .off .se2_right,#smart_editor2 .off .se2_justify,#smart_editor2 .off .se2_ol,#smart_editor2 .off .se2_ul,#smart_editor2 .off .se2_indent,#smart_editor2 .off .se2_outdent,#smart_editor2 .off .se2_lineheight,#smart_editor2 .off .se2_del_style,#smart_editor2 .off .se2_blockquote,#smart_editor2 .off .se2_summary,#smart_editor2 .off .se2_footnote,#smart_editor2 .off .se2_url,#smart_editor2 .off .se2_emoticon,#smart_editor2 .off .se2_character,#smart_editor2 .off .se2_table,#smart_editor2 .off .se2_find,#smart_editor2 .off .se2_spelling,#smart_editor2 .off .se2_sup,#smart_editor2 .off .se2_sub,#smart_editor2 .off .se2_text_tool_more,#smart_editor2 .off .se2_new,#smart_editor2 .off .selected_color,#smart_editor2 .off .se2_lineSticker{-ms-filter:alpha(opacity=50);opacity:.5;cursor:default;filter:alpha(opacity=50)} +/* LAYER */ +#smart_editor2 .se2_text_tool .se2_layer{display:none;float:left;position:absolute;top:20px;left:0;z-index:50;margin:0;padding:0;border:1px solid #bcbbbb;background:#fafafa} +#smart_editor2 .se2_text_tool li.active{z-index:50} +#smart_editor2 .se2_text_tool .active .se2_layer{display:block} +#smart_editor2 .se2_text_tool .active li .se2_layer{display:none} +#smart_editor2 .se2_text_tool .active .active .se2_layer{display:block} +#smart_editor2 .se2_text_tool .se2_layer .se2_in_layer{float:left;margin:0;padding:0;border:1px solid #fff;background:#fafafa} +#smart_editor2 .se2_content_loading{display:none;z-index:10;position:absolute;top:0;left:0;width:100%;height:100%;text-align:center} +#smart_editor2 .se2_content_loading img{position:absolute;top:50%;left:50%;margin:-27px 0 0 -27px} +#smart_editor2 .se2_alert_wrap{display:none;z-index:20;position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;text-align:center} +#smart_editor2 .se2_alert_wrap.active{display:block} +#smart_editor2 .se2_alert_wrap .dimmed{position:absolute;top:0;left:0;width:100%;height:100%;background:#000;opacity:0.4;filter:alpha(opacity=40)} +#smart_editor2 .se2_alert_wrap .ie_cover{position:absolute;top:0;left:0;width:100%;height:100%;background:#fff;opacity:0;filter:alpha(opacity=0)} +#smart_editor2 .se2_alert_wrap .va_line{display:inline-block;height:100%;vertical-align:middle;*zoom:1} +#smart_editor2 .se2_alert_wrap .se2_alert_content{z-index:10;position:relative;display:inline-block;*display:inline;*zoom:1;border:1px solid #727272;background:#fff;padding:26px 33px 22px;vertical-align:middle} +#smart_editor2 .se2_alert_wrap .se2_alert_content{margin-top:47px} +#smart_editor2 .se2_alert_wrap .txt1{color:#333;line-height:18px} +#smart_editor2 .se2_alert_wrap .txt2{margin-top:3px;color:#999} +#smart_editor2 .se2_alert_wrap .btn_close,#smart_editor2 .se2_alert_btns button{background:url("../../img/ja_JP/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_alert_wrap .btn_close{z-index:10;position:absolute;top:7px;right:7px;width:11px;height:11px;background-position:-122px -32px;text-indent:-5000px} +#smart_editor2 .se2_alert_btns{margin-top:19px} +#smart_editor2 .se2_alert_btns button{display:inline;float:none;width:48px;height:27px} +#smart_editor2 .se2_alert_btns button + button{margin-left:10px} +#smart_editor2 .se2_alert_btns .se2_confirm{background-position:-369px -434px} +#smart_editor2 .se2_alert_btns .se2_cancel{background-position:-419px -434px} +/* TEXT_TOOLBAR */ +#smart_editor2 .se2_text_tool{position:relative;clear:both;z-index:30;padding:4px 0 4px 3px;background:#f4f4f4 url("../../img/bg_text_tool.gif") 0 0 repeat-x;border-bottom:1px solid #b5b5b5;*zoom:1} +#smart_editor2 .se2_text_tool:after{content:"";display:block;clear:both} +#smart_editor2 .se2_text_tool ul{float:left;display:inline;margin-right:3px;padding-left:1px;white-space:nowrap} +#smart_editor2 .se2_text_tool li{_display:inline;float:left;position:relative;z-index:30} +#smart_editor2 .se2_text_tool button,#smart_editor2 .se2_multy .se2_icon{width:21px;height:21px;background:url("../../img/ja_JP/text_tool_set.png?140317") no-repeat;vertical-align:top} +#smart_editor2 .se2_text_tool .se2_font_type{position:relative} +#smart_editor2 .se2_text_tool .se2_font_type li{margin-left:3px} +#smart_editor2 .se2_text_tool .se2_font_type button{text-align:left} +#smart_editor2 .se2_text_tool .se2_font_type button.se2_font_family span,#smart_editor2 .se2_text_tool .se2_font_type button.se2_font_size span{display:inline-block;visibility:visible;position:static;width:52px;height:20px;padding:0 0 0 6px;font-size:12px;line-height:20px;*line-height:22px;color:#333;*zoom:1} +#smart_editor2 .se2_text_tool .se2_multy{position:absolute;top:0;right:0;padding-left:0;margin-right:0;white-space:nowrap;border-left:1px solid #e0dedf} +#smart_editor2 .se2_text_tool .se2_multy .se2_mn{float:left;white-space:nowrap} +#smart_editor2 .se2_text_tool .se2_multy button{background-image:none;width:47px} +#smart_editor2 .se2_text_tool .se2_multy .se2_icon{display:inline-block;visibility:visible;overflow:visible;position:static;width:16px;height:29px;margin:-1px 2px 0 -1px;background-position:0 -132px;line-height:30px;vertical-align:top} +#smart_editor2 .se2_text_tool .se2_multy button,#smart_editor2 .se2_text_tool .se2_multy button span{height:29px;line-height:29px} +#smart_editor2 .se2_text_tool .se2_map .se2_icon{background-position:-29px -132px} +#smart_editor2 .se2_text_tool button span.se2_mntxt{display:inline-block;visibility:visible;overflow:visible;_overflow-y:hidden;position:relative;*margin-right:-1px;width:auto;height:29px;font-weight:normal;font-size:11px;line-height:30px;*line-height:29px;_line-height:30px;color:#444;letter-spacing:-1px;vertical-align:top} +#smart_editor2 .se2_text_tool .se2_multy .se2_photo{margin-right:1px} +#smart_editor2 .se2_text_tool .se2_multy .hover .ico_btn{background:#e8e8e8} +#smart_editor2 .se2_text_tool .se2_multy .se2_mn.hover{background:#e0dedf} +/* TEXT_TOOLBAR : ROUNDING */ +#smart_editor2 ul li.first_child button span.tool_bg, #smart_editor2 ul li.last_child button span.tool_bg, #smart_editor2 ul li.single_child button span.tool_bg{visibility:visible;height:21px} +#smart_editor2 ul li.first_child button span.tool_bg{left:-1px;width:3px;background:url("../../img/bg_button_left.gif?20121228") no-repeat} +#smart_editor2 ul li.last_child button span.tool_bg{right:0px;_right:-1px;width:2px;background:url("../../img/bg_button_right.gif") no-repeat} +#smart_editor2 ul li.single_child{padding-right:1px} +#smart_editor2 ul li.single_child button span.tool_bg{left:0;background:url("../../img/bg_button.gif?20121228") no-repeat;width:22px} +#smart_editor2 div.se2_text_tool ul li.hover button span.tool_bg{background-position:0 -21px} +#smart_editor2 div.se2_text_tool ul li.active button span.tool_bg, #smart_editor2 div.se2_text_tool ul li.active li.active button span.tool_bg{background-position:0 -42px} +#smart_editor2 div.se2_text_tool ul li.active li button span.tool_bg{background-position:0 0} +/* TEXT_TOOLBAR : SUB_MENU */ +#smart_editor2 .se2_sub_text_tool{display:none;position:absolute;top:20px;left:0;z-index:40;width:auto;height:29px;padding:0 4px 0 0;border:1px solid #b5b5b5;border-top:1px solid #9a9a9a;background:#f4f4f4} +#smart_editor2 .active .se2_sub_text_tool{display:block} +#smart_editor2 .se2_sub_text_tool ul{float:left;height:25px;margin:0;padding:4px 0 0 4px} +/* TEXT_TOOLBAR : SUB_MENU_SIZE */ +#smart_editor2 .se2_sub_step1{width:88px} +#smart_editor2 .se2_sub_step2{width:199px} +#smart_editor2 .se2_sub_step2_1{width:178px} +/* TEXT_TOOLBAR : BUTTON */ +#smart_editor2 .se2_text_tool .se2_font_family{width:70px;height:21px;background-position:0 -10px} +#smart_editor2 .se2_text_tool .hover .se2_font_family{background-position:0 -72px} +#smart_editor2 .se2_text_tool .active .se2_font_family{background-position:0 -103px} +#smart_editor2 .se2_text_tool .se2_font_size{width:45px;height:21px;background-position:-70px -10px} +#smart_editor2 .se2_text_tool .hover .se2_font_size{background-position:-70px -72px} +#smart_editor2 .se2_text_tool .active .se2_font_size{background-position:-70px -103px} +#smart_editor2 .se2_text_tool .se2_bold{background-position:-115px -10px} +#smart_editor2 .se2_text_tool .hover .se2_bold{background-position:-115px -72px} +#smart_editor2 .se2_text_tool .active .se2_bold{background-position:-115px -103px} +#smart_editor2 .se2_text_tool .se2_underline{background-position:-136px -10px} +#smart_editor2 .se2_text_tool .hover .se2_underline{background-position:-136px -72px} +#smart_editor2 .se2_text_tool .active .se2_underline{background-position:-136px -103px} +#smart_editor2 .se2_text_tool .se2_italic{background-position:-157px -10px} +#smart_editor2 .se2_text_tool .hover .se2_italic{background-position:-157px -72px} +#smart_editor2 .se2_text_tool .active .se2_italic{background-position:-157px -103px} +#smart_editor2 .se2_text_tool .se2_tdel{background-position:-178px -10px} +#smart_editor2 .se2_text_tool .hover .se2_tdel{background-position:-178px -72px} +#smart_editor2 .se2_text_tool .active .se2_tdel{background-position:-178px -103px} +#smart_editor2 .se2_text_tool .se2_fcolor{position:relative;background-position:-199px -10px} +#smart_editor2 .se2_text_tool .hover .se2_fcolor{background-position:-199px -72px} +#smart_editor2 .se2_text_tool .active .se2_fcolor{background-position:-199px -103px} +#smart_editor2 .se2_text_tool .se2_fcolor_more{background-position:-220px -10px;width:10px} +#smart_editor2 .se2_text_tool .hover .se2_fcolor_more{background-position:-220px -72px} +#smart_editor2 .se2_text_tool .active .se2_fcolor_more{background-position:-220px -103px} +#smart_editor2 .se2_text_tool .selected_color{position:absolute;top:14px;left:5px;width:11px;height:3px;font-size:0} +#smart_editor2 .se2_text_tool .se2_ol,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_ol{background-position:-345px -10px} +#smart_editor2 .se2_text_tool .se2_ul,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_ul{background-position:-366px -10px} +#smart_editor2 .se2_text_tool .hover .se2_ol,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_ol{background-position:-345px -72px} +#smart_editor2 .se2_text_tool .hover .se2_ul,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_ul{background-position:-366px -72px} +#smart_editor2 .se2_text_tool .active .se2_ol,#smart_editor2 .se2_text_tool .active .active .se2_ol{background-position:-345px -103px} +#smart_editor2 .se2_text_tool .active .se2_ul,#smart_editor2 .se2_text_tool .active .active .se2_ul{background-position:-366px -103px} +#smart_editor2 .se2_text_tool .se2_indent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_indent{background-position:-408px -10px} +#smart_editor2 .se2_text_tool .se2_outdent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_outdent{background-position:-387px -10px} +#smart_editor2 .se2_text_tool .hover .se2_indent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_indent{background-position:-408px -72px} +#smart_editor2 .se2_text_tool .hover .se2_outdent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_outdent{background-position:-387px -72px} +#smart_editor2 .se2_text_tool .active .se2_indent,#smart_editor2 .se2_text_tool .active .active .se2_indent{background-position:-408px -103px} +#smart_editor2 .se2_text_tool .active .se2_outdent,#smart_editor2 .se2_text_tool .active .active .se2_outdent{background-position:-387px -103px} +#smart_editor2 .se2_text_tool .se2_lineheight{background-position:-429px -10px} +#smart_editor2 .se2_text_tool .hover .se2_lineheight{background-position:-429px -72px} +#smart_editor2 .se2_text_tool .active .se2_lineheight{background-position:-429px -103px} +#smart_editor2 .se2_text_tool .se2_url{background-position:-513px -10px} +#smart_editor2 .se2_text_tool .hover .se2_url{background-position:-513px -72px} +#smart_editor2 .se2_text_tool .active .se2_url{background-position:-513px -103px} +#smart_editor2 .se2_text_tool .se2_bgcolor{position:relative;background-position:-230px -10px} +#smart_editor2 .se2_text_tool .hover .se2_bgcolor{background-position:-230px -72px} +#smart_editor2 .se2_text_tool .active .se2_bgcolor{background-position:-230px -103px} +#smart_editor2 .se2_text_tool .se2_bgcolor_more{background-position:-251px -10px;width:10px} +#smart_editor2 .se2_text_tool .hover .se2_bgcolor_more{background-position:-251px -72px} +#smart_editor2 .se2_text_tool .active .se2_bgcolor_more{background-position:-251px -103px} +#smart_editor2 .se2_text_tool .se2_left{background-position:-261px -10px} +#smart_editor2 .se2_text_tool .hover .se2_left{background-position:-261px -72px} +#smart_editor2 .se2_text_tool .active .se2_left{background-position:-261px -103px} +#smart_editor2 .se2_text_tool .se2_center{background-position:-282px -10px} +#smart_editor2 .se2_text_tool .hover .se2_center{background-position:-282px -72px} +#smart_editor2 .se2_text_tool .active .se2_center{background-position:-282px -103px} +#smart_editor2 .se2_text_tool .se2_right{background-position:-303px -10px} +#smart_editor2 .se2_text_tool .hover .se2_right{background-position:-303px -72px} +#smart_editor2 .se2_text_tool .active .se2_right{background-position:-303px -103px} +#smart_editor2 .se2_text_tool .se2_justify{background-position:-324px -10px} +#smart_editor2 .se2_text_tool .hover .se2_justify{background-position:-324px -72px} +#smart_editor2 .se2_text_tool .active .se2_justify{background-position:-324px -103px} +#smart_editor2 .se2_text_tool .se2_blockquote{background-position:-471px -10px} +#smart_editor2 .se2_text_tool .hover .se2_blockquote{background-position:-471px -72px} +#smart_editor2 .se2_text_tool .active .se2_blockquote{background-position:-471px -103px} +#smart_editor2 .se2_text_tool .se2_character{background-position:-555px -10px} +#smart_editor2 .se2_text_tool .hover .se2_character{background-position:-555px -72px} +#smart_editor2 .se2_text_tool .active .se2_character{background-position:-555px -103px} +#smart_editor2 .se2_text_tool .se2_table{background-position:-576px -10px} +#smart_editor2 .se2_text_tool .hover .se2_table{background-position:-576px -72px} +#smart_editor2 .se2_text_tool .active .se2_table{background-position:-576px -103px} +#smart_editor2 .se2_text_tool .se2_find{background-position:-597px -10px} +#smart_editor2 .se2_text_tool .hover .se2_find{background-position:-597px -72px} +#smart_editor2 .se2_text_tool .active .se2_find{background-position:-597px -103px} +#smart_editor2 .se2_text_tool .se2_sup{background-position:-660px -10px} +#smart_editor2 .se2_text_tool .hover .se2_sup{background-position:-660px -72px} +#smart_editor2 .se2_text_tool .active .se2_sup{background-position:-660px -103px} +#smart_editor2 .se2_text_tool .se2_sub{background-position:-681px -10px} +#smart_editor2 .se2_text_tool .hover .se2_sub{background-position:-681px -72px} +#smart_editor2 .se2_text_tool .active .se2_sub{background-position:-681px -103px} +#smart_editor2 .se2_text_tool .se2_text_tool_more{background-position:0 -41px;width:13px} +#smart_editor2 .se2_text_tool .se2_text_tool_more span.tool_bg{background:none} +#smart_editor2 .se2_text_tool .hover .se2_text_tool_more{background-position:-13px -41px} +#smart_editor2 .se2_text_tool .active .se2_text_tool_more{background-position:-26px -41px} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/ja_JP/smart_editor2_in.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/ja_JP/smart_editor2_in.css new file mode 100644 index 00000000..fdecc092 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/ja_JP/smart_editor2_in.css @@ -0,0 +1,24 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* COMMON */ +body,.se2_inputarea{margin:0;padding:0;font-family:'돋움',Dotum,Helvetica,Sans-serif;font-size:12px;line-height:1.5} +/* body,.se2_inputarea,.se2_inputarea th,.se2_inputarea td{margin:0;padding:0;font-family:'돋움',Dotum,Helvetica,Sans-serif;font-size:12px;line-height:1.5;color:#666} */ +.se2_inputarea p,.se2_inputarea br{margin:0;padding:0} +.se2_inputarea{margin:15px;word-wrap:break-word;*word-wrap:normal;*word-break:break-all} +.se2_inputarea td{word-break:break-all} +.se2_inputarea_890{width:741px;margin:20px 0 10px 64px} +.se2_inputarea_698{width:548px;margin:20px 0 10px 64px} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + .se2_inputarea td:empty:after,.se2_inputarea td > p:empty:after{content:"\00A0";line-height:1} +} +/* TEXT_TOOLBAR : QUOTE */ +.se2_quote1{margin:0 0 30px 20px;padding:0 8px;border-left:2px solid #ccc;color:#888} +.se2_quote2{margin:0 0 30px 13px;padding:0 8px 0 16px;background:url("../../img/bg_quote2.gif") 0 3px no-repeat;color:#888} +.se2_quote3{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #ccc;color:#888} +.se2_quote4{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #66b246;color:#888} +.se2_quote5{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #ccc;background:#fafafa;color:#888} +.se2_quote6{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #e5e5e5;color:#888} +.se2_quote7{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #66b246;color:#888} +.se2_quote8{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #e5e5e5;background:#fafafa;color:#888} +.se2_quote9{margin:0 0 30px;padding:12px 10px 11px;border:2px solid #e5e5e5;color:#888} +.se2_quote10{margin:0 0 30px;padding:12px 10px 11px;border:2px solid #e5e5e5;background:#fafafa;color:#888} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/ja_JP/smart_editor2_items.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/ja_JP/smart_editor2_items.css new file mode 100644 index 00000000..f3a58e6c --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/ja_JP/smart_editor2_items.css @@ -0,0 +1,447 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* TEXT_TOOLBAR : FONTNAME */ +#smart_editor2 .se2_tool .se2_l_font_fam{width:186px;margin:0;padding:0} +#smart_editor2 .se2_tool .se2_l_font_fam li{display:block;width:186px;height:21px;margin:0;padding:0;color:#333;cursor:pointer} +#smart_editor2 .se2_l_font_fam .hover,#smart_editor2 .se2_l_font_fam .active{background:#ebebeb} +#smart_editor2 .se2_l_font_fam button{width:184px;height:21px;margin:0;padding:2px 0 2px 0px;background:none;text-align:left} +#smart_editor2 .se2_l_font_fam button span{display:block;visibility:visible;overflow:visible;position:relative;top:auto;left:auto;width:auto;height:auto;margin:0 0 0 4px;padding:0;font-size:12px;line-height:normal;color:#333} +#smart_editor2 .se2_l_font_fam button span span{display:inline;visibility:visible;overflow:visible;width:auto;height:auto;margin:0 0 0 4px;font-family:Verdana;font-size:12px;line-height:14px;color:#888} +#smart_editor2 .se2_l_font_fam button span em{visibility:visible;overflow:auto;position:static;width:auto;height:auto;margin-right:-4px;font-size:12px;color:#888} +#smart_editor2 .se2_l_font_fam .se2_division{width:162px;height:2px !important;margin:1px 0 1px 0px;border:0;background:url("../../img/bg_line1.gif") 0 0 repeat-x;font-size:0;cursor:default} +/* TEXT_TOOLBAR : FONTSIZE */ +#smart_editor2 .se2_tool .se2_l_font_size{width:302px;margin:0;padding:0} +#smart_editor2 .se2_tool .se2_l_font_size li{width:302px;margin:0;padding:0;color:#333;cursor:pointer} +#smart_editor2 .se2_l_font_size .hover,#smart_editor2 .se2_l_font_size .active{background:#ebebeb} +#smart_editor2 .se2_l_font_size button{width:300px;height:auto;margin:0;padding:2px 0 1px 0px;*padding:4px 0 1px 0px;background:none;text-align:left} +#smart_editor2 .se2_l_font_size button span{display:block;visibility:visible;overflow:visible;position:relative;top:auto;left:auto;width:auto;height:auto;margin:0 0 0 4px;padding:0;line-height:normal;color:#373737;letter-spacing:0px} +#smart_editor2 .se2_l_font_size button span span{display:inline;margin:0 0 0 5px;padding:0} +#smart_editor2 .se2_l_font_size span em{visibility:visible;overflow:auto;position:static;width:auto;height:auto;color:#888} +/* TEXT_TOOLBAR : FONTCOLOR */ +#smart_editor2 .se2_palette{float:left;position:relative;width:225px;margin:0;padding:11px 0 10px 0} +#smart_editor2 .se2_palette .se2_pick_color{_display:inline;float:left;clear:both;width:205px;margin:0 0 0 11px;padding:0} +#smart_editor2 .se2_palette .se2_pick_color li{float:left;width:12px;height:12px;margin:0;padding:0} +#smart_editor2 .se2_palette .se2_pick_color li button{width:11px;height:11px;border:0} +#smart_editor2 .se2_palette .se2_pick_color li button span{display:block;visibility:visible;overflow:visible;position:absolute;top:1px;left:1px;width:11px;height:11px} +#smart_editor2 .se2_palette .se2_pick_color li button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0} +#smart_editor2 .se2_palette .se2_pick_color .hover button,#smart_editor2 .se2_palette .se2_pick_color .active button{width:11px;height:11px;border:1px solid #666} +#smart_editor2 .se2_palette .se2_pick_color .hover span,#smart_editor2 .se2_palette .se2_pick_color .active span{width:7px;height:7px;border:1px solid #fff} +#smart_editor2 .se2_palette .se2_view_more{_display:inline;float:left;width:46px;height:23px;margin:1px 0 0 1px;background:url("../../img/ja_JP/btn_set.png?160622") 0 -47px no-repeat} +#smart_editor2 .se2_palette .se2_view_more2{_display:inline;float:left;width:46px;height:23px;margin:1px 0 0 1px;background:url("../../img/ja_JP/btn_set.png?160622") 0 -24px no-repeat} +#smart_editor2 .se2_palette h4{_display:inline;float:left;width:203px;margin:9px 0 0 11px;padding:10px 0 4px 0;background:url("../../img/bg_line1.gif") repeat-x;font-weight:normal;font-size:12px;line-height:14px;color:#333;letter-spacing:-1px} +#smart_editor2 .se2_palette2{float:left;_float:none;width:214px;margin:9px 0 0 0;padding:11px 0 0 11px;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_palette2 .se2_color_set{float:left} +#smart_editor2 .se2_palette2 .se2_selected_color{_display:inline;float:left;width:83px;height:18px;margin:0;border:1px solid #c7c7c7;background:#fff} +#smart_editor2 .se2_palette2 .se2_selected_color span{_display:inline;float:left;width:79px;height:14px;margin:2px} +#smart_editor2 .se2_palette2 .input_ty1{_display:inline;float:left;width:67px;height:16px;margin:0 3px 0 3px;padding:2px 2px 0 4px;font-family:tahoma;font-size:11px} +#smart_editor2 .se2_palette2 button.se2_btn_insert{float:left;width:35px;height:21px;margin-left:2px;padding:0;background:url("../../img/ja_JP/btn_set.png?160622") -80px 0 no-repeat} +#smart_editor2 .se2_gradation1{float:left;_float:none;width:201px;height:128px;margin:4px 0 0 0;border:1px solid #c7c7c7;cursor:crosshair} +#smart_editor2 .se2_gradation2{float:left;_float:none;width:201px;height:10px;margin:4px 0 1px 0;border:1px solid #c7c7c7;cursor:crosshair} +/* TEXT_TOOLBAR : BGCOLOR */ +#smart_editor2 .se2_palette_bgcolor{width:225px;margin:11px 0 0;padding:0} +#smart_editor2 .se2_palette_bgcolor .se2_background{width:205px;margin:0 11px 0 11px} +#smart_editor2 .se2_palette_bgcolor .se2_background li{width:68px;height:20px} +#smart_editor2 .se2_palette_bgcolor .se2_background button{width:67px;height:19px;border:0} +#smart_editor2 .se2_palette_bgcolor .se2_background span{left:0;display:block;visibility:visible;overflow:visible;width:65px;height:17px;padding:0} +#smart_editor2 .se2_palette_bgcolor .se2_background span span{display:block;visibility:visible;overflow:visible;width:64px;height:16px;padding:3px 0 0 3px;font-size:11px;line-height:14px;text-align:left} +#smart_editor2 .se2_palette_bgcolor .se2_background .hover span{width:65px;height:17px;border:1px solid #666} +#smart_editor2 .se2_palette_bgcolor .se2_background .hover span span{width:62px;height:14px;padding:1px 0 0 1px;border:1px solid #fff} +/* TEXT_TOOLBAR : LINEHEIGHT */ +#smart_editor2 .se2_l_line_height{width:107px;margin:0;padding:0} +#smart_editor2 .se2_l_line_height li{width:107px;margin:0;padding:0;border-top:0;border-bottom:0;color:#333;cursor:pointer} +#smart_editor2 .se2_l_line_height .hover{background:#ebebeb} +#smart_editor2 .se2_l_line_height button{width:105px;height:19px;margin:0;padding:3px 0 2px 0px;background:none;text-align:left} +#smart_editor2 .se2_l_line_height button span{visibility:visible;overflow:visible;position:relative;width:auto;height:auto;margin:0;padding:0 0 0 15px;font-size:12px;line-height:normal;color:#373737} +#smart_editor2 .se2_l_line_height li button.active span{background:url("../../img/icon_set.gif?141007") 5px -30px no-repeat} +#smart_editor2 .se2_l_line_height_user{clear:both;width:83px;margin:5px 0 0 12px;padding:10px 0 0 0;_padding:11px 0 0 0;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_l_line_height_user h3{margin:0 0 4px 0;_margin:0 0 2px -1px;padding:0;line-height:14px;color:#000;letter-spacing:-1px} +#smart_editor2 .se2_l_line_height_user .bx_input{display:block;position:relative;width:83px} +#smart_editor2 .se2_l_line_height_user .btn_up{position:absolute;top:2px;*top:3px;left:68px;width:13px;height:8px;background:url("../../img/ja_JP/btn_set.png?160622") -86px -54px no-repeat} +#smart_editor2 .se2_l_line_height_user .btn_down{position:absolute;top:10px;*top:11px;left:68px;width:13px;height:8px;background:url("../../img/ja_JP/btn_set.png?160622") -86px -62px no-repeat} +#smart_editor2 .se2_l_line_height_user .btn_area{margin:5px 0 10px 0} +#smart_editor2 .se2_tool .btn_area .se2_btn_apply3{width:41px;height:24px;background:url("../../img/ja_JP/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_tool .btn_area .se2_btn_cancel3{width:39px;height:24px;margin-left:3px;background:url("../../img/ja_JP/btn_set.png?160622") -41px 0 no-repeat} +/* TEXT_TOOLBAR : QUOTE */ +#smart_editor2 .se2_quote{width:425px;height:56px} +#smart_editor2 .se2_quote ul{_display:inline;float:left;margin:11px 0 0 9px;padding:0} +#smart_editor2 .se2_quote li{_display:inline;float:left;margin:0 0 0 2px;padding:0} +#smart_editor2 .se2_quote button{width:34px;height:34px;margin:0;padding:0;background:url("../../img/ja_JP/btn_set.png?160622") no-repeat;cursor:pointer} +#smart_editor2 .se2_quote button span{left:0;display:block;visibility:visible;overflow:visible;width:32px;height:32px;margin:0;padding:0;border:1px solid #c7c7c7} +#smart_editor2 .se2_quote button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0} +#smart_editor2 .se2_quote .se2_quote1{background-position:1px -375px} +#smart_editor2 .se2_quote .se2_quote2{background-position:-32px -375px} +#smart_editor2 .se2_quote .se2_quote3{background-position:-65px -375px} +#smart_editor2 .se2_quote .se2_quote4{background-position:-98px -375px} +#smart_editor2 .se2_quote .se2_quote5{background-position:-131px -375px} +#smart_editor2 .se2_quote .se2_quote6{background-position:-164px -375px} +#smart_editor2 .se2_quote .se2_quote7{background-position:-197px -375px} +#smart_editor2 .se2_quote .se2_quote8{background-position:-230px -375px} +#smart_editor2 .se2_quote .se2_quote9{background-position:-263px -375px} +#smart_editor2 .se2_quote .se2_quote10{background-position:-296px -375px} +#smart_editor2 .se2_quote .hover button span,#smart_editor2 .se2_quote .active button span{width:30px;height:30px;margin:0;padding:0;border:2px solid #44b525} +#smart_editor2 .se2_quote .hover button span span,#smart_editor2 .se2_quote .active button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0} +#smart_editor2 .se2_quote .se2_cancel2{float:left;width:40px;height:35px;margin:11px 0 0 5px;background:url("../../img/ja_JP/btn_set.png?160622") -46px -24px no-repeat} +#smart_editor2 .se2_quote .se2_cancel2 span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0} +/* TEXT_TOOLBAR : HYPERLINK */ +#smart_editor2 .se2_url2{width:281px;padding:11px 11px 6px 11px;color:#666} +#smart_editor2 .se2_url2 .input_ty1{display:block;width:185px;height:16px;margin:0 5px 5px 0;*margin:-1px 5px 5px 0;padding:5px 2px 0 4px} +#smart_editor2 .se2_url2 .se2_url_new{width:15px;height:15px;margin:-1px 3px 1px -1px;*margin:-2px 3px 2px -1px;vertical-align:middle} +#smart_editor2 .se2_url2 label{font-size:11px;line-height:14px;vertical-align:middle} +#smart_editor2 .se2_url2 .se2_apply{position:absolute;top:13px;right:51px;width:41px;height:24px;margin:-1px 3px 1px 0;background:url("../../img/ja_JP/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_url2 .se2_cancel{position:absolute;top:13px;right:9px;width:39px;height:24px;margin:-1px 3px 1px 0;background:url("../../img/ja_JP/btn_set.png?160622") -41px 0 no-repeat} +/* TEXT_TOOLBAR : SCHARACTER */ +#smart_editor2 .se2_bx_character{width:469px;height:272px;margin:0;padding:0;background:url("../../img/bx_set_110302.gif") 9px -1230px no-repeat} +#smart_editor2 .se2_bx_character .se2_char_tab{_display:inline;float:left;position:relative;width:443px;margin:11px 10px 200px 11px;padding:0 0 0 1px} +#smart_editor2 .se2_bx_character .se2_char_tab li{position:static;margin:0 0 0 -1px;padding:0} +#smart_editor2 .se2_bx_character .se2_char1{width:72px;height:26px;background:url("../../img/ja_JP/btn_set.png?160622") 0 -204px no-repeat} +#smart_editor2 .se2_bx_character .se2_char2{width:84px;height:26px;background:url("../../img/ja_JP/btn_set.png?160622") -71px -204px no-repeat} +#smart_editor2 .se2_bx_character .se2_char3{width:67px;height:26px;background:url("../../img/ja_JP/btn_set.png?160622") -154px -204px no-repeat} +#smart_editor2 .se2_bx_character .se2_char4{width:62px;height:26px;background:url("../../img/ja_JP/btn_set.png?160622") -220px -204px no-repeat} +#smart_editor2 .se2_bx_character .se2_char5{width:104px;height:26px;background:url("../../img/ja_JP/btn_set.png?160622") -281px -204px no-repeat} +#smart_editor2 .se2_bx_character .se2_char6{width:59px;height:26px;background:url("../../img/ja_JP/btn_set.png?160622") -384px -204px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char1{width:72px;height:26px;background:url("../../img/ja_JP/btn_set.png?160622") 0 -230px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char2{width:84px;height:26px;background:url("../../img/ja_JP/btn_set.png?160622") -71px -230px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char3{width:67px;height:26px;background:url("../../img/ja_JP/btn_set.png?160622") -154px -230px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char4{width:62px;height:26px;background:url("../../img/ja_JP/btn_set.png?160622") -220px -230px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char5{width:104px;height:26px;background:url("../../img/ja_JP/btn_set.png?160622") -281px -230px no-repeat !important} +#smart_editor2 .se2_bx_character .active .se2_char6{width:59px;height:26px;background:url("../../img/ja_JP/btn_set.png?160622") -384px -230px no-repeat} +#smart_editor2 .se2_bx_character .se2_s_character{display:none;position:absolute;top:26px;left:0;width:448px;height:194px;margin:0;padding:0} +#smart_editor2 .se2_bx_character .active .se2_s_character{display:block} +#smart_editor2 .se2_bx_character .se2_s_character ul{float:left;width:422px;height:172px;margin:0;padding:9px 0 0 11px} +#smart_editor2 .se2_bx_character .se2_s_character li{_display:inline;float:left;position:relative;width:20px;height:18px;margin:0 0 1px 1px;background:#fff} +#smart_editor2 .se2_bx_character .se2_s_character button{width:20px;height:18px;margin:0;padding:2px;background:none} +#smart_editor2 .se2_bx_character .se2_s_character .hover,#smart_editor2 .se2_bx_character .se2_s_character .active{background:url("../../img/ja_JP/btn_set.png?160622") -446px -274px no-repeat} +#smart_editor2 .se2_bx_character .se2_s_character button span{left:0;display:block;visibility:visible;overflow:visible;width:14px;height:16px;margin:3px 0 0 3px;border:0;background:none;font-size:12px;line-height:normal} +#smart_editor2 .se2_apply_character{clear:both;position:relative;padding:0 0 0 11px} +#smart_editor2 .se2_apply_character label{margin:0 3px 0 0;font-size:12px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_apply_character .input_ty1{width:283px;height:17px;margin:-1px 5px 1px 0;padding:4px 0 0 5px;font-size:12px;color:#666;letter-spacing:0;vertical-align:middle} +#smart_editor2 .se2_apply_character .se2_confirm{width:41px;height:24px;margin-right:3px;background:url("../../img/ja_JP/btn_set.png?160622") no-repeat;vertical-align:middle} +#smart_editor2 .se2_apply_character .se2_cancel{width:39px;height:24px;background:url("../../img/ja_JP/btn_set.png?160622") -41px 0 no-repeat;vertical-align:middle} +/* TEXT_TOOLBAR : TABLECREATOR */ +#smart_editor2 .se2_table_set{position:relative;width:166px;margin:3px 11px 0 11px;padding:8px 0 0 0} +#smart_editor2 .se2_table_set .se2_cell_num{float:left;width:73px} +#smart_editor2 .se2_table_set .se2_cell_num dt{float:left;clear:both;width:17px;height:23px;margin:0;padding:0} +#smart_editor2 .se2_table_set .se2_cell_num dt label{display:block;margin:5px 0 0 0;font-size:11px;color:#666} +#smart_editor2 .se2_table_set .se2_cell_num dd{float:left;position:relative;width:54px;height:23px;margin:0;padding:0} +#smart_editor2 .se2_table_set .se2_cell_num .input_ty2{display:block;width:32px;height:16px;*margin:-1px 0 0 0;padding:2px 19px 0 0px;border:1px solid #c7c7c7;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666;text-align:right;*direction:rtl} +#smart_editor2 .se2_table_set .se2_cell_num .input_ty2::-ms-clear{display:none} +#smart_editor2 .se2_table_set .se2_pre_table{float:right;width:91px;height:43px;background:#c7c7c7;border-spacing:1px} +#smart_editor2 .se2_table_set .se2_pre_table tr{background:#fff} +#smart_editor2 .se2_table_set .se2_pre_table td{font-size:0;line-height:0} +#smart_editor2 .se2_table_set .se2_add{position:absolute;top:2px;right:3px;width:13px;height:8px;background:url("../../img/ja_JP/btn_set.png?160622") -86px -54px no-repeat} +#smart_editor2 .se2_table_set .se2_del{position:absolute;top:10px;right:3px;width:13px;height:8px;background:url("../../img/ja_JP/btn_set.png?160622") -86px -62px no-repeat} +/* TEXT_TOOLBAR : TABLEEDITOR */ +#smart_editor2 .se2_table_set .se2_t_proper1{float:left;width:166px;margin:7px 0 0 0;padding:10px 0 5px;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_table_set .se2_t_proper1 dt{width:166px;margin:0 0 6px 0} +#smart_editor2 .se2_table_set .se2_t_proper1 dd{width:166px} +#smart_editor2 .se2_table_set .se2_t_proper1 dt input{width:15px;height:15px;margin:-1px 3px 1px 0;_margin:-2px 3px 2px 0;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper1 dt label{font-weight:bold;font-size:11px;color:#666;letter-spacing:-1px;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper1_1{float:left;position:relative;z-index:59;width:166px;margin:1px 0 0 0} +#smart_editor2 .se2_table_set .se2_t_proper1_2{z-index:54;margin:0} +#smart_editor2 .se2_table_set .se2_t_proper1_3{z-index:53;margin:0} +#smart_editor2 .se2_table_set .se2_t_proper1_4{z-index:52;margin:0} +#smart_editor2 .se2_table_set .se2_t_proper1_1 dt{_display:inline;float:left;clear:both;width:66px;height:22px;margin:1px 0 0 18px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 dt label{display:block;margin:4px 0 0 0;font-weight:normal;font-size:11px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 dd{float:left;position:relative;width:82px;height:23px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .input_ty1{width:72px;height:16px;*margin:-1px 0 0 0;padding:2px 2px 0 6px;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .input_ty3{float:left;width:49px;height:16px;margin:0 3px 0 0;padding:2px 4px 0 4px;border:1px solid #c7c7c7;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_add{top:2px;right:2px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_del{top:10px;right:2px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_color_set .input_ty1{_display:inline;float:left;width:67px;height:16px;margin:0 3px 0 3px;padding:2px 2px 0 4px;font-family:tahoma,verdana,times New Roman;font-size:11px} +#smart_editor2 .se2_select_ty1{position:relative;width:80px;height:18px;border:1px solid #c7c7c7;background:#fff;font-size:11px;line-height:14px;text-align:left} +#smart_editor2 .se2_select_ty1 span{float:left;width:54px;height:18px;margin:0 0 0 5px;font-size:11px;line-height:14px;color:#666} +#smart_editor2 .se2_select_ty1 .se2_b_style0{position:relative;top:3px;left:-3px;white-space:nowrap} +#smart_editor2 .se2_select_ty1 .se2_b_style1{height:15px;margin:3px 0 0 4px;font-size:11px;line-height:14px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_select_ty1 .se2_b_style2{background:url("../../img/bg_set.gif") 0 -50px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style3{background:url("../../img/bg_set.gif") 0 -68px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style4{background:url("../../img/bg_set.gif") 0 -85px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style5{background:url("../../img/bg_set.gif") 0 -103px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style6{background:url("../../img/bg_set.gif") 0 -121px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style7{background:url("../../img/bg_set.gif") 0 -139px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_view_more{position:absolute;top:1px;right:1px;width:13px;height:16px;background:url("../../img/ja_JP/btn_set.png?160622") -112px -54px no-repeat} +#smart_editor2 .se2_select_ty1 .se2_view_more2{position:absolute;top:1px;right:1px;width:13px;height:16px;background:url("../../img/ja_JP/btn_set.png?160622") -99px -54px no-repeat} +/* TEXT_TOOLBAR : TABLEEDITOR > BORDER */ +#smart_editor2 .se2_table_set .se2_b_t_b1{border-top:1px solid #b1b1b1} +#smart_editor2 .se2_layer_b_style{position:absolute;top:20px;right:0px;width:80px;padding-bottom:1px;border:1px solid #c7c7c7;border-top:1px solid #a8a8a8;background:#fff} +#smart_editor2 .se2_layer_b_style ul{width:80px;margin:0;padding:1px 0 0 0} +#smart_editor2 .se2_layer_b_style li{width:80px;height:18px;margin:0;padding:0} +#smart_editor2 .se2_layer_b_style .hover,#smart_editor2 .se2_layer_b_style .active{background:#ebebeb} +#smart_editor2 .se2_layer_b_style button{width:80px;height:18px;background:none} +#smart_editor2 .se2_layer_b_style button span{left:0;display:block;visibility:visible;overflow:visible;width:71px;height:18px;margin:0 0 0 5px;font-size:11px;line-height:15px;text-align:left} +#smart_editor2 .se2_layer_b_style button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0} +#smart_editor2 .se2_layer_b_style .se2_b_style1 span{margin:3px 0 0 4px;font-size:11px;line-height:14px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_layer_b_style .se2_b_style2 span{background:url("../../img/bg_set.gif") 0 -50px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style3 span{background:url("../../img/bg_set.gif") 0 -68px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style4 span{background:url("../../img/bg_set.gif") 0 -86px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style5 span{background:url("../../img/bg_set.gif") 0 -103px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style6 span{background:url("../../img/bg_set.gif") 0 -121px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style7 span{background:url("../../img/bg_set.gif") 0 -139px repeat-x} +/* TEXT_TOOLBAR : TABLEEDITOR > COLOR */ +#smart_editor2 .se2_pre_color{float:left;width:18px;height:18px;border:1px solid #c7c7c7} +#smart_editor2 .se2_pre_color button{float:left;width:14px;height:14px;margin:2px 0 0 2px;padding:0} +#smart_editor2 .se2_pre_color button span{overflow:hidden;position:absolute;top:-10000px;left:-10000px;z-index:-100;width:0;height:0} +/* TEXT_TOOLBAR : TABLEEDITOR > DIMMED */ +#smart_editor2 .se2_table_set .se2_t_dim1{clear:both;position:absolute;top:71px;left:16px;z-index:60;width:157px;height:118px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_table_set .se2_t_dim2{position:absolute;top:116px;left:16px;z-index:55;width:157px;height:45px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_table_set .se2_t_dim3{clear:both;position:absolute;top:192px;left:16px;z-index:51;width:157px;height:39px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +/* TEXT_TOOLBAR : TABLEEDITOR > STYLE PREVIEW */ +#smart_editor2 .se2_table_set .se2_t_proper2{float:left;position:relative;z-index:50;width:166px;margin:2px 0 0 0} +#smart_editor2 .se2_table_set .se2_t_proper2 dt{float:left;width:90px;height:33px;margin:4px 0 0 0} +#smart_editor2 .se2_table_set .se2_t_proper2 dt input{width:15px;height:15px;margin:-1px 3px 1px 0;_margin:-2px 3px 2px 0;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper2 dt label{font-weight:bold;font-size:11px;color:#666;letter-spacing:-1px;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper2 dd{float:left;width:66px;height:33px} +#smart_editor2 .se2_select_ty2{position:relative;width:65px;height:31px;border:1px solid #c7c7c7;background:#fff;font-size:11px;line-height:14px;text-align:left} +#smart_editor2 .se2_select_ty2 span{float:left;width:45px;height:25px;margin:3px 0 0 3px;background:url("../../img/ja_JP/btn_set.png?160622") repeat-x} +#smart_editor2 .se2_select_ty2 .se2_t_style1{background-position:0 -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style2{background-position:-46px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style3{background-position:-92px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style4{background-position:-138px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style5{background-position:-184px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style6{background-position:-230px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style7{background-position:-276px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style8{background-position:-322px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style9{background-position:0 -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style10{background-position:-46px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style11{background-position:-92px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style12{background-position:-138px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style13{background-position:-184px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style14{background-position:-230px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style15{background-position:-276px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style16{background-position:-322px -436px} +#smart_editor2 .se2_select_ty2 .se2_view_more{position:absolute;top:1px;right:1px;_right:0px;width:13px !important;height:29px !important;background:url("../../img/ja_JP/btn_set.png?160622") -353px -48px no-repeat !important} +#smart_editor2 .se2_select_ty2 .se2_view_more2{position:absolute;top:1px;right:1px;_right:0px;width:13px !important;height:29px !important;background:url("../../img/ja_JP/btn_set.png?160622") -340px -48px no-repeat !important} +#smart_editor2 .se2_select_ty2 .se2_view_more span{display:none} +/* TEXT_TOOLBAR : TABLEEDITOR > STYLE */ +#smart_editor2 .se2_layer_t_style{position:absolute;top:33px;right:15px;width:208px;border:1px solid #c7c7c7;border-top:1px solid #a8a8a8;background:#fff} +#smart_editor2 .se2_layer_t_style ul{width:204px;height:126px;margin:1px 2px;padding:1px 0 0 0;background:#fff} +#smart_editor2 .se2_layer_t_style li{_display:inline;float:left;width:45px;height:25px;margin:1px;padding:1px;border:1px solid #fff} +#smart_editor2 .se2_layer_t_style .hover,#smart_editor2 .se2_layer_t_style .active{border:1px solid #666;background:#fff} +#smart_editor2 .se2_layer_t_style button{width:45px;height:25px;background:url("../../img/ja_JP/btn_set.png?160622") repeat-x !important} +#smart_editor2 .se2_layer_t_style .se2_t_style1{background-position:0 -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style2{background-position:-46px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style3{background-position:-92px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style4{background-position:-138px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style5{background-position:-184px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style6{background-position:-230px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style7{background-position:-276px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style8{background-position:-322px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style9{background-position:0 -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style10{background-position:-46px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style11{background-position:-92px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style12{background-position:-138px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style13{background-position:-184px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style14{background-position:-230px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style15{background-position:-276px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style16{background-position:-322px -436px !important} +#smart_editor2 .se2_table_set .se2_btn_area{float:left;width:166px;margin:6px 0 0 0;padding:12px 0 8px 0;background:url("../../img/bg_line1.gif") repeat-x;text-align:center} +#smart_editor2 .se2_table_set button.se2_apply{width:41px;height:24px;margin-right:3px;background:url("../../img/ja_JP/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_table_set button.se2_cancel{width:39px;height:24px;background:url("../../img/ja_JP/btn_set.png?160622") -41px 0 no-repeat} +#smart_editor2 .se2_table_set .se2_rd{width:14px;height:14px;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_celltit{font-size:11px;font-size:11px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_table_set dt label.se2_celltit{display:inline} +/* TEXT_TOOLBAR : FINDREPLACE */ +#smart_editor2 .se2_bx_find_revise{position:relative;width:255px;margin:0;padding:0} +#smart_editor2 .se2_bx_find_revise .se2_close{position:absolute;top:5px;right:8px;width:20px;height:20px;background:url("../../img/ja_JP/btn_set.png?160622") -151px -1px no-repeat} +#smart_editor2 .se2_bx_find_revise h3{margin:0;padding:10px 0 13px 10px;background:url("../../img/bg_find_h3.gif") 0 -1px repeat-x;font-size:12px;line-height:14px;letter-spacing:-1px} +#smart_editor2 .se2_bx_find_revise ul{position:relative;margin:8px 0 0 0;padding:0 0 0 12px} +#smart_editor2 .se2_bx_find_revise ul li{_display:inline;float:left;position:static;margin:0 0 0 -1px;padding:0} +#smart_editor2 .se2_bx_find_revise .se2_tabfind{width:117px;height:26px;background:url("../../img/ja_JP/btn_set.png?160622") 0 -100px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_tabrevise{width:117px;height:26px;background:url("../../img/ja_JP/btn_set.png?160622") -116px -100px no-repeat} +#smart_editor2 .se2_bx_find_revise .active .se2_tabfind{width:117px;height:26px;background:url("../../img/ja_JP/btn_set.png?160622") 0 -126px no-repeat} +#smart_editor2 .se2_bx_find_revise .active .se2_tabrevise{width:117px;height:26px;background:url("../../img/ja_JP/btn_set.png?160622") -116px -126px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_in_bx_find dl{_display:inline;float:left;width:223px;margin:0 0 0 9px;padding:7px 0 13px 14px;background:url("../../img/bx_set_110302.gif") -289px -1518px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_in_bx_revise dl{_display:inline;float:left;width:223px;margin:0 0 0 9px;padding:7px 0 13px 14px;background:url("../../img/bx_set_110302.gif") -289px -1619px no-repeat} +#smart_editor2 .se2_bx_find_revise dt{_display:inline;float:left;clear:both;width:60px;margin:1px 0 2px 0} +#smart_editor2 .se2_bx_find_revise dd{float:left;margin:0 0 2px 0} +#smart_editor2 .se2_bx_find_revise label{float:left;padding:5px 0 0 0;font-size:11px;color:#666;letter-spacing:-2px} +#smart_editor2 .se2_bx_find_revise input{float:left;width:145px;height:12px;margin:1px 0 0 0;padding:3px 2px 3px 4px;font-size:12px;color:#666} +#smart_editor2 .se2_bx_find_revise .se2_find_btns{float:left;clear:both;width:255px;padding:8px 0 10px 0;text-align:center} +#smart_editor2 .se2_bx_find_revise .se2_find_next{width:65px;height:24px;margin:0 3px 0 0;background:url("../../img/ja_JP/btn_set.png?160622") -180px -48px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_find_next2{width:61px;height:24px;margin:0 3px 0 0;background:url("../../img/ja_JP/btn_set.png?160622") -180px -24px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_revise1{width:54px;height:24px;margin:0 3px 0 0;background:url("../../img/ja_JP/btn_set.png?160622") -245px -48px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_revise2{width:70px;height:24px;margin:0 3px 0 0;background:url("../../img/ja_JP/btn_set.png?160622") -245px -24px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_cancel{width:39px;height:24px;background:url("../../img/ja_JP/btn_set.png?160622") -41px 0 no-repeat} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE */ +#smart_editor2 .se2_qmax{position:absolute;width:18px;height:18px;background:url("../../img/ja_JP/btn_set.png?160622") -339px -169px no-repeat} +#smart_editor2 .se2_qeditor{position:absolute;top:0;left:0;width:183px;margin:0;padding:0;border:1px solid #c7c7c7;border-right:1px solid #ababab;border-bottom:1px solid #ababab;background:#fafafa} +#smart_editor2 .se2_qeditor label,#smart_editor2 .se2_qeditor span,#smart_editor2 .se2_qeditor dt{font-size:11px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_qbar{position:relative;width:183px;height:11px;background:url("../../img/bx_set_110302.gif") 0 -731px no-repeat} +#smart_editor2 .se2_qbar .se2_qmini{position:absolute;top:-1px;right:0;*right:-1px;_right:-3px;width:18px;height:14px;background:url("../../img/ja_JP/btn_set.png?160622") -315px -170px no-repeat} +#smart_editor2 .se2_qbar .se2_qmini button{width:20px;height:14px;margin-top:-1px} +#smart_editor2 .se2_qeditor .se2_qbody0{float:left;border:1px solid #fefefe} +#smart_editor2 .se2_qeditor .se2_qbody{position:relative;z-index:90;width:174px;padding:4px 0 0 7px} +#smart_editor2 .se2_qeditor .se2_qe1{overflow:hidden;width:174px} +#smart_editor2 .se2_qeditor .se2_qe1 dt{float:left;width:22px;height:18px;padding:4px 0 0 0} +#smart_editor2 .se2_qeditor .se2_qe1 dd{float:left;width:65px;height:22px} +#smart_editor2 .se2_qeditor .se2_addrow{width:28px;height:19px;background:url("../../img/ja_JP/btn_set.png?160622") no-repeat -385px -49px} +#smart_editor2 .se2_qeditor .se2_addcol{width:29px;height:19px;background:url("../../img/ja_JP/btn_set.png?160622") no-repeat -413px -49px} +#smart_editor2 .se2_qeditor .se2_seprow{width:28px;height:19px;background:url("../../img/ja_JP/btn_set.png?160622") no-repeat -385px -68px} +#smart_editor2 .se2_qeditor .se2_sepcol{width:29px;height:19px;background:url("../../img/ja_JP/btn_set.png?160622") no-repeat -413px -68px} +#smart_editor2 .se2_qeditor .se2_delrow{width:28px;height:19px;background:url("../../img/ja_JP/btn_set.png?160622") no-repeat -385px -106px} +#smart_editor2 .se2_qeditor .se2_delcol{width:29px;height:19px;background:url("../../img/ja_JP/btn_set.png?160622") no-repeat -413px -106px} +#smart_editor2 .se2_qeditor .se2_merrow{width:57px;height:19px;background:url("../../img/ja_JP/btn_set.png?160622") no-repeat -385px -125px} +#smart_editor2 .se2_qeditor .se2_mercol{width:57px;height:19px;background:url("../../img/ja_JP/btn_set.png?160622") no-repeat -413px -125px} +#smart_editor2 .se2_qeditor .se2_seprow_off{width:28px;height:19px;background:url("../../img/ja_JP/btn_set.png?160622") no-repeat -385px -87px} +#smart_editor2 .se2_qeditor .se2_sepcol_off{width:29px;height:19px;background:url("../../img/ja_JP/btn_set.png?160622") no-repeat -413px -87px} +#smart_editor2 .se2_qeditor .se2_merrow_off{width:57px;height:19px;background:url("../../img/ja_JP/btn_set.png?160622") no-repeat -385px -144px} +#smart_editor2 .se2_qeditor .se2_mercol_off{width:57px;height:19px;background:url("../../img/ja_JP/btn_set.png?160622") no-repeat -413px -144px} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND */ +#smart_editor2 .se2_qeditor .se2_qe2{_display:inline;float:left;position:relative;z-index:100;width:165px;margin:2px 0 0 1px;padding:7px 0 0 0;background:url("../../img/bg_line1.gif") repeat-x;zoom:1} +#smart_editor2 .se2_qeditor .se2_qe2_1 dt{float:left;width:69px;padding:3px 0 0 0} +#smart_editor2 .se2_qeditor .se2_qe2_1 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qeditor .se2_qe2_1 dd{float:left;position:relative;zoom:1} +#smart_editor2 .se2_qeditor .se2_qe2_3{padding:7px 0 6px 0} +/* My글양식 없을때 */ +#smart_editor2 .se2_qeditor .se2_qe2_2{position:relative;_position:absolute} +#smart_editor2 .se2_qeditor .se2_qe2_2 dt{float:left;width:50px;padding:3px 0 0 13px} +#smart_editor2 .se2_qeditor .se2_qe2_2 dt input{width:15px;height:15px;margin:-1px 2px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qeditor .se2_qe2_2 dd{float:left} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > STYLE */ +#smart_editor2 .se2_table_set .se2_qbody .se2_t_proper2{float:left;*float:none;position:static;width:166px;margin:5px 0 0 1px} +#smart_editor2 .se2_qeditor .se2_qe3 dt{float:left;width:69px;padding:0} +#smart_editor2 .se2_qeditor .se2_qe3 dt label{font-weight:normal} +#smart_editor2 .se2_qeditor .se2_qe3 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qeditor .se2_qe3 dd .se2_qe3_table{position:relative} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND PREWVIEW */ +#smart_editor2 .se2_qeditor .se2_pre_color{float:left;width:18px;height:18px;border:1px solid #c7c7c7} +#smart_editor2 .se2_qeditor .se2_pre_color button{float:left;width:14px;height:14px;margin:2px 0 0 2px;padding:0} +#smart_editor2 .se2_qeditor .se2_pre_color button span{overflow:hidden;position:absolute;top:-10000px;left:-10000px;z-index:-100;width:0;height:0} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND LAYER */ +#smart_editor2 .se2_qeditor .se2_layer{float:left;clear:both;position:absolute;top:20px;left:0;margin:0;padding:0;border:1px solid #c7c7c7;border-top:1px solid #9a9a9a;background:#fafafa} +#smart_editor2 .se2_qeditor .se2_layer .se2_in_layer{float:left;margin:0;padding:0;border:1px solid #fff;background:#fafafa} +#smart_editor2 .se2_qeditor .se2_layer button{vertical-align:top} +#smart_editor2 .se2_qeditor .se2_layer .se2_pick_color li{position:relative} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND IMAGE */ +#smart_editor2 .se2_qeditor .se2_pre_bgimg{float:left;width:14px;height:14px;padding:2px;border:1px solid #c7c7c7} +#smart_editor2 .se2_qeditor .se2_qe2_2 button{width:16px;height:16px;background:url("../../img/ja_JP/btn_set.png?160622") 0 -261px no-repeat} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND IMAGE LAYER */ +#smart_editor2 .se2_cellimg_set{_display:inline;float:left;width:136px;margin:4px 3px 0 4px;padding-bottom:4px} +#smart_editor2 .se2_cellimg_set li{_display:inline;float:left;width:16px;height:16px;margin:0 1px 1px 0} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg0{background-position:-255px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg1{background-position:0 -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg2{background-position:-17px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg3{background-position:-34px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg4{background-position:-51px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg5{background-position:-68px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg6{background-position:-85px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg7{background-position:-102px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg8{background-position:-119px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg9{background-position:-136px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg10{background-position:-153px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg11{background-position:-170px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg12{background-position:-187px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg13{background-position:-204px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg14{background-position:-221px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg15{background-position:-238px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg16{background-position:-255px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg17{background-position:0 -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg18{background-position:-17px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg19{background-position:-34px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg20{background-position:-51px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg21{background-position:-68px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg22{background-position:-85px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg23{background-position:-102px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg24{background-position:-119px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg25{background-position:-136px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg26{background-position:-153px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg27{background-position:-170px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg28{background-position:-187px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg29{background-position:-204px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg30{background-position:-221px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg31{background-position:-238px -278px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg button{width:14px;height:14px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg1{background-position:-1px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg2{background-position:-18px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg3{background-position:-35px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg4{background-position:-52px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg5{background-position:-69px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg6{background-position:-86px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg7{background-position:-103px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg8{background-position:-120px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg9{background-position:-137px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg10{background-position:-154px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg11{background-position:-171px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg12{background-position:-188px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg13{background-position:-205px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg14{background-position:-222px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg15{background-position:-239px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg16{background-position:-256px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg17{background-position:-1px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg18{background-position:-18px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg19{background-position:-35px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg20{background-position:-52px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg21{background-position:-69px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg22{background-position:-86px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg23{background-position:-103px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg24{background-position:-120px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg25{background-position:-137px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg26{background-position:-154px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg27{background-position:-171px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg28{background-position:-188px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg29{background-position:-205px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg30{background-position:-222px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg31{background-position:-239px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg32{background-position:-256px -279px} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > MY REVIEW */ +#smart_editor2 .se2_btn_area{_display:inline;float:left;clear:both;width:166px;margin:5px 0 0 1px;padding:7px 0 6px 0;background:url("../../img/bg_line1.gif") repeat-x;text-align:center} +#smart_editor2 .se2_btn_area .se2_btn_save{width:97px;height:21px;background:url("../../img/ja_JP/btn_set.png?160622") -369px -163px no-repeat} +/* TEXT_TOOLBAR : QUICKEDITOR_IMAGE */ +#smart_editor2 .se2_qe10{width:166px;margin:0;*margin:-2px 0 0 0} +#smart_editor2 .se2_qe10 label{margin:0 1px 0 0;vertical-align:middle} +#smart_editor2 .se2_qe10 .se2_sheight{margin-left:4px} +#smart_editor2 .se2_qe10 .input_ty1{width:30px;height:13px;margin:0 0 1px 1px;padding:3px 4px 0 1px;font-size:11px;letter-spacing:0;text-align:right;vertical-align:middle} +#smart_editor2 .se2_qe10 .se2_sreset{width:41px;height:19px;margin-left:3px;background:url("../../img/ja_JP/btn_set.png?160622") -401px -184px no-repeat;vertical-align:middle} +#smart_editor2 .se2_qe10_1{margin-top:4px;padding:10px 0 3px;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_qe10_1 input{width:15px;height:15px;margin:-1px 3px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qe11{float:left;width:166px;margin:4px 0 0 0;padding:7px 0 2px 0;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_qe11_1{float:left;width:99px} +#smart_editor2 .se2_qe11_1 dt{float:left;width:56px;height:15px;padding:5px 0 0 0} +#smart_editor2 .se2_qe11_1 dd{float:left;position:relative;width:38px;height:20px} +#smart_editor2 .se2_qe11_1 .input_ty1{display:block;width:29px;height:15px;margin:0;*margin:-1px 0 1px 0;padding:3px 1px 0 5px;font-size:11px;letter-spacing:0;text-align:left} +#smart_editor2 .se2_qe11_1 .se2_add{position:absolute;top:2px;right:3px;width:13px;height:8px;background:url("../../img/ja_JP/btn_set.png?160622") -86px -54px no-repeat} +#smart_editor2 .se2_qe11_1 .se2_del{position:absolute;top:10px;right:3px;width:13px;height:8px;background:url("../../img/ja_JP/btn_set.png?160622") -86px -62px no-repeat} +#smart_editor2 .se2_qe11_2{float:left;width:67px} +#smart_editor2 .se2_qe11_2 dt{float:left;width:47px;margin:5px 0 0 0} +#smart_editor2 .se2_qe11_2 dd{float:left;position:relative;width:20px} +#smart_editor2 .se2_qe12{float:left;width:166px;margin:3px 0 0 0;padding:7px 0 0 0;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_qe12 dt{float:left;margin:5px 4px 0 0} +#smart_editor2 .se2_qe12 dd{float:left;padding:0 0 6px 0} +#smart_editor2 .se2_qe12 .se2_align0{float:left;width:19px;height:21px;background:url("../../img/ja_JP/btn_set.png?160622") -276px -121px no-repeat} +#smart_editor2 .se2_qe12 .se2_align1{float:left;width:19px;height:21px;background:url("../../img/ja_JP/btn_set.png?160622") -295px -121px no-repeat} +#smart_editor2 .se2_qe12 .se2_align2{float:left;width:20px;height:21px;background:url("../../img/ja_JP/btn_set.png?160622") -314px -121px no-repeat} +#smart_editor2 .se2_qe13{position:relative;z-index:10;zoom:1} +#smart_editor2 .se2_qe13 dt{float:left;width:62px;padding:3px 0 0} +#smart_editor2 .se2_qe13 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle;zoom:1} +#smart_editor2 .se2_qe13 dt .se2_qdim2{width:32px} +#smart_editor2 .se2_qe13 dd .se2_select_ty1{width:38px} +#smart_editor2 .se2_qe13 dd .se2_select_ty1 span{width:15px} +#smart_editor2 .se2_qe13 dd .input_ty1{width:20px} +#smart_editor2 .se2_qe13 dd .se2_palette2 .input_ty1{width:67px} +#smart_editor2 .se2_qe13 .se2_add{*top:3px} +#smart_editor2 .se2_qe13 .se2_del{*top:11px} +#smart_editor2 .se2_qe13 .se2_layer_b_style{right:-2px;_right:0} +#smart_editor2 .se2_qe13 .se2_layer_b_style li span{width:auto;margin:0 4px 0 5px;padding-top:2px} +#smart_editor2 .se2_qe13 dd{_display:inline;float:left;position:relative;width:29px;margin-right:5px;_margin-right:3px;zoom:1} +#smart_editor2 .se2_qe13 dd .se2_palette h4{margin-top:9px;font-family:dotum;font-size:12px} +#smart_editor2 .se2_qe13 dd.dd_type{width:38px} +#smart_editor2 .se2_qe13 dd.dd_type2{width:37px;margin-right:3px} +#smart_editor2 .se2_qe13 dd.dd_type2 .input_ty1{width:29px} +#smart_editor2 .se2_qe13 dd.dd_type2 button{right:2px;_right:1px} +#smart_editor2 .se2_qe13 dd.dd_type3{width:20px;margin:0} +#smart_editor2 .se2_qe13_v1{_display:inline;float:left;margin:2px 0 1px} +#smart_editor2 .se2_qe13_v1 dt{padding:4px 0 0 1px} +#smart_editor2 .se2_qe13_v2{_display:inline;float:left;position:relative;z-index:100;width:165px;margin:4px 0 0 1px;zoom:1} +#smart_editor2 .se2_qe13_v2 dd{width:18px;margin:0} +#smart_editor2 .se2_qeditor .se2_qdim1{clear:both;position:absolute;top:25px;left:115px;width:60px;height:23px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim2{clear:both;position:absolute;top:55px;left:24px;z-index:110;width:74px;height:22px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim3{clear:both;position:absolute;top:55px;left:118px;z-index:110;width:56px;height:22px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim4{clear:both;position:absolute;top:81px;left:23px;z-index:35;width:123px;height:35px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim5{clear:both;position:absolute;top:31px;left:106px;width:68px;height:26px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim6c{clear:both;position:absolute;top:25px;left:28px;width:29px;height:23px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim6r{clear:both;position:absolute;top:25px;left:57px;width:29px;height:23px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_highedit{float:right;width:56px;height:21px;margin:-27px 8px 0 0;background:url("../../img/ja_JP/btn_set.png?160622") -329px -142px no-repeat} +#smart_editor2 .se2_qeditor .se2_qdim7{clear:both;position:absolute;top:55px;left:24px;z-index:110;width:150px;height:48px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim8{clear:both;position:absolute;top:105px;left:24px;z-index:110;width:150px;height:37px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim9{clear:both;position:absolute;top:55px;left:111px;z-index:110;width:65px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim10{clear:both;position:absolute;top:55px;left:100px;z-index:110;width:77px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim11{clear:both;position:absolute;top:55px;left:65px;z-index:110;width:115px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/ja_JP/smart_editor2_out.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/ja_JP/smart_editor2_out.css new file mode 100644 index 00000000..0baf3770 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/ja_JP/smart_editor2_out.css @@ -0,0 +1,12 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* COMMON */ +.se2_outputarea, .se2_outputarea th, .se2_outputarea td{margin:0;padding:0;color:#666;font-size:12px;font-family:'돋움',Dotum,'굴림',Gulim,Helvetica,Sans-serif;line-height:1.5} +.se2_outputarea p{margin:0;padding:0} +.se2_outputarea a:hover{text-decoration:underline} +.se2_outputarea a:link{color:#0000ff} +.se2_outputarea ul{margin:0 0 0 40px;padding:0} +.se2_outputarea ul li{margin:0;list-style-type:disc;padding:0} +.se2_outputarea ul ul li{list-style-type:circle} +.se2_outputarea ul ul ul li{list-style-type:square} +.se2_outputarea img, .se2_outputarea fieldset{border:0} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/ko_KR/smart_editor2.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/ko_KR/smart_editor2.css new file mode 100644 index 00000000..70e3e3ba --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/ko_KR/smart_editor2.css @@ -0,0 +1,193 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* COMMON */ +body,#smart_editor2,#smart_editor2 p,#smart_editor2 h1,#smart_editor2 h2,#smart_editor2 h3,#smart_editor2 h4,#smart_editor2 h5,#smart_editor2 h6,#smart_editor2 ul,#smart_editor2 ol,#smart_editor2 li,#smart_editor2 dl,#smart_editor2 dt,#smart_editor2 dd,#smart_editor2 table,#smart_editor2 th,#smart_editor2 td,#smart_editor2 form,#smart_editor2 fieldset,#smart_editor2 legend,#smart_editor2 input,#smart_editor2 textarea,#smart_editor2 button,#smart_editor2 select{margin:0;padding:0} +#smart_editor2,#smart_editor2 h1,#smart_editor2 h2,#smart_editor2 h3,#smart_editor2 h4,#smart_editor2 h5,#smart_editor2 h6,#smart_editor2 input,#smart_editor2 textarea,#smart_editor2 select,#smart_editor2 table,#smart_editor2 button{font-family:'돋움',Dotum,Helvetica,sans-serif;font-size:12px;color:#666} +#smart_editor2 span,#smart_editor2 em{font-size:12px} +#smart_editor2 em,#smart_editor2 address{font-style:normal} +#smart_editor2 img,#smart_editor2 fieldset{border:0} +#smart_editor2 hr{display:none} +#smart_editor2 ol,#smart_editor2 ul{list-style:none} +#smart_editor2 button{border:0;background:none;font-size:11px;vertical-align:top;cursor:pointer} +#smart_editor2 button span,#smart_editor2 button em{visibility:hidden;overflow:hidden;position:absolute;top:0;font-size:0;line-height:0} +#smart_editor2 legend,#smart_editor2 .blind{visibility:hidden;overflow:hidden;position:absolute;width:0;height:0;font-size:0;line-height:0} +#smart_editor2 .input_ty1{height:14px;margin:0;padding:4px 2px 0 4px;border:1px solid #c7c7c7;font-size:11px;color:#666} +#smart_editor2 a:link,#smart_editor2 a:visited,#smart_editor2 a:active,#smart_editor2 a:focus{color:#666;text-decoration:none} +#smart_editor2 a:hover{color:#666;text-decoration:underline} +/* LAYOUT */ +#smart_editor2 .se2_header{margin:10px 0 29px 0} +#smart_editor2 .se2_bi{float:left;width:93px;height:20px;margin:0;padding:0;background:url("../../img/ko_KR/btn_set.png?160622") -343px -358px no-repeat;font-size:0;line-height:0;text-indent:-10000px;vertical-align:middle} +#smart_editor2 .se2_allhelp{display:inline-block;width:18px;height:18px;padding:0;background:url("../../img/ko_KR/btn_set.png?160622") -437px -358px no-repeat;font-size:0;line-height:0;text-indent:-10000px;vertical-align:middle} +#smart_editor2 #smart_editor2_content{position:relative;border:1px solid #b5b5b5} +#smart_editor2 .se2_tool{overflow:visible;position:relative;z-index:25} +/* EDITINGAREA */ +#smart_editor2 .se2_input_area{position:relative;z-index:22;height:400px;margin:0;padding:0;*zoom:1} +#smart_editor2 .se2_input_wysiwyg,#smart_editor2 .se2_input_syntax{display:block;overflow:auto;width:100%;height:100%;margin:0;*margin:-1px 0 0 0;border:0} +/* EDITINGMODE */ +#smart_editor2 .se2_conversion_mode{position:relative;height:15px;padding-top:1px;border-top:1px solid #b5b5b5;background:url("../../img/icon_set.gif?141007") 0 -896px repeat-x} +#smart_editor2 .se2_inputarea_controller{display:block;clear:both;position:relative;width:100%;height:15px;text-align:center;cursor:n-resize} +#smart_editor2 .se2_inputarea_controller span,#smart_editor2 .controller_on span{background:url("../../img/ico_extend.png") no-repeat} +#smart_editor2 .se2_inputarea_controller span{position:static;display:inline-block;visibility:visible;overflow:hidden;height:15px;padding-left:11px;background-position:0 2px;color:#888;font-size:11px;letter-spacing:-1px;line-height:16px;white-space:nowrap} +* + html #smart_editor2 .se2_inputarea_controller span{line-height:14px} +#smart_editor2 .controller_on span{background-position:0 -21px;color:#249c04} +#smart_editor2 .ly_controller{display:block;position:absolute;bottom:2px;left:50%;width:287px;margin-left:-148px;padding:8px 0 7px 9px;border:1px solid #827f7c;background:#fffdef} +#smart_editor2 .ly_controller p{color:#666;font-size:11px;letter-spacing:-1px;line-height:11px} +#smart_editor2 .ly_controller .bt_clse,#smart_editor2 .ly_controller .ic_arr{position:absolute;background:url("../../img/ico_extend.png") no-repeat} +#smart_editor2 .ly_controller .bt_clse{top:5px;right:4px;width:14px;height:15px;background-position:1px -43px} +#smart_editor2 .ly_controller .ic_arr{top:25px;left:50%;width:10px;height:6px;margin-left:-5px;background-position:0 -65px} +#smart_editor2 .se2_converter{float:left;position:absolute;top:-1px;right:3px;z-index:20} +#smart_editor2 .se2_converter li{float:left} +#smart_editor2 .se2_converter .se2_to_editor{width:59px;height:15px;background:url("../../img/ko_KR/btn_set.png?160622") 0 -85px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .se2_to_html{width:59px;height:15px;background:url("../../img/ko_KR/btn_set.png?160622") -59px -70px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .se2_to_text{width:60px;height:15px;background:url("../../img/ko_KR/btn_set.png?160622") -417px -466px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .active .se2_to_editor{width:59px;height:15px;background:url("../../img/ko_KR/btn_set.png?160622") 0 -70px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .active .se2_to_html{width:59px;height:15px;background:url("../../img/ko_KR/btn_set.png?160622") -59px -85px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .active .se2_to_text{width:60px;height:15px;background:url("../../img/ko_KR/btn_set.png?160622") -417px -481px no-repeat;vertical-align:top} +/* EDITINGAREA_HTMLSRC */ +#smart_editor2 .off .ico_btn,#smart_editor2 .off .se2_more,#smart_editor2 .off .se2_more2,#smart_editor2 .off .se2_font_family,#smart_editor2 .off .se2_font_size,#smart_editor2 .off .se2_bold,#smart_editor2 .off .se2_underline,#smart_editor2 .off .se2_italic,#smart_editor2 .off .se2_tdel,#smart_editor2 .off .se2_fcolor,#smart_editor2 .off .se2_fcolor_more,#smart_editor2 .off .se2_bgcolor,#smart_editor2 .off .se2_bgcolor_more,#smart_editor2 .off .se2_left,#smart_editor2 .off .se2_center,#smart_editor2 .off .se2_right,#smart_editor2 .off .se2_justify,#smart_editor2 .off .se2_ol,#smart_editor2 .off .se2_ul,#smart_editor2 .off .se2_indent,#smart_editor2 .off .se2_outdent,#smart_editor2 .off .se2_lineheight,#smart_editor2 .off .se2_del_style,#smart_editor2 .off .se2_blockquote,#smart_editor2 .off .se2_summary,#smart_editor2 .off .se2_footnote,#smart_editor2 .off .se2_url,#smart_editor2 .off .se2_emoticon,#smart_editor2 .off .se2_character,#smart_editor2 .off .se2_table,#smart_editor2 .off .se2_find,#smart_editor2 .off .se2_spelling,#smart_editor2 .off .se2_sup,#smart_editor2 .off .se2_sub,#smart_editor2 .off .se2_text_tool_more,#smart_editor2 .off .se2_new,#smart_editor2 .off .selected_color,#smart_editor2 .off .se2_lineSticker{-ms-filter:alpha(opacity=50);opacity:.5;cursor:default;filter:alpha(opacity=50)} +/* LAYER */ +#smart_editor2 .se2_text_tool .se2_layer{display:none;float:left;position:absolute;top:20px;left:0;z-index:50;margin:0;padding:0;border:1px solid #bcbbbb;background:#fafafa} +#smart_editor2 .se2_text_tool li.active{z-index:50} +#smart_editor2 .se2_text_tool .active .se2_layer{display:block} +#smart_editor2 .se2_text_tool .active li .se2_layer{display:none} +#smart_editor2 .se2_text_tool .active .active .se2_layer{display:block} +#smart_editor2 .se2_text_tool .se2_layer .se2_in_layer{float:left;margin:0;padding:0;border:1px solid #fff;background:#fafafa} +#smart_editor2 .se2_content_loading{display:none;z-index:10;position:absolute;top:0;left:0;width:100%;height:100%;text-align:center} +#smart_editor2 .se2_content_loading img{position:absolute;top:50%;left:50%;margin:-27px 0 0 -27px} +#smart_editor2 .se2_alert_wrap{display:none;z-index:20;position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;text-align:center} +#smart_editor2 .se2_alert_wrap.active{display:block} +#smart_editor2 .se2_alert_wrap .dimmed{position:absolute;top:0;left:0;width:100%;height:100%;background:#000;opacity:0.4;filter:alpha(opacity=40)} +#smart_editor2 .se2_alert_wrap .ie_cover{position:absolute;top:0;left:0;width:100%;height:100%;background:#fff;opacity:0;filter:alpha(opacity=0)} +#smart_editor2 .se2_alert_wrap .va_line{display:inline-block;height:100%;vertical-align:middle;*zoom:1} +#smart_editor2 .se2_alert_wrap .se2_alert_content{z-index:10;position:relative;display:inline-block;*display:inline;*zoom:1;border:1px solid #727272;background:#fff;padding:26px 33px 22px;vertical-align:middle} +#smart_editor2 .se2_alert_wrap .se2_alert_content{margin-top:47px} +#smart_editor2 .se2_alert_wrap .txt1{color:#333;line-height:18px} +#smart_editor2 .se2_alert_wrap .txt2{margin-top:3px;color:#999} +#smart_editor2 .se2_alert_wrap .btn_close,#smart_editor2 .se2_alert_btns button{background:url("../../img/ko_KR/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_alert_wrap .btn_close{z-index:10;position:absolute;top:7px;right:7px;width:11px;height:11px;background-position:-122px -32px;text-indent:-5000px} +#smart_editor2 .se2_alert_btns{margin-top:19px} +#smart_editor2 .se2_alert_btns button{display:inline;float:none;width:48px;height:27px} +#smart_editor2 .se2_alert_btns button + button{margin-left:10px} +#smart_editor2 .se2_alert_btns .se2_confirm{background-position:-369px -434px} +#smart_editor2 .se2_alert_btns .se2_cancel{background-position:-419px -434px} +/* TEXT_TOOLBAR */ +#smart_editor2 .se2_text_tool{position:relative;clear:both;z-index:30;padding:4px 0 4px 3px;background:#f4f4f4 url("../../img/bg_text_tool.gif") 0 0 repeat-x;border-bottom:1px solid #b5b5b5;*zoom:1} +#smart_editor2 .se2_text_tool:after{content:"";display:block;clear:both} +#smart_editor2 .se2_text_tool ul{float:left;display:inline;margin-right:3px;padding-left:1px;white-space:nowrap} +#smart_editor2 .se2_text_tool li{_display:inline;float:left;position:relative;z-index:30} +#smart_editor2 .se2_text_tool button,#smart_editor2 .se2_multy .se2_icon{width:21px;height:21px;background:url("../../img/ko_KR/text_tool_set.png?140317") no-repeat;vertical-align:top} +#smart_editor2 .se2_text_tool .se2_font_type{position:relative} +#smart_editor2 .se2_text_tool .se2_font_type li{margin-left:3px} +#smart_editor2 .se2_text_tool .se2_font_type button{text-align:left} +#smart_editor2 .se2_text_tool .se2_font_type button.se2_font_family span,#smart_editor2 .se2_text_tool .se2_font_type button.se2_font_size span{display:inline-block;visibility:visible;position:static;width:52px;height:20px;padding:0 0 0 6px;font-size:12px;line-height:20px;*line-height:22px;color:#333;*zoom:1} +#smart_editor2 .se2_text_tool .se2_multy{position:absolute;top:0;right:0;padding-left:0;margin-right:0;white-space:nowrap;border-left:1px solid #e0dedf} +#smart_editor2 .se2_text_tool .se2_multy .se2_mn{float:left;white-space:nowrap} +#smart_editor2 .se2_text_tool .se2_multy button{background-image:none;width:47px} +#smart_editor2 .se2_text_tool .se2_multy .se2_icon{display:inline-block;visibility:visible;overflow:visible;position:static;width:16px;height:29px;margin:-1px 2px 0 -1px;background-position:0 -132px;line-height:30px;vertical-align:top} +#smart_editor2 .se2_text_tool .se2_multy button,#smart_editor2 .se2_text_tool .se2_multy button span{height:29px;line-height:29px} +#smart_editor2 .se2_text_tool .se2_map .se2_icon{background-position:-29px -132px} +#smart_editor2 .se2_text_tool button span.se2_mntxt{display:inline-block;visibility:visible;overflow:visible;_overflow-y:hidden;position:relative;*margin-right:-1px;width:auto;height:29px;font-weight:normal;font-size:11px;line-height:30px;*line-height:29px;_line-height:30px;color:#444;letter-spacing:-1px;vertical-align:top} +#smart_editor2 .se2_text_tool .se2_multy .se2_photo{margin-right:1px} +#smart_editor2 .se2_text_tool .se2_multy .hover .ico_btn{background:#e8e8e8} +#smart_editor2 .se2_text_tool .se2_multy .se2_mn.hover{background:#e0dedf} +/* TEXT_TOOLBAR : ROUNDING */ +#smart_editor2 ul li.first_child button span.tool_bg, #smart_editor2 ul li.last_child button span.tool_bg, #smart_editor2 ul li.single_child button span.tool_bg{visibility:visible;height:21px} +#smart_editor2 ul li.first_child button span.tool_bg{left:-1px;width:3px;background:url("../../img/bg_button_left.gif?20121228") no-repeat} +#smart_editor2 ul li.last_child button span.tool_bg{right:0px;_right:-1px;width:2px;background:url("../../img/bg_button_right.gif") no-repeat} +#smart_editor2 ul li.single_child{padding-right:1px} +#smart_editor2 ul li.single_child button span.tool_bg{left:0;background:url("../../img/bg_button.gif?20121228") no-repeat;width:22px} +#smart_editor2 div.se2_text_tool ul li.hover button span.tool_bg{background-position:0 -21px} +#smart_editor2 div.se2_text_tool ul li.active button span.tool_bg, #smart_editor2 div.se2_text_tool ul li.active li.active button span.tool_bg{background-position:0 -42px} +#smart_editor2 div.se2_text_tool ul li.active li button span.tool_bg{background-position:0 0} +/* TEXT_TOOLBAR : SUB_MENU */ +#smart_editor2 .se2_sub_text_tool{display:none;position:absolute;top:20px;left:0;z-index:40;width:auto;height:29px;padding:0 4px 0 0;border:1px solid #b5b5b5;border-top:1px solid #9a9a9a;background:#f4f4f4} +#smart_editor2 .active .se2_sub_text_tool{display:block} +#smart_editor2 .se2_sub_text_tool ul{float:left;height:25px;margin:0;padding:4px 0 0 4px} +/* TEXT_TOOLBAR : SUB_MENU_SIZE */ +#smart_editor2 .se2_sub_step1{width:88px} +#smart_editor2 .se2_sub_step2{width:199px} +#smart_editor2 .se2_sub_step2_1{width:178px} +/* TEXT_TOOLBAR : BUTTON */ +#smart_editor2 .se2_text_tool .se2_font_family{width:70px;height:21px;background-position:0 -10px} +#smart_editor2 .se2_text_tool .hover .se2_font_family{background-position:0 -72px} +#smart_editor2 .se2_text_tool .active .se2_font_family{background-position:0 -103px} +#smart_editor2 .se2_text_tool .se2_font_size{width:45px;height:21px;background-position:-70px -10px} +#smart_editor2 .se2_text_tool .hover .se2_font_size{background-position:-70px -72px} +#smart_editor2 .se2_text_tool .active .se2_font_size{background-position:-70px -103px} +#smart_editor2 .se2_text_tool .se2_bold{background-position:-115px -10px} +#smart_editor2 .se2_text_tool .hover .se2_bold{background-position:-115px -72px} +#smart_editor2 .se2_text_tool .active .se2_bold{background-position:-115px -103px} +#smart_editor2 .se2_text_tool .se2_underline{background-position:-136px -10px} +#smart_editor2 .se2_text_tool .hover .se2_underline{background-position:-136px -72px} +#smart_editor2 .se2_text_tool .active .se2_underline{background-position:-136px -103px} +#smart_editor2 .se2_text_tool .se2_italic{background-position:-157px -10px} +#smart_editor2 .se2_text_tool .hover .se2_italic{background-position:-157px -72px} +#smart_editor2 .se2_text_tool .active .se2_italic{background-position:-157px -103px} +#smart_editor2 .se2_text_tool .se2_tdel{background-position:-178px -10px} +#smart_editor2 .se2_text_tool .hover .se2_tdel{background-position:-178px -72px} +#smart_editor2 .se2_text_tool .active .se2_tdel{background-position:-178px -103px} +#smart_editor2 .se2_text_tool .se2_fcolor{position:relative;background-position:-199px -10px} +#smart_editor2 .se2_text_tool .hover .se2_fcolor{background-position:-199px -72px} +#smart_editor2 .se2_text_tool .active .se2_fcolor{background-position:-199px -103px} +#smart_editor2 .se2_text_tool .se2_fcolor_more{background-position:-220px -10px;width:10px} +#smart_editor2 .se2_text_tool .hover .se2_fcolor_more{background-position:-220px -72px} +#smart_editor2 .se2_text_tool .active .se2_fcolor_more{background-position:-220px -103px} +#smart_editor2 .se2_text_tool .selected_color{position:absolute;top:14px;left:5px;width:11px;height:3px;font-size:0} +#smart_editor2 .se2_text_tool .se2_ol,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_ol{background-position:-345px -10px} +#smart_editor2 .se2_text_tool .se2_ul,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_ul{background-position:-366px -10px} +#smart_editor2 .se2_text_tool .hover .se2_ol,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_ol{background-position:-345px -72px} +#smart_editor2 .se2_text_tool .hover .se2_ul,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_ul{background-position:-366px -72px} +#smart_editor2 .se2_text_tool .active .se2_ol,#smart_editor2 .se2_text_tool .active .active .se2_ol{background-position:-345px -103px} +#smart_editor2 .se2_text_tool .active .se2_ul,#smart_editor2 .se2_text_tool .active .active .se2_ul{background-position:-366px -103px} +#smart_editor2 .se2_text_tool .se2_indent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_indent{background-position:-408px -10px} +#smart_editor2 .se2_text_tool .se2_outdent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_outdent{background-position:-387px -10px} +#smart_editor2 .se2_text_tool .hover .se2_indent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_indent{background-position:-408px -72px} +#smart_editor2 .se2_text_tool .hover .se2_outdent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_outdent{background-position:-387px -72px} +#smart_editor2 .se2_text_tool .active .se2_indent,#smart_editor2 .se2_text_tool .active .active .se2_indent{background-position:-408px -103px} +#smart_editor2 .se2_text_tool .active .se2_outdent,#smart_editor2 .se2_text_tool .active .active .se2_outdent{background-position:-387px -103px} +#smart_editor2 .se2_text_tool .se2_lineheight{background-position:-429px -10px} +#smart_editor2 .se2_text_tool .hover .se2_lineheight{background-position:-429px -72px} +#smart_editor2 .se2_text_tool .active .se2_lineheight{background-position:-429px -103px} +#smart_editor2 .se2_text_tool .se2_url{background-position:-513px -10px} +#smart_editor2 .se2_text_tool .hover .se2_url{background-position:-513px -72px} +#smart_editor2 .se2_text_tool .active .se2_url{background-position:-513px -103px} +#smart_editor2 .se2_text_tool .se2_bgcolor{position:relative;background-position:-230px -10px} +#smart_editor2 .se2_text_tool .hover .se2_bgcolor{background-position:-230px -72px} +#smart_editor2 .se2_text_tool .active .se2_bgcolor{background-position:-230px -103px} +#smart_editor2 .se2_text_tool .se2_bgcolor_more{background-position:-251px -10px;width:10px} +#smart_editor2 .se2_text_tool .hover .se2_bgcolor_more{background-position:-251px -72px} +#smart_editor2 .se2_text_tool .active .se2_bgcolor_more{background-position:-251px -103px} +#smart_editor2 .se2_text_tool .se2_left{background-position:-261px -10px} +#smart_editor2 .se2_text_tool .hover .se2_left{background-position:-261px -72px} +#smart_editor2 .se2_text_tool .active .se2_left{background-position:-261px -103px} +#smart_editor2 .se2_text_tool .se2_center{background-position:-282px -10px} +#smart_editor2 .se2_text_tool .hover .se2_center{background-position:-282px -72px} +#smart_editor2 .se2_text_tool .active .se2_center{background-position:-282px -103px} +#smart_editor2 .se2_text_tool .se2_right{background-position:-303px -10px} +#smart_editor2 .se2_text_tool .hover .se2_right{background-position:-303px -72px} +#smart_editor2 .se2_text_tool .active .se2_right{background-position:-303px -103px} +#smart_editor2 .se2_text_tool .se2_justify{background-position:-324px -10px} +#smart_editor2 .se2_text_tool .hover .se2_justify{background-position:-324px -72px} +#smart_editor2 .se2_text_tool .active .se2_justify{background-position:-324px -103px} +#smart_editor2 .se2_text_tool .se2_blockquote{background-position:-471px -10px} +#smart_editor2 .se2_text_tool .hover .se2_blockquote{background-position:-471px -72px} +#smart_editor2 .se2_text_tool .active .se2_blockquote{background-position:-471px -103px} +#smart_editor2 .se2_text_tool .se2_character{background-position:-555px -10px} +#smart_editor2 .se2_text_tool .hover .se2_character{background-position:-555px -72px} +#smart_editor2 .se2_text_tool .active .se2_character{background-position:-555px -103px} +#smart_editor2 .se2_text_tool .se2_table{background-position:-576px -10px} +#smart_editor2 .se2_text_tool .hover .se2_table{background-position:-576px -72px} +#smart_editor2 .se2_text_tool .active .se2_table{background-position:-576px -103px} +#smart_editor2 .se2_text_tool .se2_find{background-position:-597px -10px} +#smart_editor2 .se2_text_tool .hover .se2_find{background-position:-597px -72px} +#smart_editor2 .se2_text_tool .active .se2_find{background-position:-597px -103px} +#smart_editor2 .se2_text_tool .se2_sup{background-position:-660px -10px} +#smart_editor2 .se2_text_tool .hover .se2_sup{background-position:-660px -72px} +#smart_editor2 .se2_text_tool .active .se2_sup{background-position:-660px -103px} +#smart_editor2 .se2_text_tool .se2_sub{background-position:-681px -10px} +#smart_editor2 .se2_text_tool .hover .se2_sub{background-position:-681px -72px} +#smart_editor2 .se2_text_tool .active .se2_sub{background-position:-681px -103px} +#smart_editor2 .se2_text_tool .se2_text_tool_more{background-position:0 -41px;width:13px} +#smart_editor2 .se2_text_tool .se2_text_tool_more span.tool_bg{background:none} +#smart_editor2 .se2_text_tool .hover .se2_text_tool_more{background-position:-13px -41px} +#smart_editor2 .se2_text_tool .active .se2_text_tool_more{background-position:-26px -41px} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/ko_KR/smart_editor2_in.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/ko_KR/smart_editor2_in.css new file mode 100644 index 00000000..fdecc092 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/ko_KR/smart_editor2_in.css @@ -0,0 +1,24 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* COMMON */ +body,.se2_inputarea{margin:0;padding:0;font-family:'돋움',Dotum,Helvetica,Sans-serif;font-size:12px;line-height:1.5} +/* body,.se2_inputarea,.se2_inputarea th,.se2_inputarea td{margin:0;padding:0;font-family:'돋움',Dotum,Helvetica,Sans-serif;font-size:12px;line-height:1.5;color:#666} */ +.se2_inputarea p,.se2_inputarea br{margin:0;padding:0} +.se2_inputarea{margin:15px;word-wrap:break-word;*word-wrap:normal;*word-break:break-all} +.se2_inputarea td{word-break:break-all} +.se2_inputarea_890{width:741px;margin:20px 0 10px 64px} +.se2_inputarea_698{width:548px;margin:20px 0 10px 64px} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + .se2_inputarea td:empty:after,.se2_inputarea td > p:empty:after{content:"\00A0";line-height:1} +} +/* TEXT_TOOLBAR : QUOTE */ +.se2_quote1{margin:0 0 30px 20px;padding:0 8px;border-left:2px solid #ccc;color:#888} +.se2_quote2{margin:0 0 30px 13px;padding:0 8px 0 16px;background:url("../../img/bg_quote2.gif") 0 3px no-repeat;color:#888} +.se2_quote3{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #ccc;color:#888} +.se2_quote4{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #66b246;color:#888} +.se2_quote5{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #ccc;background:#fafafa;color:#888} +.se2_quote6{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #e5e5e5;color:#888} +.se2_quote7{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #66b246;color:#888} +.se2_quote8{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #e5e5e5;background:#fafafa;color:#888} +.se2_quote9{margin:0 0 30px;padding:12px 10px 11px;border:2px solid #e5e5e5;color:#888} +.se2_quote10{margin:0 0 30px;padding:12px 10px 11px;border:2px solid #e5e5e5;background:#fafafa;color:#888} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/ko_KR/smart_editor2_items.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/ko_KR/smart_editor2_items.css new file mode 100644 index 00000000..e4726267 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/ko_KR/smart_editor2_items.css @@ -0,0 +1,462 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* TEXT_TOOLBAR : FONTNAME */ +#smart_editor2 .se2_tool .se2_l_font_fam{width:202px;margin:0;padding:0} +#smart_editor2 .se2_tool .se2_l_font_fam li{display:block;width:202px;height:21px;margin:0;padding:0;color:#333;cursor:pointer} +#smart_editor2 .se2_l_font_fam .hover,#smart_editor2 .se2_l_font_fam .active{background:#ebebeb} +#smart_editor2 .se2_l_font_fam button{width:200px;height:21px;margin:0;padding:2px 0 2px 0px;background:none;text-align:left} +#smart_editor2 .se2_l_font_fam button span{display:block;visibility:visible;overflow:visible;position:relative;top:auto;left:auto;width:auto;height:auto;margin:0 0 0 4px;padding:0;font-size:12px;line-height:normal;color:#333} +#smart_editor2 .se2_l_font_fam button span span{display:inline;visibility:visible;overflow:visible;width:auto;height:auto;margin:0 0 0 4px;font-family:Verdana;font-size:12px;line-height:14px;color:#888} +#smart_editor2 .se2_l_font_fam button span em{visibility:visible;overflow:auto;position:static;width:auto;height:auto;margin-right:-4px;font-size:12px;color:#888} +#smart_editor2 .se2_l_font_fam .se2_division{width:162px;height:2px !important;margin:1px 0 1px 0px;border:0;background:url("../../img/bg_line1.gif") 0 0 repeat-x;font-size:0;cursor:default} +/* TEXT_TOOLBAR : FONTSIZE */ +#smart_editor2 .se2_tool .se2_l_font_size{width:302px;margin:0;padding:0} +#smart_editor2 .se2_tool .se2_l_font_size li{width:302px;margin:0;padding:0;color:#333;cursor:pointer} +#smart_editor2 .se2_l_font_size .hover,#smart_editor2 .se2_l_font_size .active{background:#ebebeb} +#smart_editor2 .se2_l_font_size button{width:300px;height:auto;margin:0;padding:2px 0 1px 0px;*padding:4px 0 1px 0px;background:none;text-align:left} +#smart_editor2 .se2_l_font_size button span{display:block;visibility:visible;overflow:visible;position:relative;top:auto;left:auto;width:auto;height:auto;margin:0 0 0 4px;padding:0;line-height:normal;color:#373737;letter-spacing:0px} +#smart_editor2 .se2_l_font_size button span span{display:inline;margin:0 0 0 5px;padding:0} +#smart_editor2 .se2_l_font_size span em{visibility:visible;overflow:auto;position:static;width:auto;height:auto;color:#888} +/* TEXT_TOOLBAR : FONTCOLOR */ +#smart_editor2 .se2_palette{float:left;position:relative;width:225px;margin:0;padding:11px 0 10px 0} +#smart_editor2 .se2_palette .se2_pick_color{_display:inline;float:left;clear:both;width:205px;margin:0 0 0 11px;padding:0} +#smart_editor2 .se2_palette .se2_pick_color li{float:left;width:12px;height:12px;margin:0;padding:0} +#smart_editor2 .se2_palette .se2_pick_color li button{width:11px;height:11px;border:0} +#smart_editor2 .se2_palette .se2_pick_color li button span{display:block;visibility:visible;overflow:visible;position:absolute;top:1px;left:1px;width:11px;height:11px} +#smart_editor2 .se2_palette .se2_pick_color li button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0} +#smart_editor2 .se2_palette .se2_pick_color .hover button,#smart_editor2 .se2_palette .se2_pick_color .active button{width:11px;height:11px;border:1px solid #666} +#smart_editor2 .se2_palette .se2_pick_color .hover span,#smart_editor2 .se2_palette .se2_pick_color .active span{width:7px;height:7px;border:1px solid #fff} +#smart_editor2 .se2_palette .se2_view_more{_display:inline;float:left;width:46px;height:23px;margin:1px 0 0 1px;background:url("../../img/ko_KR/btn_set.png?160622") 0 -47px no-repeat} +#smart_editor2 .se2_palette .se2_view_more2{_display:inline;float:left;width:46px;height:23px;margin:1px 0 0 1px;background:url("../../img/ko_KR/btn_set.png?160622") 0 -24px no-repeat} +#smart_editor2 .se2_palette h4{_display:inline;float:left;width:203px;margin:9px 0 0 11px;padding:10px 0 4px 0;background:url("../../img/bg_line1.gif") repeat-x;font-weight:normal;font-size:12px;line-height:14px;color:#333;letter-spacing:-1px} +#smart_editor2 .se2_palette2{float:left;_float:none;width:214px;margin:9px 0 0 0;padding:11px 0 0 11px;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_palette2 .se2_color_set{float:left} +#smart_editor2 .se2_palette2 .se2_selected_color{_display:inline;float:left;width:83px;height:18px;margin:0;border:1px solid #c7c7c7;background:#fff} +#smart_editor2 .se2_palette2 .se2_selected_color span{_display:inline;float:left;width:79px;height:14px;margin:2px} +#smart_editor2 .se2_palette2 .input_ty1{_display:inline;float:left;width:67px;height:16px;margin:0 3px 0 3px;padding:2px 2px 0 4px;font-family:tahoma;font-size:11px} +#smart_editor2 .se2_palette2 button.se2_btn_insert{float:left;width:35px;height:21px;margin-left:2px;padding:0;background:url("../../img/ko_KR/btn_set.png?160622") -80px 0 no-repeat} +#smart_editor2 .se2_gradation1{float:left;_float:none;width:201px;height:128px;margin:4px 0 0 0;border:1px solid #c7c7c7;cursor:crosshair} +#smart_editor2 .se2_gradation2{float:left;_float:none;width:201px;height:10px;margin:4px 0 1px 0;border:1px solid #c7c7c7;cursor:crosshair} +/* TEXT_TOOLBAR : BGCOLOR */ +#smart_editor2 .se2_palette_bgcolor{width:225px;margin:11px 0 0;padding:0} +#smart_editor2 .se2_palette_bgcolor .se2_background{width:205px;margin:0 11px 0 11px} +#smart_editor2 .se2_palette_bgcolor .se2_background li{width:68px;height:20px} +#smart_editor2 .se2_palette_bgcolor .se2_background button{width:67px;height:19px;border:0} +#smart_editor2 .se2_palette_bgcolor .se2_background span{left:0;display:block;visibility:visible;overflow:visible;width:65px;height:17px;padding:0} +#smart_editor2 .se2_palette_bgcolor .se2_background span span{display:block;visibility:visible;overflow:visible;width:64px;height:16px;padding:3px 0 0 3px;font-size:11px;line-height:14px;text-align:left} +#smart_editor2 .se2_palette_bgcolor .se2_background .hover span{width:65px;height:17px;border:1px solid #666} +#smart_editor2 .se2_palette_bgcolor .se2_background .hover span span{width:62px;height:14px;padding:1px 0 0 1px;border:1px solid #fff} +/* TEXT_TOOLBAR : LINEHEIGHT */ +#smart_editor2 .se2_l_line_height{width:107px;margin:0;padding:0} +#smart_editor2 .se2_l_line_height li{width:107px;margin:0;padding:0;border-top:0;border-bottom:0;color:#333;cursor:pointer} +#smart_editor2 .se2_l_line_height .hover{background:#ebebeb} +#smart_editor2 .se2_l_line_height button{width:105px;height:19px;margin:0;padding:3px 0 2px 0px;background:none;text-align:left} +#smart_editor2 .se2_l_line_height button span{visibility:visible;overflow:visible;position:relative;width:auto;height:auto;margin:0;padding:0 0 0 15px;font-size:12px;line-height:normal;color:#373737} +#smart_editor2 .se2_l_line_height li button.active span{background:url("../../img/icon_set.gif?141007") 5px -30px no-repeat} +#smart_editor2 .se2_l_line_height_user{clear:both;width:83px;margin:5px 0 0 12px;padding:10px 0 0 0;_padding:11px 0 0 0;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_l_line_height_user h3{margin:0 0 4px 0;_margin:0 0 2px -1px;padding:0;line-height:14px;color:#000;letter-spacing:-1px} +#smart_editor2 .se2_l_line_height_user .bx_input{display:block;position:relative;width:83px} +#smart_editor2 .se2_l_line_height_user .btn_up{position:absolute;top:2px;*top:3px;left:68px;width:13px;height:8px;background:url("../../img/ko_KR/btn_set.png?160622") -86px -54px no-repeat} +#smart_editor2 .se2_l_line_height_user .btn_down{position:absolute;top:10px;*top:11px;left:68px;width:13px;height:8px;background:url("../../img/ko_KR/btn_set.png?160622") -86px -62px no-repeat} +#smart_editor2 .se2_l_line_height_user .btn_area{margin:5px 0 10px 0} +#smart_editor2 .se2_tool .btn_area .se2_btn_apply3{width:41px;height:24px;background:url("../../img/ko_KR/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_tool .btn_area .se2_btn_cancel3{width:39px;height:24px;margin-left:3px;background:url("../../img/ko_KR/btn_set.png?160622") -41px 0 no-repeat} +/* TEXT_TOOLBAR : QUOTE */ +#smart_editor2 .se2_quote{width:425px;height:56px} +#smart_editor2 .se2_quote ul{_display:inline;float:left;margin:11px 0 0 9px;padding:0} +#smart_editor2 .se2_quote li{_display:inline;float:left;margin:0 0 0 2px;padding:0} +#smart_editor2 .se2_quote button{width:34px;height:34px;margin:0;padding:0;background:url("../../img/ko_KR/btn_set.png?160622") no-repeat;cursor:pointer} +#smart_editor2 .se2_quote button span{left:0;display:block;visibility:visible;overflow:visible;width:32px;height:32px;margin:0;padding:0;border:1px solid #c7c7c7} +#smart_editor2 .se2_quote button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0} +#smart_editor2 .se2_quote .se2_quote1{background-position:1px -375px} +#smart_editor2 .se2_quote .se2_quote2{background-position:-32px -375px} +#smart_editor2 .se2_quote .se2_quote3{background-position:-65px -375px} +#smart_editor2 .se2_quote .se2_quote4{background-position:-98px -375px} +#smart_editor2 .se2_quote .se2_quote5{background-position:-131px -375px} +#smart_editor2 .se2_quote .se2_quote6{background-position:-164px -375px} +#smart_editor2 .se2_quote .se2_quote7{background-position:-197px -375px} +#smart_editor2 .se2_quote .se2_quote8{background-position:-230px -375px} +#smart_editor2 .se2_quote .se2_quote9{background-position:-263px -375px} +#smart_editor2 .se2_quote .se2_quote10{background-position:-296px -375px} +#smart_editor2 .se2_quote .hover button span,#smart_editor2 .se2_quote .active button span{width:30px;height:30px;margin:0;padding:0;border:2px solid #44b525} +#smart_editor2 .se2_quote .hover button span span,#smart_editor2 .se2_quote .active button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0} +#smart_editor2 .se2_quote .se2_cancel2{float:left;width:40px;height:35px;margin:11px 0 0 5px;background:url("../../img/ko_KR/btn_set.png?160622") -46px -24px no-repeat} +#smart_editor2 .se2_quote .se2_cancel2 span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0} +/* TEXT_TOOLBAR : HYPERLINK */ +#smart_editor2 .se2_url2{width:281px;padding:11px 11px 6px 11px;color:#666} +#smart_editor2 .se2_url2 .input_ty1{display:block;width:185px;height:16px;margin:0 5px 5px 0;*margin:-1px 5px 5px 0;padding:5px 2px 0 4px} +#smart_editor2 .se2_url2 .se2_url_new{width:15px;height:15px;margin:-1px 3px 1px -1px;*margin:-2px 3px 2px -1px;vertical-align:middle} +#smart_editor2 .se2_url2 label{font-size:11px;line-height:14px;vertical-align:middle} +#smart_editor2 .se2_url2 .se2_apply{position:absolute;top:13px;right:51px;width:41px;height:24px;margin:-1px 3px 1px 0;background:url("../../img/ko_KR/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_url2 .se2_cancel{position:absolute;top:13px;right:9px;width:39px;height:24px;margin:-1px 3px 1px 0;background:url("../../img/ko_KR/btn_set.png?160622") -41px 0 no-repeat} +/* TEXT_TOOLBAR : SCHARACTER */ +#smart_editor2 .se2_bx_character{width:469px;height:272px;margin:0;padding:0;background:url("../../img/bx_set_110302.gif") 9px -1230px no-repeat} +#smart_editor2 .se2_bx_character .se2_char_tab{_display:inline;float:left;position:relative;width:443px;margin:11px 10px 200px 11px;padding:0 0 0 1px} +#smart_editor2 .se2_bx_character .se2_char_tab li{position:static;margin:0 0 0 -1px;padding:0} +#smart_editor2 .se2_bx_character .se2_char1{width:76px;height:26px;background:url("../../img/ko_KR/btn_set.png?160622") 0 -204px no-repeat} +#smart_editor2 .se2_bx_character .se2_char2{width:86px;height:26px;background:url("../../img/ko_KR/btn_set.png?160622") -75px -204px no-repeat} +#smart_editor2 .se2_bx_character .se2_char3{width:68px;height:26px;background:url("../../img/ko_KR/btn_set.png?160622") -160px -204px no-repeat} +#smart_editor2 .se2_bx_character .se2_char4{width:55px;height:26px;background:url("../../img/ko_KR/btn_set.png?160622") -227px -204px no-repeat} +#smart_editor2 .se2_bx_character .se2_char5{width:97px;height:26px;background:url("../../img/ko_KR/btn_set.png?160622") -281px -204px no-repeat} +#smart_editor2 .se2_bx_character .se2_char6{width:66px;height:26px;background:url("../../img/ko_KR/btn_set.png?160622") -377px -204px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char1{width:76px;height:26px;background:url("../../img/ko_KR/btn_set.png?160622") 0 -230px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char2{width:86px;height:26px;background:url("../../img/ko_KR/btn_set.png?160622") -75px -230px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char3{width:68px;height:26px;background:url("../../img/ko_KR/btn_set.png?160622") -160px -230px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char4{width:55px;height:26px;background:url("../../img/ko_KR/btn_set.png?160622") -227px -230px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char5{width:97px;height:26px;background:url("../../img/ko_KR/btn_set.png?160622") -281px -230px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char6{width:66px;height:26px;background:url("../../img/ko_KR/btn_set.png?160622") -377px -230px no-repeat} +#smart_editor2 .se2_bx_character .se2_s_character{display:none;position:absolute;top:26px;left:0;width:448px;height:194px;margin:0;padding:0} +#smart_editor2 .se2_bx_character .active .se2_s_character{display:block} +#smart_editor2 .se2_bx_character .se2_s_character ul{float:left;width:422px;height:172px;margin:0;padding:9px 0 0 11px} +#smart_editor2 .se2_bx_character .se2_s_character li{_display:inline;float:left;position:relative;width:20px;height:18px;margin:0 0 1px 1px;background:#fff} +#smart_editor2 .se2_bx_character .se2_s_character button{width:20px;height:18px;margin:0;padding:2px;background:none} +#smart_editor2 .se2_bx_character .se2_s_character .hover,#smart_editor2 .se2_bx_character .se2_s_character .active{background:url("../../img/ko_KR/btn_set.png?160622") -446px -274px no-repeat} +#smart_editor2 .se2_bx_character .se2_s_character button span{left:0;display:block;visibility:visible;overflow:visible;width:14px;height:16px;margin:3px 0 0 3px;border:0;background:none;font-size:12px;line-height:normal} +#smart_editor2 .se2_apply_character{clear:both;position:relative;padding:0 0 0 11px} +#smart_editor2 .se2_apply_character label{margin:0 3px 0 0;font-size:12px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_apply_character .input_ty1{width:283px;height:17px;margin:-1px 5px 1px 0;padding:4px 0 0 5px;font-size:12px;color:#666;letter-spacing:0;vertical-align:middle} +#smart_editor2 .se2_apply_character .se2_confirm{width:41px;height:24px;margin-right:3px;background:url("../../img/ko_KR/btn_set.png?160622") no-repeat;vertical-align:middle} +#smart_editor2 .se2_apply_character .se2_cancel{width:39px;height:24px;background:url("../../img/ko_KR/btn_set.png?160622") -41px 0 no-repeat;vertical-align:middle} +/* TEXT_TOOLBAR : TABLECREATOR */ +#smart_editor2 .se2_table_set{position:relative;width:166px;margin:3px 11px 0 11px;padding:8px 0 0 0} +#smart_editor2 .se2_table_set .se2_cell_num{float:left;width:73px} +#smart_editor2 .se2_table_set .se2_cell_num dt{float:left;clear:both;width:17px;height:23px;margin:0;padding:0} +#smart_editor2 .se2_table_set .se2_cell_num dt label{display:block;margin:5px 0 0 0;font-size:11px;color:#666} +#smart_editor2 .se2_table_set .se2_cell_num dd{float:left;position:relative;width:54px;height:23px;margin:0;padding:0} +#smart_editor2 .se2_table_set .se2_cell_num .input_ty2{display:block;width:32px;height:16px;*margin:-1px 0 0 0;padding:2px 19px 0 0px;border:1px solid #c7c7c7;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666;text-align:right;*direction:rtl} +#smart_editor2 .se2_table_set .se2_cell_num .input_ty2::-ms-clear{display:none} +#smart_editor2 .se2_table_set .se2_pre_table{float:right;width:91px;height:43px;background:#c7c7c7;border-spacing:1px} +#smart_editor2 .se2_table_set .se2_pre_table tr{background:#fff} +#smart_editor2 .se2_table_set .se2_pre_table td{font-size:0;line-height:0} +#smart_editor2 .se2_table_set .se2_add{position:absolute;top:2px;right:3px;width:13px;height:8px;background:url("../../img/ko_KR/btn_set.png?160622") -86px -54px no-repeat} +#smart_editor2 .se2_table_set .se2_del{position:absolute;top:10px;right:3px;width:13px;height:8px;background:url("../../img/ko_KR/btn_set.png?160622") -86px -62px no-repeat} +/* TEXT_TOOLBAR : TABLEEDITOR */ +#smart_editor2 .se2_table_set .se2_t_proper1{float:left;width:166px;margin:7px 0 0 0;padding:10px 0 5px;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_table_set .se2_t_proper1 dt{width:166px;margin:0 0 6px 0} +#smart_editor2 .se2_table_set .se2_t_proper1 dd{width:166px} +#smart_editor2 .se2_table_set .se2_t_proper1 dt input{width:15px;height:15px;margin:-1px 3px 1px 0;_margin:-2px 3px 2px 0;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper1 dt label{font-weight:bold;font-size:11px;color:#666;letter-spacing:-1px;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper1_1{float:left;position:relative;z-index:59;width:166px;margin:1px 0 0 0} +#smart_editor2 .se2_table_set .se2_t_proper1_2{z-index:54;margin:0} +#smart_editor2 .se2_table_set .se2_t_proper1_3{z-index:53;margin:0} +#smart_editor2 .se2_table_set .se2_t_proper1_4{z-index:52;margin:0} +#smart_editor2 .se2_table_set .se2_t_proper1_1 dt{_display:inline;float:left;clear:both;width:66px;height:22px;margin:1px 0 0 18px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 dt label{display:block;margin:4px 0 0 0;font-weight:normal;font-size:11px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 dd{float:left;position:relative;width:82px;height:23px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .input_ty1{width:72px;height:16px;*margin:-1px 0 0 0;padding:2px 2px 0 6px;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .input_ty3{float:left;width:49px;height:16px;margin:0 3px 0 0;padding:2px 4px 0 4px;border:1px solid #c7c7c7;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_add{top:2px;right:2px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_del{top:10px;right:2px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_color_set .input_ty1{_display:inline;float:left;width:67px;height:16px;margin:0 3px 0 3px;padding:2px 2px 0 4px;font-family:tahoma,verdana,times New Roman;font-size:11px} +#smart_editor2 .se2_select_ty1{position:relative;width:80px;height:18px;border:1px solid #c7c7c7;background:#fff;font-size:11px;line-height:14px;text-align:left} +#smart_editor2 .se2_select_ty1 span{float:left;width:54px;height:18px;margin:0 0 0 5px;font-size:11px;line-height:14px;color:#666} +#smart_editor2 .se2_select_ty1 .se2_b_style0{position:relative;top:3px;left:-3px;white-space:nowrap} +#smart_editor2 .se2_select_ty1 .se2_b_style1{height:15px;margin:3px 0 0 4px;font-size:11px;line-height:14px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_select_ty1 .se2_b_style2{background:url("../../img/bg_set.gif") 0 -50px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style3{background:url("../../img/bg_set.gif") 0 -68px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style4{background:url("../../img/bg_set.gif") 0 -85px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style5{background:url("../../img/bg_set.gif") 0 -103px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style6{background:url("../../img/bg_set.gif") 0 -121px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style7{background:url("../../img/bg_set.gif") 0 -139px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_view_more{position:absolute;top:1px;right:1px;width:13px;height:16px;background:url("../../img/ko_KR/btn_set.png?160622") -112px -54px no-repeat} +#smart_editor2 .se2_select_ty1 .se2_view_more2{position:absolute;top:1px;right:1px;width:13px;height:16px;background:url("../../img/ko_KR/btn_set.png?160622") -99px -54px no-repeat} +/* TEXT_TOOLBAR : TABLEEDITOR > BORDER */ +#smart_editor2 .se2_table_set .se2_b_t_b1{border-top:1px solid #b1b1b1} +#smart_editor2 .se2_layer_b_style{position:absolute;top:20px;right:0px;width:80px;padding-bottom:1px;border:1px solid #c7c7c7;border-top:1px solid #a8a8a8;background:#fff} +#smart_editor2 .se2_layer_b_style ul{width:80px;margin:0;padding:1px 0 0 0} +#smart_editor2 .se2_layer_b_style li{width:80px;height:18px;margin:0;padding:0} +#smart_editor2 .se2_layer_b_style .hover,#smart_editor2 .se2_layer_b_style .active{background:#ebebeb} +#smart_editor2 .se2_layer_b_style button{width:80px;height:18px;background:none} +#smart_editor2 .se2_layer_b_style button span{left:0;display:block;visibility:visible;overflow:visible;width:71px;height:18px;margin:0 0 0 5px;font-size:11px;line-height:15px;text-align:left} +#smart_editor2 .se2_layer_b_style button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0} +#smart_editor2 .se2_layer_b_style .se2_b_style1 span{margin:3px 0 0 4px;font-size:11px;line-height:14px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_layer_b_style .se2_b_style2 span{background:url("../../img/bg_set.gif") 0 -50px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style3 span{background:url("../../img/bg_set.gif") 0 -68px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style4 span{background:url("../../img/bg_set.gif") 0 -86px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style5 span{background:url("../../img/bg_set.gif") 0 -103px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style6 span{background:url("../../img/bg_set.gif") 0 -121px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style7 span{background:url("../../img/bg_set.gif") 0 -139px repeat-x} +/* TEXT_TOOLBAR : TABLEEDITOR > COLOR */ +#smart_editor2 .se2_pre_color{float:left;width:18px;height:18px;border:1px solid #c7c7c7} +#smart_editor2 .se2_pre_color button{float:left;width:14px;height:14px;margin:2px 0 0 2px;padding:0} +#smart_editor2 .se2_pre_color button span{overflow:hidden;position:absolute;top:-10000px;left:-10000px;z-index:-100;width:0;height:0} +/* TEXT_TOOLBAR : TABLEEDITOR > DIMMED */ +#smart_editor2 .se2_table_set .se2_t_dim1{clear:both;position:absolute;top:71px;left:16px;z-index:60;width:157px;height:118px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_table_set .se2_t_dim2{position:absolute;top:116px;left:16px;z-index:55;width:157px;height:45px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_table_set .se2_t_dim3{clear:both;position:absolute;top:192px;left:16px;z-index:51;width:157px;height:39px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +/* TEXT_TOOLBAR : TABLEEDITOR > STYLE PREVIEW */ +#smart_editor2 .se2_table_set .se2_t_proper2{float:left;position:relative;z-index:50;width:166px;margin:2px 0 0 0} +#smart_editor2 .se2_table_set .se2_t_proper2 dt{float:left;width:84px;height:33px;margin:4px 0 0 0} +#smart_editor2 .se2_table_set .se2_t_proper2 dt input{width:15px;height:15px;margin:-1px 3px 1px 0;_margin:-2px 3px 2px 0;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper2 dt label{font-weight:bold;font-size:11px;color:#666;letter-spacing:-1px;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper2 dd{float:left;width:66px;height:33px} +#smart_editor2 .se2_select_ty2{position:relative;width:65px;height:31px;border:1px solid #c7c7c7;background:#fff;font-size:11px;line-height:14px;text-align:left} +#smart_editor2 .se2_select_ty2 span{float:left;width:45px;height:25px;margin:3px 0 0 3px;background:url("../../img/ko_KR/btn_set.png?160622") repeat-x} +#smart_editor2 .se2_select_ty2 .se2_t_style1{background-position:0 -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style2{background-position:-46px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style3{background-position:-92px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style4{background-position:-138px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style5{background-position:-184px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style6{background-position:-230px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style7{background-position:-276px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style8{background-position:-322px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style9{background-position:0 -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style10{background-position:-46px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style11{background-position:-92px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style12{background-position:-138px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style13{background-position:-184px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style14{background-position:-230px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style15{background-position:-276px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style16{background-position:-322px -436px} +#smart_editor2 .se2_select_ty2 .se2_view_more{position:absolute;top:1px;right:1px;_right:0px;width:13px !important;height:29px !important;background:url("../../img/ko_KR/btn_set.png?160622") -353px -48px no-repeat !important} +#smart_editor2 .se2_select_ty2 .se2_view_more2{position:absolute;top:1px;right:1px;_right:0px;width:13px !important;height:29px !important;background:url("../../img/ko_KR/btn_set.png?160622") -340px -48px no-repeat !important} +#smart_editor2 .se2_select_ty2 .se2_view_more span{display:none} +/* TEXT_TOOLBAR : TABLEEDITOR > STYLE */ +#smart_editor2 .se2_layer_t_style{position:absolute;top:33px;right:15px;width:208px;border:1px solid #c7c7c7;border-top:1px solid #a8a8a8;background:#fff} +#smart_editor2 .se2_layer_t_style ul{width:204px;height:126px;margin:1px 2px;padding:1px 0 0 0;background:#fff} +#smart_editor2 .se2_layer_t_style li{_display:inline;float:left;width:45px;height:25px;margin:1px;padding:1px;border:1px solid #fff} +#smart_editor2 .se2_layer_t_style .hover,#smart_editor2 .se2_layer_t_style .active{border:1px solid #666;background:#fff} +#smart_editor2 .se2_layer_t_style button{width:45px;height:25px;background:url("../../img/ko_KR/btn_set.png?160622") repeat-x !important} +#smart_editor2 .se2_layer_t_style .se2_t_style1{background-position:0 -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style2{background-position:-46px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style3{background-position:-92px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style4{background-position:-138px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style5{background-position:-184px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style6{background-position:-230px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style7{background-position:-276px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style8{background-position:-322px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style9{background-position:0 -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style10{background-position:-46px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style11{background-position:-92px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style12{background-position:-138px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style13{background-position:-184px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style14{background-position:-230px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style15{background-position:-276px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style16{background-position:-322px -436px !important} +#smart_editor2 .se2_table_set .se2_btn_area{float:left;width:166px;margin:6px 0 0 0;padding:12px 0 8px 0;background:url("../../img/bg_line1.gif") repeat-x;text-align:center} +#smart_editor2 .se2_table_set button.se2_apply{width:41px;height:24px;margin-right:3px;background:url("../../img/ko_KR/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_table_set button.se2_cancel{width:39px;height:24px;background:url("../../img/ko_KR/btn_set.png?160622") -41px 0 no-repeat} +#smart_editor2 .se2_table_set .se2_rd{width:14px;height:14px;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_celltit{font-size:11px;font-size:11px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_table_set dt label.se2_celltit{display:inline} +/* TEXT_TOOLBAR : FINDREPLACE */ +#smart_editor2 .se2_bx_find_revise{position:relative;width:255px;margin:0;padding:0} +#smart_editor2 .se2_bx_find_revise .se2_close{position:absolute;top:5px;right:8px;width:20px;height:20px;background:url("../../img/ko_KR/btn_set.png?160622") -151px -1px no-repeat} +#smart_editor2 .se2_bx_find_revise h3{margin:0;padding:10px 0 13px 10px;background:url("../../img/bg_find_h3.gif") 0 -1px repeat-x;font-size:12px;line-height:14px;letter-spacing:-1px} +#smart_editor2 .se2_bx_find_revise ul{position:relative;margin:8px 0 0 0;padding:0 0 0 12px} +#smart_editor2 .se2_bx_find_revise ul li{_display:inline;float:left;position:static;margin:0 0 0 -1px;padding:0} +#smart_editor2 .se2_bx_find_revise .se2_tabfind{width:117px;height:26px;background:url("../../img/ko_KR/btn_set.png?160622") 0 -100px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_tabrevise{width:117px;height:26px;background:url("../../img/ko_KR/btn_set.png?160622") -116px -100px no-repeat} +#smart_editor2 .se2_bx_find_revise .active .se2_tabfind{width:117px;height:26px;background:url("../../img/ko_KR/btn_set.png?160622") 0 -126px no-repeat} +#smart_editor2 .se2_bx_find_revise .active .se2_tabrevise{width:117px;height:26px;background:url("../../img/ko_KR/btn_set.png?160622") -116px -126px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_in_bx_find dl{_display:inline;float:left;width:223px;margin:0 0 0 9px;padding:7px 0 13px 14px;background:url("../../img/bx_set_110302.gif") -289px -1518px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_in_bx_revise dl{_display:inline;float:left;width:223px;margin:0 0 0 9px;padding:7px 0 13px 14px;background:url("../../img/bx_set_110302.gif") -289px -1619px no-repeat} +#smart_editor2 .se2_bx_find_revise dt{_display:inline;float:left;clear:both;width:47px;margin:1px 0 2px 0} +#smart_editor2 .se2_bx_find_revise dd{float:left;margin:0 0 2px 0} +#smart_editor2 .se2_bx_find_revise label{float:left;padding:5px 0 0 0;font-size:11px;color:#666;letter-spacing:-2px} +#smart_editor2 .se2_bx_find_revise input{float:left;width:155px;height:12px;margin:1px 0 0 0;padding:3px 2px 3px 4px;font-size:12px;color:#666} +#smart_editor2 .se2_bx_find_revise .se2_find_btns{float:left;clear:both;width:255px;padding:8px 0 10px 0;text-align:center} +#smart_editor2 .se2_bx_find_revise .se2_find_next{width:65px;height:24px;margin:0 3px 0 0;background:url("../../img/ko_KR/btn_set.png?160622") -180px -48px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_find_next2{width:61px;height:24px;margin:0 3px 0 0;background:url("../../img/ko_KR/btn_set.png?160622") -180px -24px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_revise1{width:54px;height:24px;margin:0 3px 0 0;background:url("../../img/ko_KR/btn_set.png?160622") -245px -48px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_revise2{width:70px;height:24px;margin:0 3px 0 0;background:url("../../img/ko_KR/btn_set.png?160622") -245px -24px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_cancel{width:39px;height:24px;background:url("../../img/ko_KR/btn_set.png?160622") -41px 0 no-repeat} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE */ +#smart_editor2 .se2_qmax{position:absolute;width:18px;height:18px;background:url("../../img/ko_KR/btn_set.png?160622") -339px -169px no-repeat} +#smart_editor2 .se2_qeditor{position:absolute;top:0;left:0;width:183px;margin:0;padding:0;border:1px solid #c7c7c7;border-right:1px solid #ababab;border-bottom:1px solid #ababab;background:#fafafa} +#smart_editor2 .se2_qeditor label,#smart_editor2 .se2_qeditor span,#smart_editor2 .se2_qeditor dt{font-size:11px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_qbar{position:relative;width:183px;height:11px;background:url("../../img/bx_set_110302.gif") 0 -731px no-repeat} +#smart_editor2 .se2_qbar .se2_qmini{position:absolute;top:-1px;right:0;*right:-1px;_right:-3px;width:18px;height:14px;background:url("../../img/ko_KR/btn_set.png?160622") -315px -170px no-repeat} +#smart_editor2 .se2_qbar .se2_qmini button{width:20px;height:14px;margin-top:-1px} +#smart_editor2 .se2_qeditor .se2_qbody0{float:left;border:1px solid #fefefe} +#smart_editor2 .se2_qeditor .se2_qbody{position:relative;z-index:90;width:174px;padding:4px 0 0 7px} +#smart_editor2 .se2_qeditor .se2_qe1{overflow:hidden;width:174px} +#smart_editor2 .se2_qeditor .se2_qe1 dt{float:left;width:22px;height:18px;padding:4px 0 0 0} +#smart_editor2 .se2_qeditor .se2_qe1 dd{float:left;width:65px;height:22px} +#smart_editor2 .se2_qeditor .se2_addrow{width:28px;height:19px;background:url("../../img/ko_KR/btn_set.png?160622") no-repeat -385px -49px} +#smart_editor2 .se2_qeditor .se2_addcol{width:29px;height:19px;background:url("../../img/ko_KR/btn_set.png?160622") no-repeat -413px -49px} +#smart_editor2 .se2_qeditor .se2_seprow{width:28px;height:19px;background:url("../../img/ko_KR/btn_set.png?160622") no-repeat -385px -68px} +#smart_editor2 .se2_qeditor .se2_sepcol{width:29px;height:19px;background:url("../../img/ko_KR/btn_set.png?160622") no-repeat -413px -68px} +#smart_editor2 .se2_qeditor .se2_delrow{width:28px;height:19px;background:url("../../img/ko_KR/btn_set.png?160622") no-repeat -385px -106px} +#smart_editor2 .se2_qeditor .se2_delcol{width:29px;height:19px;background:url("../../img/ko_KR/btn_set.png?160622") no-repeat -413px -106px} +#smart_editor2 .se2_qeditor .se2_merrow{width:57px;height:19px;background:url("../../img/ko_KR/btn_set.png?160622") no-repeat -385px -125px} +#smart_editor2 .se2_qeditor .se2_mercol{width:57px;height:19px;background:url("../../img/ko_KR/btn_set.png?160622") no-repeat -413px -125px} +#smart_editor2 .se2_qeditor .se2_seprow_off{width:28px;height:19px;background:url("../../img/ko_KR/btn_set.png?160622") no-repeat -385px -87px} +#smart_editor2 .se2_qeditor .se2_sepcol_off{width:29px;height:19px;background:url("../../img/ko_KR/btn_set.png?160622") no-repeat -413px -87px} +#smart_editor2 .se2_qeditor .se2_merrow_off{width:57px;height:19px;background:url("../../img/ko_KR/btn_set.png?160622") no-repeat -385px -144px} +#smart_editor2 .se2_qeditor .se2_mercol_off{width:57px;height:19px;background:url("../../img/ko_KR/btn_set.png?160622") no-repeat -413px -144px} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND */ +#smart_editor2 .se2_qeditor .se2_qe2{_display:inline;float:left;position:relative;z-index:100;width:165px;margin:2px 0 0 1px;padding:7px 0 0 0;background:url("../../img/bg_line1.gif") repeat-x;zoom:1} +#smart_editor2 .se2_qeditor .se2_qe2_1 dt{float:left;width:62px;padding:3px 0 0 0} +#smart_editor2 .se2_qeditor .se2_qe2_1 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qeditor .se2_qe2_1 dd{float:left;position:relative;zoom:1} +#smart_editor2 .se2_qeditor .se2_qe2_3{padding:7px 0 6px 0} +/* My글양식 없을때 */ +#smart_editor2 .se2_qeditor .se2_qe2_2{position:relative;_position:absolute} +#smart_editor2 .se2_qeditor .se2_qe2_2 dt{float:left;width:50px;padding:3px 0 0 13px} +#smart_editor2 .se2_qeditor .se2_qe2_2 dt input{width:15px;height:15px;margin:-1px 2px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qeditor .se2_qe2_2 dd{float:left} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > STYLE */ +#smart_editor2 .se2_table_set .se2_qbody .se2_t_proper2{float:left;*float:none;position:static;width:166px;margin:5px 0 0 1px} +#smart_editor2 .se2_qeditor .se2_qe3 dt{float:left;width:62px;padding:0} +#smart_editor2 .se2_qeditor .se2_qe3 dt label{font-weight:normal} +#smart_editor2 .se2_qeditor .se2_qe3 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qeditor .se2_qe3 dd .se2_qe3_table{position:relative} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND PREWVIEW */ +#smart_editor2 .se2_qeditor .se2_pre_color{float:left;width:18px;height:18px;border:1px solid #c7c7c7} +#smart_editor2 .se2_qeditor .se2_pre_color button{float:left;width:14px;height:14px;margin:2px 0 0 2px;padding:0} +#smart_editor2 .se2_qeditor .se2_pre_color button span{overflow:hidden;position:absolute;top:-10000px;left:-10000px;z-index:-100;width:0;height:0} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND LAYER */ +#smart_editor2 .se2_qeditor .se2_layer{float:left;clear:both;position:absolute;top:20px;left:0;margin:0;padding:0;border:1px solid #c7c7c7;border-top:1px solid #9a9a9a;background:#fafafa} +#smart_editor2 .se2_qeditor .se2_layer .se2_in_layer{float:left;margin:0;padding:0;border:1px solid #fff;background:#fafafa} +#smart_editor2 .se2_qeditor .se2_layer button{vertical-align:top} +#smart_editor2 .se2_qeditor .se2_layer .se2_pick_color li{position:relative} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND IMAGE */ +#smart_editor2 .se2_qeditor .se2_pre_bgimg{float:left;width:14px;height:14px;padding:2px;border:1px solid #c7c7c7} +#smart_editor2 .se2_qeditor .se2_qe2_2 button{width:16px;height:16px;background:url("../../img/ko_KR/btn_set.png?160622") 0 -261px no-repeat} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND IMAGE LAYER */ +#smart_editor2 .se2_cellimg_set{_display:inline;float:left;width:136px;margin:4px 3px 0 4px;padding-bottom:4px} +#smart_editor2 .se2_cellimg_set li{_display:inline;float:left;width:16px;height:16px;margin:0 1px 1px 0} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg0{background-position:-255px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg1{background-position:0 -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg2{background-position:-17px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg3{background-position:-34px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg4{background-position:-51px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg5{background-position:-68px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg6{background-position:-85px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg7{background-position:-102px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg8{background-position:-119px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg9{background-position:-136px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg10{background-position:-153px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg11{background-position:-170px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg12{background-position:-187px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg13{background-position:-204px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg14{background-position:-221px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg15{background-position:-238px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg16{background-position:-255px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg17{background-position:0 -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg18{background-position:-17px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg19{background-position:-34px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg20{background-position:-51px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg21{background-position:-68px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg22{background-position:-85px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg23{background-position:-102px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg24{background-position:-119px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg25{background-position:-136px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg26{background-position:-153px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg27{background-position:-170px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg28{background-position:-187px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg29{background-position:-204px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg30{background-position:-221px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg31{background-position:-238px -278px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg button{width:14px;height:14px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg1{background-position:-1px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg2{background-position:-18px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg3{background-position:-35px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg4{background-position:-52px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg5{background-position:-69px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg6{background-position:-86px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg7{background-position:-103px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg8{background-position:-120px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg9{background-position:-137px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg10{background-position:-154px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg11{background-position:-171px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg12{background-position:-188px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg13{background-position:-205px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg14{background-position:-222px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg15{background-position:-239px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg16{background-position:-256px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg17{background-position:-1px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg18{background-position:-18px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg19{background-position:-35px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg20{background-position:-52px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg21{background-position:-69px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg22{background-position:-86px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg23{background-position:-103px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg24{background-position:-120px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg25{background-position:-137px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg26{background-position:-154px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg27{background-position:-171px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg28{background-position:-188px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg29{background-position:-205px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg30{background-position:-222px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg31{background-position:-239px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg32{background-position:-256px -279px} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > MY REVIEW */ +#smart_editor2 .se2_btn_area{_display:inline;float:left;clear:both;width:166px;margin:5px 0 0 1px;padding:7px 0 6px 0;background:url("../../img/bg_line1.gif") repeat-x;text-align:center} +#smart_editor2 .se2_btn_area .se2_btn_save{width:97px;height:21px;background:url("../../img/ko_KR/btn_set.png?160622") -369px -163px no-repeat} +/* TEXT_TOOLBAR : QUICKEDITOR_IMAGE */ +#smart_editor2 .se2_qe10{width:166px;margin:0;*margin:-2px 0 0 0} +#smart_editor2 .se2_qe10 label{margin:0 1px 0 0;vertical-align:middle} +#smart_editor2 .se2_qe10 .se2_sheight{margin-left:4px} +#smart_editor2 .se2_qe10 .input_ty1{width:30px;height:13px;margin:0 0 1px 1px;padding:3px 4px 0 1px;font-size:11px;letter-spacing:0;text-align:right;vertical-align:middle} +#smart_editor2 .se2_qe10 .se2_sreset{width:41px;height:19px;margin-left:3px;background:url("../../img/ko_KR/btn_set.png?160622") -401px -184px no-repeat;vertical-align:middle} +#smart_editor2 .se2_qe10_1{margin-top:4px;padding:10px 0 3px;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_qe10_1 input{width:15px;height:15px;margin:-1px 3px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qe11{float:left;width:166px;margin:4px 0 0 0;padding:7px 0 2px 0;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_qe11_1{float:left;width:99px} +#smart_editor2 .se2_qe11_1 dt{float:left;width:56px;height:15px;padding:5px 0 0 0} +#smart_editor2 .se2_qe11_1 dd{float:left;position:relative;width:38px;height:20px} +#smart_editor2 .se2_qe11_1 .input_ty1{display:block;width:29px;height:15px;margin:0;*margin:-1px 0 1px 0;padding:3px 1px 0 5px;font-size:11px;letter-spacing:0;text-align:left} +#smart_editor2 .se2_qe11_1 .se2_add{position:absolute;top:2px;right:3px;width:13px;height:8px;background:url("../../img/ko_KR/btn_set.png?160622") -86px -54px no-repeat} +#smart_editor2 .se2_qe11_1 .se2_del{position:absolute;top:10px;right:3px;width:13px;height:8px;background:url("../../img/ko_KR/btn_set.png?160622") -86px -62px no-repeat} +#smart_editor2 .se2_qe11_2{float:left;width:67px} +#smart_editor2 .se2_qe11_2 dt{float:left;width:47px;margin:5px 0 0 0} +#smart_editor2 .se2_qe11_2 dd{float:left;position:relative;width:20px} +#smart_editor2 .se2_qe12{float:left;width:166px;margin:3px 0 0 0;padding:7px 0 0 0;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_qe12 dt{float:left;margin:5px 4px 0 0} +#smart_editor2 .se2_qe12 dd{float:left;padding:0 0 6px 0} +#smart_editor2 .se2_qe12 .se2_align0{float:left;width:19px;height:21px;background:url("../../img/ko_KR/btn_set.png?160622") -276px -121px no-repeat} +#smart_editor2 .se2_qe12 .se2_align1{float:left;width:19px;height:21px;background:url("../../img/ko_KR/btn_set.png?160622") -295px -121px no-repeat} +#smart_editor2 .se2_qe12 .se2_align2{float:left;width:20px;height:21px;background:url("../../img/ko_KR/btn_set.png?160622") -314px -121px no-repeat} +#smart_editor2 .se2_qe13{position:relative;z-index:10;zoom:1} +#smart_editor2 .se2_qe13 dt{float:left;width:62px;padding:3px 0 0} +#smart_editor2 .se2_qe13 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle;zoom:1} +#smart_editor2 .se2_qe13 dt .se2_qdim2{width:32px} +#smart_editor2 .se2_qe13 dd .se2_select_ty1{width:38px} +#smart_editor2 .se2_qe13 dd .se2_select_ty1 span{width:15px} +#smart_editor2 .se2_qe13 dd .input_ty1{width:20px} +#smart_editor2 .se2_qe13 dd .se2_palette2 .input_ty1{width:67px} +#smart_editor2 .se2_qe13 .se2_add{*top:3px} +#smart_editor2 .se2_qe13 .se2_del{*top:11px} +#smart_editor2 .se2_qe13 .se2_layer_b_style{right:-2px;_right:0} +#smart_editor2 .se2_qe13 .se2_layer_b_style li span{width:auto;margin:0 4px 0 5px;padding-top:2px} +#smart_editor2 .se2_qe13 dd{_display:inline;float:left;position:relative;width:29px;margin-right:5px;_margin-right:3px;zoom:1} +#smart_editor2 .se2_qe13 dd .se2_palette h4{margin-top:9px;font-family:dotum;font-size:12px} +#smart_editor2 .se2_qe13 dd.dd_type{width:38px} +#smart_editor2 .se2_qe13 dd.dd_type2{width:37px;margin-right:3px} +#smart_editor2 .se2_qe13 dd.dd_type2 .input_ty1{width:29px} +#smart_editor2 .se2_qe13 dd.dd_type2 button{right:2px;_right:1px} +#smart_editor2 .se2_qe13 dd.dd_type3{width:20px;margin:0} +#smart_editor2 .se2_qe13_v1{_display:inline;float:left;margin:2px 0 1px} +#smart_editor2 .se2_qe13_v1 dt{padding:4px 0 0 1px} +#smart_editor2 .se2_qe13_v2{_display:inline;float:left;position:relative;z-index:100;width:165px;margin:4px 0 0 1px;zoom:1} +#smart_editor2 .se2_qe13_v2 dd{width:18px;margin:0} +#smart_editor2 .se2_qeditor .se2_qdim1{clear:both;position:absolute;top:25px;left:115px;width:60px;height:23px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim2{clear:both;position:absolute;top:55px;left:24px;z-index:110;width:70px;height:22px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim3{clear:both;position:absolute;top:55px;left:118px;z-index:110;width:56px;height:22px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim4{clear:both;position:absolute;top:81px;left:23px;z-index:35;width:116px;height:35px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim5{clear:both;position:absolute;top:31px;left:106px;width:68px;height:26px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim6c{clear:both;position:absolute;top:25px;left:28px;width:29px;height:23px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim6r{clear:both;position:absolute;top:25px;left:57px;width:29px;height:23px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_highedit{float:right;width:56px;height:21px;margin:-27px 8px 0 0;background:url("../../img/ko_KR/btn_set.png?160622") -329px -142px no-repeat} +#smart_editor2 .se2_qeditor .se2_qdim7{clear:both;position:absolute;top:55px;left:24px;z-index:110;width:150px;height:48px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim8{clear:both;position:absolute;top:105px;left:24px;z-index:110;width:150px;height:37px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim9{clear:both;position:absolute;top:55px;left:111px;z-index:110;width:65px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim10{clear:both;position:absolute;top:55px;left:100px;z-index:110;width:77px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim11{clear:both;position:absolute;top:55px;left:65px;z-index:110;width:115px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +/* HELP : ACCESSIBILITY */ +#smart_editor2 .se2_accessibility{z-index:90} +#smart_editor2 .se2_accessibility .se2_in_layer{width:568px;padding:0 10px;background:#fafafa;border:1px solid #bcbbbb} +#smart_editor2 .se2_accessibility h3{margin:0 -10px;padding:6px 0 12px 0;background:url("../../img/bg_find_h3.gif") repeat-x;font-size:12px;line-height:14px;letter-spacing:-1px} +#smart_editor2 .se2_accessibility h3 strong{display:inline-block;padding:4px 0 3px 11px;color:#333;letter-spacing:0} +#smart_editor2 .se2_accessibility .se2_close{position:absolute;top:10px;right:12px;width:13px;height:12px;background:url("../../img/ko_KR/btn_set.png?160622") -155px -5px no-repeat} +#smart_editor2 .se2_accessibility .box_help{padding:0 2px;margin-top:8px;background:url("../../img/bg_help.gif") 0 100% no-repeat} +#smart_editor2 .se2_accessibility .box_help div{overflow:hidden;padding:20px 21px 24px;border-top:1px solid #d0d0d0;color:#333} +#smart_editor2 .se2_accessibility .box_help strong{display:block;margin-bottom:2px} +#smart_editor2 .se2_accessibility .box_help p{margin-bottom:28px;line-height:1.5} +#smart_editor2 .se2_accessibility .box_help ul{width:150%;margin-top:10px} +#smart_editor2 .se2_accessibility .box_help li{position:relative;float:left;width:252px;padding:5px 0 5px 9px;margin-right:40px;background:url("../../img/ko_KR/btn_set.png?160622") -475px -51px no-repeat;border-right:1px solid #f0f0f0;*zoom:1;line-height:1} +#smart_editor2 .se2_accessibility .box_help li span{position:absolute;top:4px;left:138px;line-height:1.2} +#smart_editor2 .se2_accessibility .se2_btns{padding:9px 0 10px;text-align:center} +#smart_editor2 .se2_accessibility .se2_btns .se2_close2{width:39px;height:24px;background:url("../../img/ko_KR/btn_set.png?160622") -235px -120px no-repeat} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/ko_KR/smart_editor2_out.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/ko_KR/smart_editor2_out.css new file mode 100644 index 00000000..0baf3770 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/ko_KR/smart_editor2_out.css @@ -0,0 +1,12 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* COMMON */ +.se2_outputarea, .se2_outputarea th, .se2_outputarea td{margin:0;padding:0;color:#666;font-size:12px;font-family:'돋움',Dotum,'굴림',Gulim,Helvetica,Sans-serif;line-height:1.5} +.se2_outputarea p{margin:0;padding:0} +.se2_outputarea a:hover{text-decoration:underline} +.se2_outputarea a:link{color:#0000ff} +.se2_outputarea ul{margin:0 0 0 40px;padding:0} +.se2_outputarea ul li{margin:0;list-style-type:disc;padding:0} +.se2_outputarea ul ul li{list-style-type:circle} +.se2_outputarea ul ul ul li{list-style-type:square} +.se2_outputarea img, .se2_outputarea fieldset{border:0} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_CN/smart_editor2.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_CN/smart_editor2.css new file mode 100644 index 00000000..f2a6b479 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_CN/smart_editor2.css @@ -0,0 +1,190 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* COMMON */ +body,#smart_editor2,#smart_editor2 p,#smart_editor2 h1,#smart_editor2 h2,#smart_editor2 h3,#smart_editor2 h4,#smart_editor2 h5,#smart_editor2 h6,#smart_editor2 ul,#smart_editor2 ol,#smart_editor2 li,#smart_editor2 dl,#smart_editor2 dt,#smart_editor2 dd,#smart_editor2 table,#smart_editor2 th,#smart_editor2 td,#smart_editor2 form,#smart_editor2 fieldset,#smart_editor2 legend,#smart_editor2 input,#smart_editor2 textarea,#smart_editor2 button,#smart_editor2 select{margin:0;padding:0} +#smart_editor2,#smart_editor2 h1,#smart_editor2 h2,#smart_editor2 h3,#smart_editor2 h4,#smart_editor2 h5,#smart_editor2 h6,#smart_editor2 input,#smart_editor2 textarea,#smart_editor2 select,#smart_editor2 table,#smart_editor2 button{font-family:'돋움',Dotum,Helvetica,sans-serif;font-size:12px;color:#666} +#smart_editor2 span,#smart_editor2 em{font-size:12px} +#smart_editor2 em,#smart_editor2 address{font-style:normal} +#smart_editor2 img,#smart_editor2 fieldset{border:0} +#smart_editor2 hr{display:none} +#smart_editor2 ol,#smart_editor2 ul{list-style:none} +#smart_editor2 button{border:0;background:none;font-size:11px;vertical-align:top;cursor:pointer} +#smart_editor2 button span,#smart_editor2 button em{visibility:hidden;overflow:hidden;position:absolute;top:0;font-size:0;line-height:0} +#smart_editor2 legend,#smart_editor2 .blind{visibility:hidden;overflow:hidden;position:absolute;width:0;height:0;font-size:0;line-height:0} +#smart_editor2 .input_ty1{height:14px;margin:0;padding:4px 2px 0 4px;border:1px solid #c7c7c7;font-size:11px;color:#666} +#smart_editor2 a:link,#smart_editor2 a:visited,#smart_editor2 a:active,#smart_editor2 a:focus{color:#666;text-decoration:none} +#smart_editor2 a:hover{color:#666;text-decoration:underline} +/* LAYOUT */ +#smart_editor2 .se2_header{margin:10px 0 29px 0} +#smart_editor2 .se2_bi{float:left;width:93px;height:20px;margin:0;padding:0;background:url("../../img/zh_CN/btn_set.png?160622") -343px -358px no-repeat;font-size:0;line-height:0;text-indent:-10000px;vertical-align:middle} +#smart_editor2 .se2_allhelp{display:inline-block;width:18px;height:18px;padding:0;background:url("../../img/zh_CN/btn_set.png?160622") -437px -358px no-repeat;font-size:0;line-height:0;text-indent:-10000px;vertical-align:middle} +#smart_editor2 #smart_editor2_content{position:relative;border:1px solid #b5b5b5} +#smart_editor2 .se2_tool{overflow:visible;position:relative;z-index:25} +/* EDITINGAREA */ +#smart_editor2 .se2_input_area{position:relative;z-index:22;height:400px;margin:0;padding:0;*zoom:1} +#smart_editor2 .se2_input_wysiwyg,#smart_editor2 .se2_input_syntax{display:block;overflow:auto;width:100%;height:100%;margin:0;*margin:-1px 0 0 0;border:0} +/* EDITINGMODE */ +#smart_editor2 .se2_conversion_mode{position:relative;height:15px;padding-top:1px;border-top:1px solid #b5b5b5;background:url("../../img/icon_set.gif?141007") 0 -896px repeat-x} +#smart_editor2 .se2_inputarea_controller{display:block;clear:both;position:relative;width:100%;height:15px;background:url("../../img/icon_set.gif?141007") center -47px no-repeat;text-align:center;cursor:n-resize} +#smart_editor2 .se2_inputarea_controller span{display:block;visibility:visible;height:15px;font-size:0;line-height:0;color:#fff;white-space:nowrap} +#smart_editor2 .ly_controller{display:block;position:absolute;bottom:2px;left:50%;width:287px;margin-left:-148px;padding:8px 0 7px 9px;border:1px solid #827f7c;background:#fffdef} +#smart_editor2 .ly_controller p{color:#666;font-size:11px;letter-spacing:-1px;line-height:11px} +#smart_editor2 .ly_controller .bt_clse,#smart_editor2 .ly_controller .ic_arr{position:absolute;background:url("../../img/ico_extend.png") no-repeat} +#smart_editor2 .ly_controller .bt_clse{top:5px;right:4px;width:14px;height:15px;background-position:1px -43px} +#smart_editor2 .ly_controller .ic_arr{top:25px;left:50%;width:10px;height:6px;margin-left:-5px;background-position:0 -65px} +#smart_editor2 .se2_converter{float:left;position:absolute;top:-1px;right:3px;z-index:20} +#smart_editor2 .se2_converter li{float:left} +#smart_editor2 .se2_converter .se2_to_editor{width:59px;height:15px;background:url("../../img/zh_CN/btn_set.png?160622") 0 -85px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .se2_to_html{width:59px;height:15px;background:url("../../img/zh_CN/btn_set.png?160622") -59px -70px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .se2_to_text{width:60px;height:15px;background:url("../../img/zh_CN/btn_set.png?160622") -417px -466px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .active .se2_to_editor{width:59px;height:15px;background:url("../../img/zh_CN/btn_set.png?160622") 0 -70px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .active .se2_to_html{width:59px;height:15px;background:url("../../img/zh_CN/btn_set.png?160622") -59px -85px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .active .se2_to_text{width:60px;height:15px;background:url("../../img/zh_CN/btn_set.png?160622") -417px -481px no-repeat;vertical-align:top} +/* EDITINGAREA_HTMLSRC */ +#smart_editor2 .off .ico_btn,#smart_editor2 .off .se2_more,#smart_editor2 .off .se2_more2,#smart_editor2 .off .se2_font_family,#smart_editor2 .off .se2_font_size,#smart_editor2 .off .se2_bold,#smart_editor2 .off .se2_underline,#smart_editor2 .off .se2_italic,#smart_editor2 .off .se2_tdel,#smart_editor2 .off .se2_fcolor,#smart_editor2 .off .se2_fcolor_more,#smart_editor2 .off .se2_bgcolor,#smart_editor2 .off .se2_bgcolor_more,#smart_editor2 .off .se2_left,#smart_editor2 .off .se2_center,#smart_editor2 .off .se2_right,#smart_editor2 .off .se2_justify,#smart_editor2 .off .se2_ol,#smart_editor2 .off .se2_ul,#smart_editor2 .off .se2_indent,#smart_editor2 .off .se2_outdent,#smart_editor2 .off .se2_lineheight,#smart_editor2 .off .se2_del_style,#smart_editor2 .off .se2_blockquote,#smart_editor2 .off .se2_summary,#smart_editor2 .off .se2_footnote,#smart_editor2 .off .se2_url,#smart_editor2 .off .se2_emoticon,#smart_editor2 .off .se2_character,#smart_editor2 .off .se2_table,#smart_editor2 .off .se2_find,#smart_editor2 .off .se2_spelling,#smart_editor2 .off .se2_sup,#smart_editor2 .off .se2_sub,#smart_editor2 .off .se2_text_tool_more,#smart_editor2 .off .se2_new,#smart_editor2 .off .selected_color,#smart_editor2 .off .se2_lineSticker{-ms-filter:alpha(opacity=50);opacity:.5;cursor:default;filter:alpha(opacity=50)} +/* LAYER */ +#smart_editor2 .se2_text_tool .se2_layer{display:none;float:left;position:absolute;top:20px;left:0;z-index:50;margin:0;padding:0;border:1px solid #bcbbbb;background:#fafafa} +#smart_editor2 .se2_text_tool li.active{z-index:50} +#smart_editor2 .se2_text_tool .active .se2_layer{display:block} +#smart_editor2 .se2_text_tool .active li .se2_layer{display:none} +#smart_editor2 .se2_text_tool .active .active .se2_layer{display:block} +#smart_editor2 .se2_text_tool .se2_layer .se2_in_layer{float:left;margin:0;padding:0;border:1px solid #fff;background:#fafafa} +#smart_editor2 .se2_content_loading{display:none;z-index:10;position:absolute;top:0;left:0;width:100%;height:100%;text-align:center} +#smart_editor2 .se2_content_loading img{position:absolute;top:50%;left:50%;margin:-27px 0 0 -27px} +#smart_editor2 .se2_alert_wrap{display:none;z-index:20;position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;text-align:center} +#smart_editor2 .se2_alert_wrap.active{display:block} +#smart_editor2 .se2_alert_wrap .dimmed{position:absolute;top:0;left:0;width:100%;height:100%;background:#000;opacity:0.4;filter:alpha(opacity=40)} +#smart_editor2 .se2_alert_wrap .ie_cover{position:absolute;top:0;left:0;width:100%;height:100%;background:#fff;opacity:0;filter:alpha(opacity=0)} +#smart_editor2 .se2_alert_wrap .va_line{display:inline-block;height:100%;vertical-align:middle;*zoom:1} +#smart_editor2 .se2_alert_wrap .se2_alert_content{z-index:10;position:relative;display:inline-block;*display:inline;*zoom:1;border:1px solid #727272;background:#fff;padding:26px 33px 22px;vertical-align:middle} +#smart_editor2 .se2_alert_wrap .se2_alert_content{margin-top:47px} +#smart_editor2 .se2_alert_wrap .txt1{color:#333;line-height:18px} +#smart_editor2 .se2_alert_wrap .txt2{margin-top:3px;color:#999} +#smart_editor2 .se2_alert_wrap .btn_close,#smart_editor2 .se2_alert_btns button{background:url("../../img/zh_CN/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_alert_wrap .btn_close{z-index:10;position:absolute;top:7px;right:7px;width:11px;height:11px;background-position:-122px -32px;text-indent:-5000px} +#smart_editor2 .se2_alert_btns{margin-top:19px} +#smart_editor2 .se2_alert_btns button{display:inline;float:none;width:48px;height:27px} +#smart_editor2 .se2_alert_btns button + button{margin-left:10px} +#smart_editor2 .se2_alert_btns .se2_confirm{background-position:-369px -434px} +#smart_editor2 .se2_alert_btns .se2_cancel{background-position:-419px -434px} +/* TEXT_TOOLBAR */ +#smart_editor2 .se2_text_tool{position:relative;clear:both;z-index:30;padding:4px 0 4px 3px;background:#f4f4f4 url("../../img/bg_text_tool.gif") 0 0 repeat-x;border-bottom:1px solid #b5b5b5;*zoom:1} +#smart_editor2 .se2_text_tool:after{content:"";display:block;clear:both} +#smart_editor2 .se2_text_tool ul{float:left;display:inline;margin-right:3px;padding-left:1px;white-space:nowrap} +#smart_editor2 .se2_text_tool li{_display:inline;float:left;position:relative;z-index:30} +#smart_editor2 .se2_text_tool button,#smart_editor2 .se2_multy .se2_icon{width:21px;height:21px;background:url("../../img/zh_CN/text_tool_set.png?140317") no-repeat;vertical-align:top} +#smart_editor2 .se2_text_tool .se2_font_type{position:relative} +#smart_editor2 .se2_text_tool .se2_font_type li{margin-left:3px} +#smart_editor2 .se2_text_tool .se2_font_type button{text-align:left} +#smart_editor2 .se2_text_tool .se2_font_type button.se2_font_family span,#smart_editor2 .se2_text_tool .se2_font_type button.se2_font_size span{display:inline-block;visibility:visible;position:static;width:52px;height:20px;padding:0 0 0 6px;font-size:12px;line-height:20px;*line-height:22px;color:#333;*zoom:1} +#smart_editor2 .se2_text_tool .se2_multy{position:absolute;top:0;right:0;padding-left:0;margin-right:0;white-space:nowrap;border-left:1px solid #e0dedf} +#smart_editor2 .se2_text_tool .se2_multy .se2_mn{float:left;white-space:nowrap} +#smart_editor2 .se2_text_tool .se2_multy button{background-image:none;width:47px} +#smart_editor2 .se2_text_tool .se2_multy .se2_icon{display:inline-block;visibility:visible;overflow:visible;position:static;width:16px;height:29px;margin:-1px 2px 0 -1px;background-position:0 -132px;line-height:30px;vertical-align:top} +#smart_editor2 .se2_text_tool .se2_multy button,#smart_editor2 .se2_text_tool .se2_multy button span{height:29px;line-height:29px} +#smart_editor2 .se2_text_tool .se2_map .se2_icon{background-position:-29px -132px} +#smart_editor2 .se2_text_tool button span.se2_mntxt{display:inline-block;visibility:visible;overflow:visible;_overflow-y:hidden;position:relative;*margin-right:-1px;width:auto;height:29px;font-weight:normal;font-size:11px;line-height:30px;*line-height:29px;_line-height:30px;color:#444;letter-spacing:-1px;vertical-align:top} +#smart_editor2 .se2_text_tool .se2_multy .se2_photo{margin-right:1px} +#smart_editor2 .se2_text_tool .se2_multy .hover .ico_btn{background:#e8e8e8} +#smart_editor2 .se2_text_tool .se2_multy .se2_mn.hover{background:#e0dedf} +/* TEXT_TOOLBAR : ROUNDING */ +#smart_editor2 ul li.first_child button span.tool_bg, #smart_editor2 ul li.last_child button span.tool_bg, #smart_editor2 ul li.single_child button span.tool_bg{visibility:visible;height:21px} +#smart_editor2 ul li.first_child button span.tool_bg{left:-1px;width:3px;background:url("../../img/bg_button_left.gif?20121228") no-repeat} +#smart_editor2 ul li.last_child button span.tool_bg{right:0px;_right:-1px;width:2px;background:url("../../img/bg_button_right.gif") no-repeat} +#smart_editor2 ul li.single_child{padding-right:1px} +#smart_editor2 ul li.single_child button span.tool_bg{left:0;background:url("../../img/bg_button.gif?20121228") no-repeat;width:22px} +#smart_editor2 div.se2_text_tool ul li.hover button span.tool_bg{background-position:0 -21px} +#smart_editor2 div.se2_text_tool ul li.active button span.tool_bg, #smart_editor2 div.se2_text_tool ul li.active li.active button span.tool_bg{background-position:0 -42px} +#smart_editor2 div.se2_text_tool ul li.active li button span.tool_bg{background-position:0 0} +/* TEXT_TOOLBAR : SUB_MENU */ +#smart_editor2 .se2_sub_text_tool{display:none;position:absolute;top:20px;left:0;z-index:40;width:auto;height:29px;padding:0 4px 0 0;border:1px solid #b5b5b5;border-top:1px solid #9a9a9a;background:#f4f4f4} +#smart_editor2 .active .se2_sub_text_tool{display:block} +#smart_editor2 .se2_sub_text_tool ul{float:left;height:25px;margin:0;padding:4px 0 0 4px} +/* TEXT_TOOLBAR : SUB_MENU_SIZE */ +#smart_editor2 .se2_sub_step1{width:88px} +#smart_editor2 .se2_sub_step2{width:199px} +#smart_editor2 .se2_sub_step2_1{width:178px} +/* TEXT_TOOLBAR : BUTTON */ +#smart_editor2 .se2_text_tool .se2_font_family{width:70px;height:21px;background-position:0 -10px} +#smart_editor2 .se2_text_tool .hover .se2_font_family{background-position:0 -72px} +#smart_editor2 .se2_text_tool .active .se2_font_family{background-position:0 -103px} +#smart_editor2 .se2_text_tool .se2_font_size{width:45px;height:21px;background-position:-70px -10px} +#smart_editor2 .se2_text_tool .hover .se2_font_size{background-position:-70px -72px} +#smart_editor2 .se2_text_tool .active .se2_font_size{background-position:-70px -103px} +#smart_editor2 .se2_text_tool .se2_bold{background-position:-115px -10px} +#smart_editor2 .se2_text_tool .hover .se2_bold{background-position:-115px -72px} +#smart_editor2 .se2_text_tool .active .se2_bold{background-position:-115px -103px} +#smart_editor2 .se2_text_tool .se2_underline{background-position:-136px -10px} +#smart_editor2 .se2_text_tool .hover .se2_underline{background-position:-136px -72px} +#smart_editor2 .se2_text_tool .active .se2_underline{background-position:-136px -103px} +#smart_editor2 .se2_text_tool .se2_italic{background-position:-157px -10px} +#smart_editor2 .se2_text_tool .hover .se2_italic{background-position:-157px -72px} +#smart_editor2 .se2_text_tool .active .se2_italic{background-position:-157px -103px} +#smart_editor2 .se2_text_tool .se2_tdel{background-position:-178px -10px} +#smart_editor2 .se2_text_tool .hover .se2_tdel{background-position:-178px -72px} +#smart_editor2 .se2_text_tool .active .se2_tdel{background-position:-178px -103px} +#smart_editor2 .se2_text_tool .se2_fcolor{position:relative;background-position:-199px -10px} +#smart_editor2 .se2_text_tool .hover .se2_fcolor{background-position:-199px -72px} +#smart_editor2 .se2_text_tool .active .se2_fcolor{background-position:-199px -103px} +#smart_editor2 .se2_text_tool .se2_fcolor_more{background-position:-220px -10px;width:10px} +#smart_editor2 .se2_text_tool .hover .se2_fcolor_more{background-position:-220px -72px} +#smart_editor2 .se2_text_tool .active .se2_fcolor_more{background-position:-220px -103px} +#smart_editor2 .se2_text_tool .selected_color{position:absolute;top:14px;left:5px;width:11px;height:3px;font-size:0} +#smart_editor2 .se2_text_tool .se2_ol,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_ol{background-position:-345px -10px} +#smart_editor2 .se2_text_tool .se2_ul,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_ul{background-position:-366px -10px} +#smart_editor2 .se2_text_tool .hover .se2_ol,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_ol{background-position:-345px -72px} +#smart_editor2 .se2_text_tool .hover .se2_ul,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_ul{background-position:-366px -72px} +#smart_editor2 .se2_text_tool .active .se2_ol,#smart_editor2 .se2_text_tool .active .active .se2_ol{background-position:-345px -103px} +#smart_editor2 .se2_text_tool .active .se2_ul,#smart_editor2 .se2_text_tool .active .active .se2_ul{background-position:-366px -103px} +#smart_editor2 .se2_text_tool .se2_indent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_indent{background-position:-408px -10px} +#smart_editor2 .se2_text_tool .se2_outdent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_outdent{background-position:-387px -10px} +#smart_editor2 .se2_text_tool .hover .se2_indent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_indent{background-position:-408px -72px} +#smart_editor2 .se2_text_tool .hover .se2_outdent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_outdent{background-position:-387px -72px} +#smart_editor2 .se2_text_tool .active .se2_indent,#smart_editor2 .se2_text_tool .active .active .se2_indent{background-position:-408px -103px} +#smart_editor2 .se2_text_tool .active .se2_outdent,#smart_editor2 .se2_text_tool .active .active .se2_outdent{background-position:-387px -103px} +#smart_editor2 .se2_text_tool .se2_lineheight{background-position:-429px -10px} +#smart_editor2 .se2_text_tool .hover .se2_lineheight{background-position:-429px -72px} +#smart_editor2 .se2_text_tool .active .se2_lineheight{background-position:-429px -103px} +#smart_editor2 .se2_text_tool .se2_url{background-position:-513px -10px} +#smart_editor2 .se2_text_tool .hover .se2_url{background-position:-513px -72px} +#smart_editor2 .se2_text_tool .active .se2_url{background-position:-513px -103px} +#smart_editor2 .se2_text_tool .se2_bgcolor{position:relative;background-position:-230px -10px} +#smart_editor2 .se2_text_tool .hover .se2_bgcolor{background-position:-230px -72px} +#smart_editor2 .se2_text_tool .active .se2_bgcolor{background-position:-230px -103px} +#smart_editor2 .se2_text_tool .se2_bgcolor_more{background-position:-251px -10px;width:10px} +#smart_editor2 .se2_text_tool .hover .se2_bgcolor_more{background-position:-251px -72px} +#smart_editor2 .se2_text_tool .active .se2_bgcolor_more{background-position:-251px -103px} +#smart_editor2 .se2_text_tool .se2_left{background-position:-261px -10px} +#smart_editor2 .se2_text_tool .hover .se2_left{background-position:-261px -72px} +#smart_editor2 .se2_text_tool .active .se2_left{background-position:-261px -103px} +#smart_editor2 .se2_text_tool .se2_center{background-position:-282px -10px} +#smart_editor2 .se2_text_tool .hover .se2_center{background-position:-282px -72px} +#smart_editor2 .se2_text_tool .active .se2_center{background-position:-282px -103px} +#smart_editor2 .se2_text_tool .se2_right{background-position:-303px -10px} +#smart_editor2 .se2_text_tool .hover .se2_right{background-position:-303px -72px} +#smart_editor2 .se2_text_tool .active .se2_right{background-position:-303px -103px} +#smart_editor2 .se2_text_tool .se2_justify{background-position:-324px -10px} +#smart_editor2 .se2_text_tool .hover .se2_justify{background-position:-324px -72px} +#smart_editor2 .se2_text_tool .active .se2_justify{background-position:-324px -103px} +#smart_editor2 .se2_text_tool .se2_blockquote{background-position:-471px -10px} +#smart_editor2 .se2_text_tool .hover .se2_blockquote{background-position:-471px -72px} +#smart_editor2 .se2_text_tool .active .se2_blockquote{background-position:-471px -103px} +#smart_editor2 .se2_text_tool .se2_character{background-position:-555px -10px} +#smart_editor2 .se2_text_tool .hover .se2_character{background-position:-555px -72px} +#smart_editor2 .se2_text_tool .active .se2_character{background-position:-555px -103px} +#smart_editor2 .se2_text_tool .se2_table{background-position:-576px -10px} +#smart_editor2 .se2_text_tool .hover .se2_table{background-position:-576px -72px} +#smart_editor2 .se2_text_tool .active .se2_table{background-position:-576px -103px} +#smart_editor2 .se2_text_tool .se2_find{background-position:-597px -10px} +#smart_editor2 .se2_text_tool .hover .se2_find{background-position:-597px -72px} +#smart_editor2 .se2_text_tool .active .se2_find{background-position:-597px -103px} +#smart_editor2 .se2_text_tool .se2_sup{background-position:-660px -10px} +#smart_editor2 .se2_text_tool .hover .se2_sup{background-position:-660px -72px} +#smart_editor2 .se2_text_tool .active .se2_sup{background-position:-660px -103px} +#smart_editor2 .se2_text_tool .se2_sub{background-position:-681px -10px} +#smart_editor2 .se2_text_tool .hover .se2_sub{background-position:-681px -72px} +#smart_editor2 .se2_text_tool .active .se2_sub{background-position:-681px -103px} +#smart_editor2 .se2_text_tool .se2_text_tool_more{background-position:0 -41px;width:13px} +#smart_editor2 .se2_text_tool .se2_text_tool_more span.tool_bg{background:none} +#smart_editor2 .se2_text_tool .hover .se2_text_tool_more{background-position:-13px -41px} +#smart_editor2 .se2_text_tool .active .se2_text_tool_more{background-position:-26px -41px} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_CN/smart_editor2_in.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_CN/smart_editor2_in.css new file mode 100644 index 00000000..fdecc092 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_CN/smart_editor2_in.css @@ -0,0 +1,24 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* COMMON */ +body,.se2_inputarea{margin:0;padding:0;font-family:'돋움',Dotum,Helvetica,Sans-serif;font-size:12px;line-height:1.5} +/* body,.se2_inputarea,.se2_inputarea th,.se2_inputarea td{margin:0;padding:0;font-family:'돋움',Dotum,Helvetica,Sans-serif;font-size:12px;line-height:1.5;color:#666} */ +.se2_inputarea p,.se2_inputarea br{margin:0;padding:0} +.se2_inputarea{margin:15px;word-wrap:break-word;*word-wrap:normal;*word-break:break-all} +.se2_inputarea td{word-break:break-all} +.se2_inputarea_890{width:741px;margin:20px 0 10px 64px} +.se2_inputarea_698{width:548px;margin:20px 0 10px 64px} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + .se2_inputarea td:empty:after,.se2_inputarea td > p:empty:after{content:"\00A0";line-height:1} +} +/* TEXT_TOOLBAR : QUOTE */ +.se2_quote1{margin:0 0 30px 20px;padding:0 8px;border-left:2px solid #ccc;color:#888} +.se2_quote2{margin:0 0 30px 13px;padding:0 8px 0 16px;background:url("../../img/bg_quote2.gif") 0 3px no-repeat;color:#888} +.se2_quote3{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #ccc;color:#888} +.se2_quote4{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #66b246;color:#888} +.se2_quote5{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #ccc;background:#fafafa;color:#888} +.se2_quote6{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #e5e5e5;color:#888} +.se2_quote7{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #66b246;color:#888} +.se2_quote8{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #e5e5e5;background:#fafafa;color:#888} +.se2_quote9{margin:0 0 30px;padding:12px 10px 11px;border:2px solid #e5e5e5;color:#888} +.se2_quote10{margin:0 0 30px;padding:12px 10px 11px;border:2px solid #e5e5e5;background:#fafafa;color:#888} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_CN/smart_editor2_items.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_CN/smart_editor2_items.css new file mode 100644 index 00000000..6cdfa1ef --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_CN/smart_editor2_items.css @@ -0,0 +1,447 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* TEXT_TOOLBAR : FONTNAME */ +#smart_editor2 .se2_tool .se2_l_font_fam{width:186px;margin:0;padding:0} +#smart_editor2 .se2_tool .se2_l_font_fam li{display:block;width:186px;height:21px;margin:0;padding:0;color:#333;cursor:pointer} +#smart_editor2 .se2_l_font_fam .hover,#smart_editor2 .se2_l_font_fam .active{background:#ebebeb} +#smart_editor2 .se2_l_font_fam button{width:184px;height:21px;margin:0;padding:2px 0 2px 0px;background:none;text-align:left} +#smart_editor2 .se2_l_font_fam button span{display:block;visibility:visible;overflow:visible;position:relative;top:auto;left:auto;width:auto;height:auto;margin:0 0 0 4px;padding:0;font-size:12px;line-height:normal;color:#333} +#smart_editor2 .se2_l_font_fam button span span{display:inline;visibility:visible;overflow:visible;width:auto;height:auto;margin:0 0 0 4px;font-family:Verdana;font-size:12px;line-height:14px;color:#888} +#smart_editor2 .se2_l_font_fam button span em{visibility:visible;overflow:auto;position:static;width:auto;height:auto;margin-right:-4px;font-size:12px;color:#888} +#smart_editor2 .se2_l_font_fam .se2_division{width:162px;height:2px !important;margin:1px 0 1px 0px;border:0;background:url("../../img/bg_line1.gif") 0 0 repeat-x;font-size:0;cursor:default} +/* TEXT_TOOLBAR : FONTSIZE */ +#smart_editor2 .se2_tool .se2_l_font_size{width:302px;margin:0;padding:0} +#smart_editor2 .se2_tool .se2_l_font_size li{width:302px;margin:0;padding:0;color:#333;cursor:pointer} +#smart_editor2 .se2_l_font_size .hover,#smart_editor2 .se2_l_font_size .active{background:#ebebeb} +#smart_editor2 .se2_l_font_size button{width:300px;height:auto;margin:0;padding:2px 0 1px 0px;*padding:4px 0 1px 0px;background:none;text-align:left} +#smart_editor2 .se2_l_font_size button span{display:block;visibility:visible;overflow:visible;position:relative;top:auto;left:auto;width:auto;height:auto;margin:0 0 0 4px;padding:0;line-height:normal;color:#373737;letter-spacing:0px} +#smart_editor2 .se2_l_font_size button span span{display:inline;margin:0 0 0 5px;padding:0} +#smart_editor2 .se2_l_font_size span em{visibility:visible;overflow:auto;position:static;width:auto;height:auto;color:#888} +/* TEXT_TOOLBAR : FONTCOLOR */ +#smart_editor2 .se2_palette{float:left;position:relative;width:225px;margin:0;padding:11px 0 10px 0} +#smart_editor2 .se2_palette .se2_pick_color{_display:inline;float:left;clear:both;width:205px;margin:0 0 0 11px;padding:0} +#smart_editor2 .se2_palette .se2_pick_color li{float:left;width:12px;height:12px;margin:0;padding:0} +#smart_editor2 .se2_palette .se2_pick_color li button{width:11px;height:11px;border:0} +#smart_editor2 .se2_palette .se2_pick_color li button span{display:block;visibility:visible;overflow:visible;position:absolute;top:1px;left:1px;width:11px;height:11px} +#smart_editor2 .se2_palette .se2_pick_color li button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0} +#smart_editor2 .se2_palette .se2_pick_color .hover button,#smart_editor2 .se2_palette .se2_pick_color .active button{width:11px;height:11px;border:1px solid #666} +#smart_editor2 .se2_palette .se2_pick_color .hover span,#smart_editor2 .se2_palette .se2_pick_color .active span{width:7px;height:7px;border:1px solid #fff} +#smart_editor2 .se2_palette .se2_view_more{_display:inline;float:left;width:46px;height:23px;margin:1px 0 0 1px;background:url("../../img/zh_CN/btn_set.png?160622") 0 -47px no-repeat} +#smart_editor2 .se2_palette .se2_view_more2{_display:inline;float:left;width:46px;height:23px;margin:1px 0 0 1px;background:url("../../img/zh_CN/btn_set.png?160622") 0 -24px no-repeat} +#smart_editor2 .se2_palette h4{_display:inline;float:left;width:203px;margin:9px 0 0 11px;padding:10px 0 4px 0;background:url("../../img/bg_line1.gif") repeat-x;font-weight:normal;font-size:12px;line-height:14px;color:#333;letter-spacing:-1px} +#smart_editor2 .se2_palette2{float:left;_float:none;width:214px;margin:9px 0 0 0;padding:11px 0 0 11px;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_palette2 .se2_color_set{float:left} +#smart_editor2 .se2_palette2 .se2_selected_color{_display:inline;float:left;width:83px;height:18px;margin:0;border:1px solid #c7c7c7;background:#fff} +#smart_editor2 .se2_palette2 .se2_selected_color span{_display:inline;float:left;width:79px;height:14px;margin:2px} +#smart_editor2 .se2_palette2 .input_ty1{_display:inline;float:left;width:67px;height:16px;margin:0 3px 0 3px;padding:2px 2px 0 4px;font-family:tahoma;font-size:11px} +#smart_editor2 .se2_palette2 button.se2_btn_insert{float:left;width:35px;height:21px;margin-left:2px;padding:0;background:url("../../img/zh_CN/btn_set.png?160622") -80px 0 no-repeat} +#smart_editor2 .se2_gradation1{float:left;_float:none;width:201px;height:128px;margin:4px 0 0 0;border:1px solid #c7c7c7;cursor:crosshair} +#smart_editor2 .se2_gradation2{float:left;_float:none;width:201px;height:10px;margin:4px 0 1px 0;border:1px solid #c7c7c7;cursor:crosshair} +/* TEXT_TOOLBAR : BGCOLOR */ +#smart_editor2 .se2_palette_bgcolor{width:225px;margin:11px 0 0;padding:0} +#smart_editor2 .se2_palette_bgcolor .se2_background{width:205px;margin:0 11px 0 11px} +#smart_editor2 .se2_palette_bgcolor .se2_background li{width:68px;height:20px} +#smart_editor2 .se2_palette_bgcolor .se2_background button{width:67px;height:19px;border:0} +#smart_editor2 .se2_palette_bgcolor .se2_background span{left:0;display:block;visibility:visible;overflow:visible;width:65px;height:17px;padding:0} +#smart_editor2 .se2_palette_bgcolor .se2_background span span{display:block;visibility:visible;overflow:visible;width:64px;height:16px;padding:3px 0 0 3px;font-size:11px;line-height:14px;text-align:left} +#smart_editor2 .se2_palette_bgcolor .se2_background .hover span{width:65px;height:17px;border:1px solid #666} +#smart_editor2 .se2_palette_bgcolor .se2_background .hover span span{width:62px;height:14px;padding:1px 0 0 1px;border:1px solid #fff} +/* TEXT_TOOLBAR : LINEHEIGHT */ +#smart_editor2 .se2_l_line_height{width:107px;margin:0;padding:0} +#smart_editor2 .se2_l_line_height li{width:107px;margin:0;padding:0;border-top:0;border-bottom:0;color:#333;cursor:pointer} +#smart_editor2 .se2_l_line_height .hover{background:#ebebeb} +#smart_editor2 .se2_l_line_height button{width:105px;height:19px;margin:0;padding:3px 0 2px 0px;background:none;text-align:left} +#smart_editor2 .se2_l_line_height button span{visibility:visible;overflow:visible;position:relative;width:auto;height:auto;margin:0;padding:0 0 0 15px;font-size:12px;line-height:normal;color:#373737} +#smart_editor2 .se2_l_line_height li button.active span{background:url("../../img/icon_set.gif?141007") 5px -30px no-repeat} +#smart_editor2 .se2_l_line_height_user{clear:both;width:83px;margin:5px 0 0 12px;padding:10px 0 0 0;_padding:11px 0 0 0;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_l_line_height_user h3{margin:0 0 4px 0;_margin:0 0 2px -1px;padding:0;line-height:14px;color:#000;letter-spacing:-1px} +#smart_editor2 .se2_l_line_height_user .bx_input{display:block;position:relative;width:83px} +#smart_editor2 .se2_l_line_height_user .btn_up{position:absolute;top:2px;*top:3px;left:68px;width:13px;height:8px;background:url("../../img/zh_CN/btn_set.png?160622") -86px -54px no-repeat} +#smart_editor2 .se2_l_line_height_user .btn_down{position:absolute;top:10px;*top:11px;left:68px;width:13px;height:8px;background:url("../../img/zh_CN/btn_set.png?160622") -86px -62px no-repeat} +#smart_editor2 .se2_l_line_height_user .btn_area{margin:5px 0 10px 0} +#smart_editor2 .se2_tool .btn_area .se2_btn_apply3{width:41px;height:24px;background:url("../../img/zh_CN/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_tool .btn_area .se2_btn_cancel3{width:39px;height:24px;margin-left:3px;background:url("../../img/zh_CN/btn_set.png?160622") -41px 0 no-repeat} +/* TEXT_TOOLBAR : QUOTE */ +#smart_editor2 .se2_quote{width:425px;height:56px} +#smart_editor2 .se2_quote ul{_display:inline;float:left;margin:11px 0 0 9px;padding:0} +#smart_editor2 .se2_quote li{_display:inline;float:left;margin:0 0 0 2px;padding:0} +#smart_editor2 .se2_quote button{width:34px;height:34px;margin:0;padding:0;background:url("../../img/zh_CN/btn_set.png?160622") no-repeat;cursor:pointer} +#smart_editor2 .se2_quote button span{left:0;display:block;visibility:visible;overflow:visible;width:32px;height:32px;margin:0;padding:0;border:1px solid #c7c7c7} +#smart_editor2 .se2_quote button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0} +#smart_editor2 .se2_quote .se2_quote1{background-position:1px -375px} +#smart_editor2 .se2_quote .se2_quote2{background-position:-32px -375px} +#smart_editor2 .se2_quote .se2_quote3{background-position:-65px -375px} +#smart_editor2 .se2_quote .se2_quote4{background-position:-98px -375px} +#smart_editor2 .se2_quote .se2_quote5{background-position:-131px -375px} +#smart_editor2 .se2_quote .se2_quote6{background-position:-164px -375px} +#smart_editor2 .se2_quote .se2_quote7{background-position:-197px -375px} +#smart_editor2 .se2_quote .se2_quote8{background-position:-230px -375px} +#smart_editor2 .se2_quote .se2_quote9{background-position:-263px -375px} +#smart_editor2 .se2_quote .se2_quote10{background-position:-296px -375px} +#smart_editor2 .se2_quote .hover button span,#smart_editor2 .se2_quote .active button span{width:30px;height:30px;margin:0;padding:0;border:2px solid #44b525} +#smart_editor2 .se2_quote .hover button span span,#smart_editor2 .se2_quote .active button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0} +#smart_editor2 .se2_quote .se2_cancel2{float:left;width:40px;height:35px;margin:11px 0 0 5px;background:url("../../img/zh_CN/btn_set.png?160622") -46px -24px no-repeat} +#smart_editor2 .se2_quote .se2_cancel2 span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0} +/* TEXT_TOOLBAR : HYPERLINK */ +#smart_editor2 .se2_url2{width:281px;padding:11px 11px 6px 11px;color:#666} +#smart_editor2 .se2_url2 .input_ty1{display:block;width:185px;height:16px;margin:0 5px 5px 0;*margin:-1px 5px 5px 0;padding:5px 2px 0 4px} +#smart_editor2 .se2_url2 .se2_url_new{width:15px;height:15px;margin:-1px 3px 1px -1px;*margin:-2px 3px 2px -1px;vertical-align:middle} +#smart_editor2 .se2_url2 label{font-size:11px;line-height:14px;vertical-align:middle} +#smart_editor2 .se2_url2 .se2_apply{position:absolute;top:13px;right:51px;width:41px;height:24px;margin:-1px 3px 1px 0;background:url("../../img/zh_CN/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_url2 .se2_cancel{position:absolute;top:13px;right:9px;width:39px;height:24px;margin:-1px 3px 1px 0;background:url("../../img/zh_CN/btn_set.png?160622") -41px 0 no-repeat} +/* TEXT_TOOLBAR : SCHARACTER */ +#smart_editor2 .se2_bx_character{width:469px;height:272px;margin:0;padding:0;background:url("../../img/bx_set_110302.gif") 9px -1230px no-repeat} +#smart_editor2 .se2_bx_character .se2_char_tab{_display:inline;float:left;position:relative;width:443px;margin:11px 10px 200px 11px;padding:0 0 0 1px} +#smart_editor2 .se2_bx_character .se2_char_tab li{position:static;margin:0 0 0 -1px;padding:0} +#smart_editor2 .se2_bx_character .se2_char1{width:77px;height:26px;background:url("../../img/zh_CN/btn_set.png?160622") 0 -204px no-repeat} +#smart_editor2 .se2_bx_character .se2_char2{width:90px;height:26px;background:url("../../img/zh_CN/btn_set.png?160622") -76px -204px no-repeat} +#smart_editor2 .se2_bx_character .se2_char3{width:84px;height:26px;background:url("../../img/zh_CN/btn_set.png?160622") -165px -204px no-repeat} +#smart_editor2 .se2_bx_character .se2_char4{width:52px;height:26px;background:url("../../img/zh_CN/btn_set.png?160622") -248px -204px no-repeat} +#smart_editor2 .se2_bx_character .se2_char5{width:91px;height:26px;background:url("../../img/zh_CN/btn_set.png?160622") -299px -204px no-repeat} +#smart_editor2 .se2_bx_character .se2_char6{width:54px;height:26px;background:url("../../img/zh_CN/btn_set.png?160622") -389px -204px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char1{width:77px;height:26px;background:url("../../img/zh_CN/btn_set.png?160622") 0 -230px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char2{width:90px;height:26px;background:url("../../img/zh_CN/btn_set.png?160622") -76px -230px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char3{width:84px;height:26px;background:url("../../img/zh_CN/btn_set.png?160622") -165px -230px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char4{width:52px;height:26px;background:url("../../img/zh_CN/btn_set.png?160622") -248px -230px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char5{width:91px;height:26px;background:url("../../img/zh_CN/btn_set.png?160622") -299px -230px no-repeat} +#smart_editor2 .se2_bx_character .active .se2_char6{width:54px;height:26px;background:url("../../img/zh_CN/btn_set.png?160622") -389px -230px no-repeat} +#smart_editor2 .se2_bx_character .se2_s_character{display:none;position:absolute;top:26px;left:0;width:448px;height:194px;margin:0;padding:0} +#smart_editor2 .se2_bx_character .active .se2_s_character{display:block} +#smart_editor2 .se2_bx_character .se2_s_character ul{float:left;width:422px;height:172px;margin:0;padding:9px 0 0 11px} +#smart_editor2 .se2_bx_character .se2_s_character li{_display:inline;float:left;position:relative;width:20px;height:18px;margin:0 0 1px 1px;background:#fff} +#smart_editor2 .se2_bx_character .se2_s_character button{width:20px;height:18px;margin:0;padding:2px;background:none} +#smart_editor2 .se2_bx_character .se2_s_character .hover,#smart_editor2 .se2_bx_character .se2_s_character .active{background:url("../../img/zh_CN/btn_set.png?160622") -446px -274px no-repeat} +#smart_editor2 .se2_bx_character .se2_s_character button span{left:0;display:block;visibility:visible;overflow:visible;width:14px;height:16px;margin:3px 0 0 3px;border:0;background:none;font-size:12px;line-height:normal} +#smart_editor2 .se2_apply_character{clear:both;position:relative;padding:0 0 0 11px} +#smart_editor2 .se2_apply_character label{margin:0 3px 0 0;font-size:12px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_apply_character .input_ty1{width:283px;height:17px;margin:-1px 5px 1px 0;padding:4px 0 0 5px;font-size:12px;color:#666;letter-spacing:0;vertical-align:middle} +#smart_editor2 .se2_apply_character .se2_confirm{width:41px;height:24px;margin-right:3px;background:url("../../img/zh_CN/btn_set.png?160622") no-repeat;vertical-align:middle} +#smart_editor2 .se2_apply_character .se2_cancel{width:39px;height:24px;background:url("../../img/zh_CN/btn_set.png?160622") -41px 0 no-repeat;vertical-align:middle} +/* TEXT_TOOLBAR : TABLECREATOR */ +#smart_editor2 .se2_table_set{position:relative;width:166px;margin:3px 11px 0 11px;padding:8px 0 0 0} +#smart_editor2 .se2_table_set .se2_cell_num{float:left;width:73px} +#smart_editor2 .se2_table_set .se2_cell_num dt{float:left;clear:both;width:17px;height:23px;margin:0;padding:0} +#smart_editor2 .se2_table_set .se2_cell_num dt label{display:block;margin:5px 0 0 0;font-size:11px;color:#666} +#smart_editor2 .se2_table_set .se2_cell_num dd{float:left;position:relative;width:54px;height:23px;margin:0;padding:0} +#smart_editor2 .se2_table_set .se2_cell_num .input_ty2{display:block;width:32px;height:16px;*margin:-1px 0 0 0;padding:2px 19px 0 0px;border:1px solid #c7c7c7;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666;text-align:right;*direction:rtl} +#smart_editor2 .se2_table_set .se2_cell_num .input_ty2::-ms-clear{display:none} +#smart_editor2 .se2_table_set .se2_pre_table{float:right;width:91px;height:43px;background:#c7c7c7;border-spacing:1px} +#smart_editor2 .se2_table_set .se2_pre_table tr{background:#fff} +#smart_editor2 .se2_table_set .se2_pre_table td{font-size:0;line-height:0} +#smart_editor2 .se2_table_set .se2_add{position:absolute;top:2px;right:3px;width:13px;height:8px;background:url("../../img/zh_CN/btn_set.png?160622") -86px -54px no-repeat} +#smart_editor2 .se2_table_set .se2_del{position:absolute;top:10px;right:3px;width:13px;height:8px;background:url("../../img/zh_CN/btn_set.png?160622") -86px -62px no-repeat} +/* TEXT_TOOLBAR : TABLEEDITOR */ +#smart_editor2 .se2_table_set .se2_t_proper1{float:left;width:166px;margin:7px 0 0 0;padding:10px 0 5px;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_table_set .se2_t_proper1 dt{width:166px;margin:0 0 6px 0} +#smart_editor2 .se2_table_set .se2_t_proper1 dd{width:166px} +#smart_editor2 .se2_table_set .se2_t_proper1 dt input{width:15px;height:15px;margin:-1px 3px 1px 0;_margin:-2px 3px 2px 0;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper1 dt label{font-weight:bold;font-size:11px;color:#666;letter-spacing:-1px;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper1_1{float:left;position:relative;z-index:59;width:166px;margin:1px 0 0 0} +#smart_editor2 .se2_table_set .se2_t_proper1_2{z-index:54;margin:0} +#smart_editor2 .se2_table_set .se2_t_proper1_3{z-index:53;margin:0} +#smart_editor2 .se2_table_set .se2_t_proper1_4{z-index:52;margin:0} +#smart_editor2 .se2_table_set .se2_t_proper1_1 dt{_display:inline;float:left;clear:both;width:66px;height:22px;margin:1px 0 0 18px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 dt label{display:block;margin:4px 0 0 0;font-weight:normal;font-size:11px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 dd{float:left;position:relative;width:82px;height:23px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .input_ty1{width:72px;height:16px;*margin:-1px 0 0 0;padding:2px 2px 0 6px;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .input_ty3{float:left;width:49px;height:16px;margin:0 3px 0 0;padding:2px 4px 0 4px;border:1px solid #c7c7c7;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_add{top:2px;right:2px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_del{top:10px;right:2px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_color_set .input_ty1{_display:inline;float:left;width:67px;height:16px;margin:0 3px 0 3px;padding:2px 2px 0 4px;font-family:tahoma,verdana,times New Roman;font-size:11px} +#smart_editor2 .se2_select_ty1{position:relative;width:80px;height:18px;border:1px solid #c7c7c7;background:#fff;font-size:11px;line-height:14px;text-align:left} +#smart_editor2 .se2_select_ty1 span{float:left;width:54px;height:18px;margin:0 0 0 5px;font-size:11px;line-height:14px;color:#666} +#smart_editor2 .se2_select_ty1 .se2_b_style0{position:relative;top:3px;left:-3px;white-space:nowrap} +#smart_editor2 .se2_select_ty1 .se2_b_style1{height:15px;margin:3px 0 0 4px;font-size:11px;line-height:14px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_select_ty1 .se2_b_style2{background:url("../../img/bg_set.gif") 0 -50px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style3{background:url("../../img/bg_set.gif") 0 -68px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style4{background:url("../../img/bg_set.gif") 0 -85px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style5{background:url("../../img/bg_set.gif") 0 -103px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style6{background:url("../../img/bg_set.gif") 0 -121px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style7{background:url("../../img/bg_set.gif") 0 -139px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_view_more{position:absolute;top:1px;right:1px;width:13px;height:16px;background:url("../../img/zh_CN/btn_set.png?160622") -112px -54px no-repeat} +#smart_editor2 .se2_select_ty1 .se2_view_more2{position:absolute;top:1px;right:1px;width:13px;height:16px;background:url("../../img/zh_CN/btn_set.png?160622") -99px -54px no-repeat} +/* TEXT_TOOLBAR : TABLEEDITOR > BORDER */ +#smart_editor2 .se2_table_set .se2_b_t_b1{border-top:1px solid #b1b1b1} +#smart_editor2 .se2_layer_b_style{position:absolute;top:20px;right:0px;width:80px;padding-bottom:1px;border:1px solid #c7c7c7;border-top:1px solid #a8a8a8;background:#fff} +#smart_editor2 .se2_layer_b_style ul{width:80px;margin:0;padding:1px 0 0 0} +#smart_editor2 .se2_layer_b_style li{width:80px;height:18px;margin:0;padding:0} +#smart_editor2 .se2_layer_b_style .hover,#smart_editor2 .se2_layer_b_style .active{background:#ebebeb} +#smart_editor2 .se2_layer_b_style button{width:80px;height:18px;background:none} +#smart_editor2 .se2_layer_b_style button span{left:0;display:block;visibility:visible;overflow:visible;width:71px;height:18px;margin:0 0 0 5px;font-size:11px;line-height:15px;text-align:left} +#smart_editor2 .se2_layer_b_style button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0} +#smart_editor2 .se2_layer_b_style .se2_b_style1 span{margin:3px 0 0 4px;font-size:11px;line-height:14px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_layer_b_style .se2_b_style2 span{background:url("../../img/bg_set.gif") 0 -50px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style3 span{background:url("../../img/bg_set.gif") 0 -68px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style4 span{background:url("../../img/bg_set.gif") 0 -86px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style5 span{background:url("../../img/bg_set.gif") 0 -103px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style6 span{background:url("../../img/bg_set.gif") 0 -121px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style7 span{background:url("../../img/bg_set.gif") 0 -139px repeat-x} +/* TEXT_TOOLBAR : TABLEEDITOR > COLOR */ +#smart_editor2 .se2_pre_color{float:left;width:18px;height:18px;border:1px solid #c7c7c7} +#smart_editor2 .se2_pre_color button{float:left;width:14px;height:14px;margin:2px 0 0 2px;padding:0} +#smart_editor2 .se2_pre_color button span{overflow:hidden;position:absolute;top:-10000px;left:-10000px;z-index:-100;width:0;height:0} +/* TEXT_TOOLBAR : TABLEEDITOR > DIMMED */ +#smart_editor2 .se2_table_set .se2_t_dim1{clear:both;position:absolute;top:71px;left:16px;z-index:60;width:157px;height:118px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_table_set .se2_t_dim2{position:absolute;top:116px;left:16px;z-index:55;width:157px;height:45px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_table_set .se2_t_dim3{clear:both;position:absolute;top:192px;left:16px;z-index:51;width:157px;height:39px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +/* TEXT_TOOLBAR : TABLEEDITOR > STYLE PREVIEW */ +#smart_editor2 .se2_table_set .se2_t_proper2{float:left;position:relative;z-index:50;width:166px;margin:2px 0 0 0} +#smart_editor2 .se2_table_set .se2_t_proper2 dt{float:left;width:84px;height:33px;margin:4px 0 0 0} +#smart_editor2 .se2_table_set .se2_t_proper2 dt input{width:15px;height:15px;margin:-1px 3px 1px 0;_margin:-2px 3px 2px 0;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper2 dt label{font-weight:bold;font-size:11px;color:#666;letter-spacing:-1px;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper2 dd{float:left;width:66px;height:33px} +#smart_editor2 .se2_select_ty2{position:relative;width:65px;height:31px;border:1px solid #c7c7c7;background:#fff;font-size:11px;line-height:14px;text-align:left} +#smart_editor2 .se2_select_ty2 span{float:left;width:45px;height:25px;margin:3px 0 0 3px;background:url("../../img/zh_CN/btn_set.png?160622") repeat-x} +#smart_editor2 .se2_select_ty2 .se2_t_style1{background-position:0 -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style2{background-position:-46px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style3{background-position:-92px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style4{background-position:-138px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style5{background-position:-184px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style6{background-position:-230px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style7{background-position:-276px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style8{background-position:-322px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style9{background-position:0 -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style10{background-position:-46px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style11{background-position:-92px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style12{background-position:-138px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style13{background-position:-184px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style14{background-position:-230px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style15{background-position:-276px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style16{background-position:-322px -436px} +#smart_editor2 .se2_select_ty2 .se2_view_more{position:absolute;top:1px;right:1px;_right:0px;width:13px !important;height:29px !important;background:url("../../img/zh_CN/btn_set.png?160622") -355px -48px no-repeat !important} +#smart_editor2 .se2_select_ty2 .se2_view_more2{position:absolute;top:1px;right:1px;_right:0px;width:13px !important;height:29px !important;background:url("../../img/zh_CN/btn_set.png?160622") -368px -48px no-repeat !important} +#smart_editor2 .se2_select_ty2 .se2_view_more span{display:none} +/* TEXT_TOOLBAR : TABLEEDITOR > STYLE */ +#smart_editor2 .se2_layer_t_style{position:absolute;top:33px;right:15px;width:208px;border:1px solid #c7c7c7;border-top:1px solid #a8a8a8;background:#fff} +#smart_editor2 .se2_layer_t_style ul{width:204px;height:126px;margin:1px 2px;padding:1px 0 0 0;background:#fff} +#smart_editor2 .se2_layer_t_style li{_display:inline;float:left;width:45px;height:25px;margin:1px;padding:1px;border:1px solid #fff} +#smart_editor2 .se2_layer_t_style .hover,#smart_editor2 .se2_layer_t_style .active{border:1px solid #666;background:#fff} +#smart_editor2 .se2_layer_t_style button{width:45px;height:25px;background:url("../../img/zh_CN/btn_set.png?160622") repeat-x !important} +#smart_editor2 .se2_layer_t_style .se2_t_style1{background-position:0 -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style2{background-position:-46px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style3{background-position:-92px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style4{background-position:-138px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style5{background-position:-184px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style6{background-position:-230px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style7{background-position:-276px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style8{background-position:-322px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style9{background-position:0 -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style10{background-position:-46px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style11{background-position:-92px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style12{background-position:-138px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style13{background-position:-184px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style14{background-position:-230px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style15{background-position:-276px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style16{background-position:-322px -436px !important} +#smart_editor2 .se2_table_set .se2_btn_area{float:left;width:166px;margin:6px 0 0 0;padding:12px 0 8px 0;background:url("../../img/bg_line1.gif") repeat-x;text-align:center} +#smart_editor2 .se2_table_set button.se2_apply{width:41px;height:24px;margin-right:3px;background:url("../../img/zh_CN/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_table_set button.se2_cancel{width:39px;height:24px;background:url("../../img/zh_CN/btn_set.png?160622") -41px 0 no-repeat} +#smart_editor2 .se2_table_set .se2_rd{width:14px;height:14px;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_celltit{font-size:11px;font-size:11px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_table_set dt label.se2_celltit{display:inline} +/* TEXT_TOOLBAR : FINDREPLACE */ +#smart_editor2 .se2_bx_find_revise{position:relative;width:255px;margin:0;padding:0} +#smart_editor2 .se2_bx_find_revise .se2_close{position:absolute;top:5px;right:8px;width:20px;height:20px;background:url("../../img/zh_CN/btn_set.png?160622") -151px -1px no-repeat} +#smart_editor2 .se2_bx_find_revise h3{margin:0;padding:10px 0 13px 10px;background:url("../../img/bg_find_h3.gif") 0 -1px repeat-x;font-size:12px;line-height:14px;letter-spacing:-1px} +#smart_editor2 .se2_bx_find_revise ul{position:relative;margin:8px 0 0 0;padding:0 0 0 12px} +#smart_editor2 .se2_bx_find_revise ul li{_display:inline;float:left;position:static;margin:0 0 0 -1px;padding:0} +#smart_editor2 .se2_bx_find_revise .se2_tabfind{width:117px;height:26px;background:url("../../img/zh_CN/btn_set.png?160622") 0 -100px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_tabrevise{width:117px;height:26px;background:url("../../img/zh_CN/btn_set.png?160622") -116px -100px no-repeat} +#smart_editor2 .se2_bx_find_revise .active .se2_tabfind{width:117px;height:26px;background:url("../../img/zh_CN/btn_set.png?160622") 0 -126px no-repeat} +#smart_editor2 .se2_bx_find_revise .active .se2_tabrevise{width:117px;height:26px;background:url("../../img/zh_CN/btn_set.png?160622") -116px -126px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_in_bx_find dl{_display:inline;float:left;width:223px;margin:0 0 0 9px;padding:7px 0 13px 14px;background:url("../../img/bx_set_110302.gif") -289px -1518px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_in_bx_revise dl{_display:inline;float:left;width:223px;margin:0 0 0 9px;padding:7px 0 13px 14px;background:url("../../img/bx_set_110302.gif") -289px -1619px no-repeat} +#smart_editor2 .se2_bx_find_revise dt{_display:inline;float:left;clear:both;width:55px;margin:1px 0 2px 0} +#smart_editor2 .se2_bx_find_revise dd{float:left;margin:0 0 2px 0} +#smart_editor2 .se2_bx_find_revise label{float:left;padding:5px 0 0 0;font-size:11px;color:#666;letter-spacing:-2px} +#smart_editor2 .se2_bx_find_revise input{float:left;width:151px;height:12px;margin:1px 0 0 0;padding:3px 2px 3px 4px;font-size:12px;color:#666} +#smart_editor2 .se2_bx_find_revise .se2_find_btns{float:left;clear:both;width:255px;padding:8px 0 10px 0;text-align:center} +#smart_editor2 .se2_bx_find_revise .se2_find_next{width:81px;height:24px;margin:0 3px 0 0;background:url("../../img/zh_CN/btn_set.png?160622") -180px -48px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_find_next2{width:78px;height:24px;margin:0 3px 0 0;background:url("../../img/zh_CN/btn_set.png?160622") -180px -24px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_revise1{width:52px;height:24px;margin:0 3px 0 0;background:url("../../img/zh_CN/btn_set.png?160622") -261px -48px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_revise2{width:55px;height:24px;margin:0 3px 0 0;background:url("../../img/zh_CN/btn_set.png?160622") -259px -24px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_cancel{width:39px;height:24px;background:url("../../img/zh_CN/btn_set.png?160622") -41px 0 no-repeat} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE */ +#smart_editor2 .se2_qmax{position:absolute;width:18px;height:18px;background:url("../../img/zh_CN/btn_set.png?160622") -339px -169px no-repeat} +#smart_editor2 .se2_qeditor{position:absolute;top:0;left:0;width:183px;margin:0;padding:0;border:1px solid #c7c7c7;border-right:1px solid #ababab;border-bottom:1px solid #ababab;background:#fafafa} +#smart_editor2 .se2_qeditor label,#smart_editor2 .se2_qeditor span,#smart_editor2 .se2_qeditor dt{font-size:11px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_qbar{position:relative;width:183px;height:11px;background:url("../../img/bx_set_110302.gif") 0 -731px no-repeat} +#smart_editor2 .se2_qbar .se2_qmini{position:absolute;top:-1px;right:0;*right:-1px;_right:-3px;width:18px;height:14px;background:url("../../img/zh_CN/btn_set.png?160622") -315px -170px no-repeat} +#smart_editor2 .se2_qbar .se2_qmini button{width:20px;height:14px;margin-top:-1px} +#smart_editor2 .se2_qeditor .se2_qbody0{float:left;border:1px solid #fefefe} +#smart_editor2 .se2_qeditor .se2_qbody{position:relative;z-index:90;width:174px;padding:4px 0 0 7px} +#smart_editor2 .se2_qeditor .se2_qe1{overflow:hidden;width:174px} +#smart_editor2 .se2_qeditor .se2_qe1 dt{float:left;width:22px;height:18px;padding:4px 0 0 0} +#smart_editor2 .se2_qeditor .se2_qe1 dd{float:left;width:65px;height:22px} +#smart_editor2 .se2_qeditor .se2_addrow{width:28px;height:19px;background:url("../../img/zh_CN/btn_set.png?160622") no-repeat -385px -49px} +#smart_editor2 .se2_qeditor .se2_addcol{width:29px;height:19px;background:url("../../img/zh_CN/btn_set.png?160622") no-repeat -413px -49px} +#smart_editor2 .se2_qeditor .se2_seprow{width:28px;height:19px;background:url("../../img/zh_CN/btn_set.png?160622") no-repeat -385px -68px} +#smart_editor2 .se2_qeditor .se2_sepcol{width:29px;height:19px;background:url("../../img/zh_CN/btn_set.png?160622") no-repeat -413px -68px} +#smart_editor2 .se2_qeditor .se2_delrow{width:28px;height:19px;background:url("../../img/zh_CN/btn_set.png?160622") no-repeat -385px -106px} +#smart_editor2 .se2_qeditor .se2_delcol{width:29px;height:19px;background:url("../../img/zh_CN/btn_set.png?160622") no-repeat -413px -106px} +#smart_editor2 .se2_qeditor .se2_merrow{width:57px;height:19px;background:url("../../img/zh_CN/btn_set.png?160622") no-repeat -385px -125px} +#smart_editor2 .se2_qeditor .se2_mercol{width:57px;height:19px;background:url("../../img/zh_CN/btn_set.png?160622") no-repeat -413px -125px} +#smart_editor2 .se2_qeditor .se2_seprow_off{width:28px;height:19px;background:url("../../img/zh_CN/btn_set.png?160622") no-repeat -385px -87px} +#smart_editor2 .se2_qeditor .se2_sepcol_off{width:29px;height:19px;background:url("../../img/zh_CN/btn_set.png?160622") no-repeat -413px -87px} +#smart_editor2 .se2_qeditor .se2_merrow_off{width:57px;height:19px;background:url("../../img/zh_CN/btn_set.png?160622") no-repeat -385px -144px} +#smart_editor2 .se2_qeditor .se2_mercol_off{width:57px;height:19px;background:url("../../img/zh_CN/btn_set.png?160622") no-repeat -413px -144px} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND */ +#smart_editor2 .se2_qeditor .se2_qe2{_display:inline;float:left;position:relative;z-index:100;width:165px;margin:2px 0 0 1px;padding:7px 0 0 0;background:url("../../img/bg_line1.gif") repeat-x;zoom:1} +#smart_editor2 .se2_qeditor .se2_qe2_1 dt{float:left;width:79px;padding:3px 0 0 0} +#smart_editor2 .se2_qeditor .se2_qe2_1 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qeditor .se2_qe2_1 dd{float:left;position:relative;zoom:1} +#smart_editor2 .se2_qeditor .se2_qe2_3{padding:7px 0 6px 0} +/* My글양식 없을때 */ +#smart_editor2 .se2_qeditor .se2_qe2_2{position:relative;_position:absolute} +#smart_editor2 .se2_qeditor .se2_qe2_2 dt{float:left;width:50px;padding:3px 0 0 13px} +#smart_editor2 .se2_qeditor .se2_qe2_2 dt input{width:15px;height:15px;margin:-1px 2px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qeditor .se2_qe2_2 dd{float:left} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > STYLE */ +#smart_editor2 .se2_table_set .se2_qbody .se2_t_proper2{float:left;*float:none;position:static;width:166px;margin:5px 0 0 1px} +#smart_editor2 .se2_qeditor .se2_qe3 dt{float:left;width:79px;padding:0} +#smart_editor2 .se2_qeditor .se2_qe3 dt label{font-weight:normal} +#smart_editor2 .se2_qeditor .se2_qe3 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qeditor .se2_qe3 dd .se2_qe3_table{position:relative} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND PREWVIEW */ +#smart_editor2 .se2_qeditor .se2_pre_color{float:left;width:18px;height:18px;border:1px solid #c7c7c7} +#smart_editor2 .se2_qeditor .se2_pre_color button{float:left;width:14px;height:14px;margin:2px 0 0 2px;padding:0} +#smart_editor2 .se2_qeditor .se2_pre_color button span{overflow:hidden;position:absolute;top:-10000px;left:-10000px;z-index:-100;width:0;height:0} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND LAYER */ +#smart_editor2 .se2_qeditor .se2_layer{float:left;clear:both;position:absolute;top:20px;left:0;margin:0;padding:0;border:1px solid #c7c7c7;border-top:1px solid #9a9a9a;background:#fafafa} +#smart_editor2 .se2_qeditor .se2_layer .se2_in_layer{float:left;margin:0;padding:0;border:1px solid #fff;background:#fafafa} +#smart_editor2 .se2_qeditor .se2_layer button{vertical-align:top} +#smart_editor2 .se2_qeditor .se2_layer .se2_pick_color li{position:relative} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND IMAGE */ +#smart_editor2 .se2_qeditor .se2_pre_bgimg{float:left;width:14px;height:14px;padding:2px;border:1px solid #c7c7c7} +#smart_editor2 .se2_qeditor .se2_qe2_2 button{width:16px;height:16px;background:url("../../img/zh_CN/btn_set.png?160622") 0 -261px no-repeat} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND IMAGE LAYER */ +#smart_editor2 .se2_cellimg_set{_display:inline;float:left;width:136px;margin:4px 3px 0 4px;padding-bottom:4px} +#smart_editor2 .se2_cellimg_set li{_display:inline;float:left;width:16px;height:16px;margin:0 1px 1px 0} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg0{background-position:-255px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg1{background-position:0 -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg2{background-position:-17px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg3{background-position:-34px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg4{background-position:-51px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg5{background-position:-68px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg6{background-position:-85px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg7{background-position:-102px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg8{background-position:-119px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg9{background-position:-136px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg10{background-position:-153px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg11{background-position:-170px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg12{background-position:-187px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg13{background-position:-204px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg14{background-position:-221px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg15{background-position:-238px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg16{background-position:-255px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg17{background-position:0 -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg18{background-position:-17px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg19{background-position:-34px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg20{background-position:-51px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg21{background-position:-68px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg22{background-position:-85px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg23{background-position:-102px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg24{background-position:-119px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg25{background-position:-136px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg26{background-position:-153px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg27{background-position:-170px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg28{background-position:-187px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg29{background-position:-204px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg30{background-position:-221px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg31{background-position:-238px -278px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg button{width:14px;height:14px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg1{background-position:-1px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg2{background-position:-18px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg3{background-position:-35px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg4{background-position:-52px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg5{background-position:-69px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg6{background-position:-86px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg7{background-position:-103px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg8{background-position:-120px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg9{background-position:-137px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg10{background-position:-154px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg11{background-position:-171px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg12{background-position:-188px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg13{background-position:-205px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg14{background-position:-222px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg15{background-position:-239px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg16{background-position:-256px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg17{background-position:-1px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg18{background-position:-18px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg19{background-position:-35px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg20{background-position:-52px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg21{background-position:-69px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg22{background-position:-86px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg23{background-position:-103px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg24{background-position:-120px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg25{background-position:-137px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg26{background-position:-154px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg27{background-position:-171px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg28{background-position:-188px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg29{background-position:-205px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg30{background-position:-222px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg31{background-position:-239px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg32{background-position:-256px -279px} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > MY REVIEW */ +#smart_editor2 .se2_btn_area{_display:inline;float:left;clear:both;width:166px;margin:5px 0 0 1px;padding:7px 0 6px 0;background:url("../../img/bg_line1.gif") repeat-x;text-align:center} +#smart_editor2 .se2_btn_area .se2_btn_save{width:97px;height:21px;background:url("../../img/zh_CN/btn_set.png?160622") -369px -163px no-repeat} +/* TEXT_TOOLBAR : QUICKEDITOR_IMAGE */ +#smart_editor2 .se2_qe10{width:166px;margin:0;*margin:-2px 0 0 0} +#smart_editor2 .se2_qe10 label{margin:0 1px 0 0;vertical-align:middle} +#smart_editor2 .se2_qe10 .se2_sheight{margin-left:4px} +#smart_editor2 .se2_qe10 .input_ty1{width:30px;height:13px;margin:0 0 1px 1px;padding:3px 4px 0 1px;font-size:11px;letter-spacing:0;text-align:right;vertical-align:middle} +#smart_editor2 .se2_qe10 .se2_sreset{width:41px;height:19px;margin-left:3px;background:url("../../img/zh_CN/btn_set.png?160622") -401px -184px no-repeat;vertical-align:middle} +#smart_editor2 .se2_qe10_1{margin-top:4px;padding:10px 0 3px;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_qe10_1 input{width:15px;height:15px;margin:-1px 3px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qe11{float:left;width:166px;margin:4px 0 0 0;padding:7px 0 2px 0;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_qe11_1{float:left;width:99px} +#smart_editor2 .se2_qe11_1 dt{float:left;width:56px;height:15px;padding:5px 0 0 0} +#smart_editor2 .se2_qe11_1 dd{float:left;position:relative;width:38px;height:20px} +#smart_editor2 .se2_qe11_1 .input_ty1{display:block;width:29px;height:15px;margin:0;*margin:-1px 0 1px 0;padding:3px 1px 0 5px;font-size:11px;letter-spacing:0;text-align:left} +#smart_editor2 .se2_qe11_1 .se2_add{position:absolute;top:2px;right:3px;width:13px;height:8px;background:url("../../img/zh_CN/btn_set.png?160622") -86px -54px no-repeat} +#smart_editor2 .se2_qe11_1 .se2_del{position:absolute;top:10px;right:3px;width:13px;height:8px;background:url("../../img/zh_CN/btn_set.png?160622") -86px -62px no-repeat} +#smart_editor2 .se2_qe11_2{float:left;width:67px} +#smart_editor2 .se2_qe11_2 dt{float:left;width:47px;margin:5px 0 0 0} +#smart_editor2 .se2_qe11_2 dd{float:left;position:relative;width:20px} +#smart_editor2 .se2_qe12{float:left;width:166px;margin:3px 0 0 0;padding:7px 0 0 0;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_qe12 dt{float:left;margin:5px 4px 0 0} +#smart_editor2 .se2_qe12 dd{float:left;padding:0 0 6px 0} +#smart_editor2 .se2_qe12 .se2_align0{float:left;width:19px;height:21px;background:url("../../img/zh_CN/btn_set.png?160622") -276px -121px no-repeat} +#smart_editor2 .se2_qe12 .se2_align1{float:left;width:19px;height:21px;background:url("../../img/zh_CN/btn_set.png?160622") -295px -121px no-repeat} +#smart_editor2 .se2_qe12 .se2_align2{float:left;width:20px;height:21px;background:url("../../img/zh_CN/btn_set.png?160622") -314px -121px no-repeat} +#smart_editor2 .se2_qe13{position:relative;z-index:10;zoom:1} +#smart_editor2 .se2_qe13 dt{float:left;width:62px;padding:3px 0 0} +#smart_editor2 .se2_qe13 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle;zoom:1} +#smart_editor2 .se2_qe13 dt .se2_qdim2{width:32px} +#smart_editor2 .se2_qe13 dd .se2_select_ty1{width:38px} +#smart_editor2 .se2_qe13 dd .se2_select_ty1 span{width:15px} +#smart_editor2 .se2_qe13 dd .input_ty1{width:20px} +#smart_editor2 .se2_qe13 dd .se2_palette2 .input_ty1{width:67px} +#smart_editor2 .se2_qe13 .se2_add{*top:3px} +#smart_editor2 .se2_qe13 .se2_del{*top:11px} +#smart_editor2 .se2_qe13 .se2_layer_b_style{right:-2px;_right:0} +#smart_editor2 .se2_qe13 .se2_layer_b_style li span{width:auto;margin:0 4px 0 5px;padding-top:2px} +#smart_editor2 .se2_qe13 dd{_display:inline;float:left;position:relative;width:29px;margin-right:5px;_margin-right:3px;zoom:1} +#smart_editor2 .se2_qe13 dd .se2_palette h4{margin-top:9px;font-family:dotum;font-size:12px} +#smart_editor2 .se2_qe13 dd.dd_type{width:38px} +#smart_editor2 .se2_qe13 dd.dd_type2{width:37px;margin-right:3px} +#smart_editor2 .se2_qe13 dd.dd_type2 .input_ty1{width:29px} +#smart_editor2 .se2_qe13 dd.dd_type2 button{right:2px;_right:1px} +#smart_editor2 .se2_qe13 dd.dd_type3{width:20px;margin:0} +#smart_editor2 .se2_qe13_v1{_display:inline;float:left;margin:2px 0 1px} +#smart_editor2 .se2_qe13_v1 dt{padding:4px 0 0 1px} +#smart_editor2 .se2_qe13_v2{_display:inline;float:left;position:relative;z-index:100;width:165px;margin:4px 0 0 1px;zoom:1} +#smart_editor2 .se2_qe13_v2 dd{width:18px;margin:0} +#smart_editor2 .se2_qeditor .se2_qdim1{clear:both;position:absolute;top:25px;left:115px;width:60px;height:23px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim2{clear:both;position:absolute;top:55px;left:24px;z-index:110;width:87px;height:22px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim3{clear:both;position:absolute;top:55px;left:118px;z-index:110;width:56px;height:22px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim4{clear:both;position:absolute;top:81px;left:23px;z-index:35;width:154px;height:35px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim5{clear:both;position:absolute;top:31px;left:106px;width:68px;height:26px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim6c{clear:both;position:absolute;top:25px;left:28px;width:29px;height:23px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim6r{clear:both;position:absolute;top:25px;left:57px;width:29px;height:23px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_highedit{float:right;width:56px;height:21px;margin:-27px 8px 0 0;background:url("../../img/zh_CN/btn_set.png?160622") -329px -142px no-repeat} +#smart_editor2 .se2_qeditor .se2_qdim7{clear:both;position:absolute;top:55px;left:24px;z-index:110;width:150px;height:48px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim8{clear:both;position:absolute;top:105px;left:24px;z-index:110;width:150px;height:37px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim9{clear:both;position:absolute;top:55px;left:111px;z-index:110;width:65px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim10{clear:both;position:absolute;top:55px;left:100px;z-index:110;width:77px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim11{clear:both;position:absolute;top:55px;left:65px;z-index:110;width:115px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_CN/smart_editor2_out.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_CN/smart_editor2_out.css new file mode 100644 index 00000000..0baf3770 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_CN/smart_editor2_out.css @@ -0,0 +1,12 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* COMMON */ +.se2_outputarea, .se2_outputarea th, .se2_outputarea td{margin:0;padding:0;color:#666;font-size:12px;font-family:'돋움',Dotum,'굴림',Gulim,Helvetica,Sans-serif;line-height:1.5} +.se2_outputarea p{margin:0;padding:0} +.se2_outputarea a:hover{text-decoration:underline} +.se2_outputarea a:link{color:#0000ff} +.se2_outputarea ul{margin:0 0 0 40px;padding:0} +.se2_outputarea ul li{margin:0;list-style-type:disc;padding:0} +.se2_outputarea ul ul li{list-style-type:circle} +.se2_outputarea ul ul ul li{list-style-type:square} +.se2_outputarea img, .se2_outputarea fieldset{border:0} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_TW/smart_editor2.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_TW/smart_editor2.css new file mode 100644 index 00000000..61866f42 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_TW/smart_editor2.css @@ -0,0 +1,190 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* COMMON */ +body,#smart_editor2,#smart_editor2 p,#smart_editor2 h1,#smart_editor2 h2,#smart_editor2 h3,#smart_editor2 h4,#smart_editor2 h5,#smart_editor2 h6,#smart_editor2 ul,#smart_editor2 ol,#smart_editor2 li,#smart_editor2 dl,#smart_editor2 dt,#smart_editor2 dd,#smart_editor2 table,#smart_editor2 th,#smart_editor2 td,#smart_editor2 form,#smart_editor2 fieldset,#smart_editor2 legend,#smart_editor2 input,#smart_editor2 textarea,#smart_editor2 button,#smart_editor2 select{margin:0;padding:0} +#smart_editor2,#smart_editor2 h1,#smart_editor2 h2,#smart_editor2 h3,#smart_editor2 h4,#smart_editor2 h5,#smart_editor2 h6,#smart_editor2 input,#smart_editor2 textarea,#smart_editor2 select,#smart_editor2 table,#smart_editor2 button{font-family:'돋움',Dotum,Helvetica,sans-serif;font-size:12px;color:#666} +#smart_editor2 span,#smart_editor2 em{font-size:12px} +#smart_editor2 em,#smart_editor2 address{font-style:normal} +#smart_editor2 img,#smart_editor2 fieldset{border:0} +#smart_editor2 hr{display:none} +#smart_editor2 ol,#smart_editor2 ul{list-style:none} +#smart_editor2 button{border:0;background:none;font-size:11px;vertical-align:top;cursor:pointer} +#smart_editor2 button span,#smart_editor2 button em{visibility:hidden;overflow:hidden;position:absolute;top:0;font-size:0;line-height:0} +#smart_editor2 legend,#smart_editor2 .blind{visibility:hidden;overflow:hidden;position:absolute;width:0;height:0;font-size:0;line-height:0} +#smart_editor2 .input_ty1{height:14px;margin:0;padding:4px 2px 0 4px;border:1px solid #c7c7c7;font-size:11px;color:#666} +#smart_editor2 a:link,#smart_editor2 a:visited,#smart_editor2 a:active,#smart_editor2 a:focus{color:#666;text-decoration:none} +#smart_editor2 a:hover{color:#666;text-decoration:underline} +/* LAYOUT */ +#smart_editor2 .se2_header{margin:10px 0 29px 0} +#smart_editor2 .se2_bi{float:left;width:93px;height:20px;margin:0;padding:0;background:url("../../img/zh_TW/btn_set.png?160622") -343px -358px no-repeat;font-size:0;line-height:0;text-indent:-10000px;vertical-align:middle} +#smart_editor2 .se2_allhelp{display:inline-block;width:18px;height:18px;padding:0;background:url("../../img/zh_TW/btn_set.png?160622") -437px -358px no-repeat;font-size:0;line-height:0;text-indent:-10000px;vertical-align:middle} +#smart_editor2 #smart_editor2_content{position:relative;border:1px solid #b5b5b5} +#smart_editor2 .se2_tool{overflow:visible;position:relative;z-index:25} +/* EDITINGAREA */ +#smart_editor2 .se2_input_area{position:relative;z-index:22;height:400px;margin:0;padding:0;*zoom:1} +#smart_editor2 .se2_input_wysiwyg,#smart_editor2 .se2_input_syntax{display:block;overflow:auto;width:100%;height:100%;margin:0;*margin:-1px 0 0 0;border:0} +/* EDITINGMODE */ +#smart_editor2 .se2_conversion_mode{position:relative;height:15px;padding-top:1px;border-top:1px solid #b5b5b5;background:url("../../img/icon_set.gif?141007") 0 -896px repeat-x} +#smart_editor2 .se2_inputarea_controller{display:block;clear:both;position:relative;width:100%;height:15px;background:url("../../img/icon_set.gif?141007") center -47px no-repeat;text-align:center;cursor:n-resize} +#smart_editor2 .se2_inputarea_controller span{display:block;visibility:visible;height:15px;font-size:0;line-height:0;color:#fff;white-space:nowrap} +#smart_editor2 .ly_controller{display:block;position:absolute;bottom:2px;left:50%;width:287px;margin-left:-148px;padding:8px 0 7px 9px;border:1px solid #827f7c;background:#fffdef} +#smart_editor2 .ly_controller p{color:#666;font-size:11px;letter-spacing:-1px;line-height:11px} +#smart_editor2 .ly_controller .bt_clse,#smart_editor2 .ly_controller .ic_arr{position:absolute;background:url("../../img/ico_extend.png") no-repeat} +#smart_editor2 .ly_controller .bt_clse{top:5px;right:4px;width:14px;height:15px;background-position:1px -43px} +#smart_editor2 .ly_controller .ic_arr{top:25px;left:50%;width:10px;height:6px;margin-left:-5px;background-position:0 -65px} +#smart_editor2 .se2_converter{float:left;position:absolute;top:-1px;right:3px;z-index:20} +#smart_editor2 .se2_converter li{float:left} +#smart_editor2 .se2_converter .se2_to_editor{width:59px;height:15px;background:url("../../img/zh_TW/btn_set.png?160622") 0 -85px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .se2_to_html{width:59px;height:15px;background:url("../../img/zh_TW/btn_set.png?160622") -59px -70px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .se2_to_text{width:60px;height:15px;background:url("../../img/zh_TW/btn_set.png?160622") -417px -466px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .active .se2_to_editor{width:59px;height:15px;background:url("../../img/zh_TW/btn_set.png?160622") 0 -70px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .active .se2_to_html{width:59px;height:15px;background:url("../../img/zh_TW/btn_set.png?160622") -59px -85px no-repeat;vertical-align:top} +#smart_editor2 .se2_converter .active .se2_to_text{width:60px;height:15px;background:url("../../img/zh_TW/btn_set.png?160622") -417px -481px no-repeat;vertical-align:top} +/* EDITINGAREA_HTMLSRC */ +#smart_editor2 .off .ico_btn,#smart_editor2 .off .se2_more,#smart_editor2 .off .se2_more2,#smart_editor2 .off .se2_font_family,#smart_editor2 .off .se2_font_size,#smart_editor2 .off .se2_bold,#smart_editor2 .off .se2_underline,#smart_editor2 .off .se2_italic,#smart_editor2 .off .se2_tdel,#smart_editor2 .off .se2_fcolor,#smart_editor2 .off .se2_fcolor_more,#smart_editor2 .off .se2_bgcolor,#smart_editor2 .off .se2_bgcolor_more,#smart_editor2 .off .se2_left,#smart_editor2 .off .se2_center,#smart_editor2 .off .se2_right,#smart_editor2 .off .se2_justify,#smart_editor2 .off .se2_ol,#smart_editor2 .off .se2_ul,#smart_editor2 .off .se2_indent,#smart_editor2 .off .se2_outdent,#smart_editor2 .off .se2_lineheight,#smart_editor2 .off .se2_del_style,#smart_editor2 .off .se2_blockquote,#smart_editor2 .off .se2_summary,#smart_editor2 .off .se2_footnote,#smart_editor2 .off .se2_url,#smart_editor2 .off .se2_emoticon,#smart_editor2 .off .se2_character,#smart_editor2 .off .se2_table,#smart_editor2 .off .se2_find,#smart_editor2 .off .se2_spelling,#smart_editor2 .off .se2_sup,#smart_editor2 .off .se2_sub,#smart_editor2 .off .se2_text_tool_more,#smart_editor2 .off .se2_new,#smart_editor2 .off .selected_color,#smart_editor2 .off .se2_lineSticker{-ms-filter:alpha(opacity=50);opacity:.5;cursor:default;filter:alpha(opacity=50)} +/* LAYER */ +#smart_editor2 .se2_text_tool .se2_layer{display:none;float:left;position:absolute;top:20px;left:0;z-index:50;margin:0;padding:0;border:1px solid #bcbbbb;background:#fafafa} +#smart_editor2 .se2_text_tool li.active{z-index:50} +#smart_editor2 .se2_text_tool .active .se2_layer{display:block} +#smart_editor2 .se2_text_tool .active li .se2_layer{display:none} +#smart_editor2 .se2_text_tool .active .active .se2_layer{display:block} +#smart_editor2 .se2_text_tool .se2_layer .se2_in_layer{float:left;margin:0;padding:0;border:1px solid #fff;background:#fafafa} +#smart_editor2 .se2_content_loading{display:none;z-index:10;position:absolute;top:0;left:0;width:100%;height:100%;text-align:center} +#smart_editor2 .se2_content_loading img{position:absolute;top:50%;left:50%;margin:-27px 0 0 -27px} +#smart_editor2 .se2_alert_wrap{display:none;z-index:20;position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;text-align:center} +#smart_editor2 .se2_alert_wrap.active{display:block} +#smart_editor2 .se2_alert_wrap .dimmed{position:absolute;top:0;left:0;width:100%;height:100%;background:#000;opacity:0.4;filter:alpha(opacity=40)} +#smart_editor2 .se2_alert_wrap .ie_cover{position:absolute;top:0;left:0;width:100%;height:100%;background:#fff;opacity:0;filter:alpha(opacity=0)} +#smart_editor2 .se2_alert_wrap .va_line{display:inline-block;height:100%;vertical-align:middle;*zoom:1} +#smart_editor2 .se2_alert_wrap .se2_alert_content{z-index:10;position:relative;display:inline-block;*display:inline;*zoom:1;border:1px solid #727272;background:#fff;padding:26px 33px 22px;vertical-align:middle} +#smart_editor2 .se2_alert_wrap .se2_alert_content{margin-top:47px} +#smart_editor2 .se2_alert_wrap .txt1{color:#333;line-height:18px} +#smart_editor2 .se2_alert_wrap .txt2{margin-top:3px;color:#999} +#smart_editor2 .se2_alert_wrap .btn_close,#smart_editor2 .se2_alert_btns button{background:url("../../img/zh_TW/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_alert_wrap .btn_close{z-index:10;position:absolute;top:7px;right:7px;width:11px;height:11px;background-position:-122px -32px;text-indent:-5000px} +#smart_editor2 .se2_alert_btns{margin-top:19px} +#smart_editor2 .se2_alert_btns button{display:inline;float:none;width:48px;height:27px} +#smart_editor2 .se2_alert_btns button + button{margin-left:10px} +#smart_editor2 .se2_alert_btns .se2_confirm{background-position:-369px -434px} +#smart_editor2 .se2_alert_btns .se2_cancel{background-position:-419px -434px} +/* TEXT_TOOLBAR */ +#smart_editor2 .se2_text_tool{position:relative;clear:both;z-index:30;padding:4px 0 4px 3px;background:#f4f4f4 url("../../img/bg_text_tool.gif") 0 0 repeat-x;border-bottom:1px solid #b5b5b5;*zoom:1} +#smart_editor2 .se2_text_tool:after{content:"";display:block;clear:both} +#smart_editor2 .se2_text_tool ul{float:left;display:inline;margin-right:3px;padding-left:1px;white-space:nowrap} +#smart_editor2 .se2_text_tool li{_display:inline;float:left;position:relative;z-index:30} +#smart_editor2 .se2_text_tool button,#smart_editor2 .se2_multy .se2_icon{width:21px;height:21px;background:url("../../img/zh_TW/text_tool_set.png?140317") no-repeat;vertical-align:top} +#smart_editor2 .se2_text_tool .se2_font_type{position:relative} +#smart_editor2 .se2_text_tool .se2_font_type li{margin-left:3px} +#smart_editor2 .se2_text_tool .se2_font_type button{text-align:left} +#smart_editor2 .se2_text_tool .se2_font_type button.se2_font_family span,#smart_editor2 .se2_text_tool .se2_font_type button.se2_font_size span{display:inline-block;visibility:visible;position:static;width:52px;height:20px;padding:0 0 0 6px;font-size:12px;line-height:20px;*line-height:22px;color:#333;*zoom:1} +#smart_editor2 .se2_text_tool .se2_multy{position:absolute;top:0;right:0;padding-left:0;margin-right:0;white-space:nowrap;border-left:1px solid #e0dedf} +#smart_editor2 .se2_text_tool .se2_multy .se2_mn{float:left;white-space:nowrap} +#smart_editor2 .se2_text_tool .se2_multy button{background-image:none;width:47px} +#smart_editor2 .se2_text_tool .se2_multy .se2_icon{display:inline-block;visibility:visible;overflow:visible;position:static;width:16px;height:29px;margin:-1px 2px 0 -1px;background-position:0 -132px;line-height:30px;vertical-align:top} +#smart_editor2 .se2_text_tool .se2_multy button,#smart_editor2 .se2_text_tool .se2_multy button span{height:29px;line-height:29px} +#smart_editor2 .se2_text_tool .se2_map .se2_icon{background-position:-29px -132px} +#smart_editor2 .se2_text_tool button span.se2_mntxt{display:inline-block;visibility:visible;overflow:visible;_overflow-y:hidden;position:relative;*margin-right:-1px;width:auto;height:29px;font-weight:normal;font-size:11px;line-height:30px;*line-height:29px;_line-height:30px;color:#444;letter-spacing:-1px;vertical-align:top} +#smart_editor2 .se2_text_tool .se2_multy .se2_photo{margin-right:1px} +#smart_editor2 .se2_text_tool .se2_multy .hover .ico_btn{background:#e8e8e8} +#smart_editor2 .se2_text_tool .se2_multy .se2_mn.hover{background:#e0dedf} +/* TEXT_TOOLBAR : ROUNDING */ +#smart_editor2 ul li.first_child button span.tool_bg, #smart_editor2 ul li.last_child button span.tool_bg, #smart_editor2 ul li.single_child button span.tool_bg{visibility:visible;height:21px} +#smart_editor2 ul li.first_child button span.tool_bg{left:-1px;width:3px;background:url("../../img/bg_button_left.gif?20121228") no-repeat} +#smart_editor2 ul li.last_child button span.tool_bg{right:0px;_right:-1px;width:2px;background:url("../../img/bg_button_right.gif") no-repeat} +#smart_editor2 ul li.single_child{padding-right:1px} +#smart_editor2 ul li.single_child button span.tool_bg{left:0;background:url("../../img/bg_button.gif?20121228") no-repeat;width:22px} +#smart_editor2 div.se2_text_tool ul li.hover button span.tool_bg{background-position:0 -21px} +#smart_editor2 div.se2_text_tool ul li.active button span.tool_bg, #smart_editor2 div.se2_text_tool ul li.active li.active button span.tool_bg{background-position:0 -42px} +#smart_editor2 div.se2_text_tool ul li.active li button span.tool_bg{background-position:0 0} +/* TEXT_TOOLBAR : SUB_MENU */ +#smart_editor2 .se2_sub_text_tool{display:none;position:absolute;top:20px;left:0;z-index:40;width:auto;height:29px;padding:0 4px 0 0;border:1px solid #b5b5b5;border-top:1px solid #9a9a9a;background:#f4f4f4} +#smart_editor2 .active .se2_sub_text_tool{display:block} +#smart_editor2 .se2_sub_text_tool ul{float:left;height:25px;margin:0;padding:4px 0 0 4px} +/* TEXT_TOOLBAR : SUB_MENU_SIZE */ +#smart_editor2 .se2_sub_step1{width:88px} +#smart_editor2 .se2_sub_step2{width:199px} +#smart_editor2 .se2_sub_step2_1{width:178px} +/* TEXT_TOOLBAR : BUTTON */ +#smart_editor2 .se2_text_tool .se2_font_family{width:70px;height:21px;background-position:0 -10px} +#smart_editor2 .se2_text_tool .hover .se2_font_family{background-position:0 -72px} +#smart_editor2 .se2_text_tool .active .se2_font_family{background-position:0 -103px} +#smart_editor2 .se2_text_tool .se2_font_size{width:45px;height:21px;background-position:-70px -10px} +#smart_editor2 .se2_text_tool .hover .se2_font_size{background-position:-70px -72px} +#smart_editor2 .se2_text_tool .active .se2_font_size{background-position:-70px -103px} +#smart_editor2 .se2_text_tool .se2_bold{background-position:-115px -10px} +#smart_editor2 .se2_text_tool .hover .se2_bold{background-position:-115px -72px} +#smart_editor2 .se2_text_tool .active .se2_bold{background-position:-115px -103px} +#smart_editor2 .se2_text_tool .se2_underline{background-position:-136px -10px} +#smart_editor2 .se2_text_tool .hover .se2_underline{background-position:-136px -72px} +#smart_editor2 .se2_text_tool .active .se2_underline{background-position:-136px -103px} +#smart_editor2 .se2_text_tool .se2_italic{background-position:-157px -10px} +#smart_editor2 .se2_text_tool .hover .se2_italic{background-position:-157px -72px} +#smart_editor2 .se2_text_tool .active .se2_italic{background-position:-157px -103px} +#smart_editor2 .se2_text_tool .se2_tdel{background-position:-178px -10px} +#smart_editor2 .se2_text_tool .hover .se2_tdel{background-position:-178px -72px} +#smart_editor2 .se2_text_tool .active .se2_tdel{background-position:-178px -103px} +#smart_editor2 .se2_text_tool .se2_fcolor{position:relative;background-position:-199px -10px} +#smart_editor2 .se2_text_tool .hover .se2_fcolor{background-position:-199px -72px} +#smart_editor2 .se2_text_tool .active .se2_fcolor{background-position:-199px -103px} +#smart_editor2 .se2_text_tool .se2_fcolor_more{background-position:-220px -10px;width:10px} +#smart_editor2 .se2_text_tool .hover .se2_fcolor_more{background-position:-220px -72px} +#smart_editor2 .se2_text_tool .active .se2_fcolor_more{background-position:-220px -103px} +#smart_editor2 .se2_text_tool .selected_color{position:absolute;top:14px;left:5px;width:11px;height:3px;font-size:0} +#smart_editor2 .se2_text_tool .se2_ol,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_ol{background-position:-345px -10px} +#smart_editor2 .se2_text_tool .se2_ul,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_ul{background-position:-366px -10px} +#smart_editor2 .se2_text_tool .hover .se2_ol,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_ol{background-position:-345px -72px} +#smart_editor2 .se2_text_tool .hover .se2_ul,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_ul{background-position:-366px -72px} +#smart_editor2 .se2_text_tool .active .se2_ol,#smart_editor2 .se2_text_tool .active .active .se2_ol{background-position:-345px -103px} +#smart_editor2 .se2_text_tool .active .se2_ul,#smart_editor2 .se2_text_tool .active .active .se2_ul{background-position:-366px -103px} +#smart_editor2 .se2_text_tool .se2_indent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_indent{background-position:-408px -10px} +#smart_editor2 .se2_text_tool .se2_outdent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_outdent{background-position:-387px -10px} +#smart_editor2 .se2_text_tool .hover .se2_indent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_indent{background-position:-408px -72px} +#smart_editor2 .se2_text_tool .hover .se2_outdent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_outdent{background-position:-387px -72px} +#smart_editor2 .se2_text_tool .active .se2_indent,#smart_editor2 .se2_text_tool .active .active .se2_indent{background-position:-408px -103px} +#smart_editor2 .se2_text_tool .active .se2_outdent,#smart_editor2 .se2_text_tool .active .active .se2_outdent{background-position:-387px -103px} +#smart_editor2 .se2_text_tool .se2_lineheight{background-position:-429px -10px} +#smart_editor2 .se2_text_tool .hover .se2_lineheight{background-position:-429px -72px} +#smart_editor2 .se2_text_tool .active .se2_lineheight{background-position:-429px -103px} +#smart_editor2 .se2_text_tool .se2_url{background-position:-513px -10px} +#smart_editor2 .se2_text_tool .hover .se2_url{background-position:-513px -72px} +#smart_editor2 .se2_text_tool .active .se2_url{background-position:-513px -103px} +#smart_editor2 .se2_text_tool .se2_bgcolor{position:relative;background-position:-230px -10px} +#smart_editor2 .se2_text_tool .hover .se2_bgcolor{background-position:-230px -72px} +#smart_editor2 .se2_text_tool .active .se2_bgcolor{background-position:-230px -103px} +#smart_editor2 .se2_text_tool .se2_bgcolor_more{background-position:-251px -10px;width:10px} +#smart_editor2 .se2_text_tool .hover .se2_bgcolor_more{background-position:-251px -72px} +#smart_editor2 .se2_text_tool .active .se2_bgcolor_more{background-position:-251px -103px} +#smart_editor2 .se2_text_tool .se2_left{background-position:-261px -10px} +#smart_editor2 .se2_text_tool .hover .se2_left{background-position:-261px -72px} +#smart_editor2 .se2_text_tool .active .se2_left{background-position:-261px -103px} +#smart_editor2 .se2_text_tool .se2_center{background-position:-282px -10px} +#smart_editor2 .se2_text_tool .hover .se2_center{background-position:-282px -72px} +#smart_editor2 .se2_text_tool .active .se2_center{background-position:-282px -103px} +#smart_editor2 .se2_text_tool .se2_right{background-position:-303px -10px} +#smart_editor2 .se2_text_tool .hover .se2_right{background-position:-303px -72px} +#smart_editor2 .se2_text_tool .active .se2_right{background-position:-303px -103px} +#smart_editor2 .se2_text_tool .se2_justify{background-position:-324px -10px} +#smart_editor2 .se2_text_tool .hover .se2_justify{background-position:-324px -72px} +#smart_editor2 .se2_text_tool .active .se2_justify{background-position:-324px -103px} +#smart_editor2 .se2_text_tool .se2_blockquote{background-position:-471px -10px} +#smart_editor2 .se2_text_tool .hover .se2_blockquote{background-position:-471px -72px} +#smart_editor2 .se2_text_tool .active .se2_blockquote{background-position:-471px -103px} +#smart_editor2 .se2_text_tool .se2_character{background-position:-555px -10px} +#smart_editor2 .se2_text_tool .hover .se2_character{background-position:-555px -72px} +#smart_editor2 .se2_text_tool .active .se2_character{background-position:-555px -103px} +#smart_editor2 .se2_text_tool .se2_table{background-position:-576px -10px} +#smart_editor2 .se2_text_tool .hover .se2_table{background-position:-576px -72px} +#smart_editor2 .se2_text_tool .active .se2_table{background-position:-576px -103px} +#smart_editor2 .se2_text_tool .se2_find{background-position:-597px -10px} +#smart_editor2 .se2_text_tool .hover .se2_find{background-position:-597px -72px} +#smart_editor2 .se2_text_tool .active .se2_find{background-position:-597px -103px} +#smart_editor2 .se2_text_tool .se2_sup{background-position:-660px -10px} +#smart_editor2 .se2_text_tool .hover .se2_sup{background-position:-660px -72px} +#smart_editor2 .se2_text_tool .active .se2_sup{background-position:-660px -103px} +#smart_editor2 .se2_text_tool .se2_sub{background-position:-681px -10px} +#smart_editor2 .se2_text_tool .hover .se2_sub{background-position:-681px -72px} +#smart_editor2 .se2_text_tool .active .se2_sub{background-position:-681px -103px} +#smart_editor2 .se2_text_tool .se2_text_tool_more{background-position:0 -41px;width:13px} +#smart_editor2 .se2_text_tool .se2_text_tool_more span.tool_bg{background:none} +#smart_editor2 .se2_text_tool .hover .se2_text_tool_more{background-position:-13px -41px} +#smart_editor2 .se2_text_tool .active .se2_text_tool_more{background-position:-26px -41px} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_TW/smart_editor2_in.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_TW/smart_editor2_in.css new file mode 100644 index 00000000..fdecc092 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_TW/smart_editor2_in.css @@ -0,0 +1,24 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* COMMON */ +body,.se2_inputarea{margin:0;padding:0;font-family:'돋움',Dotum,Helvetica,Sans-serif;font-size:12px;line-height:1.5} +/* body,.se2_inputarea,.se2_inputarea th,.se2_inputarea td{margin:0;padding:0;font-family:'돋움',Dotum,Helvetica,Sans-serif;font-size:12px;line-height:1.5;color:#666} */ +.se2_inputarea p,.se2_inputarea br{margin:0;padding:0} +.se2_inputarea{margin:15px;word-wrap:break-word;*word-wrap:normal;*word-break:break-all} +.se2_inputarea td{word-break:break-all} +.se2_inputarea_890{width:741px;margin:20px 0 10px 64px} +.se2_inputarea_698{width:548px;margin:20px 0 10px 64px} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + .se2_inputarea td:empty:after,.se2_inputarea td > p:empty:after{content:"\00A0";line-height:1} +} +/* TEXT_TOOLBAR : QUOTE */ +.se2_quote1{margin:0 0 30px 20px;padding:0 8px;border-left:2px solid #ccc;color:#888} +.se2_quote2{margin:0 0 30px 13px;padding:0 8px 0 16px;background:url("../../img/bg_quote2.gif") 0 3px no-repeat;color:#888} +.se2_quote3{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #ccc;color:#888} +.se2_quote4{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #66b246;color:#888} +.se2_quote5{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #ccc;background:#fafafa;color:#888} +.se2_quote6{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #e5e5e5;color:#888} +.se2_quote7{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #66b246;color:#888} +.se2_quote8{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #e5e5e5;background:#fafafa;color:#888} +.se2_quote9{margin:0 0 30px;padding:12px 10px 11px;border:2px solid #e5e5e5;color:#888} +.se2_quote10{margin:0 0 30px;padding:12px 10px 11px;border:2px solid #e5e5e5;background:#fafafa;color:#888} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_TW/smart_editor2_items.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_TW/smart_editor2_items.css new file mode 100644 index 00000000..2dd31221 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_TW/smart_editor2_items.css @@ -0,0 +1,417 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* TEXT_TOOLBAR : FONTNAME */ +#smart_editor2 .se2_l_font_fam .hover,#smart_editor2 .se2_l_font_fam .active{background:#ebebeb} +#smart_editor2 .se2_l_font_fam button span{display:block;visibility:visible;overflow:visible;position:relative;top:auto;left:auto;width:auto;height:auto;margin:0 0 0 4px;padding:0;font-size:12px;line-height:normal;color:#333} +#smart_editor2 .se2_l_font_fam button span span{display:inline;visibility:visible;overflow:visible;width:auto;height:auto;margin:0 0 0 4px;font-family:Verdana;font-size:12px;line-height:14px;color:#888} +#smart_editor2 .se2_l_font_fam button span em{visibility:visible;overflow:auto;position:static;width:auto;height:auto;margin-right:-4px;font-size:12px;color:#888} +#smart_editor2 .se2_l_font_fam .se2_division{width:162px;height:2px !important;margin:1px 0 1px 0px;border:0;background:url("../../img/bg_line1.gif") 0 0 repeat-x;font-size:0;cursor:default} +/* TEXT_TOOLBAR : FONTSIZE */ +#smart_editor2 .se2_tool .se2_l_font_size{width:302px;margin:0;padding:0} +#smart_editor2 .se2_tool .se2_l_font_size li{width:302px;margin:0;padding:0;color:#333;cursor:pointer} +#smart_editor2 .se2_l_font_size .hover,#smart_editor2 .se2_l_font_size .active{background:#ebebeb} +#smart_editor2 .se2_l_font_size button{width:300px;height:auto;margin:0;padding:2px 0 1px 0px;*padding:4px 0 1px 0px;background:none;text-align:left} +#smart_editor2 .se2_l_font_size button span{display:block;visibility:visible;overflow:visible;position:relative;top:auto;left:auto;width:auto;height:auto;margin:0 0 0 4px;padding:0;line-height:normal;color:#373737;letter-spacing:0px} +#smart_editor2 .se2_l_font_size button span span{display:inline;margin:0 0 0 5px;padding:0} +#smart_editor2 .se2_l_font_size span em{visibility:visible;overflow:auto;position:static;width:auto;height:auto;color:#888} +/* TEXT_TOOLBAR : FONTCOLOR */ +#smart_editor2 .se2_palette{float:left;position:relative;width:225px;margin:0;padding:11px 0 10px 0} +#smart_editor2 .se2_palette .se2_pick_color{_display:inline;float:left;clear:both;width:205px;margin:0 0 0 11px;padding:0} +#smart_editor2 .se2_palette .se2_pick_color li{float:left;width:12px;height:12px;margin:0;padding:0} +#smart_editor2 .se2_palette .se2_pick_color li button{width:11px;height:11px;border:0} +#smart_editor2 .se2_palette .se2_pick_color li button span{display:block;visibility:visible;overflow:visible;position:absolute;top:1px;left:1px;width:11px;height:11px} +#smart_editor2 .se2_palette .se2_pick_color li button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0} +#smart_editor2 .se2_palette .se2_pick_color .hover button,#smart_editor2 .se2_palette .se2_pick_color .active button{width:11px;height:11px;border:1px solid #666} +#smart_editor2 .se2_palette .se2_pick_color .hover span,#smart_editor2 .se2_palette .se2_pick_color .active span{width:7px;height:7px;border:1px solid #fff} +#smart_editor2 .se2_palette .se2_view_more{_display:inline;float:left;width:46px;height:23px;margin:1px 0 0 1px;background:url("../../img/zh_TW/btn_set.png?160622") 0 -47px no-repeat} +#smart_editor2 .se2_palette .se2_view_more2{_display:inline;float:left;width:46px;height:23px;margin:1px 0 0 1px;background:url("../../img/zh_TW/btn_set.png?160622") 0 -24px no-repeat} +#smart_editor2 .se2_palette h4{_display:inline;float:left;width:203px;margin:9px 0 0 11px;padding:10px 0 4px 0;background:url("../../img/bg_line1.gif") repeat-x;font-weight:normal;font-size:12px;line-height:14px;color:#333;letter-spacing:-1px} +#smart_editor2 .se2_palette2{float:left;_float:none;width:214px;margin:9px 0 0 0;padding:11px 0 0 11px;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_palette2 .se2_color_set{float:left} +#smart_editor2 .se2_palette2 .se2_selected_color{_display:inline;float:left;width:83px;height:18px;margin:0;border:1px solid #c7c7c7;background:#fff} +#smart_editor2 .se2_palette2 .se2_selected_color span{_display:inline;float:left;width:79px;height:14px;margin:2px} +#smart_editor2 .se2_palette2 .input_ty1{_display:inline;float:left;width:67px;height:16px;margin:0 3px 0 3px;padding:2px 2px 0 4px;font-family:tahoma;font-size:11px} +#smart_editor2 .se2_palette2 button.se2_btn_insert{float:left;width:35px;height:21px;margin-left:2px;padding:0;background:url("../../img/zh_TW/btn_set.png?160622") -80px 0 no-repeat} +#smart_editor2 .se2_gradation1{float:left;_float:none;width:201px;height:128px;margin:4px 0 0 0;border:1px solid #c7c7c7;cursor:crosshair} +#smart_editor2 .se2_gradation2{float:left;_float:none;width:201px;height:10px;margin:4px 0 1px 0;border:1px solid #c7c7c7;cursor:crosshair} +/* TEXT_TOOLBAR : BGCOLOR */ +#smart_editor2 .se2_palette_bgcolor{width:225px;margin:11px 0 0;padding:0} +#smart_editor2 .se2_palette_bgcolor .se2_background{width:205px;margin:0 11px 0 11px} +#smart_editor2 .se2_palette_bgcolor .se2_background li{width:68px;height:20px} +#smart_editor2 .se2_palette_bgcolor .se2_background button{width:67px;height:19px;border:0} +#smart_editor2 .se2_palette_bgcolor .se2_background span{left:0;display:block;visibility:visible;overflow:visible;width:65px;height:17px;padding:0} +#smart_editor2 .se2_palette_bgcolor .se2_background span span{display:block;visibility:visible;overflow:visible;width:64px;height:16px;padding:3px 0 0 3px;font-size:11px;line-height:14px;text-align:left} +#smart_editor2 .se2_palette_bgcolor .se2_background .hover span{width:65px;height:17px;border:1px solid #666} +#smart_editor2 .se2_palette_bgcolor .se2_background .hover span span{width:62px;height:14px;padding:1px 0 0 1px;border:1px solid #fff} +/* TEXT_TOOLBAR : LINEHEIGHT */ +#smart_editor2 .se2_l_line_height{width:107px;margin:0;padding:0} +#smart_editor2 .se2_l_line_height li{width:107px;margin:0;padding:0;border-top:0;border-bottom:0;color:#333;cursor:pointer} +#smart_editor2 .se2_l_line_height .hover{background:#ebebeb} +#smart_editor2 .se2_l_line_height button{width:105px;height:19px;margin:0;padding:3px 0 2px 0px;background:none;text-align:left} +#smart_editor2 .se2_l_line_height button span{visibility:visible;overflow:visible;position:relative;width:auto;height:auto;margin:0;padding:0 0 0 15px;font-size:12px;line-height:normal;color:#373737} +#smart_editor2 .se2_l_line_height li button.active span{background:url("../../img/icon_set.gif?141007") 5px -30px no-repeat} +#smart_editor2 .se2_l_line_height_user{clear:both;width:83px;margin:5px 0 0 12px;padding:10px 0 0 0;_padding:11px 0 0 0;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_l_line_height_user h3{margin:0 0 4px 0;_margin:0 0 2px -1px;padding:0;line-height:14px;color:#000;letter-spacing:-1px} +#smart_editor2 .se2_l_line_height_user .bx_input{display:block;position:relative;width:83px} +#smart_editor2 .se2_l_line_height_user .btn_up{position:absolute;top:2px;*top:3px;left:68px;width:13px;height:8px;background:url("../../img/zh_TW/btn_set.png?160622") -86px -54px no-repeat} +#smart_editor2 .se2_l_line_height_user .btn_down{position:absolute;top:10px;*top:11px;left:68px;width:13px;height:8px;background:url("../../img/zh_TW/btn_set.png?160622") -86px -62px no-repeat} +#smart_editor2 .se2_l_line_height_user .btn_area{margin:5px 0 10px 0} +#smart_editor2 .se2_tool .btn_area .se2_btn_apply3{width:41px;height:24px;background:url("../../img/zh_TW/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_tool .btn_area .se2_btn_cancel3{width:39px;height:24px;margin-left:3px;background:url("../../img/zh_TW/btn_set.png?160622") -41px 0 no-repeat} +/* TEXT_TOOLBAR : QUOTE */ +#smart_editor2 .se2_quote{width:425px;height:56px} +#smart_editor2 .se2_quote ul{_display:inline;float:left;margin:11px 0 0 9px;padding:0} +#smart_editor2 .se2_quote li{_display:inline;float:left;margin:0 0 0 2px;padding:0} +#smart_editor2 .se2_quote button{width:34px;height:34px;margin:0;padding:0;background:url("../../img/zh_TW/btn_set.png?160622") no-repeat;cursor:pointer} +#smart_editor2 .se2_quote button span{left:0;display:block;visibility:visible;overflow:visible;width:32px;height:32px;margin:0;padding:0;border:1px solid #c7c7c7} +#smart_editor2 .se2_quote button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0} +#smart_editor2 .se2_quote .se2_quote1{background-position:1px -375px} +#smart_editor2 .se2_quote .se2_quote2{background-position:-32px -375px} +#smart_editor2 .se2_quote .se2_quote3{background-position:-65px -375px} +#smart_editor2 .se2_quote .se2_quote4{background-position:-98px -375px} +#smart_editor2 .se2_quote .se2_quote5{background-position:-131px -375px} +#smart_editor2 .se2_quote .se2_quote6{background-position:-164px -375px} +#smart_editor2 .se2_quote .se2_quote7{background-position:-197px -375px} +#smart_editor2 .se2_quote .se2_quote8{background-position:-230px -375px} +#smart_editor2 .se2_quote .se2_quote9{background-position:-263px -375px} +#smart_editor2 .se2_quote .se2_quote10{background-position:-296px -375px} +#smart_editor2 .se2_quote .hover button span,#smart_editor2 .se2_quote .active button span{width:30px;height:30px;margin:0;padding:0;border:2px solid #44b525} +#smart_editor2 .se2_quote .hover button span span,#smart_editor2 .se2_quote .active button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0} +#smart_editor2 .se2_quote .se2_cancel2{float:left;width:40px;height:35px;margin:11px 0 0 5px;background:url("../../img/zh_TW/btn_set.png?160622") -46px -24px no-repeat} +#smart_editor2 .se2_quote .se2_cancel2 span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0} +/* TEXT_TOOLBAR : HYPERLINK */ +#smart_editor2 .se2_url2{width:281px;padding:11px 11px 6px 11px;color:#666} +#smart_editor2 .se2_url2 .input_ty1{display:block;width:185px;height:16px;margin:0 5px 5px 0;*margin:-1px 5px 5px 0;padding:5px 2px 0 4px} +#smart_editor2 .se2_url2 .se2_url_new{width:15px;height:15px;margin:-1px 3px 1px -1px;*margin:-2px 3px 2px -1px;vertical-align:middle} +#smart_editor2 .se2_url2 label{font-size:11px;line-height:14px;vertical-align:middle} +#smart_editor2 .se2_url2 .se2_apply{position:absolute;top:13px;right:51px;width:41px;height:24px;margin:-1px 3px 1px 0;background:url("../../img/zh_TW/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_url2 .se2_cancel{position:absolute;top:13px;right:9px;width:39px;height:24px;margin:-1px 3px 1px 0;background:url("../../img/zh_TW/btn_set.png?160622") -41px 0 no-repeat} +/* TEXT_TOOLBAR : SCHARACTER */ +#smart_editor2 .se2_bx_character{width:469px;height:272px;margin:0;padding:0;background:url("../../img/bx_set_110302.gif") 9px -1230px no-repeat} +#smart_editor2 .se2_bx_character .se2_char_tab{_display:inline;float:left;position:relative;width:443px;margin:11px 10px 200px 11px;padding:0 0 0 1px} +#smart_editor2 .se2_bx_character .se2_char_tab li{position:static;margin:0 0 0 -1px;padding:0} +#smart_editor2 .se2_bx_character .se2_s_character{display:none;position:absolute;top:26px;left:0;width:448px;height:194px;margin:0;padding:0} +#smart_editor2 .se2_bx_character .active .se2_s_character{display:block} +#smart_editor2 .se2_bx_character .se2_s_character ul{float:left;width:422px;height:172px;margin:0;padding:9px 0 0 11px} +#smart_editor2 .se2_bx_character .se2_s_character li{_display:inline;float:left;position:relative;width:20px;height:18px;margin:0 0 1px 1px;background:#fff} +#smart_editor2 .se2_bx_character .se2_s_character button{width:20px;height:18px;margin:0;padding:2px;background:none} +#smart_editor2 .se2_bx_character .se2_s_character .hover,#smart_editor2 .se2_bx_character .se2_s_character .active{background:url("../../img/zh_TW/btn_set.png?160622") -446px -274px no-repeat} +#smart_editor2 .se2_bx_character .se2_s_character button span{left:0;display:block;visibility:visible;overflow:visible;width:14px;height:16px;margin:3px 0 0 3px;border:0;background:none;font-size:12px;line-height:normal} +#smart_editor2 .se2_apply_character{clear:both;position:relative;padding:0 0 0 11px} +#smart_editor2 .se2_apply_character label{margin:0 3px 0 0;font-size:12px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_apply_character .input_ty1{width:283px;height:17px;margin:-1px 5px 1px 0;padding:4px 0 0 5px;font-size:12px;color:#666;letter-spacing:0;vertical-align:middle} +#smart_editor2 .se2_apply_character .se2_confirm{width:41px;height:24px;margin-right:3px;background:url("../../img/zh_TW/btn_set.png?160622") no-repeat;vertical-align:middle} +#smart_editor2 .se2_apply_character .se2_cancel{width:39px;height:24px;background:url("../../img/zh_TW/btn_set.png?160622") -41px 0 no-repeat;vertical-align:middle} +/* TEXT_TOOLBAR : TABLECREATOR */ +#smart_editor2 .se2_table_set{position:relative;width:166px;margin:3px 11px 0 11px;padding:8px 0 0 0} +#smart_editor2 .se2_table_set .se2_cell_num{float:left;width:73px} +#smart_editor2 .se2_table_set .se2_cell_num dt{float:left;clear:both;width:17px;height:23px;margin:0;padding:0} +#smart_editor2 .se2_table_set .se2_cell_num dt label{display:block;margin:5px 0 0 0;font-size:11px;color:#666} +#smart_editor2 .se2_table_set .se2_cell_num dd{float:left;position:relative;width:54px;height:23px;margin:0;padding:0} +#smart_editor2 .se2_table_set .se2_cell_num .input_ty2{display:block;width:32px;height:16px;*margin:-1px 0 0 0;padding:2px 19px 0 0px;border:1px solid #c7c7c7;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666;text-align:right;*direction:rtl} +#smart_editor2 .se2_table_set .se2_cell_num .input_ty2::-ms-clear{display:none} +#smart_editor2 .se2_table_set .se2_pre_table{float:right;width:91px;height:43px;background:#c7c7c7;border-spacing:1px} +#smart_editor2 .se2_table_set .se2_pre_table tr{background:#fff} +#smart_editor2 .se2_table_set .se2_pre_table td{font-size:0;line-height:0} +#smart_editor2 .se2_table_set .se2_add{position:absolute;top:2px;right:3px;width:13px;height:8px;background:url("../../img/zh_TW/btn_set.png?160622") -86px -54px no-repeat} +#smart_editor2 .se2_table_set .se2_del{position:absolute;top:10px;right:3px;width:13px;height:8px;background:url("../../img/zh_TW/btn_set.png?160622") -86px -62px no-repeat} +/* TEXT_TOOLBAR : TABLEEDITOR */ +#smart_editor2 .se2_table_set .se2_t_proper1{float:left;width:166px;margin:7px 0 0 0;padding:10px 0 5px;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_table_set .se2_t_proper1 dt{width:166px;margin:0 0 6px 0} +#smart_editor2 .se2_table_set .se2_t_proper1 dd{width:166px} +#smart_editor2 .se2_table_set .se2_t_proper1 dt input{width:15px;height:15px;margin:-1px 3px 1px 0;_margin:-2px 3px 2px 0;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper1 dt label{font-weight:bold;font-size:11px;color:#666;letter-spacing:-1px;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper1_1{float:left;position:relative;z-index:59;width:166px;margin:1px 0 0 0} +#smart_editor2 .se2_table_set .se2_t_proper1_2{z-index:54;margin:0} +#smart_editor2 .se2_table_set .se2_t_proper1_3{z-index:53;margin:0} +#smart_editor2 .se2_table_set .se2_t_proper1_4{z-index:52;margin:0} +#smart_editor2 .se2_table_set .se2_t_proper1_1 dt{_display:inline;float:left;clear:both;width:66px;height:22px;margin:1px 0 0 18px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 dt label{display:block;margin:4px 0 0 0;font-weight:normal;font-size:11px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 dd{float:left;position:relative;width:82px;height:23px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .input_ty1{width:72px;height:16px;*margin:-1px 0 0 0;padding:2px 2px 0 6px;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .input_ty3{float:left;width:49px;height:16px;margin:0 3px 0 0;padding:2px 4px 0 4px;border:1px solid #c7c7c7;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_add{top:2px;right:2px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_del{top:10px;right:2px} +#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_color_set .input_ty1{_display:inline;float:left;width:67px;height:16px;margin:0 3px 0 3px;padding:2px 2px 0 4px;font-family:tahoma,verdana,times New Roman;font-size:11px} +#smart_editor2 .se2_select_ty1{position:relative;width:80px;height:18px;border:1px solid #c7c7c7;background:#fff;font-size:11px;line-height:14px;text-align:left} +#smart_editor2 .se2_select_ty1 span{float:left;width:54px;height:18px;margin:0 0 0 5px;font-size:11px;line-height:14px;color:#666} +#smart_editor2 .se2_select_ty1 .se2_b_style0{position:relative;top:3px;left:-3px;white-space:nowrap} +#smart_editor2 .se2_select_ty1 .se2_b_style1{height:15px;margin:3px 0 0 4px;font-size:11px;line-height:14px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_select_ty1 .se2_b_style2{background:url("../../img/bg_set.gif") 0 -50px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style3{background:url("../../img/bg_set.gif") 0 -68px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style4{background:url("../../img/bg_set.gif") 0 -85px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style5{background:url("../../img/bg_set.gif") 0 -103px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style6{background:url("../../img/bg_set.gif") 0 -121px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_b_style7{background:url("../../img/bg_set.gif") 0 -139px repeat-x} +#smart_editor2 .se2_select_ty1 .se2_view_more{position:absolute;top:1px;right:1px;width:13px;height:16px;background:url("../../img/zh_TW/btn_set.png?160622") -112px -54px no-repeat} +#smart_editor2 .se2_select_ty1 .se2_view_more2{position:absolute;top:1px;right:1px;width:13px;height:16px;background:url("../../img/zh_TW/btn_set.png?160622") -99px -54px no-repeat} +/* TEXT_TOOLBAR : TABLEEDITOR > BORDER */ +#smart_editor2 .se2_table_set .se2_b_t_b1{border-top:1px solid #b1b1b1} +#smart_editor2 .se2_layer_b_style{position:absolute;top:20px;right:0px;width:80px;padding-bottom:1px;border:1px solid #c7c7c7;border-top:1px solid #a8a8a8;background:#fff} +#smart_editor2 .se2_layer_b_style ul{width:80px;margin:0;padding:1px 0 0 0} +#smart_editor2 .se2_layer_b_style li{width:80px;height:18px;margin:0;padding:0} +#smart_editor2 .se2_layer_b_style .hover,#smart_editor2 .se2_layer_b_style .active{background:#ebebeb} +#smart_editor2 .se2_layer_b_style button{width:80px;height:18px;background:none} +#smart_editor2 .se2_layer_b_style button span{left:0;display:block;visibility:visible;overflow:visible;width:71px;height:18px;margin:0 0 0 5px;font-size:11px;line-height:15px;text-align:left} +#smart_editor2 .se2_layer_b_style button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0} +#smart_editor2 .se2_layer_b_style .se2_b_style1 span{margin:3px 0 0 4px;font-size:11px;line-height:14px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_layer_b_style .se2_b_style2 span{background:url("../../img/bg_set.gif") 0 -50px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style3 span{background:url("../../img/bg_set.gif") 0 -68px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style4 span{background:url("../../img/bg_set.gif") 0 -86px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style5 span{background:url("../../img/bg_set.gif") 0 -103px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style6 span{background:url("../../img/bg_set.gif") 0 -121px repeat-x} +#smart_editor2 .se2_layer_b_style .se2_b_style7 span{background:url("../../img/bg_set.gif") 0 -139px repeat-x} +/* TEXT_TOOLBAR : TABLEEDITOR > COLOR */ +#smart_editor2 .se2_pre_color{float:left;width:18px;height:18px;border:1px solid #c7c7c7} +#smart_editor2 .se2_pre_color button{float:left;width:14px;height:14px;margin:2px 0 0 2px;padding:0} +#smart_editor2 .se2_pre_color button span{overflow:hidden;position:absolute;top:-10000px;left:-10000px;z-index:-100;width:0;height:0} +/* TEXT_TOOLBAR : TABLEEDITOR > DIMMED */ +#smart_editor2 .se2_table_set .se2_t_dim1{clear:both;position:absolute;top:71px;left:16px;z-index:60;width:157px;height:118px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_table_set .se2_t_dim2{position:absolute;top:116px;left:16px;z-index:55;width:157px;height:45px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_table_set .se2_t_dim3{clear:both;position:absolute;top:192px;left:16px;z-index:51;width:157px;height:39px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +/* TEXT_TOOLBAR : TABLEEDITOR > STYLE PREVIEW */ +#smart_editor2 .se2_table_set .se2_t_proper2{float:left;position:relative;z-index:50;width:166px;margin:2px 0 0 0} +#smart_editor2 .se2_table_set .se2_t_proper2 dt{float:left;width:84px;height:33px;margin:4px 0 0 0} +#smart_editor2 .se2_table_set .se2_t_proper2 dt input{width:15px;height:15px;margin:-1px 3px 1px 0;_margin:-2px 3px 2px 0;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper2 dt label{font-weight:bold;font-size:11px;color:#666;letter-spacing:-1px;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_t_proper2 dd{float:left;width:66px;height:33px} +#smart_editor2 .se2_select_ty2{position:relative;width:65px;height:31px;border:1px solid #c7c7c7;background:#fff;font-size:11px;line-height:14px;text-align:left} +#smart_editor2 .se2_select_ty2 span{float:left;width:45px;height:25px;margin:3px 0 0 3px;background:url("../../img/zh_TW/btn_set.png?160622") repeat-x} +#smart_editor2 .se2_select_ty2 .se2_t_style1{background-position:0 -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style2{background-position:-46px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style3{background-position:-92px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style4{background-position:-138px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style5{background-position:-184px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style6{background-position:-230px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style7{background-position:-276px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style8{background-position:-322px -410px} +#smart_editor2 .se2_select_ty2 .se2_t_style9{background-position:0 -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style10{background-position:-46px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style11{background-position:-92px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style12{background-position:-138px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style13{background-position:-184px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style14{background-position:-230px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style15{background-position:-276px -436px} +#smart_editor2 .se2_select_ty2 .se2_t_style16{background-position:-322px -436px} +#smart_editor2 .se2_select_ty2 .se2_view_more span{display:none} +/* TEXT_TOOLBAR : TABLEEDITOR > STYLE */ +#smart_editor2 .se2_layer_t_style{position:absolute;top:33px;right:15px;width:208px;border:1px solid #c7c7c7;border-top:1px solid #a8a8a8;background:#fff} +#smart_editor2 .se2_layer_t_style ul{width:204px;height:126px;margin:1px 2px;padding:1px 0 0 0;background:#fff} +#smart_editor2 .se2_layer_t_style li{_display:inline;float:left;width:45px;height:25px;margin:1px;padding:1px;border:1px solid #fff} +#smart_editor2 .se2_layer_t_style .hover,#smart_editor2 .se2_layer_t_style .active{border:1px solid #666;background:#fff} +#smart_editor2 .se2_layer_t_style button{width:45px;height:25px;background:url("../../img/zh_TW/btn_set.png?160622") repeat-x !important} +#smart_editor2 .se2_layer_t_style .se2_t_style1{background-position:0 -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style2{background-position:-46px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style3{background-position:-92px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style4{background-position:-138px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style5{background-position:-184px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style6{background-position:-230px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style7{background-position:-276px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style8{background-position:-322px -410px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style9{background-position:0 -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style10{background-position:-46px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style11{background-position:-92px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style12{background-position:-138px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style13{background-position:-184px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style14{background-position:-230px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style15{background-position:-276px -436px !important} +#smart_editor2 .se2_layer_t_style .se2_t_style16{background-position:-322px -436px !important} +#smart_editor2 .se2_table_set .se2_btn_area{float:left;width:166px;margin:6px 0 0 0;padding:12px 0 8px 0;background:url("../../img/bg_line1.gif") repeat-x;text-align:center} +#smart_editor2 .se2_table_set button.se2_apply{width:41px;height:24px;margin-right:3px;background:url("../../img/zh_TW/btn_set.png?160622") no-repeat} +#smart_editor2 .se2_table_set button.se2_cancel{width:39px;height:24px;background:url("../../img/zh_TW/btn_set.png?160622") -41px 0 no-repeat} +#smart_editor2 .se2_table_set .se2_rd{width:14px;height:14px;vertical-align:middle} +#smart_editor2 .se2_table_set .se2_celltit{font-size:11px;font-size:11px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_table_set dt label.se2_celltit{display:inline} +/* TEXT_TOOLBAR : FINDREPLACE */ +#smart_editor2 .se2_bx_find_revise{position:relative;width:255px;margin:0;padding:0} +#smart_editor2 .se2_bx_find_revise .se2_close{position:absolute;top:5px;right:8px;width:20px;height:20px;background:url("../../img/zh_TW/btn_set.png?160622") -151px -1px no-repeat} +#smart_editor2 .se2_bx_find_revise h3{margin:0;padding:10px 0 13px 10px;background:url("../../img/bg_find_h3.gif") 0 -1px repeat-x;font-size:12px;line-height:14px;letter-spacing:-1px} +#smart_editor2 .se2_bx_find_revise ul{position:relative;margin:8px 0 0 0;padding:0 0 0 12px} +#smart_editor2 .se2_bx_find_revise ul li{_display:inline;float:left;position:static;margin:0 0 0 -1px;padding:0} +#smart_editor2 .se2_bx_find_revise .se2_tabfind{width:117px;height:26px;background:url("../../img/zh_TW/btn_set.png?160622") 0 -100px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_tabrevise{width:117px;height:26px;background:url("../../img/zh_TW/btn_set.png?160622") -116px -100px no-repeat} +#smart_editor2 .se2_bx_find_revise .active .se2_tabfind{width:117px;height:26px;background:url("../../img/zh_TW/btn_set.png?160622") 0 -126px no-repeat} +#smart_editor2 .se2_bx_find_revise .active .se2_tabrevise{width:117px;height:26px;background:url("../../img/zh_TW/btn_set.png?160622") -116px -126px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_in_bx_find dl{_display:inline;float:left;width:223px;margin:0 0 0 9px;padding:7px 0 13px 14px;background:url("../../img/bx_set_110302.gif") -289px -1518px no-repeat} +#smart_editor2 .se2_bx_find_revise .se2_in_bx_revise dl{_display:inline;float:left;width:223px;margin:0 0 0 9px;padding:7px 0 13px 14px;background:url("../../img/bx_set_110302.gif") -289px -1619px no-repeat} +#smart_editor2 .se2_bx_find_revise dd{float:left;margin:0 0 2px 0} +#smart_editor2 .se2_bx_find_revise label{float:left;padding:5px 0 0 0;font-size:11px;color:#666;letter-spacing:-2px} +#smart_editor2 .se2_bx_find_revise .se2_find_btns{float:left;clear:both;width:255px;padding:8px 0 10px 0;text-align:center} +#smart_editor2 .se2_bx_find_revise .se2_cancel{width:39px;height:24px;background:url("../../img/zh_TW/btn_set.png?160622") -41px 0 no-repeat} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE */ +#smart_editor2 .se2_qmax{position:absolute;width:18px;height:18px;background:url("../../img/zh_TW/btn_set.png?160622") -339px -169px no-repeat} +#smart_editor2 .se2_qeditor{position:absolute;top:0;left:0;width:183px;margin:0;padding:0;border:1px solid #c7c7c7;border-right:1px solid #ababab;border-bottom:1px solid #ababab;background:#fafafa} +#smart_editor2 .se2_qeditor label,#smart_editor2 .se2_qeditor span,#smart_editor2 .se2_qeditor dt{font-size:11px;color:#666;letter-spacing:-1px} +#smart_editor2 .se2_qbar{position:relative;width:183px;height:11px;background:url("../../img/bx_set_110302.gif") 0 -731px no-repeat} +#smart_editor2 .se2_qbar .se2_qmini{position:absolute;top:-1px;right:0;*right:-1px;_right:-3px;width:18px;height:14px;background:url("../../img/zh_TW/btn_set.png?160622") -315px -170px no-repeat} +#smart_editor2 .se2_qbar .se2_qmini button{width:20px;height:14px;margin-top:-1px} +#smart_editor2 .se2_qeditor .se2_qbody0{float:left;border:1px solid #fefefe} +#smart_editor2 .se2_qeditor .se2_qbody{position:relative;z-index:90;width:174px;padding:4px 0 0 7px} +#smart_editor2 .se2_qeditor .se2_qe1{overflow:hidden;width:174px} +#smart_editor2 .se2_qeditor .se2_qe1 dt{float:left;width:22px;height:18px;padding:4px 0 0 0} +#smart_editor2 .se2_qeditor .se2_qe1 dd{float:left;width:65px;height:22px} +#smart_editor2 .se2_qeditor .se2_addrow{width:28px;height:19px;background:url("../../img/zh_TW/btn_set.png?160622") no-repeat -385px -49px} +#smart_editor2 .se2_qeditor .se2_addcol{width:29px;height:19px;background:url("../../img/zh_TW/btn_set.png?160622") no-repeat -413px -49px} +#smart_editor2 .se2_qeditor .se2_seprow{width:28px;height:19px;background:url("../../img/zh_TW/btn_set.png?160622") no-repeat -385px -68px} +#smart_editor2 .se2_qeditor .se2_sepcol{width:29px;height:19px;background:url("../../img/zh_TW/btn_set.png?160622") no-repeat -413px -68px} +#smart_editor2 .se2_qeditor .se2_delrow{width:28px;height:19px;background:url("../../img/zh_TW/btn_set.png?160622") no-repeat -385px -106px} +#smart_editor2 .se2_qeditor .se2_delcol{width:29px;height:19px;background:url("../../img/zh_TW/btn_set.png?160622") no-repeat -413px -106px} +#smart_editor2 .se2_qeditor .se2_merrow{width:57px;height:19px;background:url("../../img/zh_TW/btn_set.png?160622") no-repeat -385px -125px} +#smart_editor2 .se2_qeditor .se2_mercol{width:57px;height:19px;background:url("../../img/zh_TW/btn_set.png?160622") no-repeat -413px -125px} +#smart_editor2 .se2_qeditor .se2_seprow_off{width:28px;height:19px;background:url("../../img/zh_TW/btn_set.png?160622") no-repeat -385px -87px} +#smart_editor2 .se2_qeditor .se2_sepcol_off{width:29px;height:19px;background:url("../../img/zh_TW/btn_set.png?160622") no-repeat -413px -87px} +#smart_editor2 .se2_qeditor .se2_merrow_off{width:57px;height:19px;background:url("../../img/zh_TW/btn_set.png?160622") no-repeat -385px -144px} +#smart_editor2 .se2_qeditor .se2_mercol_off{width:57px;height:19px;background:url("../../img/zh_TW/btn_set.png?160622") no-repeat -413px -144px} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND */ +#smart_editor2 .se2_qeditor .se2_qe2_1 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qeditor .se2_qe2_1 dd{float:left;position:relative;zoom:1} +#smart_editor2 .se2_qeditor .se2_qe2_3{padding:7px 0 6px 0} +/* My글양식 없을때 */ +#smart_editor2 .se2_qeditor .se2_qe2_2{position:relative;_position:absolute} +#smart_editor2 .se2_qeditor .se2_qe2_2 dt{float:left;width:50px;padding:3px 0 0 13px} +#smart_editor2 .se2_qeditor .se2_qe2_2 dt input{width:15px;height:15px;margin:-1px 2px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qeditor .se2_qe2_2 dd{float:left} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > STYLE */ +#smart_editor2 .se2_qeditor .se2_qe3 dt label{font-weight:normal} +#smart_editor2 .se2_qeditor .se2_qe3 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qeditor .se2_qe3 dd .se2_qe3_table{position:relative} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND PREWVIEW */ +#smart_editor2 .se2_qeditor .se2_pre_color{float:left;width:18px;height:18px;border:1px solid #c7c7c7} +#smart_editor2 .se2_qeditor .se2_pre_color button{float:left;width:14px;height:14px;margin:2px 0 0 2px;padding:0} +#smart_editor2 .se2_qeditor .se2_pre_color button span{overflow:hidden;position:absolute;top:-10000px;left:-10000px;z-index:-100;width:0;height:0} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND LAYER */ +#smart_editor2 .se2_qeditor .se2_layer{float:left;clear:both;position:absolute;top:20px;left:0;margin:0;padding:0;border:1px solid #c7c7c7;border-top:1px solid #9a9a9a;background:#fafafa} +#smart_editor2 .se2_qeditor .se2_layer .se2_in_layer{float:left;margin:0;padding:0;border:1px solid #fff;background:#fafafa} +#smart_editor2 .se2_qeditor .se2_layer button{vertical-align:top} +#smart_editor2 .se2_qeditor .se2_layer .se2_pick_color li{position:relative} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND IMAGE */ +#smart_editor2 .se2_qeditor .se2_pre_bgimg{float:left;width:14px;height:14px;padding:2px;border:1px solid #c7c7c7} +#smart_editor2 .se2_qeditor .se2_qe2_2 button{width:16px;height:16px;background:url("../../img/zh_TW/btn_set.png?160622") 0 -261px no-repeat} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND IMAGE LAYER */ +#smart_editor2 .se2_cellimg_set{_display:inline;float:left;width:136px;margin:4px 3px 0 4px;padding-bottom:4px} +#smart_editor2 .se2_cellimg_set li{_display:inline;float:left;width:16px;height:16px;margin:0 1px 1px 0} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg0{background-position:-255px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg1{background-position:0 -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg2{background-position:-17px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg3{background-position:-34px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg4{background-position:-51px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg5{background-position:-68px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg6{background-position:-85px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg7{background-position:-102px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg8{background-position:-119px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg9{background-position:-136px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg10{background-position:-153px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg11{background-position:-170px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg12{background-position:-187px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg13{background-position:-204px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg14{background-position:-221px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg15{background-position:-238px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg16{background-position:-255px -261px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg17{background-position:0 -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg18{background-position:-17px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg19{background-position:-34px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg20{background-position:-51px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg21{background-position:-68px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg22{background-position:-85px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg23{background-position:-102px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg24{background-position:-119px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg25{background-position:-136px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg26{background-position:-153px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg27{background-position:-170px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg28{background-position:-187px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg29{background-position:-204px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg30{background-position:-221px -278px} +#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg31{background-position:-238px -278px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg button{width:14px;height:14px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg1{background-position:-1px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg2{background-position:-18px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg3{background-position:-35px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg4{background-position:-52px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg5{background-position:-69px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg6{background-position:-86px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg7{background-position:-103px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg8{background-position:-120px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg9{background-position:-137px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg10{background-position:-154px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg11{background-position:-171px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg12{background-position:-188px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg13{background-position:-205px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg14{background-position:-222px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg15{background-position:-239px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg16{background-position:-256px -262px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg17{background-position:-1px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg18{background-position:-18px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg19{background-position:-35px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg20{background-position:-52px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg21{background-position:-69px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg22{background-position:-86px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg23{background-position:-103px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg24{background-position:-120px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg25{background-position:-137px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg26{background-position:-154px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg27{background-position:-171px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg28{background-position:-188px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg29{background-position:-205px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg30{background-position:-222px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg31{background-position:-239px -279px} +#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg32{background-position:-256px -279px} +/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > MY REVIEW */ +#smart_editor2 .se2_btn_area{_display:inline;float:left;clear:both;width:166px;margin:5px 0 0 1px;padding:7px 0 6px 0;background:url("../../img/bg_line1.gif") repeat-x;text-align:center} +#smart_editor2 .se2_btn_area .se2_btn_save{width:97px;height:21px;background:url("../../img/zh_TW/btn_set.png?160622") -369px -163px no-repeat} +/* TEXT_TOOLBAR : QUICKEDITOR_IMAGE */ +#smart_editor2 .se2_qe10{width:166px;margin:0;*margin:-2px 0 0 0} +#smart_editor2 .se2_qe10 label{margin:0 1px 0 0;vertical-align:middle} +#smart_editor2 .se2_qe10 .se2_sheight{margin-left:4px} +#smart_editor2 .se2_qe10 .input_ty1{width:30px;height:13px;margin:0 0 1px 1px;padding:3px 4px 0 1px;font-size:11px;letter-spacing:0;text-align:right;vertical-align:middle} +#smart_editor2 .se2_qe10 .se2_sreset{width:41px;height:19px;margin-left:3px;background:url("../../img/zh_TW/btn_set.png?160622") -401px -184px no-repeat;vertical-align:middle} +#smart_editor2 .se2_qe10_1{margin-top:4px;padding:10px 0 3px;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_qe10_1 input{width:15px;height:15px;margin:-1px 3px 1px -1px;vertical-align:middle} +#smart_editor2 .se2_qe11{float:left;width:166px;margin:4px 0 0 0;padding:7px 0 2px 0;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_qe11_1{float:left;width:99px} +#smart_editor2 .se2_qe11_1 dt{float:left;width:56px;height:15px;padding:5px 0 0 0} +#smart_editor2 .se2_qe11_1 dd{float:left;position:relative;width:38px;height:20px} +#smart_editor2 .se2_qe11_1 .input_ty1{display:block;width:29px;height:15px;margin:0;*margin:-1px 0 1px 0;padding:3px 1px 0 5px;font-size:11px;letter-spacing:0;text-align:left} +#smart_editor2 .se2_qe11_1 .se2_add{position:absolute;top:2px;right:3px;width:13px;height:8px;background:url("../../img/zh_TW/btn_set.png?160622") -86px -54px no-repeat} +#smart_editor2 .se2_qe11_1 .se2_del{position:absolute;top:10px;right:3px;width:13px;height:8px;background:url("../../img/zh_TW/btn_set.png?160622") -86px -62px no-repeat} +#smart_editor2 .se2_qe11_2{float:left;width:67px} +#smart_editor2 .se2_qe11_2 dt{float:left;width:47px;margin:5px 0 0 0} +#smart_editor2 .se2_qe11_2 dd{float:left;position:relative;width:20px} +#smart_editor2 .se2_qe12{float:left;width:166px;margin:3px 0 0 0;padding:7px 0 0 0;background:url("../../img/bg_line1.gif") repeat-x} +#smart_editor2 .se2_qe12 dt{float:left;margin:5px 4px 0 0} +#smart_editor2 .se2_qe12 dd{float:left;padding:0 0 6px 0} +#smart_editor2 .se2_qe12 .se2_align0{float:left;width:19px;height:21px;background:url("../../img/zh_TW/btn_set.png?160622") -276px -121px no-repeat} +#smart_editor2 .se2_qe12 .se2_align1{float:left;width:19px;height:21px;background:url("../../img/zh_TW/btn_set.png?160622") -295px -121px no-repeat} +#smart_editor2 .se2_qe12 .se2_align2{float:left;width:20px;height:21px;background:url("../../img/zh_TW/btn_set.png?160622") -314px -121px no-repeat} +#smart_editor2 .se2_qe13{position:relative;z-index:10;zoom:1} +#smart_editor2 .se2_qe13 dt{float:left;width:62px;padding:3px 0 0} +#smart_editor2 .se2_qe13 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle;zoom:1} +#smart_editor2 .se2_qe13 dt .se2_qdim2{width:32px} +#smart_editor2 .se2_qe13 dd .se2_select_ty1{width:38px} +#smart_editor2 .se2_qe13 dd .se2_select_ty1 span{width:15px} +#smart_editor2 .se2_qe13 dd .input_ty1{width:20px} +#smart_editor2 .se2_qe13 dd .se2_palette2 .input_ty1{width:67px} +#smart_editor2 .se2_qe13 .se2_add{*top:3px} +#smart_editor2 .se2_qe13 .se2_del{*top:11px} +#smart_editor2 .se2_qe13 .se2_layer_b_style{right:-2px;_right:0} +#smart_editor2 .se2_qe13 .se2_layer_b_style li span{width:auto;margin:0 4px 0 5px;padding-top:2px} +#smart_editor2 .se2_qe13 dd{_display:inline;float:left;position:relative;width:29px;margin-right:5px;_margin-right:3px;zoom:1} +#smart_editor2 .se2_qe13 dd .se2_palette h4{margin-top:9px;font-family:dotum;font-size:12px} +#smart_editor2 .se2_qe13 dd.dd_type{width:38px} +#smart_editor2 .se2_qe13 dd.dd_type2{width:37px;margin-right:3px} +#smart_editor2 .se2_qe13 dd.dd_type2 .input_ty1{width:29px} +#smart_editor2 .se2_qe13 dd.dd_type2 button{right:2px;_right:1px} +#smart_editor2 .se2_qe13 dd.dd_type3{width:20px;margin:0} +#smart_editor2 .se2_qe13_v1{_display:inline;float:left;margin:2px 0 1px} +#smart_editor2 .se2_qe13_v1 dt{padding:4px 0 0 1px} +#smart_editor2 .se2_qe13_v2{_display:inline;float:left;position:relative;z-index:100;width:165px;margin:4px 0 0 1px;zoom:1} +#smart_editor2 .se2_qe13_v2 dd{width:18px;margin:0} +#smart_editor2 .se2_qeditor .se2_qdim3{clear:both;position:absolute;top:55px;left:118px;z-index:110;width:56px;height:22px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim5{clear:both;position:absolute;top:31px;left:106px;width:68px;height:26px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim6c{clear:both;position:absolute;top:25px;left:28px;width:29px;height:23px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim6r{clear:both;position:absolute;top:25px;left:57px;width:29px;height:23px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_highedit{float:right;width:56px;height:21px;margin:-27px 8px 0 0;background:url("../../img/zh_TW/btn_set.png?160622") -329px -142px no-repeat} +#smart_editor2 .se2_qeditor .se2_qdim7{clear:both;position:absolute;top:55px;left:24px;z-index:110;width:150px;height:48px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim8{clear:both;position:absolute;top:105px;left:24px;z-index:110;width:150px;height:37px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim9{clear:both;position:absolute;top:55px;left:111px;z-index:110;width:65px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim10{clear:both;position:absolute;top:55px;left:100px;z-index:110;width:77px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} +#smart_editor2 .se2_qeditor .se2_qdim11{clear:both;position:absolute;top:55px;left:65px;z-index:110;width:115px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_TW/smart_editor2_out.css b/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_TW/smart_editor2_out.css new file mode 100644 index 00000000..0baf3770 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/css/zh_TW/smart_editor2_out.css @@ -0,0 +1,12 @@ +@charset "UTF-8"; +/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */ +/* COMMON */ +.se2_outputarea, .se2_outputarea th, .se2_outputarea td{margin:0;padding:0;color:#666;font-size:12px;font-family:'돋움',Dotum,'굴림',Gulim,Helvetica,Sans-serif;line-height:1.5} +.se2_outputarea p{margin:0;padding:0} +.se2_outputarea a:hover{text-decoration:underline} +.se2_outputarea a:link{color:#0000ff} +.se2_outputarea ul{margin:0 0 0 40px;padding:0} +.se2_outputarea ul li{margin:0;list-style-type:disc;padding:0} +.se2_outputarea ul ul li{list-style-type:circle} +.se2_outputarea ul ul ul li{list-style-type:square} +.se2_outputarea img, .se2_outputarea fieldset{border:0} diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_b1.png b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_b1.png new file mode 100644 index 00000000..8bd0c06f Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_b1.png differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_button.gif b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_button.gif new file mode 100644 index 00000000..1619320b Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_button.gif differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_button_left.gif b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_button_left.gif new file mode 100644 index 00000000..7b86ffdd Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_button_left.gif differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_button_right.gif b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_button_right.gif new file mode 100644 index 00000000..0ac699c6 Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_button_right.gif differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_find_h3.gif b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_find_h3.gif new file mode 100644 index 00000000..06627d98 Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_find_h3.gif differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_help.gif b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_help.gif new file mode 100644 index 00000000..f2aae94b Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_help.gif differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_line1.gif b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_line1.gif new file mode 100644 index 00000000..8c506a4a Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_line1.gif differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_quote2.gif b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_quote2.gif new file mode 100644 index 00000000..eb8cd04a Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_quote2.gif differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_set.gif b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_set.gif new file mode 100644 index 00000000..14d09739 Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_set.gif differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_spell.gif b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_spell.gif new file mode 100644 index 00000000..506013e0 Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_spell.gif differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_text_tool.gif b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_text_tool.gif new file mode 100644 index 00000000..60d61def Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/bg_text_tool.gif differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/bx_set_110302.gif b/legacy/nlib/src/main/webapp/js/smartEditor/img/bx_set_110302.gif new file mode 100644 index 00000000..86662e9d Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/bx_set_110302.gif differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/en_US/btn_set.png b/legacy/nlib/src/main/webapp/js/smartEditor/img/en_US/btn_set.png new file mode 100644 index 00000000..91543b34 Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/en_US/btn_set.png differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/en_US/text_tool_set.png b/legacy/nlib/src/main/webapp/js/smartEditor/img/en_US/text_tool_set.png new file mode 100644 index 00000000..4065c7c9 Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/en_US/text_tool_set.png differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/ico_extend.png b/legacy/nlib/src/main/webapp/js/smartEditor/img/ico_extend.png new file mode 100644 index 00000000..1aa88ff6 Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/ico_extend.png differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/icon_set.gif b/legacy/nlib/src/main/webapp/js/smartEditor/img/icon_set.gif new file mode 100644 index 00000000..428c84bd Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/icon_set.gif differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/ja_JP/btn_set.png b/legacy/nlib/src/main/webapp/js/smartEditor/img/ja_JP/btn_set.png new file mode 100644 index 00000000..17725b2d Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/ja_JP/btn_set.png differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/ja_JP/text_tool_set.png b/legacy/nlib/src/main/webapp/js/smartEditor/img/ja_JP/text_tool_set.png new file mode 100644 index 00000000..509f6fc5 Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/ja_JP/text_tool_set.png differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/ko_KR/btn_set.png b/legacy/nlib/src/main/webapp/js/smartEditor/img/ko_KR/btn_set.png new file mode 100644 index 00000000..b10375c9 Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/ko_KR/btn_set.png differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/ko_KR/text_tool_set.png b/legacy/nlib/src/main/webapp/js/smartEditor/img/ko_KR/text_tool_set.png new file mode 100644 index 00000000..fa6cc32a Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/ko_KR/text_tool_set.png differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/zh_CN/btn_set.png b/legacy/nlib/src/main/webapp/js/smartEditor/img/zh_CN/btn_set.png new file mode 100644 index 00000000..8a6364ed Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/zh_CN/btn_set.png differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/zh_CN/text_tool_set.png b/legacy/nlib/src/main/webapp/js/smartEditor/img/zh_CN/text_tool_set.png new file mode 100644 index 00000000..4065c7c9 Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/zh_CN/text_tool_set.png differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/zh_TW/btn_set.png b/legacy/nlib/src/main/webapp/js/smartEditor/img/zh_TW/btn_set.png new file mode 100644 index 00000000..2baacbdb Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/zh_TW/btn_set.png differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/img/zh_TW/text_tool_set.png b/legacy/nlib/src/main/webapp/js/smartEditor/img/zh_TW/text_tool_set.png new file mode 100644 index 00000000..4065c7c9 Binary files /dev/null and b/legacy/nlib/src/main/webapp/js/smartEditor/img/zh_TW/text_tool_set.png differ diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/index.html b/legacy/nlib/src/main/webapp/js/smartEditor/index.html new file mode 100644 index 00000000..3fa7b351 --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/index.html @@ -0,0 +1,846 @@ + + + + + + +네이버 :: Smart Editor 2 ™ + + + + + + + + + + + + +
            +
            글쓰기영역으로 바로가기 +
            + +
            +
              +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +
              + +
            • + +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +
              + +
            • +
              +
            • + +
            • + +
            • + +
            • + +
            • + + + +
            • + +
            • + + + +
            • + +
            • + +
            • +
              +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
            • + +
              +
              +
                +
              • +
              • +
              • +
              • +
              • +
              • +
              • +
              +
              +

              직접 입력

              + + + + + +
              + +
              +
              +
              +
              + +
            • +
              +
            • + + + +
            • +
              + + +
            • + +
              +
              +
              +
                +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              • +
                +
                  +
                • + + +
                +
                +
              • +
              +

              + +

              +
              +
              +
              + +
            • + +
            • + + +
              +
              +
              +
              + 칸수 지정 +
              +
              +
              + + +
              +
              +
              + + +
              +
              + + + + + + + + + + + + + + + + + + + +
                  
                  
                  
              +
              +
              + 속성직접입력 +
              +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              + + +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              +
              + + + +
              +
              +
              +
              +
              +
              + 표스타일 +
              +
              +
              + + + +
              +
              +
              +

              + +

              + +
              + +
              +
              +
              + + +
            • + +
            • + + +
              +
              +
              + +

              찾기/바꾸기

              +
                +
              • +
              • +
              +
              +
              +
              +
              +

              + +

              +
              + + +
              +
              +
              + + +
            • +
            +
            + +
            + + + + + +
            + +
            + + + + + + + + + +
            + + +
            + + +
            + + + + +
            + + +
            + + +
            +
            + + +
            + +
              +
            • +
            • +
            • +
            +
            + +
            + + + +
            +
            + + + +
            + + + + +
            + +
            +
            + + + + + \ No newline at end of file diff --git a/legacy/nlib/src/main/webapp/js/smartEditor/js/bundle/base.js b/legacy/nlib/src/main/webapp/js/smartEditor/js/bundle/base.js new file mode 100644 index 00000000..3c9d55fc --- /dev/null +++ b/legacy/nlib/src/main/webapp/js/smartEditor/js/bundle/base.js @@ -0,0 +1 @@ +/*! Copyright (C) NAVER corp. Licensed under LGPL v2. @see https://github.com/naver/smarteditor2/blob/master/LICENSE.md */!function(i){var n={};function o(e){if(n[e])return n[e].exports;var t=n[e]={i:e,l:!1,exports:{}};return i[e].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.m=i,o.c=n,o.d=function(e,t,i){o.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(t,e){if(1&e&&(t=o(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(o.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)o.d(i,n,function(e){return t[e]}.bind(null,n));return i},o.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return o.d(t,"a",t),t},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.p="",o(o.s=5)}([,,,,,function(e,t,i){"use strict";i(6),i(7),i(8),i(9),i(10),i(11),i(12),i(13),i(14),i(15),i(16),i(17),i(18),i(19),i(20),i(21),i(22),i(23),i(24),i(25),i(26),i(27),i(28),i(29),i(30),i(31),i(32),i(33),i(34),i(35),i(36),i(37),i(38),i(39),i(40),i(41),i(42),i(43),i(44),i(45),i(46),window.nSE2Version="2.10.0.f24352b",nhn.husky.SE_EditingAreaManager.version={revision:"f24352b",type:"open",number:"2.10.0"}},function(e,t){nhn.husky.SE2M_Toolbar=jindo.$Class({name:"SE2M_Toolbar",toolbarArea:null,toolbarButton:null,uiNameTag:"uiName",nUIStatus:1,sUIClassPrefix:"husky_seditor_ui_",aUICmdMap:null,elFirstToolbarItem:null,_hideAlert:function(e){return"function"==typeof e&&e(),this._elAlertLayer.style.display="none",this.oApp.exec("HIDE_EDITING_AREA_COVER"),!1},$ON_ALERT:function(e,t){this._elAlertLayer&&(t=t||{},this._elAlertTxts.innerHTML=e||"",this._elAlertOk.onclick=jindo.$Fn(this._hideAlert,this).bind(t.fOkCallback),this._elAlertClose.onclick=jindo.$Fn(this._hideAlert,this).bind(t.fCloseCallback),t.fCancelCallback?(this._elAlertCancel.onclick=jindo.$Fn(this._hideAlert,this).bind(t.fCancelCallback),this._elAlertCancel.style.display=""):this._elAlertCancel.style.display="none",this.oApp.exec("SHOW_EDITING_AREA_COVER",[!0]),this._elAlertLayer.style.zIndex=100,this._elAlertLayer.style.display="block",this._elAlertOk.focus())},_assignHTMLElements:function(e){e=jindo.$(e)||document,this.rxUI=new RegExp(this.sUIClassPrefix+"([^ ]+)"),this.toolbarArea=jindo.$$.getSingle(".se2_tool",e),this.aAllUI=jindo.$$("[class*="+this.sUIClassPrefix+"]",this.toolbarArea),this.elTextTool=jindo.$$.getSingle("div.husky_seditor_text_tool",this.toolbarArea),this._elAlertLayer=jindo.$$.getSingle(".se2_alert_wrap",e),this._elAlertLayer&&(this._elAlertTxts=jindo.$$.getSingle(".se2_alert_txts",this._elAlertLayer),this._elAlertOk=jindo.$$.getSingle(".se2_confirm",this._elAlertLayer),this._elAlertCancel=jindo.$$.getSingle(".se2_cancel",this._elAlertLayer),this._elAlertClose=jindo.$$.getSingle(".btn_close",this._elAlertLayer)),this.welToolbarArea=jindo.$Element(this.toolbarArea);for(var t=0,i=this.aAllUI.length;tli>button"))},$LOCAL_BEFORE_FIRST:function(){var e=jindo.$$(">ul>li[class*="+this.sUIClassPrefix+"]>button",this.elTextTool),t=e.length;this.elFirstToolbarItem=this.elFirstToolbarItem||e[0],this.elLastToolbarItem=e[t-1],this.oApp.registerBrowserEvent(this.toolbarArea,"keydown","NAVIGATE_TOOLBAR",[])},$init:function(e,t){this._htOptions=t||{},this.htUIList={},this.htWrappedUIList={},this.aUICmdMap={},this._assignHTMLElements(e)},$ON_MSG_APP_READY:function(){this.oApp.bMobile?this.oApp.registerBrowserEvent(this.toolbarArea,"touchstart","EVENT_TOOLBAR_TOUCHSTART"):(this.oApp.registerBrowserEvent(this.toolbarArea,"mouseover","EVENT_TOOLBAR_MOUSEOVER"),this.oApp.registerBrowserEvent(this.toolbarArea,"mouseout","EVENT_TOOLBAR_MOUSEOUT")),this.oApp.registerBrowserEvent(this.toolbarArea,"mousedown","EVENT_TOOLBAR_MOUSEDOWN"),this.oApp.exec("ADD_APP_PROPERTY",["getToolbarButtonByUIName",jindo.$Fn(this.getToolbarButtonByUIName,this).bind()]),this._htOptions.aDisabled&&(this._htOptions._sDisabled=","+this._htOptions.aDisabled.toString()+",",this.oApp.exec("DISABLE_UI",[this._htOptions.aDisabled]))},$ON_NAVIGATE_TOOLBAR:function(e){e.element==this.elLastToolbarItem&&9==e.key().keyCode&&(e.key().shift||(this.elFirstToolbarItem.focus(),e.stopDefault())),e.element==this.elFirstToolbarItem&&9==e.key().keyCode&&e.key().shift&&(e.stopDefault(),this.elLastToolbarItem.focus())},$ON_TOGGLE_TOOLBAR_ACTIVE_LAYER:function(e,t,i,n,o,s){this.oApp.exec("TOGGLE_ACTIVE_LAYER",[e,"MSG_TOOLBAR_LAYER_SHOWN",[e,t,i,n],o,s])},$ON_MSG_TOOLBAR_LAYER_SHOWN:function(e,t,i,n){this.oApp.exec("POSITION_TOOLBAR_LAYER",[e,t]),i&&this.oApp.exec(i,n)},$ON_SHOW_TOOLBAR_ACTIVE_LAYER:function(e,t,i,n){this.oApp.exec("SHOW_ACTIVE_LAYER",[e,t,i]),this.oApp.exec("POSITION_TOOLBAR_LAYER",[e,n])},$ON_ENABLE_UI:function(e){this._enableUI(e)},$ON_DISABLE_UI:function(e){if(e instanceof Array)for(var t,i=0;t=e[i];i++)this._disableUI(t);else this._disableUI(e)},$ON_SELECT_UI:function(e){var t=this.htWrappedUIList[e];t&&(t.removeClass("hover"),t.addClass("active"))},$ON_DESELECT_UI:function(e){var t=this.htWrappedUIList[e];t&&t.removeClass("active")},$ON_TOGGLE_UI_SELECTED:function(e){var t=this.htWrappedUIList[e];t&&(t.hasClass("active")?t.removeClass("active"):(t.removeClass("hover"),t.addClass("active")))},$ON_ENABLE_ALL_UI:function(e){if(1!==this.nUIStatus){var t;e=e||{};var i=jindo.$A(e.aExceptions||[]);for(t in this.htUIList)t&&!i.has(t)&&this._enableUI(t);this.nUIStatus=1}},$ON_DISABLE_ALL_UI:function(e){if(2!==this.nUIStatus){var t;e=e||{};var i=jindo.$A(e.aExceptions||[]),n=e.bLeaveActiveLayer||!1;for(t in n||this.oApp.exec("HIDE_ACTIVE_LAYER"),this.htUIList)t&&!i.has(t)&&this._disableUI(t);this.nUIStatus=2}},$ON_MSG_STYLE_CHANGED:function(e,t){"@^"===t?this.oApp.exec("SELECT_UI",[e]):this.oApp.exec("DESELECT_UI",[e])},$ON_POSITION_TOOLBAR_LAYER:function(e,t){var i,n,o,s;e=jindo.$(e),t=t||{};var r=jindo.$(t.elBtn),a=t.sAlign;if(e){r&&r.tagName&&"BUTTON"==r.tagName&&r.parentNode.appendChild(e);var l=jindo.$Element(e);"right"!=a?(e.style.left="0",n=(i=l.offset().left)+e.offsetWidth,(s=(o=this.welToolbarArea.offset().left)+this.toolbarArea.offsetWidth)this.oApp.elEditingAreaContainer.offsetHeight&&(e.style.top="number"==typeof t?i-e.offsetHeight-t+"px":this.oApp.elEditingAreaContainer.offsetHeight-e.offsetHeight+"px"),parseInt(e.style.left,10)+e.offsetWidth>this.oApp.elEditingAreaContainer.offsetWidth&&(e.style.left=this.oApp.elEditingAreaContainer.offsetWidth-e.offsetWidth+"px")},$ON_EVENT_EDITING_AREA_KEYDOWN:function(){this.oApp.exec("HIDE_ACTIVE_LAYER",[])},$ON_EVENT_EDITING_AREA_MOUSEDOWN:function(){this.oApp.exec("HIDE_ACTIVE_LAYER",[])},$ON_EVENT_EDITING_AREA_SCROLL:function(){this.oApp.exec("HIDE_ACTIVE_LAYER",[])},_setEditingAreaDimension:function(e){e=e||this.oActivePlugin,this._fitElementInEditingArea(e.elEditingArea)},_fitElementInEditingArea:function(e){e.style.height=this.elEditingAreaContainer.offsetHeight+"px"},attachDocumentEvents:function(e){this.oApp.registerBrowserEvent(e,"click","EVENT_EDITING_AREA_CLICK"),this.oApp.registerBrowserEvent(e,"dblclick","EVENT_EDITING_AREA_DBLCLICK"),this.oApp.registerBrowserEvent(e,"mousedown","EVENT_EDITING_AREA_MOUSEDOWN"),this.oApp.registerBrowserEvent(e,"mousemove","EVENT_EDITING_AREA_MOUSEMOVE"),this.oApp.registerBrowserEvent(e,"mouseup","EVENT_EDITING_AREA_MOUSEUP"),this.oApp.registerBrowserEvent(e,"mouseout","EVENT_EDITING_AREA_MOUSEOUT"),this.oApp.registerBrowserEvent(e,"mousewheel","EVENT_EDITING_AREA_MOUSEWHEEL"),this.oApp.registerBrowserEvent(e,"keydown","EVENT_EDITING_AREA_KEYDOWN"),this.oApp.registerBrowserEvent(e,"keypress","EVENT_EDITING_AREA_KEYPRESS"),this.oApp.registerBrowserEvent(e,"keyup","EVENT_EDITING_AREA_KEYUP"),this.oApp.registerBrowserEvent(e,"scroll","EVENT_EDITING_AREA_SCROLL")},$ON_GET_COVER_DIV:function(e,t){this.elEditingAreaCover&&(t[e]=this.elEditingAreaCover)},$ON_SHOW_LOADING_LAYER:function(){this.elLoadingLayer.style.display="block"},$ON_HIDE_LOADING_LAYER:function(){this.elLoadingLayer.style.display="none"},getIR:function(){return this.oActivePlugin?this.oActivePlugin.getIR():""},setIR:function(e,t){this.oApp.exec("SET_IR",[e,t])},getRawContents:function(){return this.oActivePlugin?this.oActivePlugin.getRawContents():""},getContents:function(){this._convertLastBrToNbsp();var e,t=this.oApp.getIR();return e=this.oApp.applyConverter?this.oApp.applyConverter("IR_TO_DB",t,this.oApp.getWYSIWYGDocument()):t,e=this._cleanContents(e)},_convertLastBrToNbsp:function(){for(var e,t,i,n,o,s,r,a,l,h,d,c=this.oApp.getWYSIWYGDocument().body,p=document.createTextNode(" "),u=0,_=(e=jindo.$$("br:last-child",c,{oneTimeOffCache:!0})).length;u<_;u++)if(d=s=null,t=e[u],(n=this._findNextSiblingRecursive(t,{isReverse:!0}))&&1===n.nodeType&&(i=n.nextSibling,!this._findNextSiblingRecursive(i))){if("IMG"===n.tagName.toUpperCase()?s=n:0<(o=jindo.$$("img:last-child",n,{oneTimeOffCache:!0})).length&&(s=o[o.length-1]),s)if(this._findNextSiblingRecursive(s)==i){if(!(a=s.parentNode))continue;r=jindo.$Element(s).width(),a=s.parentNode,l=!(r===jindo.$Element(a).width())}else l=!0;else l=!0;d=t.parentNode,l?(h=p.cloneNode(!1),d.replaceChild(h,t)):this._recursiveRemoveChild(t)}},_findNextSiblingRecursive:function(e,t){for(var i,n=e,o=!(!t||!t.isReverse),s=new RegExp("^(TD|BODY)$","i");!i;)if(i=o?n.previousSibling:n.nextSibling,n=n.parentNode,s.test(n.tagName)){i=null;break}return i},_recursiveRemoveChild:function(e){for(var t,i=e.parentNode,n=e;i.removeChild(n),(t=i.childNodes)&&0==t.length&&(n=i)&&(i=i.parentNode););},_cleanContents:function(e){return e.replace(new RegExp("(]*>)"+unescape("%uFEFF"),"ig"),"$1")},setContents:function(e,t){var i;i=this.oApp.applyConverter?this.oApp.applyConverter("DB_TO_IR",e,this.oApp.getWYSIWYGDocument()):e,this.oApp.exec("SET_IR",[i,t])},getEditingMode:function(){return this.oActivePlugin.sMode},getEditingAreaWidth:function(){return this.elEditingAreaContainer.offsetWidth},getEditingAreaHeight:function(){return this.elEditingAreaContainer.offsetHeight}})},function(e,t){nhn.husky.SE_EditingArea_WYSIWYG=jindo.$Class({name:"SE_EditingArea_WYSIWYG",status:nhn.husky.PLUGIN_STATUS.NOT_READY,sMode:"WYSIWYG",iframe:null,doc:null,bStopCheckingBodyHeight:!1,bAutoResize:!1,nBodyMinHeight:0,nScrollbarWidth:0,iLastUndoRecorded:0,_nIFrameReadyCount:50,bWYSIWYGEnabled:!1,$init:function(e){this.iframe=jindo.$(e);var t=jindo.$Agent().navigator();t.ie&&(this.iframe.style.display="none"),this.sBlankPageURL="smart_editor2_inputarea.html",this.sBlankPageURL_EmulateIE7="smart_editor2_inputarea_ie8.html",this.aAddtionalEmulateIE7=[],this.htOptions=nhn.husky.SE2M_Configuration.SE_EditingAreaManager,this.htOptions&&(this.sBlankPageURL=this.htOptions.sBlankPageURL||this.sBlankPageURL,this.sBlankPageURL_EmulateIE7=this.htOptions.sBlankPageURL_EmulateIE7||this.sBlankPageURL_EmulateIE7,this.aAddtionalEmulateIE7=this.htOptions.aAddtionalEmulateIE7||this.aAddtionalEmulateIE7),this.aAddtionalEmulateIE7.push(8),this.sIFrameSrc=this.sBlankPageURL,t.ie&&jindo.$A(this.aAddtionalEmulateIE7).has(t.nativeVersion)&&(this.sIFrameSrc=this.sBlankPageURL_EmulateIE7),e=this.iframe;var i=this.sIFrameSrc,n=jindo.$Fn(this.initIframe,this).bind(),o=jindo.$Fn(function(){this.iframe.src=i},this).bind();!t.ie||9<=t.version&&document.addEventListener?(e.addEventListener("load",n,!1),e.addEventListener("error",o,!1)):(e.attachEvent("onload",n),e.attachEvent("onerror",o)),e.src=i,this.elEditingArea=e},$BEFORE_MSG_APP_READY:function(){this.oEditingArea=this.iframe.contentWindow.document,this.oApp.exec("REGISTER_EDITING_AREA",[this]),this.oApp.exec("ADD_APP_PROPERTY",["getWYSIWYGWindow",jindo.$Fn(this.getWindow,this).bind()]),this.oApp.exec("ADD_APP_PROPERTY",["getWYSIWYGDocument",jindo.$Fn(this.getDocument,this).bind()]),this.oApp.exec("ADD_APP_PROPERTY",["isWYSIWYGEnabled",jindo.$Fn(this.isWYSIWYGEnabled,this).bind()]),this.oApp.exec("ADD_APP_PROPERTY",["getRawHTMLContents",jindo.$Fn(this.getRawHTMLContents,this).bind()]),this.oApp.exec("ADD_APP_PROPERTY",["setRawHTMLContents",jindo.$Fn(this.setRawHTMLContents,this).bind()]),this.isWYSIWYGEnabled()&&this.oApp.exec("ENABLE_WYSIWYG_RULER"),this.oApp.registerBrowserEvent(this.getDocument().body,"paste","EVENT_EDITING_AREA_PASTE"),this.oApp.registerBrowserEvent(this.getDocument().body,"drop","EVENT_EDITING_AREA_DROP")},$ON_MSG_APP_READY:function(){Object.prototype.hasOwnProperty.call(this.oApp,"saveSnapShot")||(this.$ON_EVENT_EDITING_AREA_MOUSEUP=function(){},this._recordUndo=function(){}),this._bIERangeReset=!0,this.oApp.oNavigator.ie||-1this.nBodyMinHeight?(i=this.oApp.getCurrentStyle(),(n=this._getStyleSize(i))this.nBodyMinHeight?(i=this.oApp.getCurrentStyle(),(n=this._getStyleSize(i))=t.nTop&&e.nBottom<=t.nBottom},_scrollIntoView:function(e){var t,i=this._getElementVerticalPosition(e),n=this._getVisibleVerticalPosition();this._isElementVisible(i,n)||(0<(t=i.nBottom-n.nBottom)?this.getWindow().scrollTo(0,n.nTop+t):this.getWindow().scrollTo(0,i.nTop))},$BEFORE_MSG_EDITING_AREA_RESIZE_STARTED:function(){if(!jindo.$Agent().navigator().ie){var e=null;e=this.oApp.getSelection(),this.sBM=e.placeStringBookmark()}},$AFTER_MSG_EDITING_AREA_RESIZE_ENDED:function(){if(this.oApp.getEditingMode()===this.sMode&&!jindo.$Agent().navigator().ie){var e=this.oApp.getEmptySelection();e.moveToBookmark(this.sBM),e.select(),e.removeStringBookmark(this.sBM)}},$ON_CLEAR_IE_BACKUP_SELECTION:function(){this._oIERange=null},$ON_RESTORE_IE_SELECTION:function(){if(this._oIERange)try{this._oIERange.select(),this._oPrevIERange=this._oIERange,this._oIERange=null}catch(e){}},$ON_EVENT_EDITING_AREA_PASTE:function(e){this.oApp.delayedExec("EVENT_EDITING_AREA_PASTE_DELAY",[e],0)},$ON_EVENT_EDITING_AREA_PASTE_DELAY:function(e){this._replaceBlankToNbsp(e.element)},_replaceBlankToNbsp:function(e){var t=this.oApp.oNavigator;if(t.ie&&9===t.nativeVersion&&7===document.documentMode&&1===e.nodeType&&"BR"!==e.tagName){var i=jindo.$$("p:empty()",this.oApp.getWYSIWYGDocument().body,{oneTimeOffCache:!0});jindo.$A(i).forEach(function(e){e.innerHTML=" "})}},_pageUp:function(e){var t,i=this._getEditorHeight(),n=jindo.$Document(this.oApp.getWYSIWYGDocument()).scrollPosition();t=n.top<=i?0:n.top-i,this.oApp.getWYSIWYGWindow().scrollTo(0,t),e.stop()},_pageDown:function(e){var t,i=this._getEditorHeight(),n=jindo.$Document(this.oApp.getWYSIWYGDocument()).scrollPosition(),o=this._getBodyHeight();t=n.top+i>=o?o-i:n.top+i,this.oApp.getWYSIWYGWindow().scrollTo(0,t),e.stop()},_getEditorHeight:function(){return this.oApp.elEditingAreaContainer.offsetHeight-this.nTopBottomMargin},_getBodyHeight:function(){return parseInt(this.getDocument().body.scrollHeight,10)},initIframe:function(){try{if(!this.iframe.contentWindow.document||!this.iframe.contentWindow.document.body||"about:blank"===this.iframe.contentWindow.document.location.href)throw new Error("Access denied");var e=nhn.husky.SE2M_Configuration.SE2M_CSSLoader&&nhn.husky.SE2M_Configuration.SE2M_CSSLoader.sCSSBaseURI?nhn.husky.SE2M_Configuration.SE2M_CSSLoader.sCSSBaseURI:"";if(nhn.husky.SE2M_Configuration.SE_EditingAreaManager.sCSSBaseURI&&(e=nhn.husky.SE2M_Configuration.SE_EditingAreaManager.sCSSBaseURI),e){var t=e,i=this.oApp&&this.oApp.htOptions.I18N_LOCALE;i&&(t+="/"+i),t+="/smart_editor2_in.css";var n=this.getDocument(),o=n.getElementsByTagName("head")[0],s=n.createElement("link");s.type="text/css",s.rel="stylesheet",s.href=t,s.onload=jindo.$Fn(function(){this.oApp&&this.oApp.getEditingMode&&this.oApp.getEditingMode()===this.sMode&&this.oApp.exec("RESET_STYLE_STATUS"),s.onload=null},this).bind(),o.appendChild(s)}this._enableWYSIWYG(),this.status=nhn.husky.PLUGIN_STATUS.READY}catch(r){if(!(0";if(""===(t=this.oApp.applyConverter?this.oApp.applyConverter("IR_TO_"+this.sMode,e,this.oApp.getWYSIWYGDocument()):e).replace(/[\r\n\t\s]*/,"")&&("BR"!==this.oApp.sLineBreaker&&(n="

            "+n+"

            "),t=n),this.iframe.contentWindow.document.body.innerHTML=t,i&&this.oApp.getEditingMode()===this.sMode)for(var o=this.oApp.getWYSIWYGDocument().body.getElementsByTagName("P"),s=0,r=o.length;s"!==e.toLowerCase()&&"

             

            "!==e.toLowerCase()&&"


            "!==e.toLowerCase()&&"

            "!==e.toLowerCase()||(e="");var t=jindo.$Agent().navigator();t.ie&&11==t.nativeVersion&&11==document.documentMode&&(e=e.replace(/(

            $)/,""));var i=e;this.oApp.applyConverter&&(i=this.oApp.applyConverter("IR_TO_"+this.sMode,i,this.oApp.getWYSIWYGDocument())),this.setRawContents(i)},setRawContents:function(e){void 0!==e&&(this.elEditingArea.value=e)},getRawContents:function(){return this.elEditingArea.value},focus:function(){this.elEditingArea.focus()}}),"undefined"==typeof window.TextRange&&(window.TextRange={}),TextRange=function(e,t){this._o=e,this._oDoc=t||document},TextRange.prototype.getSelection=function(){var e=this._o,t=[-1,-1];if(isNaN(this._o.selectionStart)){e.focus();var i=this._oDoc.body.createTextRange(),n=null;n=this._oDoc.selection.createRange().duplicate(),i.moveToElementText(e),n.collapse(!0),i.setEndPoint("EndToEnd",n),t[0]=i.text.length,n=this._oDoc.selection.createRange().duplicate(),i.moveToElementText(e),n.collapse(!1),i.setEndPoint("EndToEnd",n),t[1]=i.text.length,e.blur()}else t[0]=e.selectionStart,t[1]=e.selectionEnd;return t},TextRange.prototype.setSelection=function(e,t){var i=this._o;if(void 0===t&&(t=e),i.setSelectionRange)i.setSelectionRange(e,t);else if(i.createTextRange){var n=i.createTextRange();n.collapse(!0),n.moveStart("character",e),n.moveEnd("character",t-e),n.select(),i.blur()}},TextRange.prototype.copy=function(){var e=this.getSelection();return this._o.value.substring(e[0],e[1])},TextRange.prototype.paste=function(e){var t=this._o,i=this.getSelection(),n=t.value,o=n.substr(0,i[0]);n=o+e+n.substr(i[1]),t.value=n;var s=0;if("undefined"==typeof this._oDoc.body.style.maxHeight){var r=o.match(/\n/gi);s=null!==r?r.length:0}this.setSelection(i[0]+e.length-s)},TextRange.prototype.cut=function(){var e=this.copy();return this.paste(""),e}},function(e,t){nhn.husky.SE_EditingArea_TEXT=jindo.$Class({name:"SE_EditingArea_TEXT",sMode:"TEXT",sRxConverter:"@[0-9]+@",bAutoResize:!1,nMinHeight:null,$init:function(e){this.elEditingArea=jindo.$(e)},$BEFORE_MSG_APP_READY:function(){this.oNavigator=jindo.$Agent().navigator(),this.oApp.exec("REGISTER_EDITING_AREA",[this]),this.oApp.exec("ADD_APP_PROPERTY",["getTextAreaContents",jindo.$Fn(this.getRawContents,this).bind()])},$ON_MSG_APP_READY:function(){this.oApp.getEditingAreaHeight&&(this.nMinHeight=this.oApp.getEditingAreaHeight())},$ON_REGISTER_CONVERTERS:function(){this.oApp.exec("ADD_CONVERTER",["IR_TO_TEXT",jindo.$Fn(this.irToText,this).bind()]),this.oApp.exec("ADD_CONVERTER",["TEXT_TO_IR",jindo.$Fn(this.textToIr,this).bind()])},$ON_CHANGE_EDITING_MODE:function(e){e==this.sMode?(this.elEditingArea.style.display="block",this.elEditingArea.style.position="absolute",this.elEditingArea.style.top="0px"):(this.elEditingArea.style.display="none",this.elEditingArea.style.position="",this.elEditingArea.style.top="")},$AFTER_CHANGE_EDITING_MODE:function(e,t){e!=this.sMode||t||new TextRange(this.elEditingArea).setSelection(0,0)},irToText:function(e){var t,i=e,n=i.match(new RegExp(this.sRxConverter));return null!==n&&(i=i.replace(new RegExp(this.sRxConverter),"")),-1<(t=(i=(i=(i=(i=(i=(i=(i=(i=(i=(i=i.replace(/\r/g,"")).replace(/[\n|\t]/g,"")).replace(/[\v|\f]/g,"")).replace(/


            <\/p>/gi,"\n")).replace(/

             <\/P>/gi,"\n")).replace(//gi,"\n")).replace(//gi,"\n")).replace(/<\/p(\s[^/]*)?>/gi,"\n")).replace(/<\/li(\s[^/]*)?>/gi,"\n")).replace(/<\/tr(\s[^/]*)?>/gi,"\n")).lastIndexOf("\n"))&&"\n"==i.substring(t)&&(i=i.substring(0,t)),i=jindo.$S(i).stripTags().toString(),i=this.unhtmlSpecialChars(i),null!==n&&(i=n[0]+i),i},textToIr:function(e){if(e){var t,i=e;return null!==(t=i.match(new RegExp(this.sRxConverter)))&&(i=i.replace(t[0],"")),i=this.htmlSpecialChars(i),i=this._addLineBreaker(i),null!==t&&(i=t[0]+i),i}},_addLineBreaker:function(e){if("BR"===this.oApp.sLineBreaker)return e.replace(/\r?\n/g,"
            ");for(var t=new StringBuffer,i=e.split("\n"),n=i.length,o="",s=0;s"),t.append(i[s]),t.append("

            ")):jindo.$Agent().navigator().ie?t.append("

             

            "):t.append("


            ");return t.toString()},startAutoResize:function(){var e={nMinHeight:this.nMinHeight,wfnCallback:jindo.$Fn(this.oApp.checkResizeGripPosition,this).bind()};this.oNavigator.msafari&&(e.wfnCallback=function(){}),this.bAutoResize=!0,this.AutoResizer=new nhn.husky.AutoResizer(this.elEditingArea,e),this.AutoResizer.bind()},stopAutoResize:function(){this.AutoResizer.unbind()},getIR:function(){var e=this.getRawContents();return this.oApp.applyConverter&&(e=this.oApp.applyConverter(this.sMode+"_TO_IR",e,this.oApp.getWYSIWYGDocument())),e},setIR:function(e){var t=e;this.oApp.applyConverter&&(t=this.oApp.applyConverter("IR_TO_"+this.sMode,t,this.oApp.getWYSIWYGDocument())),this.setRawContents(t)},setRawContents:function(e){void 0!==e&&(this.elEditingArea.value=e)},getRawContents:function(){return this.elEditingArea.value},focus:function(){this.elEditingArea.focus()},htmlSpecialChars:function(e){return e.replace(/&/g,"&").replace(//g,">").replace(/ /g," ")},unhtmlSpecialChars:function(e){return e.replace(/</g,"<").replace(/>/g,">").replace(/ /g," ").replace(/&/g,"&")}})},function(e,t){nhn.husky.SE_EditingAreaVerticalResizer=jindo.$Class({name:"SE_EditingAreaVerticalResizer",oResizeGrip:null,sCookieNotice:"bHideResizeNotice",nEditingAreaMinHeight:null,htConversionMode:null,$init:function(e,t){this.htConversionMode=t,this._assignHTMLElements(e)},$BEFORE_MSG_APP_READY:function(){this.oApp.exec("ADD_APP_PROPERTY",["isUseVerticalResizer",jindo.$Fn(this.isUseVerticalResizer,this).bind()])},$ON_MSG_APP_READY:function(){this.oApp.bMobile?(this.oResizeGrip.disabled=!0,this.oResizeGrip.style.height="0"):(this.oApp.exec("REGISTER_HOTKEY",["shift+esc","FOCUS_RESIZER"]),this.isUseVerticalResizer()?(this.oResizeGrip.style.display="block",this.welNoticeLayer&&!Number(jindo.$Cookie().get(this.sCookieNotice))&&(this.welNoticeLayer.delegate("click","BUTTON.bt_clse",jindo.$Fn(this._closeNotice,this).bind()),this.welNoticeLayer.show()),this.$FnMouseDown=jindo.$Fn(this._mousedown,this),this.$FnMouseMove=jindo.$Fn(this._mousemove,this),this.$FnMouseUp=jindo.$Fn(this._mouseup,this),this.$FnMouseOver=jindo.$Fn(this._mouseover,this),this.$FnMouseOut=jindo.$Fn(this._mouseout,this),this.$FnMouseDown.attach(this.oResizeGrip,"mousedown"),this.$FnMouseOver.attach(this.oResizeGrip,"mouseover"),this.$FnMouseOut.attach(this.oResizeGrip,"mouseout")):(this.oResizeGrip.style.display="none",this.oApp.isUseModeChanger()||(this.elModeToolbar.style.display="none"))),this.oApp.exec("ADD_APP_PROPERTY",["checkResizeGripPosition",jindo.$Fn(this.checkResizeGripPosition,this).bind()]),this.oApp.getEditingAreaHeight&&(this.nEditingAreaMinHeight=this.oApp.getEditingAreaHeight())},$ON_DISABLE_ALL_UI:function(){this.oResizeGrip.style.cursor="default",this.welConversionMode.addClass("off"),this.oResizeGrip.disabled=!0},$ON_ENABLE_ALL_UI:function(){this.oResizeGrip.style.cursor="n-resize",this.welConversionMode.removeClass("off"),this.oResizeGrip.disabled=!1},isUseVerticalResizer:function(){return"undefined"==typeof this.htConversionMode||"undefined"==typeof this.htConversionMode.bUseVerticalResizer||!0===this.htConversionMode.bUseVerticalResizer},checkResizeGripPosition:function(e){var t=jindo.$Document(),i=jindo.$Element(this.oResizeGrip).offset().top-t.scrollPosition().top+25-t.clientSize().height;i<=0||(e&&(this.nEditingAreaMinHeight>this.oApp.getEditingAreaHeight()-i&&(i=-1*(this.nEditingAreaMinHeight-this.oApp.getEditingAreaHeight())),this.oApp.exec("MSG_EDITING_AREA_RESIZE_STARTED"),this.oApp.exec("RESIZE_EDITING_AREA_BY",[0,-1*i]),this.oApp.exec("MSG_EDITING_AREA_RESIZE_ENDED")),this.oApp.exec("STOP_AUTORESIZE_EDITING_AREA"))},$ON_FOCUS_RESIZER:function(){this.oApp.exec("IE_HIDE_CURSOR"),this.oResizeGrip.focus()},_assignHTMLElements:function(e){this.oResizeGrip=jindo.$$.getSingle("BUTTON.husky_seditor_editingArea_verticalResizer",e),this.elModeToolbar=jindo.$$.getSingle("DIV.se2_conversion_mode",e),this.welNoticeLayer=jindo.$Element(jindo.$$.getSingle("DIV.husky_seditor_resize_notice",e)),this.welConversionMode=jindo.$Element(this.oResizeGrip.parentNode)},_mouseover:function(e){e.stopBubble(),this.welConversionMode.addClass("controller_on")},_mouseout:function(e){e.stopBubble(),this.welConversionMode.removeClass("controller_on")},_mousedown:function(e){this.iStartHeight=e.pos().clientY,this.iStartHeightOffset=e.pos().layerY,this.$FnMouseMove.attach(document,"mousemove"),this.$FnMouseUp.attach(document,"mouseup"),this.iStartHeight=e.pos().clientY,this.oApp.exec("HIDE_ACTIVE_LAYER"),this.oApp.exec("HIDE_ALL_DIALOG_LAYER"),this.oApp.exec("MSG_EDITING_AREA_RESIZE_STARTED",[this.$FnMouseDown,this.$FnMouseMove,this.$FnMouseUp])},_mousemove:function(e){var t=e.pos().clientY-this.iStartHeight;this.oApp.exec("RESIZE_EDITING_AREA_BY",[0,t])},_mouseup:function(){this.$FnMouseMove.detach(document,"mousemove"),this.$FnMouseUp.detach(document,"mouseup"),this.oApp.exec("MSG_EDITING_AREA_RESIZE_ENDED",[this.$FnMouseDown,this.$FnMouseMove,this.$FnMouseUp])},_closeNotice:function(){this.welNoticeLayer.hide(),jindo.$Cookie().set(this.sCookieNotice,1,3650)}})},function(e,t){nhn.husky.SE_WYSIWYGEnterKey=jindo.$Class({name:"SE_WYSIWYGEnterKey",$init:function(e){this.sLineBreaker="BR"==e?"BR":"P",this.htBrowser=jindo.$Agent().navigator(),this.htBrowser.opera&&"P"==this.sLineBreaker&&(this.$ON_MSG_APP_READY=function(){}),this.htBrowser.ie?this._addCursorHolder=this._addCursorHolderSpace:(this._addExtraCursorHolder=function(){},this._addBlankText=function(){})},$ON_MSG_APP_READY:function(){this.oApp.exec("ADD_APP_PROPERTY",["sLineBreaker",this.sLineBreaker]),this.oSelection=this.oApp.getEmptySelection(),this.tmpTextNode=this.oSelection._document.createTextNode(unescape("%u00A0")),jindo.$Fn(this._onKeyDown,this).attach(this.oApp.getWYSIWYGDocument(),"keydown")},_onKeyDown:function(e){var t=e.key();t.shift||t.enter&&("BR"==this.sLineBreaker?this._insertBR(e):this._wrapBlock(e))},$ON_REGISTER_CONVERTERS:function(){this.oApp.exec("ADD_CONVERTER",["IR_TO_DB",jindo.$Fn(this.onIrToDB,this).bind()])},onIrToDB:function(e){var t=e,i=/(]*>)(?:\s*)(<\/p>)/gi;return t=this.htBrowser.ie&&this.htBrowser.version<11?t.replace(i,"$1 $2"):t.replace(i,"")},_addBlankText:function(e){var t,i,n,o,s,r=e.getNodes();for(t=0,i=r.length;t"),t=t||this._getStyleNode(e)},_addCursorHolderSpace:function(e){var t;if(this._addSpace(e),""==(t=this._getStyleNode(e)).innerHTML&&"param"!=t.nodeName.toLowerCase())try{t.innerHTML=unescape("%uFEFF")}catch(i){}return t},_getBlockEndNode:function(e,t){return e?"BR"===e.nodeName?e:e===t?t:this._getBlockEndNode(e.nextSibling,t):t},_convertHeadSpace:function(e){if(e&&3===e.nodeType){for(var t,i=e.nodeValue,n="",o=0;(t=i[o])&&" "===t;o++)n+=" ";0"),t.collapseToEnd())}}t.insertNode(this.oApp.getWYSIWYGDocument().createTextNode("")),t.select()}})},function(e,t){nhn.husky.SE2M_EditingModeChanger=jindo.$Class({name:"SE2M_EditingModeChanger",htConversionMode:null,$init:function(e,t){this.htConversionMode=t,this._assignHTMLElements(e)},_assignHTMLElements:function(e){e=jindo.$(e)||document,this.elWYSIWYGButton=jindo.$$.getSingle("BUTTON.se2_to_editor",e),this.elHTMLSrcButton=jindo.$$.getSingle("BUTTON.se2_to_html",e),this.elTEXTButton=jindo.$$.getSingle("BUTTON.se2_to_text",e),this.elModeToolbar=jindo.$$.getSingle("DIV.se2_conversion_mode",e),this.welWYSIWYGButtonLi=jindo.$Element(this.elWYSIWYGButton.parentNode),this.welHTMLSrcButtonLi=jindo.$Element(this.elHTMLSrcButton.parentNode),this.welTEXTButtonLi=jindo.$Element(this.elTEXTButton.parentNode)},$BEFORE_MSG_APP_READY:function(){this.oApp.exec("ADD_APP_PROPERTY",["isUseModeChanger",jindo.$Fn(this.isUseModeChanger,this).bind()])},$ON_MSG_APP_READY:function(){this.oApp.htOptions.bOnlyTextMode?(this.elWYSIWYGButton.style.display="none",this.elHTMLSrcButton.style.display="none",this.elTEXTButton.style.display="block",this.oApp.exec("CHANGE_EDITING_MODE",["TEXT"])):(this.oApp.registerBrowserEvent(this.elWYSIWYGButton,"click","EVENT_CHANGE_EDITING_MODE_CLICKED",["WYSIWYG"]),this.oApp.registerBrowserEvent(this.elHTMLSrcButton,"click","EVENT_CHANGE_EDITING_MODE_CLICKED",["HTMLSrc"]),this.oApp.registerBrowserEvent(this.elTEXTButton,"click","EVENT_CHANGE_EDITING_MODE_CLICKED",["TEXT",!1]),this.showModeChanger(),!1===this.isUseModeChanger()&&!1===this.oApp.isUseVerticalResizer()&&(this.elModeToolbar.style.display="none"))},showModeChanger:function(){this.isUseModeChanger()?(this.elWYSIWYGButton.style.display="block",this.elHTMLSrcButton.style.display="block",this.elTEXTButton.style.display="block"):(this.elWYSIWYGButton.style.display="none",this.elHTMLSrcButton.style.display="none",this.elTEXTButton.style.display="none")},isUseModeChanger:function(){return"undefined"==typeof this.htConversionMode||"undefined"==typeof this.htConversionMode.bUseModeChanger||!0===this.htConversionMode.bUseModeChanger},$ON_EVENT_CHANGE_EDITING_MODE_CLICKED:function(e,t){if("TEXT"==e){if(0]*)?>(?:.|\r|\n)*?<\/style>/gi,_rxStyleTagStrip:/<\/?style(?:\s+[^>]*)?>/gi,_rxClassSelector:/\w*\.\w+/g,_rxClassSelectorStart:/\w*\./g,$init:function(){},_getTmpDocument:function(){if(!this._oTmpDoc){var e=document.createElement("IFRAME");e.style.display="none",document.body.appendChild(e);var t=e.contentWindow.document;t.open(),t.write(""),t.close(),this._oTmpDoc=t}return this._oTmpDoc},_getCSSStyleRule:function(e){for(var t,i={},n=0;t=e[n];n++)t.type===CSSRule.STYLE_RULE&&(i[t.selectorText]=t.style);return i},_extractStyle:function(e){if(e){var t=(e.match(this._rxStyleTag)||[]).join("\n");t=t.replace(this._rxStyleTagStrip,"");var i=this._getTmpDocument(),n=i.getElementsByTagName("HEAD")[0],o=i.createElement("STYLE");o.innerHTML=t,n.appendChild(o),this._htStyleRule=this._getCSSStyleRule(o.sheet.cssRules),o.parentNode.removeChild(o)}},_applyInlineStyle:function(e,t,i){for(var n,o=0,s=t.length;oo.nRecursiveCount&&(i=!0):i=!0}}i&&this._insertDummyParagraph_IE(e)},_insertDummyParagraph_IE:function(e){this._elDummyParagraph=document.createElement("P"),e.appendChild(this._elDummyParagraph)},_removeDummyParagraph_IE:function(){this._elDummyParagraph&&this._elDummyParagraph.parentNode&&this._elDummyParagraph.parentNode.removeChild(this._elDummyParagraph)},$ON_EXECCOMMAND:function(e,t,i){var n={},o=this.oApp.getSelection();if(t=!(""!=t&&!t)&&t,i=!(""!=i&&!i)&&i,this.oApp.exec("IS_SELECTED_TD_BLOCK",["bIsSelectedTd",n]),n.bIsSelectedTd)"indent"==e?this.oApp.exec("SET_LINE_BLOCK_STYLE",[null,jindo.$Fn(this._indentMargin,this).bind()]):"outdent"==e?this.oApp.exec("SET_LINE_BLOCK_STYLE",[null,jindo.$Fn(this._outdentMargin,this).bind()]):this._setBlockExecCommand(e,t,i);else switch(e){case"indent":case"outdent":this.oApp.exec("RECORD_UNDO_BEFORE_ACTION",[e]);var s=o.placeStringBookmark();"indent"===e?this.oApp.exec("SET_LINE_STYLE",[null,jindo.$Fn(this._indentMargin,this).bind(),{bDoNotSelect:!0,bDontAddUndoHistory:!0}]):this.oApp.exec("SET_LINE_STYLE",[null,jindo.$Fn(this._outdentMargin,this).bind(),{bDoNotSelect:!0,bDontAddUndoHistory:!0}]),o.moveToStringBookmark(s),o.select(),o.removeStringBookmark(s),setTimeout(jindo.$Fn(function(e){this.oApp.exec("RECORD_UNDO_AFTER_ACTION",[e])},this).bind(e),25);break;case"justifyleft":case"justifycenter":case"justifyright":case"justifyfull":var r=this._extendBlock();this.oEditingArea.execCommand(e,t,i),r&&r.select(),this.oNavigator.ie&&this._removeElementAlign("table");break;default:if(o.collapsed&&this._rxCmdInline.test(e)){var a=o.placeStringBookmark(),l=o.getStringBookmark(a).previousSibling;l&&"​"===l.nodeValue||(l=this.oApp.getWYSIWYGDocument().createTextNode("​"),o.insertNode(l)),o.removeStringBookmark(a),o.selectNodeContents(l),o.select(),this.oEditingArea.execCommand(e,t,i),o.collapseToEnd(),o.select();var h=this._findSingleNode(l);h&&o._hasCursorHolderOnly(h.nextSibling)&&h.parentNode.removeChild(h.nextSibling)}else this.oEditingArea.execCommand(e,t,i)}this._countClickCr(e)},_findSingleNode:function(e){return e?1===e.parentNode.childNodes.length?this._findSingleNode(e.parentNode):e:null},$AFTER_EXECCOMMAND:function(e,t,i,n){this.elP1&&this.elP1.parentNode&&this.elP1.parentNode.removeChild(this.elP1),this.elP2&&this.elP2.parentNode&&this.elP2.parentNode.removeChild(this.elP2),/^insertorderedlist|insertunorderedlist$/i.test(e)&&(this._removeDummyParagraph_IE(),this._fixCorruptedBlockQuote("insertorderedlist"===e?"OL":"UL"),this.oNavigator.bGalaxyBrowser&&this._removeBlockQuote()),/^justify*/i.test(e)&&this._fixAlign("justifyfull"===e?"justify":e.substring(7)),"indent"!=e&&"outdent"!=e||((n=n||{}).bDontAddUndoHistory=!0),n&&n.bDontAddUndoHistory||this._bOnlyCursorChanged||this.oApp.exec("RECORD_UNDO_AFTER_ACTION",[e,this.oUndoOption]),this.oApp.exec("CHECK_STYLE_CHANGE",[])},_removeElementAlign:function(e){for(var t=this.oApp.getSelection().getNodes(),i=null,n=new RegExp("^"+e+"$","i"),o=0,s=t.length;o 

            ",this.oApp.getWYSIWYGDocument()),t.parentNode.insertBefore(this.elP1,t),this.elP2=jindo.$("

             

            ",this.oApp.getWYSIWYGDocument()),t.parentNode.insertBefore(this.elP2,t.nextSibling);break}t=t.parentNode}if(!this.elP1&&!this.elP2){var i=(t=1!==(t=e.commonAncestorContainer).nodeType?t.parentNode:t).previousSibling,n=t.nextSibling;i&&"BLOCKQUOTE"===i.tagName&&(this.elP1=jindo.$("

             

            ",this.oApp.getWYSIWYGDocument()),i.parentNode.insertBefore(this.elP1,i.nextSibling)),n&&"BLOCKQUOTE"===n.tagName&&(this.elP1=jindo.$("

             

            ",this.oApp.getWYSIWYGDocument()),n.parentNode.insertBefore(this.elP1,n))}},_fixCorruptedBlockQuote:function(e){var t,i,n,o,s,r,a,l,h,d=this.oApp.getWYSIWYGDocument().getElementsByTagName(e);for(s=0,r=d.length;s',$init:function(e){this.elAppContainer=e},$ON_MSG_APP_READY:function(){},_assignHTMLElements:function(e){var t=nhn.husky.SE2M_Configuration.SE2M_ColorPalette;if(t){var i=(nhn.husky.SE2M_Configuration.LinkageDomain||{}).sCommonAPI||"";this.bUseRecentColor=t.bUseRecentColor||!1,this.URL_COLOR_ADD=t.addColorURL||i+"/1/colortable/TextAdd.nhn",this.URL_COLOR_UPDATE=t.updateColorURL||i+"/1/colortable/TextUpdate.nhn",this.URL_COLOR_LIST=t.colorListURL||i+"/1/colortable/TextList.nhn"}this.elColorPaletteLayer=jindo.$$.getSingle("DIV.husky_se2m_color_palette",e),this.elColorPaletteLayerColorPicker=jindo.$$.getSingle("DIV.husky_se2m_color_palette_colorpicker",this.elColorPaletteLayer),this.elRecentColorForm=jindo.$$.getSingle("form",this.elColorPaletteLayerColorPicker),this.elBackgroundColor=jindo.$$.getSingle("ul.husky_se2m_bgcolor_list",e),this.elInputColorCode=jindo.$$.getSingle("INPUT.husky_se2m_cp_colorcode",this.elColorPaletteLayerColorPicker),this.elPreview=jindo.$$.getSingle("SPAN.husky_se2m_cp_preview",this.elColorPaletteLayerColorPicker),this.elCP_ColPanel=jindo.$$.getSingle("DIV.husky_se2m_cp_colpanel",this.elColorPaletteLayerColorPicker),this.elCP_HuePanel=jindo.$$.getSingle("DIV.husky_se2m_cp_huepanel",this.elColorPaletteLayerColorPicker),this.elCP_ColPanel.style.position="relative",this.elCP_HuePanel.style.position="relative",this.elColorPaletteLayerColorPicker.style.display="none",this.elMoreBtn=jindo.$$.getSingle("BUTTON.husky_se2m_color_palette_more_btn",this.elColorPaletteLayer),this.welMoreBtn=jindo.$Element(this.elMoreBtn),this.elOkBtn=jindo.$$.getSingle("BUTTON.husky_se2m_color_palette_ok_btn",this.elColorPaletteLayer),this.bUseRecentColor&&(this.elColorPaletteLayerRecent=jindo.$$.getSingle("DIV.husky_se2m_color_palette_recent",this.elColorPaletteLayer),this.elRecentColor=jindo.$$.getSingle("ul.se2_pick_color",this.elColorPaletteLayerRecent),this.elDummyNode=jindo.$$.getSingle("ul.se2_pick_color > li",this.elColorPaletteLayerRecent)||null,this.elColorPaletteLayerRecent.style.display="none")},$LOCAL_BEFORE_FIRST:function(){this._assignHTMLElements(this.elAppContainer),this.elDummyNode&&jindo.$Element(jindo.$$.getSingle("ul.se2_pick_color > li",this.elColorPaletteLayerRecent)).leave(),this.bUseRecentColor&&this._ajaxRecentColor(this._ajaxRecentColorCallback),this.oApp.registerBrowserEvent(this.elColorPaletteLayer,"click","EVENT_CLICK_COLOR_PALETTE"),this.oApp.bMobile||(this.oApp.registerBrowserEvent(this.elBackgroundColor,"mouseover","EVENT_MOUSEOVER_COLOR_PALETTE"),this.oApp.registerBrowserEvent(this.elColorPaletteLayer,"mouseover","EVENT_MOUSEOVER_COLOR_PALETTE"),this.oApp.registerBrowserEvent(this.elBackgroundColor,"mouseout","EVENT_MOUSEOUT_COLOR_PALETTE"),this.oApp.registerBrowserEvent(this.elColorPaletteLayer,"mouseout","EVENT_MOUSEOUT_COLOR_PALETTE"))},$ON_EVENT_MOUSEOVER_COLOR_PALETTE:function(e){for(var t=e.element;t&&t.tagName&&"li"!=t.tagName.toLowerCase();)t=t.parentNode;t&&t.nodeType&&9!=t.nodeType&&(""!=t.className&&t.className&&"undefined"!=typeof t.className||jindo.$Element(t).addClass("hover"))},$ON_EVENT_MOUSEOUT_COLOR_PALETTE:function(e){for(var t=e.element;t&&t.tagName&&"li"!=t.tagName.toLowerCase();)t=t.parentNode;t&&"hover"==t.className&&jindo.$Element(t).removeClass("hover")},$ON_EVENT_CLICK_COLOR_PALETTE:function(e){for(var t=e.element;"SPAN"==t.tagName;)t=t.parentNode;if(t.tagName&&"BUTTON"==t.tagName){if(t==this.elMoreBtn)return void this.oApp.exec("TOGGLE_COLOR_PICKER");this.oApp.exec("APPLY_COLOR",[t])}},$ON_APPLY_COLOR:function(e){var t=this.elInputColorCode.value,i=null;if(-1==t.indexOf("#")&&(t="#"+t,this.elInputColorCode.value=t),e==this.elOkBtn)return this._verifyColorCode(t)?void this.oApp.exec("COLOR_PALETTE_APPLY_COLOR",[t,!0]):(this.elInputColorCode.value="",alert(this.oApp.$MSG("SE_Color.invalidColorCode")),void this.elInputColorCode.focus());i=jindo.$Element(e.parentNode.parentNode.parentNode),t=e.title,i.hasClass("husky_se2m_color_palette")?this.oApp.exec("COLOR_PALETTE_APPLY_COLOR",[t,!1]):i.hasClass("husky_se2m_color_palette_recent")&&this.oApp.exec("COLOR_PALETTE_APPLY_COLOR",[t,!0])},$ON_RESET_COLOR_PALETTE:function(){this._initColor()},$ON_TOGGLE_COLOR_PICKER:function(){"none"==this.elColorPaletteLayerColorPicker.style.display?this.oApp.exec("SHOW_COLOR_PICKER"):this.oApp.exec("HIDE_COLOR_PICKER")},$ON_SHOW_COLOR_PICKER:function(){this.elColorPaletteLayerColorPicker.style.display="",this.cpp=new nhn.ColorPicker(this.elCP_ColPanel,{huePanel:this.elCP_HuePanel});var e=jindo.$Fn(function(e){this.elPreview.style.backgroundColor=e.hexColor,this.elInputColorCode.value=e.hexColor},this).bind();this.cpp.attach("colorchange",e),this.$ON_SHOW_COLOR_PICKER=this._showColorPickerMain,this.$ON_SHOW_COLOR_PICKER()},$ON_HIDE_COLOR_PICKER:function(){this.elColorPaletteLayerColorPicker.style.display="none",this.welMoreBtn.addClass("se2_view_more"),this.welMoreBtn.removeClass("se2_view_more2")},$ON_SHOW_COLOR_PALETTE:function(e,t){this.sCallbackCmd=e,this.oLayerContainer=t,this.oLayerContainer.insertBefore(this.elColorPaletteLayer,null),this.elColorPaletteLayer.style.display="block",this.oApp.delayedExec("POSITION_TOOLBAR_LAYER",[this.elColorPaletteLayer.parentNode.parentNode],0)},$ON_HIDE_COLOR_PALETTE:function(){this.elColorPaletteLayer.style.display="none"},$ON_COLOR_PALETTE_APPLY_COLOR:function(e,t){t=t||!1,e=this._getHexColorCode(e),this.bUseRecentColor&&t&&this.oApp.exec("ADD_RECENT_COLOR",[e]),this.oApp.exec(this.sCallbackCmd,[e])},$ON_EVENT_MOUSEUP_COLOR_PALETTE:function(e){var t=e.element;t.style.backgroundColor&&this.oApp.exec("COLOR_PALETTE_APPLY_COLOR",[t.style.backgroundColor,!1])},$ON_ADD_RECENT_COLOR:function(e){var t=0===this.aRecentColor.length;this._addRecentColor(e),t?this._ajaxAddColor():this._ajaxUpdateColor(),this._redrawRecentColorElement()},_verifyColorCode:function(e){return this.rxColorPattern.test(e)},_getHexColorCode:function(e){if(this.rxRGBColorPattern.test(e)){function t(e){var t=parseInt(e,10).toString(16);return t.length<2&&(t="0"+t),t.toUpperCase()}e="#"+t(RegExp.$1)+t(RegExp.$2)+t(RegExp.$3)}return e},_addRecentColor:function(e){var t=jindo.$A(this.aRecentColor);(t=t.refuse(e)).unshift(e),t.length()>this.nLimitRecentColor&&t.length(this.nLimitRecentColor),this.aRecentColor=t.$value()},_redrawRecentColorElement:function(){var e,t=[],i=this.aRecentColor.length;if(0!==i){for(e=0;ethis.nLimitRecentColor&&t.length(this.nLimitRecentColor),i=0,n=(o=t.reverse().$value()).length;i'+i+"":''+i+"")},$BEFORE_MSG_APP_READY:function(){var e=nhn.husky.SE2M_Configuration.SE2M_Hyperlink;if(e&&!1===e.bAutolink){this.$ON_REGISTER_CONVERTERS=null,this.$ON_DISABLE_MESSAGE=null,this.$ON_ENABLE_MESSAGE=null;try{this.oApp.getWYSIWYGDocument().execCommand("AutoUrlDetect",!1,!1)}catch(t){}}},$ON_MSG_APP_READY:function(){this.bLayerShown=!1,jindo.$Agent().os().mac?this.oApp.exec("REGISTER_HOTKEY",["meta+k","TOGGLE_HYPERLINK_LAYER",[]]):this.oApp.exec("REGISTER_HOTKEY",["ctrl+k","TOGGLE_HYPERLINK_LAYER",[]]),this.oApp.exec("REGISTER_UI_EVENT",["hyperlink","click","TOGGLE_HYPERLINK_LAYER"]),this.oApp.registerLazyMessage(["TOGGLE_HYPERLINK_LAYER","APPLY_HYPERLINK"],["hp_SE2M_Hyperlink$Lazy.js"])},$ON_REGISTER_CONVERTERS:function(){this.oApp.exec("ADD_CONVERTER_DOM",["IR_TO_DB",jindo.$Fn(this.irToDb,this).bind()])},$LOCAL_BEFORE_FIRST:function(e){if(e.match(/(REGISTER_CONVERTERS)/))return this.oApp.acceptLocalBeforeFirstAgain(this,!0),!0;this._assignHTMLElements(this.oApp.htOptions.elAppContainer),this.sRXATagMarker=this.sATagMarker.replace(/\//g,"\\/").replace(/\./g,"\\."),this.oApp.registerBrowserEvent(this.oBtnConfirm,"click","APPLY_HYPERLINK"),this.oApp.registerBrowserEvent(this.oBtnCancel,"click","HIDE_ACTIVE_LAYER"),this.oApp.registerBrowserEvent(this.oLinkInput,"keydown","EVENT_HYPERLINK_KEYDOWN")},$ON_EVENT_HYPERLINK_KEYDOWN:function(e){e.key().enter&&(this.oApp.exec("APPLY_HYPERLINK"),e.stop())},$ON_DISABLE_MESSAGE:function(e){if("TOGGLE_HYPERLINK_LAYER"===e){try{this.oApp.getWYSIWYGDocument().execCommand("AutoUrlDetect",!1,!1)}catch(t){}this._bDisabled=!0}},$ON_ENABLE_MESSAGE:function(e){if("TOGGLE_HYPERLINK_LAYER"===e){try{this.oApp.getWYSIWYGDocument().execCommand("AutoUrlDetect",!1,!0)}catch(t){}this._bDisabled=!1}},irToDb:function(e){if(!this._bDisabled){var t=e.cloneNode(!0);try{t.innerHTML}catch(E){t=jindo.$(e.outerHTML)}for(var i,n,o=this.oApp.getEmptySelection(),s=o._getFirstRealChild(t),r=o._getLastRealChild(t),a=jindo.$A(o._getNodesBetween(s,r)),l=a.filter(function(e){return e&&3===e.nodeType}).$value(),h=l,d=this.oApp.getWYSIWYGDocument().createElement("DIV"),c="@"+(new Date).getTime()+"@",p=new RegExp(c,"g"),u=0,_=l.length;u<_;u++){for(i=h[u].parentNode,n=!1;i;){if("A"===i.tagName||"PRE"===i.tagName){n=!0;break}i=i.parentNode}if(!n){d.innerHTML="";try{d.appendChild(h[u].cloneNode(!0)),d.innerHTML=(c+d.innerHTML).replace(/( |\s)?(((?!http[s]?:\/\/)www\.(?:(?! |\s|"|').)+)|(http[s]?:\/\/(?:(?! |\s|"|').)+))/gi,this._generateAutoLink),h[u].parentNode.insertBefore(d,h[u]),h[u].parentNode.removeChild(h[u])}catch(g){}for(;d.firstChild;)d.parentNode.insertBefore(d.firstChild,d);d.parentNode.removeChild(d)}}d=o=s=r=a=l=h=i=null,t.innerHTML=t.innerHTML.replace(p,""),e.innerHTML=t.innerHTML,t=null}}})},function(e,t){function c(e,t,i,n,o){this.fontId=e,this.fontName=t,this.defaultSize=i,this.fontURL=n,this.fontCSSURL=o,this.displayName=t,this.isLoaded=!0,this.fontFamily=this.fontId,""!=this.fontCSSURL?(this.displayName+=""+i,this.fontFamily+="_"+i,this.isLoaded=!1,this.loadCSS=function(e){this.isLoaded||(this._importCSS(e),this.isLoaded=!0)},this.loadCSSToMenu=function(){this._importCSS(document)},this._importCSS=function(e){var t=e.styleSheets.length,i=e.styleSheets[t-1];(0===t||30'),this.oApp.welEditingAreaContainer.prepend(this.welEditingAreaCover),jindo.$Fn(this._onMouseupCover,this).attach(this.welEditingAreaCover.$value(),"mouseup")}},_onFocusWYSIWYGBody:function(){this._wfOnFocusWYSIWYGBody.detach(this.oApp.getWYSIWYGDocument().body,"focus"),this._loadAllBaseFont()},_onPasteWYSIWYGBody:function(){this._wfOnPasteWYSIWYGBody.detach(this.oApp.getWYSIWYGDocument().body,"paste"),this._loadAllBaseFont()},_onMouseupCover:function(e){e.stop(),this.welEditingAreaCover&&this.welEditingAreaCover.leave();var t=e.mouse(),i=this.oApp.getWYSIWYGDocument().body,n=jindo.$Element(i),o=this.oApp.getEmptySelection();if(o.selectNode(i),o.collapseToStart(),o.select(),n.fireEvent("mousedown",{left:t.left,middle:t.middle,right:t.right}),n.fireEvent("mouseup",{left:t.left,middle:t.middle,right:t.right}),this.oApp.oNavigator.ie&&document.documentMode<11&&"WYSIWYG"===this.oApp.getEditingMode())"

            "==this.oApp.getWYSIWYGDocument().body.innerHTML&&(this.oApp.getWYSIWYGDocument().body.innerHTML='

            ',(o=this.oApp.getSelection()).moveToStringBookmark("INIT"),o.select(),o.removeStringBookmark("INIT"));else if(this.oApp.oNavigator.ie&&11==this.oApp.oNavigator.nativeVersion&&11==document.documentMode&&"WYSIWYG"===this.oApp.getEditingMode()&&"


            "==this.oApp.getWYSIWYGDocument().body.innerHTML){var s=jindo.$$.getSingle("br",i);o.setStartBefore(s),o.setEndBefore(s),o.select()}},$ON_EVENT_TOOLBAR_MOUSEDOWN:function(){this.htBrowser.nativeVersion<9||document.documentMode<9||this.welEditingAreaCover&&this.welEditingAreaCover.leave()},_loadAllBaseFont:function(){var e,t;if(this.htBrowser.ie){if(this.htBrowser.nativeVersion<9)for(e=0,t=this.aBaseFontList.length;e").css("overflow","hidden"),this.canvasType=jindo.$(e).filters?"Filter":jindo.$("").getContext?"Canvas":null,!this.canvasType)return!1;for(var i in this.option({huePanel:null,huePanelType:"horizontal"}),this.option(t),this.option("huePanel")&&(this.huePanel=jindo.$Element(this.option("huePanel")).empty()),this._hsvColor=this._hsv(0,100,100),this)/^_on[A-Z][a-z]+[A-Z][a-z]+$/.test(i)&&(this[i+"Fn"]=jindo.$Fn(this[i],this));this._onDownColorFn.attach(this.elem,"mousedown"),this.huePanel&&this._onDownHueFn.attach(this.huePanel,"mousedown"),this.paint()},rgb:function(e){this.hsv(this._rgb2hsv(e.r,e.g,e.b))},hsv:function(e){if(void 0===e)return this._hsvColor;var t=null,i=this.elem.width(),n=this.elem.height(),o=this.cursor.width(),s=this.cursor.height(),r=0,a=0;if(this.huePanel)t=this._hsv2rgb(e.h,100,100),this.elem.css("background","#"+this._rgb2hex(t.r,t.g,t.b)),r=e.s/100*i,a=(100-e.v)/100*n;else{var l=i/2;r=e.v>e.s?(e.v=100,e.s/100*l):((e.s=100)-e.v)/100*l+l,a=e.h/360*n}r=Math.max(Math.min(r-1,i-o),1),a=Math.max(Math.min(a-1,n-s),1),this.cursor.css({left:r+"px",top:a+"px"}),this._hsvColor=e,t=this._hsv2rgb(e.h,e.s,e.v),this.fireEvent("colorchange",{type:"colorchange",element:this,currentElement:this,rgbColor:t,hexColor:"#"+this._rgb2hex(t.r,t.g,t.b),hsvColor:e})},paint:function(){this.huePanel?(this["_paintColWith"+this.canvasType](),this["_paintHueWith"+this.canvasType]()):this["_paintOneWith"+this.canvasType](),this.cursor.appendTo(this.elem),this.cursor.css({position:"absolute",top:"1px",left:"1px",background:"white",border:"1px solid black"}).width(3).height(3),this.hsv(this._hsvColor)},_paintColWithFilter:function(){jindo.$Element("
            ").css({position:"absolute",top:0,left:0,width:"100%",height:"100%",filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType=1,StartColorStr='#FFFFFFFF',EndColorStr='#00FFFFFF')"}).appendTo(this.elem),jindo.$Element("
            ").css({position:"absolute",top:0,left:0,width:"100%",height:"100%",filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#00000000',EndColorStr='#FF000000')"}).appendTo(this.elem)},_paintColWithCanvas:function(){var e=jindo.$Element("").css({width:"100%",height:"100%"});e.appendTo(this.elem.empty());var t=e.attr("width",e.width()).attr("height",e.height()).$value().getContext("2d"),i=null,n=e.width(),o=e.height();(i=t.createLinearGradient(0,0,n,0)).addColorStop(0,"rgba(255,255,255,1)"),i.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=i,t.fillRect(0,0,n,o),(i=t.createLinearGradient(0,0,0,o)).addColorStop(0,"rgba(0,0,0,0)"),i.addColorStop(1,"rgba(0,0,0,1)"),t.fillStyle=i,t.fillRect(0,0,n,o)},_paintOneWithFilter:function(){for(var e,t,i,n,o,s,r=this.elem.height(),a=1;a<7;a++)e=Math.floor((a-1)/6*r),t=Math.floor(a/6*r),i=this._hsv2rgb((a-1)/6*360,100,100),n=this._hsv2rgb(a/6*360,100,100),o="#FF"+this._rgb2hex(i.r,i.g,i.b),s="#FF"+this._rgb2hex(n.r,n.g,n.b),jindo.$Element("
            ").css({position:"absolute",left:0,width:"100%",top:e+"px",height:t-e+"px",filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='"+o+"',EndColorStr='"+s+"')"}).appendTo(this.elem);jindo.$Element("
            ").css({position:"absolute",top:0,left:0,width:"50%",height:"100%",filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType=1,StartColorStr='#FFFFFFFF',EndColorStr='#00FFFFFF')"}).appendTo(this.elem),jindo.$Element("
            ").css({position:"absolute",top:0,right:0,width:"50%",height:"100%",filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType=1,StartColorStr='#00000000',EndColorStr='#FF000000')"}).appendTo(this.elem)},_paintOneWithCanvas:function(){var e={r:0,g:0,b:0},t=jindo.$Element("").css({width:"100%",height:"100%"});t.appendTo(this.elem.empty());for(var i=t.attr("width",t.width()).attr("height",t.height()).$value().getContext("2d"),n=t.width(),o=t.height(),s=i.createLinearGradient(0,0,0,o),r=0;r<7;r++)e=this._hsv2rgb(r/6*360,100,100),s.addColorStop(r/6,"rgb("+e.join(",")+")");i.fillStyle=s,i.fillRect(0,0,n,o),(s=i.createLinearGradient(0,0,n,0)).addColorStop(0,"rgba(255,255,255,1)"),s.addColorStop(.5,"rgba(255,255,255,0)"),s.addColorStop(.5,"rgba(0,0,0,0)"),s.addColorStop(1,"rgba(0,0,0,1)"),i.fillStyle=s,i.fillRect(0,0,n,o)},_paintHueWithFilter:function(){var e,t,i,n,o,s,r="vertical"==this.option().huePanelType,a=this.huePanel.width(),l=this.huePanel.height(),h=null,d=parseInt(this.huePanel.css("borderWidth"),10);isNaN(d)&&(d=0),a-=2*d;for(var c=1;c<7;c++){e=Math.floor((c-1)/6*(r?l:a)),t=Math.floor(c/6*(r?l:a)),i=this._hsv2rgb((c-1)/6*360,100,100),n=this._hsv2rgb(c/6*360,100,100),o="#FF"+this._rgb2hex(i.r,i.g,i.b),s="#FF"+this._rgb2hex(n.r,n.g,n.b);var p=t-e+1;(h=jindo.$Element("
            ").css({position:"absolute",filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType="+(r?0:1)+",StartColorStr='"+o+"',EndColorStr='"+s+"')"})).appendTo(this.huePanel),h.css(r?"left":"top",0).css(r?"width":"height","100%"),h.css(r?"top":"left",e+"px").css(r?"height":"width",p+"px")}},_paintHueWithCanvas:function(){var e,t="vertical"==this.option().huePanelType,i=jindo.$Element("").css({width:"100%",height:"100%"});i.appendTo(this.huePanel.empty());for(var n=i.attr("width",i.width()).attr("height",i.height()).$value().getContext("2d"),o=n.createLinearGradient(0,0,t?0:i.width(),t?i.height():0),s=0;s<7;s++)e=this._hsv2rgb(s/6*360,100,100),o.addColorStop(s/6,"rgb("+e.join(",")+")");n.fillStyle=o,n.fillRect(0,0,i.width(),i.height())},_rgb2hsv:function(e,t,i){var n=0,o=0,s=Math.max(e,t,i),r=s-Math.min(e,t,i);return(o=s?r/s:0)&&(e==s?n=60*(t-i)/r:t==s?n=120+60*(i-e)/r:i==s&&(n=240+60*(e-t)/r),n<0&&(n+=360)),n=Math.floor(n),o=Math.floor(100*o),s=Math.floor(s/255*100),this._hsv(n,o,s)},_hsv2rgb:function(e,t,i){e=e%360/60,t/=100,i/=100;var n=0,o=0,s=0,r=Math.floor(e),a=e-r,l=i*(1-t),h=i*(1-t*a),d=i*(1-t*(1-a));switch(r){case 0:n=i,o=d,s=l;break;case 1:n=h,o=i,s=l;break;case 2:n=l,o=i,s=d;break;case 3:n=l,o=h,s=i;break;case 4:n=d,o=l,s=i;break;case 5:n=i,o=l,s=h}return n=Math.floor(255*n),o=Math.floor(255*o),s=Math.floor(255*s),this._rgb(n,o,s)},_rgb2hex:function(e,t,i){return 1==(e=e.toString(16)).length&&(e="0"+e),1==(t=t.toString(16)).length&&(t="0"+t),1==(i=i.toString(16)).length&&(i="0"+i),e+t+i},_hex2rgb:function(e){var t=e.match(/#?([0-9a-f]{6}|[0-9a-f]{3})/i);return t=3==t[1].length?t[1].match(/./g).filter(function(e){return e+e}):t[1].match(/../g),{r:Number("0x"+t[0]),g:Number("0x"+t[1]),b:Number("0x"+t[2])}},_rgb:function(e,t,i){var n=[e,t,i];return n.r=e,n.g=t,n.b=i,n},_hsv:function(e,t,i){var n=[e,t,i];return n.h=e,n.s=t,n.v=i,n},_onDownColor:function(e){if(!e.mouse().left)return!1;var t=e.pos();this._colPagePos=[t.pageX,t.pageY],this._colLayerPos=[t.layerX,t.layerY],this._onUpColorFn.attach(document,"mouseup"),this._onMoveColorFn.attach(document,"mousemove"),this._onMoveColor(e)},_onUpColor:function(){this._onUpColorFn.detach(document,"mouseup"),this._onMoveColorFn.detach(document,"mousemove")},_onMoveColor:function(e){var t=this._hsvColor,i=e.pos(),n=this._colLayerPos[0]+(i.pageX-this._colPagePos[0]),o=this._colLayerPos[1]+(i.pageY-this._colPagePos[1]),s=this.elem.width(),r=this.elem.height();if(n=Math.max(Math.min(n,s),0),o=Math.max(Math.min(o,r),0),this.huePanel)t.s=t[1]=n/s*100,t.v=t[2]=(r-o)/r*100;else{t.h=o/r*360;var a=s/2;n]*class=['"]?(se2_quote[0-9]+)['"]?[^>]*>/gi,"<$1 class=$2>")},this).bind()]),this.oApp.exec("ADD_CONVERTER",["IR_TO_DB",jindo.$Fn(function(e){var n=this.htQuoteStyles_view;return e=e.replace(/<(blockquote)[^>]*class=['"]?(se2_quote[0-9]+)['"]?[^>]*>/gi,function(e,t,i){return"<"+t+" class="+i+' style="'+n[i]+'">'})},this).bind()]),this.htSE1toSE2Map={"01":"1","02":"2","03":"6","04":"8","05":"9","07":"3","08":"5"}},$LOCAL_BEFORE_FIRST:function(){this._assignHTMLElements(),this.oApp.registerBrowserEvent(this.elDropdownLayer,"click","EVENT_SE2_BLOCKQUOTE_LAYER_CLICK",[]),this.oApp.delayedExec("SE2_ATTACH_HOVER_EVENTS",[this.aLI],0)},$ON_MSG_APP_READY:function(){this.oApp.exec("REGISTER_UI_EVENT",["quote","click","TOGGLE_BLOCKQUOTE_LAYER"]),this.oApp.registerLazyMessage(["TOGGLE_BLOCKQUOTE_LAYER"],["hp_SE2M_Quote$Lazy.js"])},$ON_EVENT_EDITING_AREA_KEYDOWN:function(e){var t,i;"WYSIWYG"===this.oApp.getEditingMode()&&8===e.key().keyCode&&((t=this.oApp.getSelection()).fixCommonAncestorContainer(),(i=this._findParentQuote(t.commonAncestorContainer))&&this._isBlankQuote(i)&&(e.stop(jindo.$Event.CANCEL_DEFAULT),t.selectNode(i),t.collapseToStart(),jindo.$Element(i).leave(),t.select()))},$ON_EVENT_EDITING_AREA_KEYUP:function(e){var t,i,n;if("WYSIWYG"===this.oApp.getEditingMode()&&46===e.key().keyCode){if((t=this.oApp.getSelection()).fixCommonAncestorContainer(),!(i=this._findParentQuote(t.commonAncestorContainer)))return!1;i.nextSibling||(e.stop(jindo.$Event.CANCEL_DEFAULT),(n=t._document.createElement("P")).innerHTML=" ",jindo.$Element(i).after(n),setTimeout(jindo.$Fn(function(e){var t=e.placeStringBookmark();e.select(),e.removeStringBookmark(t)},this).bind(t),0))}},_isBlankQuote:function(e){function t(e){return""===(e=e.replace(/[\r\n]/gi,"").replace(unescape("%uFEFF"),""))||(" "===e||" "===e)}var i,n,o,s,r,a,l=this.oApp.oNavigator.chrome,h=this.oApp.oNavigator.safari;if(t(e.innerHTML)||"
            "===e.innerHTML)return!0;if(l||h){var d,c=jindo.$$("TABLE",e),p=c.length;for(o=0;o"!==a.innerHTML))return!1;return!0},_findParentQuote:function(e){return this._findAncestor(jindo.$Fn(function(e){if(!e)return!1;if("BLOCKQUOTE"!==e.tagName)return!1;if(!e.className)return!1;var t=e.className;return!!this.htQuoteStyles_view[t]},this).bind(),e)},_findAncestor:function(e,t){for(;t&&!e(t);)t=t.parentNode;return t}})},function(e,t){nhn.husky.SE2M_TableCreator=jindo.$Class({name:"SE2M_TableCreator",_sSETblClass:"__se_tbl",nRows:3,nColumns:4,nBorderSize:1,sBorderColor:"#000000",sBGColor:"#000000",nBorderStyleIdx:3,nTableStyleIdx:1,nMinRows:1,nMaxRows:20,nMinColumns:1,nMaxColumns:20,nMinBorderWidth:1,nMaxBorderWidth:10,rxLastDigits:null,sReEditGuideMsg_table:null,oSelection:null,$ON_MSG_APP_READY:function(){this.sReEditGuideMsg_table=this.oApp.$MSG("SE2M_ReEditAction.reEditGuideMsg.table"),this.oApp.exec("REGISTER_UI_EVENT",["table","click","TOGGLE_TABLE_LAYER"]),this.oApp.registerLazyMessage(["TOGGLE_TABLE_LAYER"],["hp_SE2M_TableCreator$Lazy.js"])},$ON_REGISTER_CONVERTERS:function(){this.oApp.exec("ADD_CONVERTER_DOM",["IR_TO_DB",jindo.$Fn(this.irToDbDOM,this).bind()]),this.oApp.exec("ADD_CONVERTER_DOM",["DB_TO_IR",jindo.$Fn(this.dbToIrDOM,this).bind()])},irToDbDOM:function(e){var t=[],i=jindo.$$("table[class=__se_tbl]",e,{oneTimeOffCache:!0});if(jindo.$A(i).forEach(function(e){jindo.$Element(e).attr("attr_no_border_tbl")&&t.push(e)},this),!(t.length<1))for(var n,o=[],s=0,r=t.length;str>td",n),jindo.$A(o).forEach(function(e){jindo.$Element(e).css({border:"",borderTop:"",borderRight:""})})},dbToIrDOM:function(e){var t=[],i=jindo.$$("table[class=__se_tbl]",e,{oneTimeOffCache:!0});if(jindo.$A(i).forEach(function(e){jindo.$Element(e).attr("attr_no_border_tbl")&&t.push(e)},this),!(t.length<1))for(var n,o=[],s=0,r=t.length;str>td",n),jindo.$A(o).forEach(function(e){jindo.$Element(e).css({border:"1px dashed #c7c7c7",borderTop:0,borderRight:0})})}})},function(e,t){nhn.husky.SE2M_TableBlockStyler=jindo.$Class({name:"SE2M_TableBlockStyler",nSelectedTD:0,htSelectedTD:{},aTdRange:[],$init:function(){},$LOCAL_BEFORE_ALL:function(){return"WYSIWYG"==this.oApp.getEditingMode()},$ON_MSG_APP_READY:function(){this.oDocument=this.oApp.getWYSIWYGDocument()},$ON_EVENT_EDITING_AREA_MOUSEUP:function(){"WYSIWYG"==this.oApp.getEditingMode()&&this.setTdBlock()},$ON_IS_SELECTED_TD_BLOCK:function(e,t){return 0 

            ":i.firefox&&(e+="

            \ufeff

            "),r.selectNode(n),r.pasteHTML(e),s=r.getNodes()||[];for(var a=0;a",sDefaultXPath:"/HTML[0]/BODY[0]",$init:function(){this.aUndoHistory=[],this.oCurStateIdx={nIdx:0,nStep:0},this.nHardLimit=this.nMaxUndoCount+this.nAfterMaxDeleteBuffer},$LOCAL_BEFORE_ALL:function(e){if(e.match(/_DO_RECORD_UNDO_HISTORY_AT$/))return!0;try{if("WYSIWYG"!=this.oApp.getEditingMode())return!1}catch(t){return!1}return!0},$BEFORE_MSG_APP_READY:function(){this._historyLength=0,this.oApp.exec("ADD_APP_PROPERTY",["getUndoHistory",jindo.$Fn(this._getUndoHistory,this).bind()]),this.oApp.exec("ADD_APP_PROPERTY",["getUndoStateIdx",jindo.$Fn(this._getUndoStateIdx,this).bind()]),this.oApp.exec("ADD_APP_PROPERTY",["saveSnapShot",jindo.$Fn(this._saveSnapShot,this).bind()]),this.oApp.exec("ADD_APP_PROPERTY",["getLastKey",jindo.$Fn(this._getLastKey,this).bind()]),this.oApp.exec("ADD_APP_PROPERTY",["setLastKey",jindo.$Fn(this._setLastKey,this).bind()]),this._saveSnapShot(),this.oApp.exec("DO_RECORD_UNDO_HISTORY_AT",[this.oCurStateIdx,"","","",null,this.sDefaultXPath])},_getLastKey:function(){return this.sLastKey},_setLastKey:function(e){this.sLastKey=e},$ON_MSG_APP_READY:function(){var e=jindo.$Agent().navigator();this.bIE=e.ie,this.bFF=e.firefox,this.oApp.exec("REGISTER_UI_EVENT",["undo","click","UNDO"]),this.oApp.exec("REGISTER_UI_EVENT",["redo","click","REDO"]),jindo.$Agent().os().mac?(this.oApp.exec("REGISTER_HOTKEY",["meta+z","UNDO"]),this.oApp.exec("REGISTER_HOTKEY",["meta+y","REDO"])):(this.oApp.exec("REGISTER_HOTKEY",["ctrl+z","UNDO"]),this.oApp.exec("REGISTER_HOTKEY",["ctrl+y","REDO"]))},$ON_UNDO:function(){if(this._doRecordUndoHistory("UNDO",{nStep:0,bSkipIfEqual:!0,bMustBlockContainer:!0}),!(this.oCurStateIdx.nIdx<=0)){var e=this.aUndoHistory[this.oCurStateIdx.nIdx].oUndoCallback[this.oCurStateIdx.nStep],t=this.aUndoHistory[this.oCurStateIdx.nIdx].sParentXPath[this.oCurStateIdx.nStep];if(e&&this.oApp.exec(e.sMsg,e.aParams),0=this.aUndoHistory.length)){var e=this.aUndoHistory[this.oCurStateIdx.nIdx];if(!(this.oCurStateIdx.nIdx==this.aUndoHistory.length-1&&this.oCurStateIdx.nStep>=e.nTotalSteps-1)){this.oCurStateIdx.nStepthis.nHardLimit&&(this.aUndoHistory.splice(0,this.nAfterMaxDeleteBuffer),e.nIdx-=this.nAfterMaxDeleteBuffer),this.oCurStateIdx.nIdx=e.nIdx,this.oCurStateIdx.nStep=e.nStep},_saveSnapShot:function(){this.oSnapShot={oBookmark:this.oApp.getSelection().getXPathBookmark()}},_getTargetXPath:function(e,t){var i=this.sDefaultXPath,n=e[0].sXPath.split("/"),o=e[1].sXPath.split("/"),s=[],r=n.length]+)?",rxDateFormat:/^(?:\d{4}\.)?\d{1,2}\.\d{1,2}$/,_rxTable:/^(?:CAPTION|TBODY|THEAD|TFOOT|TR|TD|TH|COLGROUP|COL)$/i,_rxSpaceOnly:/^\s+$/,_rxFontStart:/]*)?>/i,_rxFontStrip:/<\/?font(?:\s+[^>]*)?>/gi,_bUnderIE8:jindo.$Agent().navigator().ie&&jindo.$Agent().navigator().version<9,_htFontSize:{1:"7pt",2:"10pt",3:"12pt",4:"13.5pt",5:"18pt",6:"24pt",7:"36pt"},isInvalidNodeInTable:function(e){if(e&&!this._rxTable.test(e.nodeName)){var t;if((t=e.previousSibling)&&this._rxTable.test(t.nodeName))return!0;if((t=e.nextSibling)&&this._rxTable.test(t.nodeName))return!0}return!1},removeInvalidNodeInTable:function(e){this.isInvalidNodeInTable(e)&&e.parentNode&&e.parentNode.removeChild(e)},removeInvalidFont:function(e){e&&(this._removeInvalidFontInTable(e),this._removeEmptyFont(e))},_removeInvalidFontInTable:function(e){for(var t,i=jindo.$$("table font",e),n=0;t=i[n];n++)this.removeInvalidNodeInTable(t)},_removeEmptyFont:function(e){for(var t,i=jindo.$$("font",e),n=0;t=i[n];n++)(t.innerHTML||"").replace(this._rxSpaceOnly,"")||t.parentNode.removeChild(t)},convertFontToSpan:function(e){if(e){for(var t,i,n,o=e.ownerDocument||document,s=jindo.$$("font",e),r=0;t=s[r];r++)("SPAN"!==(i=t.parentNode).tagName||1]*))","i").exec(e);if(!i)return"";var n=i[1]||i[2]||i[3];return n=n&&n.replace(/["]/g,"")},iframeAlignConverter:function(e,t){var i=e.tagName.toUpperCase();if("DIV"==i||"P"==i){if(null===e.parentNode)return;var n=t,o=jindo.$Element(e),s=o.html(),r=jindo.$Element(e).attr("align")||jindo.$Element(e).css("text-align"),a=jindo.$Element(jindo.$("
            ",n));a.html(s).attr("align",r),o.replace(a)}},getJsonDatafromXML:function(e){function g(e){return void 0===e?"":e.replace(/&[a-z]+;/g,function(e){return"string"==typeof i[e]?i[e]:e})}function f(e){for(var t in e)if(Object.prototype.hasOwnProperty.call(e,t)){if(Object.prototype[t])continue;return!1}return!0}var t={},A=/^[0-9]+(?:\.[0-9]+)?$/,S=/^\s+$/g,i={"&":"&"," ":" ",""":'"',"<":"<",">":">"},T={tags:["/"],stack:[t]};return(e=e.replace(/<(\?|!-)[^>]*>/g,"")).replace(/\s*<(\/?[\w:-]+)((?:\s+[\w:-]+\s*=\s*(?:"(?:\\"|[^"])*"|'(?:\\'|[^'])*'))*)\s*((?:\/>)|(?:><\/\1>|\s*))|\s*\s*|\s*>?([^<]*)/gi,function(e,t,i,n,o,s){var r,a="",l=T.stack.length-1;if("string"==typeof t&&t)if("/"!=t.substr(0,1)){var h="string"==typeof i&&i,d="string"==typeof n&&n,c=!h&&d?"":{};if("undefined"==typeof(r=T.stack[l])[t])r[t]=c,r=T.stack[1+l]=r[t];else if(r[t]instanceof Array){var p=r[t].length;r[t][p]=c,r=T.stack[1+l]=r[t][p]}else r[t]=[r[t],c],r=T.stack[1+l]=r[t][1];h&&function(e,o){e.replace(/([\w:-]+)\s*=\s*(?:"((?:\\"|[^"])*)"|'((?:\\'|[^'])*)')/g,function(e,t,i,n){o[t]=g((i?i.replace(/\\"/g,'"'):undefined)||(n?n.replace(/\\'/g,"'"):undefined))})}(i,r),T.tags[1+l]=t,d&&(T.tags.length--,T.stack.length--)}else T.tags.length--,T.stack.length--;else"string"==typeof o&&o?a=o:"string"==typeof s&&s.replace(S,"")&&(a=g(s));if(0/g,">"):""},restoreSpecialChar:function(e){return"string"==typeof e?e.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&"):""}},nhn.husky.AutoResizer=jindo.$Class({welHiddenDiv:null,welCloneDiv:null,elContainer:null,$init:function(e,t){var i=["lineHeight","textDecoration","letterSpacing","fontSize","fontFamily","fontStyle","fontWeight","textTransform","textAlign","direction","wordSpacing","fontSizeAdjust","paddingTop","paddingLeft","paddingBottom","paddingRight","width"],n=i.length,o={position:"absolute",top:-9999,left:-9999,opacity:0,overflow:"hidden",wordWrap:"break-word"};for(this.nMinHeight=t.nMinHeight,this.wfnCallback=t.wfnCallback,this.elContainer=e.parentNode,this.welTextArea=jindo.$Element(e),this.welHiddenDiv=jindo.$Element("
            "),this.wfnResize=jindo.$Fn(this._resize,this),this.sOverflow=this.welTextArea.css("overflow"),this.welTextArea.css("overflow","hidden");n--;)o[i[n]]=this.welTextArea.css(i[n]);this.welHiddenDiv.css(o),this.nLastHeight=this.welTextArea.height()},bind:function(){this.welCloneDiv=jindo.$Element(this.welHiddenDiv.$value().cloneNode(!1)),this.wfnResize.attach(this.welTextArea,"keyup"),this.welCloneDiv.appendTo(this.elContainer),this._resize()},unbind:function(){this.wfnResize.detach(this.welTextArea,"keyup"),this.welTextArea.css("overflow",this.sOverflow),this.welCloneDiv&&this.welCloneDiv.leave()},_resize:function(){var e,t=this.welTextArea.$value().value,i=!1;t!==this.sContents&&(this.sContents=t.replace(/&/g,"&").replace(//g,">").replace(/ /g," ").replace(/\n/g,"
            "),this.sContents+="
            ",this.welCloneDiv.html(this.sContents),(e=this.welCloneDiv.height())t.nodeValue.length&&(e=t.nodeValue.length):e>nhn.DOMFix.childNodes(t).length&&(e=nhn.DOMFix.childNodes(t).length),e},setEnd:function(t,e,n,i){n||(e=this._endsNodeValidation(t,e)),this.endContainer=t,this.endOffset=e,i||(this.startContainer&&-1==this._compareEndPoint(this.startContainer,this.startOffset,this.endContainer,this.endOffset)?this._updateRangeInfo():this.collapse(!1))},setEndAfter:function(t,e){if(!t)throw new Error("INVALID_NODE_TYPE_ERR in setEndAfter");"BODY"!=t.tagName?this.setEnd(nhn.DOMFix.parentNode(t),this._getPosIdx(t)+1,!0,e):this.setEnd(t,nhn.DOMFix.childNodes(t).length,!0,e)},setEndBefore:function(t,e){if(!t)throw new Error("INVALID_NODE_TYPE_ERR in setEndBefore");"BODY"!=t.tagName?this.setEnd(nhn.DOMFix.parentNode(t),this._getPosIdx(t),!0,e):this.setEnd(t,0,!0,e)},setStart:function(t,e,n,i){n||(e=this._endsNodeValidation(t,e)),this.startContainer=t,this.startOffset=e,i||(this.endContainer&&-1==this._compareEndPoint(this.startContainer,this.startOffset,this.endContainer,this.endOffset)?this._updateRangeInfo():this.collapse(!0))},setStartAfter:function(t,e){if(!t)throw new Error("INVALID_NODE_TYPE_ERR in setStartAfter");"BODY"!=t.tagName?this.setStart(nhn.DOMFix.parentNode(t),this._getPosIdx(t)+1,!0,e):this.setStart(t,nhn.DOMFix.childNodes(t).length,!0,e)},setStartBefore:function(t,e){if(!t)throw new Error("INVALID_NODE_TYPE_ERR in setStartBefore");"BODY"!=t.tagName?this.setStart(nhn.DOMFix.parentNode(t),this._getPosIdx(t),!0,e):this.setStart(t,0,!0,e)},surroundContents:function(t){t.appendChild(this.extractContents()),this.insertNode(t),this.selectNode(t)},toString:function(){var t=this._document.createElement("DIV");return t.appendChild(this.cloneContents()),t.textContent||t.innerText||""},fixCommonAncestorContainer:function(){jindo.$Agent().navigator().ie&&(this.commonAncestorContainer=this._getCommonAncestorContainer())},_isBlankTextNode:function(t){return 3==t.nodeType&&""==t.nodeValue},_isAllChildBlankText:function(t){for(var e=0,n=t.childNodes.length;e=i.nodeValue.length?t:0===o?t:(i.splitText(o),{oStartContainer:e,iStartOffset:n,oEndContainer:i,iEndOffset:o}):t},_getNodesInRange:function(){if(this.collapsed)return[];var t=this._getActualStartNode(this.startContainer,this.startOffset),e=this._getActualEndNode(this.endContainer,this.endOffset);return this._getNodesBetween(t,e)},_getActualStartNode:function(t,e){var n=t;return 3==t.nodeType?e>=t.nodeValue.length?"BODY"==(n=this._getNextNode(t)).tagName&&(n=null):n=t:e)$/i,_rxTextAlign:/text-align:[^"';]*;?/i,setWindow:function(t){this.reset(t||window)},$init:function(t){this.HUSKY_BOOMARK_START_ID_PREFIX="husky_bookmark_start_",this.HUSKY_BOOMARK_END_ID_PREFIX="husky_bookmark_end_",this.sBlockElement="P|DIV|LI|H[1-6]|PRE",this.sBlockContainer="BODY|TABLE|TH|TR|TD|UL|OL|BLOCKQUOTE|FORM",this.rxBlockElement=new RegExp("^("+this.sBlockElement+")$"),this.rxBlockContainer=new RegExp("^("+this.sBlockContainer+")$"),this.rxLineBreaker=new RegExp("^("+this.sBlockElement+"|"+this.sBlockContainer+")$"),this.rxHasBlock=new RegExp("(?:<(?:"+this.sBlockElement+"|"+this.sBlockContainer+").*?>|style=[\"']?[^>]*?(?:display\\s?:\\s?block)[^>]*?[\"']?)","i"),this.setWindow(t)},select:function(){try{this.oBrowserSelection.selectRange(this)}catch(t){}},setFromSelection:function(t){this.setRange(this.oBrowserSelection.getRangeAt(t),!0)},setRange:function(t,e){this.reset(this._window),this.setStart(t.startContainer,t.startOffset,e,!0),this.setEnd(t.endContainer,t.endOffset,e)},setEndNodes:function(t,e){this.reset(this._window),this.setEndAfter(e,!0),this.setStartBefore(t)},splitTextAtBothEnds:function(){this._splitTextEndNodesOfTheRange()},getStartNode:function(){return this.collapsed?3==this.startContainer.nodeType?0===this.startOffset?null:this.startContainer.nodeValue.length<=this.startOffset?null:this.startContainer:null:3==this.startContainer.nodeType?this.startOffset>=this.startContainer.nodeValue.length?this._getNextNode(this.startContainer):this.startContainer:this.startOffset>=nhn.DOMFix.childNodes(this.startContainer).length?this._getNextNode(this.startContainer):nhn.DOMFix.childNodes(this.startContainer)[this.startOffset]},getEndNode:function(){return this.collapsed?this.getStartNode():3==this.endContainer.nodeType?0===this.endOffset?this._getPrevNode(this.endContainer):this.endContainer:0===this.endOffset?this._getPrevNode(this.endContainer):nhn.DOMFix.childNodes(this.endContainer)[this.endOffset-1]},getNodeAroundRange:function(t,e){return this.collapsed?this.startContainer&&3==this.startContainer.nodeType?this.startContainer:(i=this.startOffset>=nhn.DOMFix.childNodes(this.startContainer).length?this._getNextNode(this.startContainer):nhn.DOMFix.childNodes(this.startContainer)[this.startOffset],n=0===this.endOffset?this._getPrevNode(this.endContainer):nhn.DOMFix.childNodes(this.endContainer)[this.endOffset-1],t?(o=n)||e||(o=i):(o=i)||e||(o=n),o):this.getStartNode();var n,i,o},_getXPath:function(t){for(var e="";t&&1==t.nodeType;)e="/"+t.tagName+"["+this._getPosIdx4XPath(t)+"]"+e,t=nhn.DOMFix.parentNode(t);return e},_getPosIdx4XPath:function(t){for(var e=0,n=t.previousSibling;n;n=n.previousSibling)n.tagName==t.tagName&&e++;return e},_evaluateXPath:function(t,e){for(var n=(t=t.substring(1,t.length-1)).split(/\//),i=e.body,o=2;o/g,">").replace(/ /g," ").replace(/"/g,"""))},pasteHTML:function(t,e){var n=this._document.createElement("DIV");if(n.innerHTML=t,n.firstChild){var i=this.cloneRange(),o=i.placeStringBookmark(),s=i.getLineInfo(),r=s.oStart,a=s.oEnd;if(r.oLineBreaker&&"P"===r.oLineBreaker.nodeName&&(e||i.rxHasBlock.test(t))){var h=r.oLineBreaker.parentNode,d=r.oLineBreaker.nextSibling;if(i.deleteContents(),r.oLineBreaker===a.oLineBreaker){var l=i.getStringBookmark(o);i.setEndNodes(l,a.oLineBreaker);var u=i.extractContents(),f=u.firstChild;d?h.insertBefore(u,d):h.appendChild(u),d=f}n.style.cssText=r.oLineBreaker.style.cssText.replace(this._rxTextAlign,""),n.align=r.oLineBreaker.align,d?h.insertBefore(n,d):h.appendChild(n),i.removeStringBookmark(o),this._removeEmptyP(this._getPrevElement(n));var c=this._getNextElement(n);if(c){var g=this._getNextElement(c);g&&this._removeEmptyP(c)&&(c=g)}else(c=this._document.createElement("P")).style.cssText=r.oLineBreaker.style.cssText,c.align=r.oLineBreaker.align,h.appendChild(c);""===c.innerHTML&&(c.innerHTML=jindo.$Agent().navigator().ie&&8"+t.innerHTML+"":"line-through"===e&&(t.innerHTML=""+t.innerHTML+"")},_checkTextDecoration:function(t){if("SPAN"===t.tagName){for(var e=!1,n=!1,i=null,o=t.firstChild;o;){if(1===o.nodeType&&(e=e||"U"===o.tagName,n=n||"S"===o.tagName||"STRIKE"===o.tagName),e&&n)return;o=o.nextSibling}for(i=nhn.DOMFix.parentNode(t);i&&"BODY"!==i.tagName;)if(1===i.nodeType){if(!e&&this._hasTextDecoration(i,"underline")&&(e=!0,this._setTextDecoration(t,"underline")),!n&&this._hasTextDecoration(i,"line-through")&&(n=!0,this._setTextDecoration(t,"line-through")),e&&n)return;i=nhn.DOMFix.parentNode(i)}else i=nhn.DOMFix.parentNode(i)}},styleRange:function(t,e,n,i,o){var s=this.aStyleParents=this._getStyleParentNodes(n,i);if(!(s.length<1)){for(var r,a,h,d=0;du.nodeValue.length&&u.nextSibling;)c-=u.nodeValue.length,u=u.nextSibling;u.nodeValue,e&&u.nextSibling&&3==u.nextSibling.nodeType&&c==u.nodeValue.length&&(c-=u.nodeValue.length,u=u.nextSibling),o=u,s=c}else o=i.parentElement(),s=n;return{oContainer:o,iOffset:s}}},nhn.DOMFix=new(jindo.$Class({$init:function(){jindo.$Agent().navigator().ie||jindo.$Agent().navigator().opera?(this.childNodes=this._childNodes_Fix,this.parentNode=this._parentNode_Fix):(this.childNodes=this._childNodes_Native,this.parentNode=this._parentNode_Native)},_parentNode_Native:function(t){return t.parentNode},_parentNode_Fix:function(t){if(!t)return t;for(;t.previousSibling;)t=t.previousSibling;return t.parentNode},_childNodes_Native:function(t){return t.childNodes},_childNodes_Fix:function(t){var e=null,n=0;if(t)for(e=[],t=t.firstChild;t;)t=(e[n++]=t).nextSibling;return e}}))},function(module,exports){nhn.husky.CorePlugin=jindo.$Class({name:"CorePlugin",htLazyLoadRequest_plugins:{},htLazyLoadRequest_allFiles:{},htHTMLLoaded:{},$AFTER_MSG_APP_READY:function(){this.oApp.exec("EXEC_ON_READY_FUNCTION",[])},$ON_ADD_APP_PROPERTY:function(t,e){this.oApp[t]=e},$ON_REGISTER_BROWSER_EVENT:function(t,e,n,i,o){this.oApp.registerBrowserEvent(t,e,n,i,o)},$ON_DISABLE_MESSAGE:function(t){this.oApp.disableMessage(t,!0)},$ON_ENABLE_MESSAGE:function(t){this.oApp.disableMessage(t,!1)},$ON_LOAD_FULL_PLUGIN:function(t,e,n,i,o){var s=t[0];this.htLazyLoadRequest_plugins[s]||(this.htLazyLoadRequest_plugins[s]={nStatus:1,sContents:""}),2===this.htLazyLoadRequest_plugins[s].nStatus?this.oApp.exec("MSG_FULL_PLUGIN_LOADED",[s,e,n,i,o,!1]):this._loadFullPlugin(t,e,n,i,o,0)},_loadFullPlugin:function(t,e,n,i,o,s){jindo.LazyLoading.load(nhn.husky.SE2M_Configuration.LazyLoad.sJsBaseURI+"/"+t[s],jindo.$Fn(function(t,e,n,i,o,s){var r=t[0];if(s==t.length-1)return this.htLazyLoadRequest_plugins[r].nStatus=2,void this.oApp.exec("MSG_FULL_PLUGIN_LOADED",[t,e,n,i,o]);this._loadFullPlugin(t,e,n,i,o,s+1)},this).bind(t,e,n,i,o,s),"utf-8")},$ON_MSG_FULL_PLUGIN_LOADED:function(aFilenames,sClassName,sMsgName,oThisRef,oArguments){for(var oPluginRef=oThisRef.$this||oThisRef,i=0,nLen=oThisRef._huskyFLT.length;ie.nodeValue.length&&(t=e.nodeValue.length):t>nhn.DOMFix.childNodes(e).length&&(t=nhn.DOMFix.childNodes(e).length),t},setEnd:function(e,t,i,n){i||(t=this._endsNodeValidation(e,t)),this.endContainer=e,this.endOffset=t,n||(this.startContainer&&-1==this._compareEndPoint(this.startContainer,this.startOffset,this.endContainer,this.endOffset)?this._updateRangeInfo():this.collapse(!1))},setEndAfter:function(e,t){if(!e)throw new Error("INVALID_NODE_TYPE_ERR in setEndAfter");"BODY"!=e.tagName?this.setEnd(nhn.DOMFix.parentNode(e),this._getPosIdx(e)+1,!0,t):this.setEnd(e,nhn.DOMFix.childNodes(e).length,!0,t)},setEndBefore:function(e,t){if(!e)throw new Error("INVALID_NODE_TYPE_ERR in setEndBefore");"BODY"!=e.tagName?this.setEnd(nhn.DOMFix.parentNode(e),this._getPosIdx(e),!0,t):this.setEnd(e,0,!0,t)},setStart:function(e,t,i,n){i||(t=this._endsNodeValidation(e,t)),this.startContainer=e,this.startOffset=t,n||(this.endContainer&&-1==this._compareEndPoint(this.startContainer,this.startOffset,this.endContainer,this.endOffset)?this._updateRangeInfo():this.collapse(!0))},setStartAfter:function(e,t){if(!e)throw new Error("INVALID_NODE_TYPE_ERR in setStartAfter");"BODY"!=e.tagName?this.setStart(nhn.DOMFix.parentNode(e),this._getPosIdx(e)+1,!0,t):this.setStart(e,nhn.DOMFix.childNodes(e).length,!0,t)},setStartBefore:function(e,t){if(!e)throw new Error("INVALID_NODE_TYPE_ERR in setStartBefore");"BODY"!=e.tagName?this.setStart(nhn.DOMFix.parentNode(e),this._getPosIdx(e),!0,t):this.setStart(e,0,!0,t)},surroundContents:function(e){e.appendChild(this.extractContents()),this.insertNode(e),this.selectNode(e)},toString:function(){var e=this._document.createElement("DIV");return e.appendChild(this.cloneContents()),e.textContent||e.innerText||""},fixCommonAncestorContainer:function(){jindo.$Agent().navigator().ie&&(this.commonAncestorContainer=this._getCommonAncestorContainer())},_isBlankTextNode:function(e){return 3==e.nodeType&&""==e.nodeValue},_isAllChildBlankText:function(e){for(var t=0,i=e.childNodes.length;t=n.nodeValue.length?e:0===o?e:(n.splitText(o),{oStartContainer:t,iStartOffset:i,oEndContainer:n,iEndOffset:o}):e},_getNodesInRange:function(){if(this.collapsed)return[];var e=this._getActualStartNode(this.startContainer,this.startOffset),t=this._getActualEndNode(this.endContainer,this.endOffset);return this._getNodesBetween(e,t)},_getActualStartNode:function(e,t){var i=e;return 3==e.nodeType?t>=e.nodeValue.length?"BODY"==(i=this._getNextNode(e)).tagName&&(i=null):i=e:t)$/i,_rxTextAlign:/text-align:[^"';]*;?/i,setWindow:function(e){this.reset(e||window)},$init:function(e){this.HUSKY_BOOMARK_START_ID_PREFIX="husky_bookmark_start_",this.HUSKY_BOOMARK_END_ID_PREFIX="husky_bookmark_end_",this.sBlockElement="P|DIV|LI|H[1-6]|PRE",this.sBlockContainer="BODY|TABLE|TH|TR|TD|UL|OL|BLOCKQUOTE|FORM",this.rxBlockElement=new RegExp("^("+this.sBlockElement+")$"),this.rxBlockContainer=new RegExp("^("+this.sBlockContainer+")$"),this.rxLineBreaker=new RegExp("^("+this.sBlockElement+"|"+this.sBlockContainer+")$"),this.rxHasBlock=new RegExp("(?:<(?:"+this.sBlockElement+"|"+this.sBlockContainer+").*?>|style=[\"']?[^>]*?(?:display\\s?:\\s?block)[^>]*?[\"']?)","i"),this.setWindow(e)},select:function(){try{this.oBrowserSelection.selectRange(this)}catch(e){}},setFromSelection:function(e){this.setRange(this.oBrowserSelection.getRangeAt(e),!0)},setRange:function(e,t){this.reset(this._window),this.setStart(e.startContainer,e.startOffset,t,!0),this.setEnd(e.endContainer,e.endOffset,t)},setEndNodes:function(e,t){this.reset(this._window),this.setEndAfter(t,!0),this.setStartBefore(e)},splitTextAtBothEnds:function(){this._splitTextEndNodesOfTheRange()},getStartNode:function(){return this.collapsed?3==this.startContainer.nodeType?0===this.startOffset?null:this.startContainer.nodeValue.length<=this.startOffset?null:this.startContainer:null:3==this.startContainer.nodeType?this.startOffset>=this.startContainer.nodeValue.length?this._getNextNode(this.startContainer):this.startContainer:this.startOffset>=nhn.DOMFix.childNodes(this.startContainer).length?this._getNextNode(this.startContainer):nhn.DOMFix.childNodes(this.startContainer)[this.startOffset]},getEndNode:function(){return this.collapsed?this.getStartNode():3==this.endContainer.nodeType?0===this.endOffset?this._getPrevNode(this.endContainer):this.endContainer:0===this.endOffset?this._getPrevNode(this.endContainer):nhn.DOMFix.childNodes(this.endContainer)[this.endOffset-1]},getNodeAroundRange:function(e,t){return this.collapsed?this.startContainer&&3==this.startContainer.nodeType?this.startContainer:(n=this.startOffset>=nhn.DOMFix.childNodes(this.startContainer).length?this._getNextNode(this.startContainer):nhn.DOMFix.childNodes(this.startContainer)[this.startOffset],i=0===this.endOffset?this._getPrevNode(this.endContainer):nhn.DOMFix.childNodes(this.endContainer)[this.endOffset-1],e?(o=i)||t||(o=n):(o=n)||t||(o=i),o):this.getStartNode();var i,n,o},_getXPath:function(e){for(var t="";e&&1==e.nodeType;)t="/"+e.tagName+"["+this._getPosIdx4XPath(e)+"]"+t,e=nhn.DOMFix.parentNode(e);return t},_getPosIdx4XPath:function(e){for(var t=0,i=e.previousSibling;i;i=i.previousSibling)i.tagName==e.tagName&&t++;return t},_evaluateXPath:function(e,t){for(var i=(e=e.substring(1,e.length-1)).split(/\//),n=t.body,o=2;o/g,">").replace(/ /g," ").replace(/"/g,"""))},pasteHTML:function(e,t){var i=this._document.createElement("DIV");if(i.innerHTML=e,i.firstChild){var n=this.cloneRange(),o=n.placeStringBookmark(),s=n.getLineInfo(),r=s.oStart,a=s.oEnd;if(r.oLineBreaker&&"P"===r.oLineBreaker.nodeName&&(t||n.rxHasBlock.test(e))){var l=r.oLineBreaker.parentNode,h=r.oLineBreaker.nextSibling;if(n.deleteContents(),r.oLineBreaker===a.oLineBreaker){var d=n.getStringBookmark(o);n.setEndNodes(d,a.oLineBreaker);var c=n.extractContents(),_=c.firstChild;h?l.insertBefore(c,h):l.appendChild(c),h=_}i.style.cssText=r.oLineBreaker.style.cssText.replace(this._rxTextAlign,""),i.align=r.oLineBreaker.align,h?l.insertBefore(i,h):l.appendChild(i),n.removeStringBookmark(o),this._removeEmptyP(this._getPrevElement(i));var p=this._getNextElement(i);if(p){var E=this._getNextElement(p);E&&this._removeEmptyP(p)&&(p=E)}else(p=this._document.createElement("P")).style.cssText=r.oLineBreaker.style.cssText,p.align=r.oLineBreaker.align,l.appendChild(p);""===p.innerHTML&&(p.innerHTML=jindo.$Agent().navigator().ie&&8"+e.innerHTML+"":"line-through"===t&&(e.innerHTML=""+e.innerHTML+"")},_checkTextDecoration:function(e){if("SPAN"===e.tagName){for(var t=!1,i=!1,n=null,o=e.firstChild;o;){if(1===o.nodeType&&(t=t||"U"===o.tagName,i=i||"S"===o.tagName||"STRIKE"===o.tagName),t&&i)return;o=o.nextSibling}for(n=nhn.DOMFix.parentNode(e);n&&"BODY"!==n.tagName;)if(1===n.nodeType){if(!t&&this._hasTextDecoration(n,"underline")&&(t=!0,this._setTextDecoration(e,"underline")),!i&&this._hasTextDecoration(n,"line-through")&&(i=!0,this._setTextDecoration(e,"line-through")),t&&i)return;n=nhn.DOMFix.parentNode(n)}else n=nhn.DOMFix.parentNode(n)}},styleRange:function(e,t,i,n,o){var s=this.aStyleParents=this._getStyleParentNodes(i,n);if(!(s.length<1)){for(var r,a,l,h=0;hc.nodeValue.length&&c.nextSibling;)p-=c.nodeValue.length,c=c.nextSibling;c.nodeValue,t&&c.nextSibling&&3==c.nextSibling.nodeType&&p==c.nodeValue.length&&(p-=c.nodeValue.length,c=c.nextSibling),o=c,s=p}else o=n.parentElement(),s=i;return{oContainer:o,iOffset:s}}},nhn.DOMFix=new(jindo.$Class({$init:function(){jindo.$Agent().navigator().ie||jindo.$Agent().navigator().opera?(this.childNodes=this._childNodes_Fix,this.parentNode=this._parentNode_Fix):(this.childNodes=this._childNodes_Native,this.parentNode=this._parentNode_Native)},_parentNode_Native:function(e){return e.parentNode},_parentNode_Fix:function(e){if(!e)return e;for(;e.previousSibling;)e=e.previousSibling;return e.parentNode},_childNodes_Native:function(e){return e.childNodes},_childNodes_Fix:function(e){var t=null,i=0;if(e)for(t=[],e=e.firstChild;e;)e=(t[i++]=e).nextSibling;return t}}))},function(module,exports){nhn.husky.CorePlugin=jindo.$Class({name:"CorePlugin",htLazyLoadRequest_plugins:{},htLazyLoadRequest_allFiles:{},htHTMLLoaded:{},$AFTER_MSG_APP_READY:function(){this.oApp.exec("EXEC_ON_READY_FUNCTION",[])},$ON_ADD_APP_PROPERTY:function(e,t){this.oApp[e]=t},$ON_REGISTER_BROWSER_EVENT:function(e,t,i,n,o){this.oApp.registerBrowserEvent(e,t,i,n,o)},$ON_DISABLE_MESSAGE:function(e){this.oApp.disableMessage(e,!0)},$ON_ENABLE_MESSAGE:function(e){this.oApp.disableMessage(e,!1)},$ON_LOAD_FULL_PLUGIN:function(e,t,i,n,o){var s=e[0];this.htLazyLoadRequest_plugins[s]||(this.htLazyLoadRequest_plugins[s]={nStatus:1,sContents:""}),2===this.htLazyLoadRequest_plugins[s].nStatus?this.oApp.exec("MSG_FULL_PLUGIN_LOADED",[s,t,i,n,o,!1]):this._loadFullPlugin(e,t,i,n,o,0)},_loadFullPlugin:function(e,t,i,n,o,s){jindo.LazyLoading.load(nhn.husky.SE2M_Configuration.LazyLoad.sJsBaseURI+"/"+e[s],jindo.$Fn(function(e,t,i,n,o,s){var r=e[0];if(s==e.length-1)return this.htLazyLoadRequest_plugins[r].nStatus=2,void this.oApp.exec("MSG_FULL_PLUGIN_LOADED",[e,t,i,n,o]);this._loadFullPlugin(e,t,i,n,o,s+1)},this).bind(e,t,i,n,o,s),"utf-8")},$ON_MSG_FULL_PLUGIN_LOADED:function(aFilenames,sClassName,sMsgName,oThisRef,oArguments){for(var oPluginRef=oThisRef.$this||oThisRef,i=0,nLen=oThisRef._huskyFLT.length;ili>button"))},$LOCAL_BEFORE_FIRST:function(){var e=jindo.$$(">ul>li[class*="+this.sUIClassPrefix+"]>button",this.elTextTool),t=e.length;this.elFirstToolbarItem=this.elFirstToolbarItem||e[0],this.elLastToolbarItem=e[t-1],this.oApp.registerBrowserEvent(this.toolbarArea,"keydown","NAVIGATE_TOOLBAR",[])},$init:function(e,t){this._htOptions=t||{},this.htUIList={},this.htWrappedUIList={},this.aUICmdMap={},this._assignHTMLElements(e)},$ON_MSG_APP_READY:function(){this.oApp.bMobile?this.oApp.registerBrowserEvent(this.toolbarArea,"touchstart","EVENT_TOOLBAR_TOUCHSTART"):(this.oApp.registerBrowserEvent(this.toolbarArea,"mouseover","EVENT_TOOLBAR_MOUSEOVER"),this.oApp.registerBrowserEvent(this.toolbarArea,"mouseout","EVENT_TOOLBAR_MOUSEOUT")),this.oApp.registerBrowserEvent(this.toolbarArea,"mousedown","EVENT_TOOLBAR_MOUSEDOWN"),this.oApp.exec("ADD_APP_PROPERTY",["getToolbarButtonByUIName",jindo.$Fn(this.getToolbarButtonByUIName,this).bind()]),this._htOptions.aDisabled&&(this._htOptions._sDisabled=","+this._htOptions.aDisabled.toString()+",",this.oApp.exec("DISABLE_UI",[this._htOptions.aDisabled]))},$ON_NAVIGATE_TOOLBAR:function(e){e.element==this.elLastToolbarItem&&9==e.key().keyCode&&(e.key().shift||(this.elFirstToolbarItem.focus(),e.stopDefault())),e.element==this.elFirstToolbarItem&&9==e.key().keyCode&&e.key().shift&&(e.stopDefault(),this.elLastToolbarItem.focus())},$ON_TOGGLE_TOOLBAR_ACTIVE_LAYER:function(e,t,i,n,o,s){this.oApp.exec("TOGGLE_ACTIVE_LAYER",[e,"MSG_TOOLBAR_LAYER_SHOWN",[e,t,i,n],o,s])},$ON_MSG_TOOLBAR_LAYER_SHOWN:function(e,t,i,n){this.oApp.exec("POSITION_TOOLBAR_LAYER",[e,t]),i&&this.oApp.exec(i,n)},$ON_SHOW_TOOLBAR_ACTIVE_LAYER:function(e,t,i,n){this.oApp.exec("SHOW_ACTIVE_LAYER",[e,t,i]),this.oApp.exec("POSITION_TOOLBAR_LAYER",[e,n])},$ON_ENABLE_UI:function(e){this._enableUI(e)},$ON_DISABLE_UI:function(e){if(e instanceof Array)for(var t,i=0;t=e[i];i++)this._disableUI(t);else this._disableUI(e)},$ON_SELECT_UI:function(e){var t=this.htWrappedUIList[e];t&&(t.removeClass("hover"),t.addClass("active"))},$ON_DESELECT_UI:function(e){var t=this.htWrappedUIList[e];t&&t.removeClass("active")},$ON_TOGGLE_UI_SELECTED:function(e){var t=this.htWrappedUIList[e];t&&(t.hasClass("active")?t.removeClass("active"):(t.removeClass("hover"),t.addClass("active")))},$ON_ENABLE_ALL_UI:function(e){if(1!==this.nUIStatus){var t;e=e||{};var i=jindo.$A(e.aExceptions||[]);for(t in this.htUIList)t&&!i.has(t)&&this._enableUI(t);this.nUIStatus=1}},$ON_DISABLE_ALL_UI:function(e){if(2!==this.nUIStatus){var t;e=e||{};var i=jindo.$A(e.aExceptions||[]),n=e.bLeaveActiveLayer||!1;for(t in n||this.oApp.exec("HIDE_ACTIVE_LAYER"),this.htUIList)t&&!i.has(t)&&this._disableUI(t);this.nUIStatus=2}},$ON_MSG_STYLE_CHANGED:function(e,t){"@^"===t?this.oApp.exec("SELECT_UI",[e]):this.oApp.exec("DESELECT_UI",[e])},$ON_POSITION_TOOLBAR_LAYER:function(e,t){var i,n,o,s;e=jindo.$(e),t=t||{};var r=jindo.$(t.elBtn),a=t.sAlign;if(e){r&&r.tagName&&"BUTTON"==r.tagName&&r.parentNode.appendChild(e);var l=jindo.$Element(e);"right"!=a?(e.style.left="0",n=(i=l.offset().left)+e.offsetWidth,(s=(o=this.welToolbarArea.offset().left)+this.toolbarArea.offsetWidth)this.oApp.elEditingAreaContainer.offsetHeight&&(e.style.top="number"==typeof t?i-e.offsetHeight-t+"px":this.oApp.elEditingAreaContainer.offsetHeight-e.offsetHeight+"px"),parseInt(e.style.left,10)+e.offsetWidth>this.oApp.elEditingAreaContainer.offsetWidth&&(e.style.left=this.oApp.elEditingAreaContainer.offsetWidth-e.offsetWidth+"px")},$ON_EVENT_EDITING_AREA_KEYDOWN:function(){this.oApp.exec("HIDE_ACTIVE_LAYER",[])},$ON_EVENT_EDITING_AREA_MOUSEDOWN:function(){this.oApp.exec("HIDE_ACTIVE_LAYER",[])},$ON_EVENT_EDITING_AREA_SCROLL:function(){this.oApp.exec("HIDE_ACTIVE_LAYER",[])},_setEditingAreaDimension:function(e){e=e||this.oActivePlugin,this._fitElementInEditingArea(e.elEditingArea)},_fitElementInEditingArea:function(e){e.style.height=this.elEditingAreaContainer.offsetHeight+"px"},attachDocumentEvents:function(e){this.oApp.registerBrowserEvent(e,"click","EVENT_EDITING_AREA_CLICK"),this.oApp.registerBrowserEvent(e,"dblclick","EVENT_EDITING_AREA_DBLCLICK"),this.oApp.registerBrowserEvent(e,"mousedown","EVENT_EDITING_AREA_MOUSEDOWN"),this.oApp.registerBrowserEvent(e,"mousemove","EVENT_EDITING_AREA_MOUSEMOVE"),this.oApp.registerBrowserEvent(e,"mouseup","EVENT_EDITING_AREA_MOUSEUP"),this.oApp.registerBrowserEvent(e,"mouseout","EVENT_EDITING_AREA_MOUSEOUT"),this.oApp.registerBrowserEvent(e,"mousewheel","EVENT_EDITING_AREA_MOUSEWHEEL"),this.oApp.registerBrowserEvent(e,"keydown","EVENT_EDITING_AREA_KEYDOWN"),this.oApp.registerBrowserEvent(e,"keypress","EVENT_EDITING_AREA_KEYPRESS"),this.oApp.registerBrowserEvent(e,"keyup","EVENT_EDITING_AREA_KEYUP"),this.oApp.registerBrowserEvent(e,"scroll","EVENT_EDITING_AREA_SCROLL")},$ON_GET_COVER_DIV:function(e,t){this.elEditingAreaCover&&(t[e]=this.elEditingAreaCover)},$ON_SHOW_LOADING_LAYER:function(){this.elLoadingLayer.style.display="block"},$ON_HIDE_LOADING_LAYER:function(){this.elLoadingLayer.style.display="none"},getIR:function(){return this.oActivePlugin?this.oActivePlugin.getIR():""},setIR:function(e,t){this.oApp.exec("SET_IR",[e,t])},getRawContents:function(){return this.oActivePlugin?this.oActivePlugin.getRawContents():""},getContents:function(){this._convertLastBrToNbsp();var e,t=this.oApp.getIR();return e=this.oApp.applyConverter?this.oApp.applyConverter("IR_TO_DB",t,this.oApp.getWYSIWYGDocument()):t,e=this._cleanContents(e)},_convertLastBrToNbsp:function(){for(var e,t,i,n,o,s,r,a,l,h,d,c=this.oApp.getWYSIWYGDocument().body,_=document.createTextNode(" "),p=0,E=(e=jindo.$$("br:last-child",c,{oneTimeOffCache:!0})).length;p]*>)"+unescape("%uFEFF"),"ig"),"$1")},setContents:function(e,t){var i;i=this.oApp.applyConverter?this.oApp.applyConverter("DB_TO_IR",e,this.oApp.getWYSIWYGDocument()):e,this.oApp.exec("SET_IR",[i,t])},getEditingMode:function(){return this.oActivePlugin.sMode},getEditingAreaWidth:function(){return this.elEditingAreaContainer.offsetWidth},getEditingAreaHeight:function(){return this.elEditingAreaContainer.offsetHeight}})},function(e,t){nhn.husky.SE_EditingArea_WYSIWYG=jindo.$Class({name:"SE_EditingArea_WYSIWYG",status:nhn.husky.PLUGIN_STATUS.NOT_READY,sMode:"WYSIWYG",iframe:null,doc:null,bStopCheckingBodyHeight:!1,bAutoResize:!1,nBodyMinHeight:0,nScrollbarWidth:0,iLastUndoRecorded:0,_nIFrameReadyCount:50,bWYSIWYGEnabled:!1,$init:function(e){this.iframe=jindo.$(e);var t=jindo.$Agent().navigator();t.ie&&(this.iframe.style.display="none"),this.sBlankPageURL="smart_editor2_inputarea.html",this.sBlankPageURL_EmulateIE7="smart_editor2_inputarea_ie8.html",this.aAddtionalEmulateIE7=[],this.htOptions=nhn.husky.SE2M_Configuration.SE_EditingAreaManager,this.htOptions&&(this.sBlankPageURL=this.htOptions.sBlankPageURL||this.sBlankPageURL,this.sBlankPageURL_EmulateIE7=this.htOptions.sBlankPageURL_EmulateIE7||this.sBlankPageURL_EmulateIE7,this.aAddtionalEmulateIE7=this.htOptions.aAddtionalEmulateIE7||this.aAddtionalEmulateIE7),this.aAddtionalEmulateIE7.push(8),this.sIFrameSrc=this.sBlankPageURL,t.ie&&jindo.$A(this.aAddtionalEmulateIE7).has(t.nativeVersion)&&(this.sIFrameSrc=this.sBlankPageURL_EmulateIE7),e=this.iframe;var i=this.sIFrameSrc,n=jindo.$Fn(this.initIframe,this).bind(),o=jindo.$Fn(function(){this.iframe.src=i},this).bind();!t.ie||9<=t.version&&document.addEventListener?(e.addEventListener("load",n,!1),e.addEventListener("error",o,!1)):(e.attachEvent("onload",n),e.attachEvent("onerror",o)),e.src=i,this.elEditingArea=e},$BEFORE_MSG_APP_READY:function(){this.oEditingArea=this.iframe.contentWindow.document,this.oApp.exec("REGISTER_EDITING_AREA",[this]),this.oApp.exec("ADD_APP_PROPERTY",["getWYSIWYGWindow",jindo.$Fn(this.getWindow,this).bind()]),this.oApp.exec("ADD_APP_PROPERTY",["getWYSIWYGDocument",jindo.$Fn(this.getDocument,this).bind()]),this.oApp.exec("ADD_APP_PROPERTY",["isWYSIWYGEnabled",jindo.$Fn(this.isWYSIWYGEnabled,this).bind()]),this.oApp.exec("ADD_APP_PROPERTY",["getRawHTMLContents",jindo.$Fn(this.getRawHTMLContents,this).bind()]),this.oApp.exec("ADD_APP_PROPERTY",["setRawHTMLContents",jindo.$Fn(this.setRawHTMLContents,this).bind()]),this.isWYSIWYGEnabled()&&this.oApp.exec("ENABLE_WYSIWYG_RULER"),this.oApp.registerBrowserEvent(this.getDocument().body,"paste","EVENT_EDITING_AREA_PASTE"),this.oApp.registerBrowserEvent(this.getDocument().body,"drop","EVENT_EDITING_AREA_DROP")},$ON_MSG_APP_READY:function(){Object.prototype.hasOwnProperty.call(this.oApp,"saveSnapShot")||(this.$ON_EVENT_EDITING_AREA_MOUSEUP=function(){},this._recordUndo=function(){}),this._bIERangeReset=!0,this.oApp.oNavigator.ie||-1this.nBodyMinHeight?(i=this.oApp.getCurrentStyle(),(n=this._getStyleSize(i))this.nBodyMinHeight?(i=this.oApp.getCurrentStyle(),(n=this._getStyleSize(i))=t.nTop&&e.nBottom<=t.nBottom},_scrollIntoView:function(e){var t,i=this._getElementVerticalPosition(e),n=this._getVisibleVerticalPosition();this._isElementVisible(i,n)||(0<(t=i.nBottom-n.nBottom)?this.getWindow().scrollTo(0,n.nTop+t):this.getWindow().scrollTo(0,i.nTop))},$BEFORE_MSG_EDITING_AREA_RESIZE_STARTED:function(){if(!jindo.$Agent().navigator().ie){var e=null;e=this.oApp.getSelection(),this.sBM=e.placeStringBookmark()}},$AFTER_MSG_EDITING_AREA_RESIZE_ENDED:function(){if(this.oApp.getEditingMode()===this.sMode&&!jindo.$Agent().navigator().ie){var e=this.oApp.getEmptySelection();e.moveToBookmark(this.sBM),e.select(),e.removeStringBookmark(this.sBM)}},$ON_CLEAR_IE_BACKUP_SELECTION:function(){this._oIERange=null},$ON_RESTORE_IE_SELECTION:function(){if(this._oIERange)try{this._oIERange.select(),this._oPrevIERange=this._oIERange,this._oIERange=null}catch(e){}},$ON_EVENT_EDITING_AREA_PASTE:function(e){this.oApp.delayedExec("EVENT_EDITING_AREA_PASTE_DELAY",[e],0)},$ON_EVENT_EDITING_AREA_PASTE_DELAY:function(e){this._replaceBlankToNbsp(e.element)},_replaceBlankToNbsp:function(e){var t=this.oApp.oNavigator;if(t.ie&&9===t.nativeVersion&&7===document.documentMode&&1===e.nodeType&&"BR"!==e.tagName){var i=jindo.$$("p:empty()",this.oApp.getWYSIWYGDocument().body,{oneTimeOffCache:!0});jindo.$A(i).forEach(function(e){e.innerHTML=" "})}},_pageUp:function(e){var t,i=this._getEditorHeight(),n=jindo.$Document(this.oApp.getWYSIWYGDocument()).scrollPosition();t=n.top<=i?0:n.top-i,this.oApp.getWYSIWYGWindow().scrollTo(0,t),e.stop()},_pageDown:function(e){var t,i=this._getEditorHeight(),n=jindo.$Document(this.oApp.getWYSIWYGDocument()).scrollPosition(),o=this._getBodyHeight();t=n.top+i>=o?o-i:n.top+i,this.oApp.getWYSIWYGWindow().scrollTo(0,t),e.stop()},_getEditorHeight:function(){return this.oApp.elEditingAreaContainer.offsetHeight-this.nTopBottomMargin},_getBodyHeight:function(){return parseInt(this.getDocument().body.scrollHeight,10)},initIframe:function(){try{if(!this.iframe.contentWindow.document||!this.iframe.contentWindow.document.body||"about:blank"===this.iframe.contentWindow.document.location.href)throw new Error("Access denied");var e=nhn.husky.SE2M_Configuration.SE2M_CSSLoader&&nhn.husky.SE2M_Configuration.SE2M_CSSLoader.sCSSBaseURI?nhn.husky.SE2M_Configuration.SE2M_CSSLoader.sCSSBaseURI:"";if(nhn.husky.SE2M_Configuration.SE_EditingAreaManager.sCSSBaseURI&&(e=nhn.husky.SE2M_Configuration.SE_EditingAreaManager.sCSSBaseURI),e){var t=e,i=this.oApp&&this.oApp.htOptions.I18N_LOCALE;i&&(t+="/"+i),t+="/smart_editor2_in.css";var n=this.getDocument(),o=n.getElementsByTagName("head")[0],s=n.createElement("link");s.type="text/css",s.rel="stylesheet",s.href=t,s.onload=jindo.$Fn(function(){this.oApp&&this.oApp.getEditingMode&&this.oApp.getEditingMode()===this.sMode&&this.oApp.exec("RESET_STYLE_STATUS"),s.onload=null},this).bind(),o.appendChild(s)}this._enableWYSIWYG(),this.status=nhn.husky.PLUGIN_STATUS.READY}catch(r){if(!(0";if(""===(t=this.oApp.applyConverter?this.oApp.applyConverter("IR_TO_"+this.sMode,e,this.oApp.getWYSIWYGDocument()):e).replace(/[\r\n\t\s]*/,"")&&("BR"!==this.oApp.sLineBreaker&&(n="

            "+n+"

            "),t=n),this.iframe.contentWindow.document.body.innerHTML=t,i&&this.oApp.getEditingMode()===this.sMode)for(var o=this.oApp.getWYSIWYGDocument().body.getElementsByTagName("P"),s=0,r=o.length;s"!==e.toLowerCase()&&"

             

            "!==e.toLowerCase()&&"


            "!==e.toLowerCase()&&"

            "!==e.toLowerCase()||(e="");var t=jindo.$Agent().navigator();t.ie&&11==t.nativeVersion&&11==document.documentMode&&(e=e.replace(/(

            $)/,""));var i=e;this.oApp.applyConverter&&(i=this.oApp.applyConverter("IR_TO_"+this.sMode,i,this.oApp.getWYSIWYGDocument())),this.setRawContents(i)},setRawContents:function(e){void 0!==e&&(this.elEditingArea.value=e)},getRawContents:function(){return this.elEditingArea.value},focus:function(){this.elEditingArea.focus()}}),"undefined"==typeof window.TextRange&&(window.TextRange={}),TextRange=function(e,t){this._o=e,this._oDoc=t||document},TextRange.prototype.getSelection=function(){var e=this._o,t=[-1,-1];if(isNaN(this._o.selectionStart)){e.focus();var i=this._oDoc.body.createTextRange(),n=null;n=this._oDoc.selection.createRange().duplicate(),i.moveToElementText(e),n.collapse(!0),i.setEndPoint("EndToEnd",n),t[0]=i.text.length,n=this._oDoc.selection.createRange().duplicate(),i.moveToElementText(e),n.collapse(!1),i.setEndPoint("EndToEnd",n),t[1]=i.text.length,e.blur()}else t[0]=e.selectionStart,t[1]=e.selectionEnd;return t},TextRange.prototype.setSelection=function(e,t){var i=this._o;if(void 0===t&&(t=e),i.setSelectionRange)i.setSelectionRange(e,t);else if(i.createTextRange){var n=i.createTextRange();n.collapse(!0),n.moveStart("character",e),n.moveEnd("character",t-e),n.select(),i.blur()}},TextRange.prototype.copy=function(){var e=this.getSelection();return this._o.value.substring(e[0],e[1])},TextRange.prototype.paste=function(e){var t=this._o,i=this.getSelection(),n=t.value,o=n.substr(0,i[0]);n=o+e+n.substr(i[1]),t.value=n;var s=0;if("undefined"==typeof this._oDoc.body.style.maxHeight){var r=o.match(/\n/gi);s=null!==r?r.length:0}this.setSelection(i[0]+e.length-s)},TextRange.prototype.cut=function(){var e=this.copy();return this.paste(""),e}},function(e,t){nhn.husky.SE_EditingArea_TEXT=jindo.$Class({name:"SE_EditingArea_TEXT",sMode:"TEXT",sRxConverter:"@[0-9]+@",bAutoResize:!1,nMinHeight:null,$init:function(e){this.elEditingArea=jindo.$(e)},$BEFORE_MSG_APP_READY:function(){this.oNavigator=jindo.$Agent().navigator(),this.oApp.exec("REGISTER_EDITING_AREA",[this]),this.oApp.exec("ADD_APP_PROPERTY",["getTextAreaContents",jindo.$Fn(this.getRawContents,this).bind()])},$ON_MSG_APP_READY:function(){this.oApp.getEditingAreaHeight&&(this.nMinHeight=this.oApp.getEditingAreaHeight())},$ON_REGISTER_CONVERTERS:function(){this.oApp.exec("ADD_CONVERTER",["IR_TO_TEXT",jindo.$Fn(this.irToText,this).bind()]),this.oApp.exec("ADD_CONVERTER",["TEXT_TO_IR",jindo.$Fn(this.textToIr,this).bind()])},$ON_CHANGE_EDITING_MODE:function(e){e==this.sMode?(this.elEditingArea.style.display="block",this.elEditingArea.style.position="absolute",this.elEditingArea.style.top="0px"):(this.elEditingArea.style.display="none",this.elEditingArea.style.position="",this.elEditingArea.style.top="")},$AFTER_CHANGE_EDITING_MODE:function(e,t){e!=this.sMode||t||new TextRange(this.elEditingArea).setSelection(0,0)},irToText:function(e){var t,i=e,n=i.match(new RegExp(this.sRxConverter));return null!==n&&(i=i.replace(new RegExp(this.sRxConverter),"")),-1<(t=(i=(i=(i=(i=(i=(i=(i=(i=(i=(i=i.replace(/\r/g,"")).replace(/[\n|\t]/g,"")).replace(/[\v|\f]/g,"")).replace(/


            <\/p>/gi,"\n")).replace(/

             <\/P>/gi,"\n")).replace(//gi,"\n")).replace(//gi,"\n")).replace(/<\/p(\s[^/]*)?>/gi,"\n")).replace(/<\/li(\s[^/]*)?>/gi,"\n")).replace(/<\/tr(\s[^/]*)?>/gi,"\n")).lastIndexOf("\n"))&&"\n"==i.substring(t)&&(i=i.substring(0,t)),i=jindo.$S(i).stripTags().toString(),i=this.unhtmlSpecialChars(i),null!==n&&(i=n[0]+i),i},textToIr:function(e){if(e){var t,i=e;return null!==(t=i.match(new RegExp(this.sRxConverter)))&&(i=i.replace(t[0],"")),i=this.htmlSpecialChars(i),i=this._addLineBreaker(i),null!==t&&(i=t[0]+i),i}},_addLineBreaker:function(e){if("BR"===this.oApp.sLineBreaker)return e.replace(/\r?\n/g,"
            ");for(var t=new StringBuffer,i=e.split("\n"),n=i.length,o="",s=0;s"),t.append(i[s]),t.append("

            ")):jindo.$Agent().navigator().ie?t.append("

             

            "):t.append("


            ");return t.toString()},startAutoResize:function(){var e={nMinHeight:this.nMinHeight,wfnCallback:jindo.$Fn(this.oApp.checkResizeGripPosition,this).bind()};this.oNavigator.msafari&&(e.wfnCallback=function(){}),this.bAutoResize=!0,this.AutoResizer=new nhn.husky.AutoResizer(this.elEditingArea,e),this.AutoResizer.bind()},stopAutoResize:function(){this.AutoResizer.unbind()},getIR:function(){var e=this.getRawContents();return this.oApp.applyConverter&&(e=this.oApp.applyConverter(this.sMode+"_TO_IR",e,this.oApp.getWYSIWYGDocument())),e},setIR:function(e){var t=e;this.oApp.applyConverter&&(t=this.oApp.applyConverter("IR_TO_"+this.sMode,t,this.oApp.getWYSIWYGDocument())),this.setRawContents(t)},setRawContents:function(e){void 0!==e&&(this.elEditingArea.value=e)},getRawContents:function(){return this.elEditingArea.value},focus:function(){this.elEditingArea.focus()},htmlSpecialChars:function(e){return e.replace(/&/g,"&").replace(//g,">").replace(/ /g," ")},unhtmlSpecialChars:function(e){return e.replace(/</g,"<").replace(/>/g,">").replace(/ /g," ").replace(/&/g,"&")}})},function(e,t){nhn.husky.SE_EditingAreaVerticalResizer=jindo.$Class({name:"SE_EditingAreaVerticalResizer",oResizeGrip:null,sCookieNotice:"bHideResizeNotice",nEditingAreaMinHeight:null,htConversionMode:null,$init:function(e,t){this.htConversionMode=t,this._assignHTMLElements(e)},$BEFORE_MSG_APP_READY:function(){this.oApp.exec("ADD_APP_PROPERTY",["isUseVerticalResizer",jindo.$Fn(this.isUseVerticalResizer,this).bind()])},$ON_MSG_APP_READY:function(){this.oApp.bMobile?(this.oResizeGrip.disabled=!0,this.oResizeGrip.style.height="0"):(this.oApp.exec("REGISTER_HOTKEY",["shift+esc","FOCUS_RESIZER"]),this.isUseVerticalResizer()?(this.oResizeGrip.style.display="block",this.welNoticeLayer&&!Number(jindo.$Cookie().get(this.sCookieNotice))&&(this.welNoticeLayer.delegate("click","BUTTON.bt_clse",jindo.$Fn(this._closeNotice,this).bind()),this.welNoticeLayer.show()),this.$FnMouseDown=jindo.$Fn(this._mousedown,this),this.$FnMouseMove=jindo.$Fn(this._mousemove,this),this.$FnMouseUp=jindo.$Fn(this._mouseup,this),this.$FnMouseOver=jindo.$Fn(this._mouseover,this),this.$FnMouseOut=jindo.$Fn(this._mouseout,this),this.$FnMouseDown.attach(this.oResizeGrip,"mousedown"),this.$FnMouseOver.attach(this.oResizeGrip,"mouseover"),this.$FnMouseOut.attach(this.oResizeGrip,"mouseout")):(this.oResizeGrip.style.display="none",this.oApp.isUseModeChanger()||(this.elModeToolbar.style.display="none"))),this.oApp.exec("ADD_APP_PROPERTY",["checkResizeGripPosition",jindo.$Fn(this.checkResizeGripPosition,this).bind()]),this.oApp.getEditingAreaHeight&&(this.nEditingAreaMinHeight=this.oApp.getEditingAreaHeight())},$ON_DISABLE_ALL_UI:function(){this.oResizeGrip.style.cursor="default",this.welConversionMode.addClass("off"),this.oResizeGrip.disabled=!0},$ON_ENABLE_ALL_UI:function(){this.oResizeGrip.style.cursor="n-resize",this.welConversionMode.removeClass("off"),this.oResizeGrip.disabled=!1},isUseVerticalResizer:function(){return"undefined"==typeof this.htConversionMode||"undefined"==typeof this.htConversionMode.bUseVerticalResizer||!0===this.htConversionMode.bUseVerticalResizer},checkResizeGripPosition:function(e){var t=jindo.$Document(),i=jindo.$Element(this.oResizeGrip).offset().top-t.scrollPosition().top+25-t.clientSize().height;i<=0||(e&&(this.nEditingAreaMinHeight>this.oApp.getEditingAreaHeight()-i&&(i=-1*(this.nEditingAreaMinHeight-this.oApp.getEditingAreaHeight())),this.oApp.exec("MSG_EDITING_AREA_RESIZE_STARTED"),this.oApp.exec("RESIZE_EDITING_AREA_BY",[0,-1*i]),this.oApp.exec("MSG_EDITING_AREA_RESIZE_ENDED")),this.oApp.exec("STOP_AUTORESIZE_EDITING_AREA"))},$ON_FOCUS_RESIZER:function(){this.oApp.exec("IE_HIDE_CURSOR"),this.oResizeGrip.focus()},_assignHTMLElements:function(e){this.oResizeGrip=jindo.$$.getSingle("BUTTON.husky_seditor_editingArea_verticalResizer",e),this.elModeToolbar=jindo.$$.getSingle("DIV.se2_conversion_mode",e),this.welNoticeLayer=jindo.$Element(jindo.$$.getSingle("DIV.husky_seditor_resize_notice",e)),this.welConversionMode=jindo.$Element(this.oResizeGrip.parentNode)},_mouseover:function(e){e.stopBubble(),this.welConversionMode.addClass("controller_on")},_mouseout:function(e){e.stopBubble(),this.welConversionMode.removeClass("controller_on")},_mousedown:function(e){this.iStartHeight=e.pos().clientY,this.iStartHeightOffset=e.pos().layerY,this.$FnMouseMove.attach(document,"mousemove"),this.$FnMouseUp.attach(document,"mouseup"),this.iStartHeight=e.pos().clientY,this.oApp.exec("HIDE_ACTIVE_LAYER"),this.oApp.exec("HIDE_ALL_DIALOG_LAYER"),this.oApp.exec("MSG_EDITING_AREA_RESIZE_STARTED",[this.$FnMouseDown,this.$FnMouseMove,this.$FnMouseUp])},_mousemove:function(e){var t=e.pos().clientY-this.iStartHeight;this.oApp.exec("RESIZE_EDITING_AREA_BY",[0,t])},_mouseup:function(){this.$FnMouseMove.detach(document,"mousemove"),this.$FnMouseUp.detach(document,"mouseup"),this.oApp.exec("MSG_EDITING_AREA_RESIZE_ENDED",[this.$FnMouseDown,this.$FnMouseMove,this.$FnMouseUp])},_closeNotice:function(){this.welNoticeLayer.hide(),jindo.$Cookie().set(this.sCookieNotice,1,3650)}})},function(e,t){nhn.husky.SE_WYSIWYGEnterKey=jindo.$Class({name:"SE_WYSIWYGEnterKey",$init:function(e){this.sLineBreaker="BR"==e?"BR":"P",this.htBrowser=jindo.$Agent().navigator(),this.htBrowser.opera&&"P"==this.sLineBreaker&&(this.$ON_MSG_APP_READY=function(){}),this.htBrowser.ie?this._addCursorHolder=this._addCursorHolderSpace:(this._addExtraCursorHolder=function(){},this._addBlankText=function(){})},$ON_MSG_APP_READY:function(){this.oApp.exec("ADD_APP_PROPERTY",["sLineBreaker",this.sLineBreaker]),this.oSelection=this.oApp.getEmptySelection(),this.tmpTextNode=this.oSelection._document.createTextNode(unescape("%u00A0")),jindo.$Fn(this._onKeyDown,this).attach(this.oApp.getWYSIWYGDocument(),"keydown")},_onKeyDown:function(e){var t=e.key();t.shift||t.enter&&("BR"==this.sLineBreaker?this._insertBR(e):this._wrapBlock(e))},$ON_REGISTER_CONVERTERS:function(){this.oApp.exec("ADD_CONVERTER",["IR_TO_DB",jindo.$Fn(this.onIrToDB,this).bind()])},onIrToDB:function(e){var t=e,i=/(]*>)(?:\s*)(<\/p>)/gi;return t=this.htBrowser.ie&&this.htBrowser.version<11?t.replace(i,"$1 $2"):t.replace(i,"")},_addBlankText:function(e){var t,i,n,o,s,r=e.getNodes();for(t=0,i=r.length;t"),t=t||this._getStyleNode(e)},_addCursorHolderSpace:function(e){var t;if(this._addSpace(e),""==(t=this._getStyleNode(e)).innerHTML&&"param"!=t.nodeName.toLowerCase())try{t.innerHTML=unescape("%uFEFF")}catch(i){}return t},_getBlockEndNode:function(e,t){return e?"BR"===e.nodeName?e:e===t?t:this._getBlockEndNode(e.nextSibling,t):t},_convertHeadSpace:function(e){if(e&&3===e.nodeType){for(var t,i=e.nodeValue,n="",o=0;(t=i[o])&&" "===t;o++)n+=" ";0"),t.collapseToEnd())}}t.insertNode(this.oApp.getWYSIWYGDocument().createTextNode("")),t.select()}})},function(e,t){nhn.husky.SE2M_EditingModeChanger=jindo.$Class({name:"SE2M_EditingModeChanger",htConversionMode:null,$init:function(e,t){this.htConversionMode=t,this._assignHTMLElements(e)},_assignHTMLElements:function(e){e=jindo.$(e)||document,this.elWYSIWYGButton=jindo.$$.getSingle("BUTTON.se2_to_editor",e),this.elHTMLSrcButton=jindo.$$.getSingle("BUTTON.se2_to_html",e),this.elTEXTButton=jindo.$$.getSingle("BUTTON.se2_to_text",e),this.elModeToolbar=jindo.$$.getSingle("DIV.se2_conversion_mode",e),this.welWYSIWYGButtonLi=jindo.$Element(this.elWYSIWYGButton.parentNode),this.welHTMLSrcButtonLi=jindo.$Element(this.elHTMLSrcButton.parentNode),this.welTEXTButtonLi=jindo.$Element(this.elTEXTButton.parentNode)},$BEFORE_MSG_APP_READY:function(){this.oApp.exec("ADD_APP_PROPERTY",["isUseModeChanger",jindo.$Fn(this.isUseModeChanger,this).bind()])},$ON_MSG_APP_READY:function(){this.oApp.htOptions.bOnlyTextMode?(this.elWYSIWYGButton.style.display="none",this.elHTMLSrcButton.style.display="none",this.elTEXTButton.style.display="block",this.oApp.exec("CHANGE_EDITING_MODE",["TEXT"])):(this.oApp.registerBrowserEvent(this.elWYSIWYGButton,"click","EVENT_CHANGE_EDITING_MODE_CLICKED",["WYSIWYG"]),this.oApp.registerBrowserEvent(this.elHTMLSrcButton,"click","EVENT_CHANGE_EDITING_MODE_CLICKED",["HTMLSrc"]),this.oApp.registerBrowserEvent(this.elTEXTButton,"click","EVENT_CHANGE_EDITING_MODE_CLICKED",["TEXT",!1]),this.showModeChanger(),!1===this.isUseModeChanger()&&!1===this.oApp.isUseVerticalResizer()&&(this.elModeToolbar.style.display="none"))},showModeChanger:function(){this.isUseModeChanger()?(this.elWYSIWYGButton.style.display="block",this.elHTMLSrcButton.style.display="block",this.elTEXTButton.style.display="block"):(this.elWYSIWYGButton.style.display="none",this.elHTMLSrcButton.style.display="none",this.elTEXTButton.style.display="none")},isUseModeChanger:function(){return"undefined"==typeof this.htConversionMode||"undefined"==typeof this.htConversionMode.bUseModeChanger||!0===this.htConversionMode.bUseModeChanger},$ON_EVENT_CHANGE_EDITING_MODE_CLICKED:function(e,t){if("TEXT"==e){if(0]*)?>(?:.|\r|\n)*?<\/style>/gi,_rxStyleTagStrip:/<\/?style(?:\s+[^>]*)?>/gi,_rxClassSelector:/\w*\.\w+/g,_rxClassSelectorStart:/\w*\./g,$init:function(){},_getTmpDocument:function(){if(!this._oTmpDoc){var e=document.createElement("IFRAME");e.style.display="none",document.body.appendChild(e);var t=e.contentWindow.document;t.open(),t.write(""),t.close(),this._oTmpDoc=t}return this._oTmpDoc},_getCSSStyleRule:function(e){for(var t,i={},n=0;t=e[n];n++)t.type===CSSRule.STYLE_RULE&&(i[t.selectorText]=t.style);return i},_extractStyle:function(e){if(e){var t=(e.match(this._rxStyleTag)||[]).join("\n");t=t.replace(this._rxStyleTagStrip,"");var i=this._getTmpDocument(),n=i.getElementsByTagName("HEAD")[0],o=i.createElement("STYLE");o.innerHTML=t,n.appendChild(o),this._htStyleRule=this._getCSSStyleRule(o.sheet.cssRules),o.parentNode.removeChild(o)}},_applyInlineStyle:function(e,t,i){for(var n,o=0,s=t.length;oo.nRecursiveCount&&(i=!0):i=!0}}i&&this._insertDummyParagraph_IE(e)},_insertDummyParagraph_IE:function(e){this._elDummyParagraph=document.createElement("P"),e.appendChild(this._elDummyParagraph)},_removeDummyParagraph_IE:function(){this._elDummyParagraph&&this._elDummyParagraph.parentNode&&this._elDummyParagraph.parentNode.removeChild(this._elDummyParagraph)},$ON_EXECCOMMAND:function(e,t,i){var n={},o=this.oApp.getSelection();if(t=!(""!=t&&!t)&&t,i=!(""!=i&&!i)&&i,this.oApp.exec("IS_SELECTED_TD_BLOCK",["bIsSelectedTd",n]),n.bIsSelectedTd)"indent"==e?this.oApp.exec("SET_LINE_BLOCK_STYLE",[null,jindo.$Fn(this._indentMargin,this).bind()]):"outdent"==e?this.oApp.exec("SET_LINE_BLOCK_STYLE",[null,jindo.$Fn(this._outdentMargin,this).bind()]):this._setBlockExecCommand(e,t,i);else switch(e){case"indent":case"outdent":this.oApp.exec("RECORD_UNDO_BEFORE_ACTION",[e]);var s=o.placeStringBookmark();"indent"===e?this.oApp.exec("SET_LINE_STYLE",[null,jindo.$Fn(this._indentMargin,this).bind(),{bDoNotSelect:!0,bDontAddUndoHistory:!0}]):this.oApp.exec("SET_LINE_STYLE",[null,jindo.$Fn(this._outdentMargin,this).bind(),{bDoNotSelect:!0,bDontAddUndoHistory:!0}]),o.moveToStringBookmark(s),o.select(),o.removeStringBookmark(s),setTimeout(jindo.$Fn(function(e){this.oApp.exec("RECORD_UNDO_AFTER_ACTION",[e])},this).bind(e),25);break;case"justifyleft":case"justifycenter":case"justifyright":case"justifyfull":var r=this._extendBlock();this.oEditingArea.execCommand(e,t,i),r&&r.select(),this.oNavigator.ie&&this._removeElementAlign("table");break;default:if(o.collapsed&&this._rxCmdInline.test(e)){var a=o.placeStringBookmark(),l=o.getStringBookmark(a).previousSibling;l&&"​"===l.nodeValue||(l=this.oApp.getWYSIWYGDocument().createTextNode("​"),o.insertNode(l)),o.removeStringBookmark(a),o.selectNodeContents(l),o.select(),this.oEditingArea.execCommand(e,t,i),o.collapseToEnd(),o.select();var h=this._findSingleNode(l);h&&o._hasCursorHolderOnly(h.nextSibling)&&h.parentNode.removeChild(h.nextSibling)}else this.oEditingArea.execCommand(e,t,i)}this._countClickCr(e)},_findSingleNode:function(e){return e?1===e.parentNode.childNodes.length?this._findSingleNode(e.parentNode):e:null},$AFTER_EXECCOMMAND:function(e,t,i,n){this.elP1&&this.elP1.parentNode&&this.elP1.parentNode.removeChild(this.elP1),this.elP2&&this.elP2.parentNode&&this.elP2.parentNode.removeChild(this.elP2),/^insertorderedlist|insertunorderedlist$/i.test(e)&&(this._removeDummyParagraph_IE(),this._fixCorruptedBlockQuote("insertorderedlist"===e?"OL":"UL"),this.oNavigator.bGalaxyBrowser&&this._removeBlockQuote()),/^justify*/i.test(e)&&this._fixAlign("justifyfull"===e?"justify":e.substring(7)),"indent"!=e&&"outdent"!=e||((n=n||{}).bDontAddUndoHistory=!0),n&&n.bDontAddUndoHistory||this._bOnlyCursorChanged||this.oApp.exec("RECORD_UNDO_AFTER_ACTION",[e,this.oUndoOption]),this.oApp.exec("CHECK_STYLE_CHANGE",[])},_removeElementAlign:function(e){for(var t=this.oApp.getSelection().getNodes(),i=null,n=new RegExp("^"+e+"$","i"),o=0,s=t.length;o 

            ",this.oApp.getWYSIWYGDocument()),t.parentNode.insertBefore(this.elP1,t),this.elP2=jindo.$("

             

            ",this.oApp.getWYSIWYGDocument()),t.parentNode.insertBefore(this.elP2,t.nextSibling);break}t=t.parentNode}if(!this.elP1&&!this.elP2){var i=(t=1!==(t=e.commonAncestorContainer).nodeType?t.parentNode:t).previousSibling,n=t.nextSibling;i&&"BLOCKQUOTE"===i.tagName&&(this.elP1=jindo.$("

             

            ",this.oApp.getWYSIWYGDocument()),i.parentNode.insertBefore(this.elP1,i.nextSibling)),n&&"BLOCKQUOTE"===n.tagName&&(this.elP1=jindo.$("

             

            ",this.oApp.getWYSIWYGDocument()),n.parentNode.insertBefore(this.elP1,n))}},_fixCorruptedBlockQuote:function(e){var t,i,n,o,s,r,a,l,h,d=this.oApp.getWYSIWYGDocument().getElementsByTagName(e);for(s=0,r=d.length;s',$init:function(e){this.elAppContainer=e},$ON_MSG_APP_READY:function(){},_assignHTMLElements:function(e){var t=nhn.husky.SE2M_Configuration.SE2M_ColorPalette;if(t){var i=(nhn.husky.SE2M_Configuration.LinkageDomain||{}).sCommonAPI||"";this.bUseRecentColor=t.bUseRecentColor||!1,this.URL_COLOR_ADD=t.addColorURL||i+"/1/colortable/TextAdd.nhn",this.URL_COLOR_UPDATE=t.updateColorURL||i+"/1/colortable/TextUpdate.nhn",this.URL_COLOR_LIST=t.colorListURL||i+"/1/colortable/TextList.nhn"}this.elColorPaletteLayer=jindo.$$.getSingle("DIV.husky_se2m_color_palette",e),this.elColorPaletteLayerColorPicker=jindo.$$.getSingle("DIV.husky_se2m_color_palette_colorpicker",this.elColorPaletteLayer),this.elRecentColorForm=jindo.$$.getSingle("form",this.elColorPaletteLayerColorPicker),this.elBackgroundColor=jindo.$$.getSingle("ul.husky_se2m_bgcolor_list",e),this.elInputColorCode=jindo.$$.getSingle("INPUT.husky_se2m_cp_colorcode",this.elColorPaletteLayerColorPicker),this.elPreview=jindo.$$.getSingle("SPAN.husky_se2m_cp_preview",this.elColorPaletteLayerColorPicker),this.elCP_ColPanel=jindo.$$.getSingle("DIV.husky_se2m_cp_colpanel",this.elColorPaletteLayerColorPicker),this.elCP_HuePanel=jindo.$$.getSingle("DIV.husky_se2m_cp_huepanel",this.elColorPaletteLayerColorPicker),this.elCP_ColPanel.style.position="relative",this.elCP_HuePanel.style.position="relative",this.elColorPaletteLayerColorPicker.style.display="none",this.elMoreBtn=jindo.$$.getSingle("BUTTON.husky_se2m_color_palette_more_btn",this.elColorPaletteLayer),this.welMoreBtn=jindo.$Element(this.elMoreBtn),this.elOkBtn=jindo.$$.getSingle("BUTTON.husky_se2m_color_palette_ok_btn",this.elColorPaletteLayer),this.bUseRecentColor&&(this.elColorPaletteLayerRecent=jindo.$$.getSingle("DIV.husky_se2m_color_palette_recent",this.elColorPaletteLayer),this.elRecentColor=jindo.$$.getSingle("ul.se2_pick_color",this.elColorPaletteLayerRecent),this.elDummyNode=jindo.$$.getSingle("ul.se2_pick_color > li",this.elColorPaletteLayerRecent)||null,this.elColorPaletteLayerRecent.style.display="none")},$LOCAL_BEFORE_FIRST:function(){this._assignHTMLElements(this.elAppContainer),this.elDummyNode&&jindo.$Element(jindo.$$.getSingle("ul.se2_pick_color > li",this.elColorPaletteLayerRecent)).leave(),this.bUseRecentColor&&this._ajaxRecentColor(this._ajaxRecentColorCallback),this.oApp.registerBrowserEvent(this.elColorPaletteLayer,"click","EVENT_CLICK_COLOR_PALETTE"),this.oApp.bMobile||(this.oApp.registerBrowserEvent(this.elBackgroundColor,"mouseover","EVENT_MOUSEOVER_COLOR_PALETTE"),this.oApp.registerBrowserEvent(this.elColorPaletteLayer,"mouseover","EVENT_MOUSEOVER_COLOR_PALETTE"),this.oApp.registerBrowserEvent(this.elBackgroundColor,"mouseout","EVENT_MOUSEOUT_COLOR_PALETTE"),this.oApp.registerBrowserEvent(this.elColorPaletteLayer,"mouseout","EVENT_MOUSEOUT_COLOR_PALETTE"))},$ON_EVENT_MOUSEOVER_COLOR_PALETTE:function(e){for(var t=e.element;t&&t.tagName&&"li"!=t.tagName.toLowerCase();)t=t.parentNode;t&&t.nodeType&&9!=t.nodeType&&(""!=t.className&&t.className&&"undefined"!=typeof t.className||jindo.$Element(t).addClass("hover"))},$ON_EVENT_MOUSEOUT_COLOR_PALETTE:function(e){for(var t=e.element;t&&t.tagName&&"li"!=t.tagName.toLowerCase();)t=t.parentNode;t&&"hover"==t.className&&jindo.$Element(t).removeClass("hover")},$ON_EVENT_CLICK_COLOR_PALETTE:function(e){for(var t=e.element;"SPAN"==t.tagName;)t=t.parentNode;if(t.tagName&&"BUTTON"==t.tagName){if(t==this.elMoreBtn)return void this.oApp.exec("TOGGLE_COLOR_PICKER");this.oApp.exec("APPLY_COLOR",[t])}},$ON_APPLY_COLOR:function(e){var t=this.elInputColorCode.value,i=null;if(-1==t.indexOf("#")&&(t="#"+t,this.elInputColorCode.value=t),e==this.elOkBtn)return this._verifyColorCode(t)?void this.oApp.exec("COLOR_PALETTE_APPLY_COLOR",[t,!0]):(this.elInputColorCode.value="",alert(this.oApp.$MSG("SE_Color.invalidColorCode")),void this.elInputColorCode.focus());i=jindo.$Element(e.parentNode.parentNode.parentNode),t=e.title,i.hasClass("husky_se2m_color_palette")?this.oApp.exec("COLOR_PALETTE_APPLY_COLOR",[t,!1]):i.hasClass("husky_se2m_color_palette_recent")&&this.oApp.exec("COLOR_PALETTE_APPLY_COLOR",[t,!0])},$ON_RESET_COLOR_PALETTE:function(){this._initColor()},$ON_TOGGLE_COLOR_PICKER:function(){"none"==this.elColorPaletteLayerColorPicker.style.display?this.oApp.exec("SHOW_COLOR_PICKER"):this.oApp.exec("HIDE_COLOR_PICKER")},$ON_SHOW_COLOR_PICKER:function(){this.elColorPaletteLayerColorPicker.style.display="",this.cpp=new nhn.ColorPicker(this.elCP_ColPanel,{huePanel:this.elCP_HuePanel});var e=jindo.$Fn(function(e){this.elPreview.style.backgroundColor=e.hexColor,this.elInputColorCode.value=e.hexColor},this).bind();this.cpp.attach("colorchange",e),this.$ON_SHOW_COLOR_PICKER=this._showColorPickerMain,this.$ON_SHOW_COLOR_PICKER()},$ON_HIDE_COLOR_PICKER:function(){this.elColorPaletteLayerColorPicker.style.display="none",this.welMoreBtn.addClass("se2_view_more"),this.welMoreBtn.removeClass("se2_view_more2")},$ON_SHOW_COLOR_PALETTE:function(e,t){this.sCallbackCmd=e,this.oLayerContainer=t,this.oLayerContainer.insertBefore(this.elColorPaletteLayer,null),this.elColorPaletteLayer.style.display="block",this.oApp.delayedExec("POSITION_TOOLBAR_LAYER",[this.elColorPaletteLayer.parentNode.parentNode],0)},$ON_HIDE_COLOR_PALETTE:function(){this.elColorPaletteLayer.style.display="none"},$ON_COLOR_PALETTE_APPLY_COLOR:function(e,t){t=t||!1,e=this._getHexColorCode(e),this.bUseRecentColor&&t&&this.oApp.exec("ADD_RECENT_COLOR",[e]),this.oApp.exec(this.sCallbackCmd,[e])},$ON_EVENT_MOUSEUP_COLOR_PALETTE:function(e){var t=e.element;t.style.backgroundColor&&this.oApp.exec("COLOR_PALETTE_APPLY_COLOR",[t.style.backgroundColor,!1])},$ON_ADD_RECENT_COLOR:function(e){var t=0===this.aRecentColor.length;this._addRecentColor(e),t?this._ajaxAddColor():this._ajaxUpdateColor(),this._redrawRecentColorElement()},_verifyColorCode:function(e){return this.rxColorPattern.test(e)},_getHexColorCode:function(e){if(this.rxRGBColorPattern.test(e)){function t(e){var t=parseInt(e,10).toString(16);return t.length<2&&(t="0"+t),t.toUpperCase()}e="#"+t(RegExp.$1)+t(RegExp.$2)+t(RegExp.$3)}return e},_addRecentColor:function(e){var t=jindo.$A(this.aRecentColor);(t=t.refuse(e)).unshift(e),t.length()>this.nLimitRecentColor&&t.length(this.nLimitRecentColor),this.aRecentColor=t.$value()},_redrawRecentColorElement:function(){var e,t=[],i=this.aRecentColor.length;if(0!==i){for(e=0;ethis.nLimitRecentColor&&t.length(this.nLimitRecentColor),i=0,n=(o=t.reverse().$value()).length;i'+i+"":''+i+"")},$BEFORE_MSG_APP_READY:function(){var e=nhn.husky.SE2M_Configuration.SE2M_Hyperlink;if(e&&!1===e.bAutolink){this.$ON_REGISTER_CONVERTERS=null,this.$ON_DISABLE_MESSAGE=null,this.$ON_ENABLE_MESSAGE=null;try{this.oApp.getWYSIWYGDocument().execCommand("AutoUrlDetect",!1,!1)}catch(t){}}},$ON_MSG_APP_READY:function(){this.bLayerShown=!1,jindo.$Agent().os().mac?this.oApp.exec("REGISTER_HOTKEY",["meta+k","TOGGLE_HYPERLINK_LAYER",[]]):this.oApp.exec("REGISTER_HOTKEY",["ctrl+k","TOGGLE_HYPERLINK_LAYER",[]]),this.oApp.exec("REGISTER_UI_EVENT",["hyperlink","click","TOGGLE_HYPERLINK_LAYER"]),this.oApp.registerLazyMessage(["TOGGLE_HYPERLINK_LAYER","APPLY_HYPERLINK"],["hp_SE2M_Hyperlink$Lazy.js"])},$ON_REGISTER_CONVERTERS:function(){this.oApp.exec("ADD_CONVERTER_DOM",["IR_TO_DB",jindo.$Fn(this.irToDb,this).bind()])},$LOCAL_BEFORE_FIRST:function(e){if(e.match(/(REGISTER_CONVERTERS)/))return this.oApp.acceptLocalBeforeFirstAgain(this,!0),!0;this._assignHTMLElements(this.oApp.htOptions.elAppContainer),this.sRXATagMarker=this.sATagMarker.replace(/\//g,"\\/").replace(/\./g,"\\."),this.oApp.registerBrowserEvent(this.oBtnConfirm,"click","APPLY_HYPERLINK"),this.oApp.registerBrowserEvent(this.oBtnCancel,"click","HIDE_ACTIVE_LAYER"),this.oApp.registerBrowserEvent(this.oLinkInput,"keydown","EVENT_HYPERLINK_KEYDOWN")},$ON_EVENT_HYPERLINK_KEYDOWN:function(e){e.key().enter&&(this.oApp.exec("APPLY_HYPERLINK"),e.stop())},$ON_DISABLE_MESSAGE:function(e){if("TOGGLE_HYPERLINK_LAYER"===e){try{this.oApp.getWYSIWYGDocument().execCommand("AutoUrlDetect",!1,!1)}catch(t){}this._bDisabled=!0}},$ON_ENABLE_MESSAGE:function(e){if("TOGGLE_HYPERLINK_LAYER"===e){try{this.oApp.getWYSIWYGDocument().execCommand("AutoUrlDetect",!1,!0)}catch(t){}this._bDisabled=!1}},irToDb:function(e){if(!this._bDisabled){var t=e.cloneNode(!0);try{t.innerHTML}catch(u){t=jindo.$(e.outerHTML)}for(var i,n,o=this.oApp.getEmptySelection(),s=o._getFirstRealChild(t),r=o._getLastRealChild(t),a=jindo.$A(o._getNodesBetween(s,r)),l=a.filter(function(e){return e&&3===e.nodeType}).$value(),h=l,d=this.oApp.getWYSIWYGDocument().createElement("DIV"),c="@"+(new Date).getTime()+"@",_=new RegExp(c,"g"),p=0,E=l.length;p
            '),this.oApp.welEditingAreaContainer.prepend(this.welEditingAreaCover),jindo.$Fn(this._onMouseupCover,this).attach(this.welEditingAreaCover.$value(),"mouseup")}},_onFocusWYSIWYGBody:function(){this._wfOnFocusWYSIWYGBody.detach(this.oApp.getWYSIWYGDocument().body,"focus"),this._loadAllBaseFont()},_onPasteWYSIWYGBody:function(){this._wfOnPasteWYSIWYGBody.detach(this.oApp.getWYSIWYGDocument().body,"paste"),this._loadAllBaseFont()},_onMouseupCover:function(e){e.stop(),this.welEditingAreaCover&&this.welEditingAreaCover.leave();var t=e.mouse(),i=this.oApp.getWYSIWYGDocument().body,n=jindo.$Element(i),o=this.oApp.getEmptySelection();if(o.selectNode(i),o.collapseToStart(),o.select(),n.fireEvent("mousedown",{left:t.left,middle:t.middle,right:t.right}),n.fireEvent("mouseup",{left:t.left,middle:t.middle,right:t.right}),this.oApp.oNavigator.ie&&document.documentMode<11&&"WYSIWYG"===this.oApp.getEditingMode())"

            "==this.oApp.getWYSIWYGDocument().body.innerHTML&&(this.oApp.getWYSIWYGDocument().body.innerHTML='

            ',(o=this.oApp.getSelection()).moveToStringBookmark("INIT"),o.select(),o.removeStringBookmark("INIT"));else if(this.oApp.oNavigator.ie&&11==this.oApp.oNavigator.nativeVersion&&11==document.documentMode&&"WYSIWYG"===this.oApp.getEditingMode()&&"


            "==this.oApp.getWYSIWYGDocument().body.innerHTML){var s=jindo.$$.getSingle("br",i);o.setStartBefore(s),o.setEndBefore(s),o.select()}},$ON_EVENT_TOOLBAR_MOUSEDOWN:function(){this.htBrowser.nativeVersion<9||document.documentMode<9||this.welEditingAreaCover&&this.welEditingAreaCover.leave()},_loadAllBaseFont:function(){var e,t;if(this.htBrowser.ie){if(this.htBrowser.nativeVersion<9)for(e=0,t=this.aBaseFontList.length;e").css("overflow","hidden"),this.canvasType=jindo.$(e).filters?"Filter":jindo.$("").getContext?"Canvas":null,!this.canvasType)return!1;for(var i in this.option({huePanel:null,huePanelType:"horizontal"}),this.option(t),this.option("huePanel")&&(this.huePanel=jindo.$Element(this.option("huePanel")).empty()),this._hsvColor=this._hsv(0,100,100),this)/^_on[A-Z][a-z]+[A-Z][a-z]+$/.test(i)&&(this[i+"Fn"]=jindo.$Fn(this[i],this));this._onDownColorFn.attach(this.elem,"mousedown"),this.huePanel&&this._onDownHueFn.attach(this.huePanel,"mousedown"),this.paint()},rgb:function(e){this.hsv(this._rgb2hsv(e.r,e.g,e.b))},hsv:function(e){if(void 0===e)return this._hsvColor;var t=null,i=this.elem.width(),n=this.elem.height(),o=this.cursor.width(),s=this.cursor.height(),r=0,a=0;if(this.huePanel)t=this._hsv2rgb(e.h,100,100),this.elem.css("background","#"+this._rgb2hex(t.r,t.g,t.b)),r=e.s/100*i,a=(100-e.v)/100*n;else{var l=i/2;r=e.v>e.s?(e.v=100,e.s/100*l):((e.s=100)-e.v)/100*l+l,a=e.h/360*n}r=Math.max(Math.min(r-1,i-o),1),a=Math.max(Math.min(a-1,n-s),1),this.cursor.css({left:r+"px",top:a+"px"}),this._hsvColor=e,t=this._hsv2rgb(e.h,e.s,e.v),this.fireEvent("colorchange",{type:"colorchange",element:this,currentElement:this,rgbColor:t,hexColor:"#"+this._rgb2hex(t.r,t.g,t.b),hsvColor:e})},paint:function(){this.huePanel?(this["_paintColWith"+this.canvasType](),this["_paintHueWith"+this.canvasType]()):this["_paintOneWith"+this.canvasType](),this.cursor.appendTo(this.elem),this.cursor.css({position:"absolute",top:"1px",left:"1px",background:"white",border:"1px solid black"}).width(3).height(3),this.hsv(this._hsvColor)},_paintColWithFilter:function(){jindo.$Element("
            ").css({position:"absolute",top:0,left:0,width:"100%",height:"100%",filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType=1,StartColorStr='#FFFFFFFF',EndColorStr='#00FFFFFF')"}).appendTo(this.elem),jindo.$Element("
            ").css({position:"absolute",top:0,left:0,width:"100%",height:"100%",filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#00000000',EndColorStr='#FF000000')"}).appendTo(this.elem)},_paintColWithCanvas:function(){var e=jindo.$Element("").css({width:"100%",height:"100%"});e.appendTo(this.elem.empty());var t=e.attr("width",e.width()).attr("height",e.height()).$value().getContext("2d"),i=null,n=e.width(),o=e.height();(i=t.createLinearGradient(0,0,n,0)).addColorStop(0,"rgba(255,255,255,1)"),i.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=i,t.fillRect(0,0,n,o),(i=t.createLinearGradient(0,0,0,o)).addColorStop(0,"rgba(0,0,0,0)"),i.addColorStop(1,"rgba(0,0,0,1)"),t.fillStyle=i,t.fillRect(0,0,n,o)},_paintOneWithFilter:function(){for(var e,t,i,n,o,s,r=this.elem.height(),a=1;a<7;a++)e=Math.floor((a-1)/6*r),t=Math.floor(a/6*r),i=this._hsv2rgb((a-1)/6*360,100,100),n=this._hsv2rgb(a/6*360,100,100),o="#FF"+this._rgb2hex(i.r,i.g,i.b),s="#FF"+this._rgb2hex(n.r,n.g,n.b),jindo.$Element("
            ").css({position:"absolute",left:0,width:"100%",top:e+"px",height:t-e+"px",filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='"+o+"',EndColorStr='"+s+"')"}).appendTo(this.elem);jindo.$Element("
            ").css({position:"absolute",top:0,left:0,width:"50%",height:"100%",filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType=1,StartColorStr='#FFFFFFFF',EndColorStr='#00FFFFFF')"}).appendTo(this.elem),jindo.$Element("
            ").css({position:"absolute",top:0,right:0,width:"50%",height:"100%",filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType=1,StartColorStr='#00000000',EndColorStr='#FF000000')"}).appendTo(this.elem)},_paintOneWithCanvas:function(){var e={r:0,g:0,b:0},t=jindo.$Element("").css({width:"100%",height:"100%"});t.appendTo(this.elem.empty());for(var i=t.attr("width",t.width()).attr("height",t.height()).$value().getContext("2d"),n=t.width(),o=t.height(),s=i.createLinearGradient(0,0,0,o),r=0;r<7;r++)e=this._hsv2rgb(r/6*360,100,100),s.addColorStop(r/6,"rgb("+e.join(",")+")");i.fillStyle=s,i.fillRect(0,0,n,o),(s=i.createLinearGradient(0,0,n,0)).addColorStop(0,"rgba(255,255,255,1)"),s.addColorStop(.5,"rgba(255,255,255,0)"),s.addColorStop(.5,"rgba(0,0,0,0)"),s.addColorStop(1,"rgba(0,0,0,1)"),i.fillStyle=s,i.fillRect(0,0,n,o)},_paintHueWithFilter:function(){var e,t,i,n,o,s,r="vertical"==this.option().huePanelType,a=this.huePanel.width(),l=this.huePanel.height(),h=null,d=parseInt(this.huePanel.css("borderWidth"),10);isNaN(d)&&(d=0),a-=2*d;for(var c=1;c<7;c++){e=Math.floor((c-1)/6*(r?l:a)),t=Math.floor(c/6*(r?l:a)),i=this._hsv2rgb((c-1)/6*360,100,100),n=this._hsv2rgb(c/6*360,100,100),o="#FF"+this._rgb2hex(i.r,i.g,i.b),s="#FF"+this._rgb2hex(n.r,n.g,n.b);var _=t-e+1;(h=jindo.$Element("
            ").css({position:"absolute",filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType="+(r?0:1)+",StartColorStr='"+o+"',EndColorStr='"+s+"')"})).appendTo(this.huePanel),h.css(r?"left":"top",0).css(r?"width":"height","100%"),h.css(r?"top":"left",e+"px").css(r?"height":"width",_+"px")}},_paintHueWithCanvas:function(){var e,t="vertical"==this.option().huePanelType,i=jindo.$Element("").css({width:"100%",height:"100%"});i.appendTo(this.huePanel.empty());for(var n=i.attr("width",i.width()).attr("height",i.height()).$value().getContext("2d"),o=n.createLinearGradient(0,0,t?0:i.width(),t?i.height():0),s=0;s<7;s++)e=this._hsv2rgb(s/6*360,100,100),o.addColorStop(s/6,"rgb("+e.join(",")+")");n.fillStyle=o,n.fillRect(0,0,i.width(),i.height())},_rgb2hsv:function(e,t,i){var n=0,o=0,s=Math.max(e,t,i),r=s-Math.min(e,t,i);return(o=s?r/s:0)&&(e==s?n=60*(t-i)/r:t==s?n=120+60*(i-e)/r:i==s&&(n=240+60*(e-t)/r),n<0&&(n+=360)),n=Math.floor(n),o=Math.floor(100*o),s=Math.floor(s/255*100),this._hsv(n,o,s)},_hsv2rgb:function(e,t,i){e=e%360/60,t/=100,i/=100;var n=0,o=0,s=0,r=Math.floor(e),a=e-r,l=i*(1-t),h=i*(1-t*a),d=i*(1-t*(1-a));switch(r){case 0:n=i,o=d,s=l;break;case 1:n=h,o=i,s=l;break;case 2:n=l,o=i,s=d;break;case 3:n=l,o=h,s=i;break;case 4:n=d,o=l,s=i;break;case 5:n=i,o=l,s=h}return n=Math.floor(255*n),o=Math.floor(255*o),s=Math.floor(255*s),this._rgb(n,o,s)},_rgb2hex:function(e,t,i){return 1==(e=e.toString(16)).length&&(e="0"+e),1==(t=t.toString(16)).length&&(t="0"+t),1==(i=i.toString(16)).length&&(i="0"+i),e+t+i},_hex2rgb:function(e){var t=e.match(/#?([0-9a-f]{6}|[0-9a-f]{3})/i);return t=3==t[1].length?t[1].match(/./g).filter(function(e){return e+e}):t[1].match(/../g),{r:Number("0x"+t[0]),g:Number("0x"+t[1]),b:Number("0x"+t[2])}},_rgb:function(e,t,i){var n=[e,t,i];return n.r=e,n.g=t,n.b=i,n},_hsv:function(e,t,i){var n=[e,t,i];return n.h=e,n.s=t,n.v=i,n},_onDownColor:function(e){if(!e.mouse().left)return!1;var t=e.pos();this._colPagePos=[t.pageX,t.pageY],this._colLayerPos=[t.layerX,t.layerY],this._onUpColorFn.attach(document,"mouseup"),this._onMoveColorFn.attach(document,"mousemove"),this._onMoveColor(e)},_onUpColor:function(){this._onUpColorFn.detach(document,"mouseup"),this._onMoveColorFn.detach(document,"mousemove")},_onMoveColor:function(e){var t=this._hsvColor,i=e.pos(),n=this._colLayerPos[0]+(i.pageX-this._colPagePos[0]),o=this._colLayerPos[1]+(i.pageY-this._colPagePos[1]),s=this.elem.width(),r=this.elem.height();if(n=Math.max(Math.min(n,s),0),o=Math.max(Math.min(o,r),0),this.huePanel)t.s=t[1]=n/s*100,t.v=t[2]=(r-o)/r*100;else{t.h=o/r*360;var a=s/2;n]*class=['"]?(se2_quote[0-9]+)['"]?[^>]*>/gi,"<$1 class=$2>")},this).bind()]),this.oApp.exec("ADD_CONVERTER",["IR_TO_DB",jindo.$Fn(function(e){var n=this.htQuoteStyles_view;return e=e.replace(/<(blockquote)[^>]*class=['"]?(se2_quote[0-9]+)['"]?[^>]*>/gi,function(e,t,i){return"<"+t+" class="+i+' style="'+n[i]+'">'})},this).bind()]),this.htSE1toSE2Map={"01":"1","02":"2","03":"6","04":"8","05":"9","07":"3","08":"5"}},$LOCAL_BEFORE_FIRST:function(){this._assignHTMLElements(),this.oApp.registerBrowserEvent(this.elDropdownLayer,"click","EVENT_SE2_BLOCKQUOTE_LAYER_CLICK",[]),this.oApp.delayedExec("SE2_ATTACH_HOVER_EVENTS",[this.aLI],0)},$ON_MSG_APP_READY:function(){this.oApp.exec("REGISTER_UI_EVENT",["quote","click","TOGGLE_BLOCKQUOTE_LAYER"]),this.oApp.registerLazyMessage(["TOGGLE_BLOCKQUOTE_LAYER"],["hp_SE2M_Quote$Lazy.js"])},$ON_EVENT_EDITING_AREA_KEYDOWN:function(e){var t,i;"WYSIWYG"===this.oApp.getEditingMode()&&8===e.key().keyCode&&((t=this.oApp.getSelection()).fixCommonAncestorContainer(),(i=this._findParentQuote(t.commonAncestorContainer))&&this._isBlankQuote(i)&&(e.stop(jindo.$Event.CANCEL_DEFAULT),t.selectNode(i),t.collapseToStart(),jindo.$Element(i).leave(),t.select()))},$ON_EVENT_EDITING_AREA_KEYUP:function(e){var t,i,n;if("WYSIWYG"===this.oApp.getEditingMode()&&46===e.key().keyCode){if((t=this.oApp.getSelection()).fixCommonAncestorContainer(),!(i=this._findParentQuote(t.commonAncestorContainer)))return!1;i.nextSibling||(e.stop(jindo.$Event.CANCEL_DEFAULT),(n=t._document.createElement("P")).innerHTML=" ",jindo.$Element(i).after(n),setTimeout(jindo.$Fn(function(e){var t=e.placeStringBookmark();e.select(),e.removeStringBookmark(t)},this).bind(t),0))}},_isBlankQuote:function(e){function t(e){return""===(e=e.replace(/[\r\n]/gi,"").replace(unescape("%uFEFF"),""))||(" "===e||" "===e)}var i,n,o,s,r,a,l=this.oApp.oNavigator.chrome,h=this.oApp.oNavigator.safari;if(t(e.innerHTML)||"
            "===e.innerHTML)return!0;if(l||h){var d,c=jindo.$$("TABLE",e),_=c.length;for(o=0;o<_;o++)d=c[o],r=d,0===jindo.$$("tr",r).length&&jindo.$Element(d).leave()}for(o=0,s=(n=e.childNodes).length;o"!==a.innerHTML))return!1;return!0},_findParentQuote:function(e){return this._findAncestor(jindo.$Fn(function(e){if(!e)return!1;if("BLOCKQUOTE"!==e.tagName)return!1;if(!e.className)return!1;var t=e.className;return!!this.htQuoteStyles_view[t]},this).bind(),e)},_findAncestor:function(e,t){for(;t&&!e(t);)t=t.parentNode;return t}})},function(e,t){nhn.husky.SE2M_TableCreator=jindo.$Class({name:"SE2M_TableCreator",_sSETblClass:"__se_tbl",nRows:3,nColumns:4,nBorderSize:1,sBorderColor:"#000000",sBGColor:"#000000",nBorderStyleIdx:3,nTableStyleIdx:1,nMinRows:1,nMaxRows:20,nMinColumns:1,nMaxColumns:20,nMinBorderWidth:1,nMaxBorderWidth:10,rxLastDigits:null,sReEditGuideMsg_table:null,oSelection:null,$ON_MSG_APP_READY:function(){this.sReEditGuideMsg_table=this.oApp.$MSG("SE2M_ReEditAction.reEditGuideMsg.table"),this.oApp.exec("REGISTER_UI_EVENT",["table","click","TOGGLE_TABLE_LAYER"]),this.oApp.registerLazyMessage(["TOGGLE_TABLE_LAYER"],["hp_SE2M_TableCreator$Lazy.js"])},$ON_REGISTER_CONVERTERS:function(){this.oApp.exec("ADD_CONVERTER_DOM",["IR_TO_DB",jindo.$Fn(this.irToDbDOM,this).bind()]),this.oApp.exec("ADD_CONVERTER_DOM",["DB_TO_IR",jindo.$Fn(this.dbToIrDOM,this).bind()])},irToDbDOM:function(e){var t=[],i=jindo.$$("table[class=__se_tbl]",e,{oneTimeOffCache:!0});if(jindo.$A(i).forEach(function(e){jindo.$Element(e).attr("attr_no_border_tbl")&&t.push(e)},this),!(t.length<1))for(var n,o=[],s=0,r=t.length;str>td",n),jindo.$A(o).forEach(function(e){jindo.$Element(e).css({border:"",borderTop:"",borderRight:""})})},dbToIrDOM:function(e){var t=[],i=jindo.$$("table[class=__se_tbl]",e,{oneTimeOffCache:!0});if(jindo.$A(i).forEach(function(e){jindo.$Element(e).attr("attr_no_border_tbl")&&t.push(e)},this),!(t.length<1))for(var n,o=[],s=0,r=t.length;str>td",n),jindo.$A(o).forEach(function(e){jindo.$Element(e).css({border:"1px dashed #c7c7c7",borderTop:0,borderRight:0})})}})},function(e,t){nhn.husky.SE2M_TableBlockStyler=jindo.$Class({name:"SE2M_TableBlockStyler",nSelectedTD:0,htSelectedTD:{},aTdRange:[],$init:function(){},$LOCAL_BEFORE_ALL:function(){return"WYSIWYG"==this.oApp.getEditingMode()},$ON_MSG_APP_READY:function(){this.oDocument=this.oApp.getWYSIWYGDocument()},$ON_EVENT_EDITING_AREA_MOUSEUP:function(){"WYSIWYG"==this.oApp.getEditingMode()&&this.setTdBlock()},$ON_IS_SELECTED_TD_BLOCK:function(e,t){return 0 

            ":i.firefox&&(e+="

            \ufeff

            "),r.selectNode(n),r.pasteHTML(e),s=r.getNodes()||[];for(var a=0;a",sDefaultXPath:"/HTML[0]/BODY[0]",$init:function(){this.aUndoHistory=[],this.oCurStateIdx={nIdx:0,nStep:0},this.nHardLimit=this.nMaxUndoCount+this.nAfterMaxDeleteBuffer},$LOCAL_BEFORE_ALL:function(e){if(e.match(/_DO_RECORD_UNDO_HISTORY_AT$/))return!0;try{if("WYSIWYG"!=this.oApp.getEditingMode())return!1}catch(t){return!1}return!0},$BEFORE_MSG_APP_READY:function(){this._historyLength=0,this.oApp.exec("ADD_APP_PROPERTY",["getUndoHistory",jindo.$Fn(this._getUndoHistory,this).bind()]),this.oApp.exec("ADD_APP_PROPERTY",["getUndoStateIdx",jindo.$Fn(this._getUndoStateIdx,this).bind()]),this.oApp.exec("ADD_APP_PROPERTY",["saveSnapShot",jindo.$Fn(this._saveSnapShot,this).bind()]),this.oApp.exec("ADD_APP_PROPERTY",["getLastKey",jindo.$Fn(this._getLastKey,this).bind()]),this.oApp.exec("ADD_APP_PROPERTY",["setLastKey",jindo.$Fn(this._setLastKey,this).bind()]),this._saveSnapShot(),this.oApp.exec("DO_RECORD_UNDO_HISTORY_AT",[this.oCurStateIdx,"","","",null,this.sDefaultXPath])},_getLastKey:function(){return this.sLastKey},_setLastKey:function(e){this.sLastKey=e},$ON_MSG_APP_READY:function(){var e=jindo.$Agent().navigator();this.bIE=e.ie,this.bFF=e.firefox,this.oApp.exec("REGISTER_UI_EVENT",["undo","click","UNDO"]),this.oApp.exec("REGISTER_UI_EVENT",["redo","click","REDO"]),jindo.$Agent().os().mac?(this.oApp.exec("REGISTER_HOTKEY",["meta+z","UNDO"]),this.oApp.exec("REGISTER_HOTKEY",["meta+y","REDO"])):(this.oApp.exec("REGISTER_HOTKEY",["ctrl+z","UNDO"]),this.oApp.exec("REGISTER_HOTKEY",["ctrl+y","REDO"]))},$ON_UNDO:function(){if(this._doRecordUndoHistory("UNDO",{nStep:0,bSkipIfEqual:!0,bMustBlockContainer:!0}),!(this.oCurStateIdx.nIdx<=0)){var e=this.aUndoHistory[this.oCurStateIdx.nIdx].oUndoCallback[this.oCurStateIdx.nStep],t=this.aUndoHistory[this.oCurStateIdx.nIdx].sParentXPath[this.oCurStateIdx.nStep];if(e&&this.oApp.exec(e.sMsg,e.aParams),0=this.aUndoHistory.length)){var e=this.aUndoHistory[this.oCurStateIdx.nIdx];if(!(this.oCurStateIdx.nIdx==this.aUndoHistory.length-1&&this.oCurStateIdx.nStep>=e.nTotalSteps-1)){this.oCurStateIdx.nStepthis.nHardLimit&&(this.aUndoHistory.splice(0,this.nAfterMaxDeleteBuffer),e.nIdx-=this.nAfterMaxDeleteBuffer),this.oCurStateIdx.nIdx=e.nIdx,this.oCurStateIdx.nStep=e.nStep},_saveSnapShot:function(){this.oSnapShot={oBookmark:this.oApp.getSelection().getXPathBookmark()}},_getTargetXPath:function(e,t){var i=this.sDefaultXPath,n=e[0].sXPath.split("/"),o=e[1].sXPath.split("/"),s=[],r=n.length]+)?",rxDateFormat:/^(?:\d{4}\.)?\d{1,2}\.\d{1,2}$/,_rxTable:/^(?:CAPTION|TBODY|THEAD|TFOOT|TR|TD|TH|COLGROUP|COL)$/i,_rxSpaceOnly:/^\s+$/,_rxFontStart:/]*)?>/i,_rxFontStrip:/<\/?font(?:\s+[^>]*)?>/gi,_bUnderIE8:jindo.$Agent().navigator().ie&&jindo.$Agent().navigator().version<9,_htFontSize:{1:"7pt",2:"10pt",3:"12pt",4:"13.5pt",5:"18pt",6:"24pt",7:"36pt"},isInvalidNodeInTable:function(e){if(e&&!this._rxTable.test(e.nodeName)){var t;if((t=e.previousSibling)&&this._rxTable.test(t.nodeName))return!0;if((t=e.nextSibling)&&this._rxTable.test(t.nodeName))return!0}return!1},removeInvalidNodeInTable:function(e){this.isInvalidNodeInTable(e)&&e.parentNode&&e.parentNode.removeChild(e)},removeInvalidFont:function(e){e&&(this._removeInvalidFontInTable(e),this._removeEmptyFont(e))},_removeInvalidFontInTable:function(e){for(var t,i=jindo.$$("table font",e),n=0;t=i[n];n++)this.removeInvalidNodeInTable(t)},_removeEmptyFont:function(e){for(var t,i=jindo.$$("font",e),n=0;t=i[n];n++)(t.innerHTML||"").replace(this._rxSpaceOnly,"")||t.parentNode.removeChild(t)},convertFontToSpan:function(e){if(e){for(var t,i,n,o=e.ownerDocument||document,s=jindo.$$("font",e),r=0;t=s[r];r++)("SPAN"!==(i=t.parentNode).tagName||1]*))","i").exec(e);if(!i)return"";var n=i[1]||i[2]||i[3];return n=n&&n.replace(/["]/g,"")},iframeAlignConverter:function(e,t){var i=e.tagName.toUpperCase();if("DIV"==i||"P"==i){if(null===e.parentNode)return;var n=t,o=jindo.$Element(e),s=o.html(),r=jindo.$Element(e).attr("align")||jindo.$Element(e).css("text-align"),a=jindo.$Element(jindo.$("
            ",n));a.html(s).attr("align",r),o.replace(a)}},getJsonDatafromXML:function(e){function g(e){return void 0===e?"":e.replace(/&[a-z]+;/g,function(e){return"string"==typeof i[e]?i[e]:e})}function f(e){for(var t in e)if(Object.prototype.hasOwnProperty.call(e,t)){if(Object.prototype[t])continue;return!1}return!0}var t={},A=/^[0-9]+(?:\.[0-9]+)?$/,S=/^\s+$/g,i={"&":"&"," ":" ",""":'"',"<":"<",">":">"},T={tags:["/"],stack:[t]};return(e=e.replace(/<(\?|!-)[^>]*>/g,"")).replace(/\s*<(\/?[\w:-]+)((?:\s+[\w:-]+\s*=\s*(?:"(?:\\"|[^"])*"|'(?:\\'|[^'])*'))*)\s*((?:\/>)|(?:><\/\1>|\s*))|\s*\s*|\s*>?([^<]*)/gi,function(e,t,i,n,o,s){var r,a="",l=T.stack.length-1;if("string"==typeof t&&t)if("/"!=t.substr(0,1)){var h="string"==typeof i&&i,d="string"==typeof n&&n,c=!h&&d?"":{};if("undefined"==typeof(r=T.stack[l])[t])r[t]=c,r=T.stack[1+l]=r[t];else if(r[t]instanceof Array){var _=r[t].length;r[t][_]=c,r=T.stack[1+l]=r[t][_]}else r[t]=[r[t],c],r=T.stack[1+l]=r[t][1];h&&function(e,o){e.replace(/([\w:-]+)\s*=\s*(?:"((?:\\"|[^"])*)"|'((?:\\'|[^'])*)')/g,function(e,t,i,n){o[t]=g((i?i.replace(/\\"/g,'"'):undefined)||(n?n.replace(/\\'/g,"'"):undefined))})}(i,r),T.tags[1+l]=t,d&&(T.tags.length--,T.stack.length--)}else T.tags.length--,T.stack.length--;else"string"==typeof o&&o?a=o:"string"==typeof s&&s.replace(S,"")&&(a=g(s));if(0/g,">"):""},restoreSpecialChar:function(e){return"string"==typeof e?e.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&"):""}},nhn.husky.AutoResizer=jindo.$Class({welHiddenDiv:null,welCloneDiv:null,elContainer:null,$init:function(e,t){var i=["lineHeight","textDecoration","letterSpacing","fontSize","fontFamily","fontStyle","fontWeight","textTransform","textAlign","direction","wordSpacing","fontSizeAdjust","paddingTop","paddingLeft","paddingBottom","paddingRight","width"],n=i.length,o={position:"absolute",top:-9999,left:-9999,opacity:0,overflow:"hidden",wordWrap:"break-word"};for(this.nMinHeight=t.nMinHeight,this.wfnCallback=t.wfnCallback,this.elContainer=e.parentNode,this.welTextArea=jindo.$Element(e),this.welHiddenDiv=jindo.$Element("
            "),this.wfnResize=jindo.$Fn(this._resize,this),this.sOverflow=this.welTextArea.css("overflow"),this.welTextArea.css("overflow","hidden");n--;)o[i[n]]=this.welTextArea.css(i[n]);this.welHiddenDiv.css(o),this.nLastHeight=this.welTextArea.height()},bind:function(){this.welCloneDiv=jindo.$Element(this.welHiddenDiv.$value().cloneNode(!1)),this.wfnResize.attach(this.welTextArea,"keyup"),this.welCloneDiv.appendTo(this.elContainer),this._resize()},unbind:function(){this.wfnResize.detach(this.welTextArea,"keyup"),this.welTextArea.css("overflow",this.sOverflow),this.welCloneDiv&&this.welCloneDiv.leave()},_resize:function(){var e,t=this.welTextArea.$value().value,i=!1;t!==this.sContents&&(this.sContents=t.replace(/&/g,"&").replace(//g,">").replace(/ /g," ").replace(/\n/g,"
            "),this.sContents+="
            ",this.welCloneDiv.html(this.sContents),(e=this.welCloneDiv.height()) .bx",this.elDropdownLayer),this.oFindInputSet=jindo.$$.getSingle(".husky_se2m_find_ui",this.elDropdownLayer),this.oReplaceInputSet=jindo.$$.getSingle(".husky_se2m_replace_ui",this.elDropdownLayer),this.elTitle=jindo.$$.getSingle("H3",this.elDropdownLayer),this.oFindInput_Keyword=jindo.$$.getSingle("INPUT",this.oFindInputSet),t=jindo.$$("INPUT",this.oReplaceInputSet),this.oReplaceInput_Original=t[0],this.oReplaceInput_Replacement=t[1],this.oFindNextButton=jindo.$$.getSingle("BUTTON.husky_se2m_find_next",this.elDropdownLayer),this.oReplaceFindNextButton=jindo.$$.getSingle("BUTTON.husky_se2m_replace_find_next",this.elDropdownLayer),this.oReplaceButton=jindo.$$.getSingle("BUTTON.husky_se2m_replace",this.elDropdownLayer),this.oReplaceAllButton=jindo.$$.getSingle("BUTTON.husky_se2m_replace_all",this.elDropdownLayer),this.aCloseButtons=jindo.$$("BUTTON.husky_se2m_cancel",this.elDropdownLayer)},$LOCAL_BEFORE_FIRST:function(){this._assignHTMLElements(),this.oFindReplace=new nhn.FindReplace(this.oEditingWindow);for(var e=0;e=this.nMaxLevel))return n;t=t.nextSibling}return n};return o(e)>=this.nMaxLevel},_unwrapBlock:function(e){for(var t=this.oApp.getSelection(),i=t.commonAncestorContainer;i&&i.tagName!=e;)i=i.parentNode;if(i){this.oApp.exec("RECORD_UNDO_BEFORE_ACTION",["CANCEL BLOCK QUOTE",{sSaveTarget:"BODY"}]);var n=t.commonAncestorContainer;if(3!==n.nodeType){var o=t.getTextNodes()||"",s=o.length-1;n=-1LI",t)},$LOCAL_BEFORE_FIRST:function(){this.bIE=jindo.$Agent().navigator().ie,this._assignHTMLObjects(this.oApp.htOptions.elAppContainer),this.charSet=[],this.charSet[0]=unescape("FF5B FF5D 3014 3015 3008 3009 300A 300B 300C 300D 300E 300F 3010 3011 2018 2019 201C 201D 3001 3002 %B7 2025 2026 %A7 203B 2606 2605 25CB 25CF 25CE 25C7 25C6 25A1 25A0 25B3 25B2 25BD 25BC 25C1 25C0 25B7 25B6 2664 2660 2661 2665 2667 2663 2299 25C8 25A3 25D0 25D1 2592 25A4 25A5 25A8 25A7 25A6 25A9 %B1 %D7 %F7 2260 2264 2265 221E 2234 %B0 2032 2033 2220 22A5 2312 2202 2261 2252 226A 226B 221A 223D 221D 2235 222B 222C 2208 220B 2286 2287 2282 2283 222A 2229 2227 2228 FFE2 21D2 21D4 2200 2203 %B4 FF5E 02C7 02D8 02DD 02DA 02D9 %B8 02DB %A1 %BF 02D0 222E 2211 220F 266D 2669 266A 266C 327F 2192 2190 2191 2193 2194 2195 2197 2199 2196 2198 321C 2116 33C7 2122 33C2 33D8 2121 2668 260F 260E 261C 261E %B6 2020 2021 %AE %AA %BA 2642 2640").replace(/(\S{4})/g,function(e){return"%u"+e}).split(" "),this.charSet[1]=unescape("%BD 2153 2154 %BC %BE 215B 215C 215D 215E %B9 %B2 %B3 2074 207F 2081 2082 2083 2084 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 FFE6 %24 FFE5 FFE1 20AC 2103 212B 2109 FFE0 %A4 2030 3395 3396 3397 2113 3398 33C4 33A3 33A4 33A5 33A6 3399 339A 339B 339C 339D 339E 339F 33A0 33A1 33A2 33CA 338D 338E 338F 33CF 3388 3389 33C8 33A7 33A8 33B0 33B1 33B2 33B3 33B4 33B5 33B6 33B7 33B8 33B9 3380 3381 3382 3383 3384 33BA 33BB 33BC 33BD 33BE 33BF 3390 3391 3392 3393 3394 2126 33C0 33C1 338A 338B 338C 33D6 33C5 33AD 33AE 33AF 33DB 33A9 33AA 33AB 33AC 33DD 33D0 33D3 33C3 33C9 33DC 33C6").replace(/(\S{4})/g,function(e){return"%u"+e}).split(" "),this.charSet[2]=unescape("3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 326A 326B 326C 326D 326E 326F 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 327A 327B 24D0 24D1 24D2 24D3 24D4 24D5 24D6 24D7 24D8 24D9 24DA 24DB 24DC 24DD 24DE 24DF 24E0 24E1 24E2 24E3 24E4 24E5 24E6 24E7 24E8 24E9 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 246A 246B 246C 246D 246E 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 320A 320B 320C 320D 320E 320F 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 321A 321B 249C 249D 249E 249F 24A0 24A1 24A2 24A3 24A4 24A5 24A6 24A7 24A8 24A9 24AA 24AB 24AC 24AD 24AE 24AF 24B0 24B1 24B2 24B3 24B4 24B5 2474 2475 2476 2477 2478 2479 247A 247B 247C 247D 247E 247F 2480 2481 2482").replace(/(\S{4})/g,function(e){return"%u"+e}).split(" "),this.charSet[3]=unescape("3131 3132 3133 3134 3135 3136 3137 3138 3139 313A 313B 313C 313D 313E 313F 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 314A 314B 314C 314D 314E 314F 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 315A 315B 315C 315D 315E 315F 3160 3161 3162 3163 3165 3166 3167 3168 3169 316A 316B 316C 316D 316E 316F 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 317A 317B 317C 317D 317E 317F 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 318A 318B 318C 318D 318E").replace(/(\S{4})/g,function(e){return"%u"+e}).split(" "),this.charSet[4]=unescape("0391 0392 0393 0394 0395 0396 0397 0398 0399 039A 039B 039C 039D 039E 039F 03A0 03A1 03A3 03A4 03A5 03A6 03A7 03A8 03A9 03B1 03B2 03B3 03B4 03B5 03B6 03B7 03B8 03B9 03BA 03BB 03BC 03BD 03BE 03BF 03C0 03C1 03C3 03C4 03C5 03C6 03C7 03C8 03C9 %C6 %D0 0126 0132 013F 0141 %D8 0152 %DE 0166 014A %E6 0111 %F0 0127 I 0133 0138 0140 0142 0142 0153 %DF %FE 0167 014B 0149 0411 0413 0414 0401 0416 0417 0418 0419 041B 041F 0426 0427 0428 0429 042A 042B 042C 042D 042E 042F 0431 0432 0433 0434 0451 0436 0437 0438 0439 043B 043F 0444 0446 0447 0448 0449 044A 044B 044C 044D 044E 044F").replace(/(\S{4})/g,function(e){return"%u"+e}).split(" "),this.charSet[5]=unescape("3041 3042 3043 3044 3045 3046 3047 3048 3049 304A 304B 304C 304D 304E 304F 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 305A 305B 305C 305D 305E 305F 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 306A 306B 306C 306D 306E 306F 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 307A 307B 307C 307D 307E 307F 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 308A 308B 308C 308D 308E 308F 3090 3091 3092 3093 30A1 30A2 30A3 30A4 30A5 30A6 30A7 30A8 30A9 30AA 30AB 30AC 30AD 30AE 30AF 30B0 30B1 30B2 30B3 30B4 30B5 30B6 30B7 30B8 30B9 30BA 30BB 30BC 30BD 30BE 30BF 30C0 30C1 30C2 30C3 30C4 30C5 30C6 30C7 30C8 30C9 30CA 30CB 30CC 30CD 30CE 30CF 30D0 30D1 30D2 30D3 30D4 30D5 30D6 30D7 30D8 30D9 30DA 30DB 30DC 30DD 30DE 30DF 30E0 30E1 30E2 30E3 30E4 30E5 30E6 30E7 30E8 30E9 30EA 30EB 30EC 30ED 30EE 30EF 30F0 30F1 30F2 30F3 30F4 30F5 30F6").replace(/(\S{4})/g,function(e){return"%u"+e}).split(" ");var e=jindo.$Fn(this.oApp.exec,this.oApp).bind("INSERT_SCHARACTERS",[this.oTextField.value]);jindo.$Fn(e,this).attach(this.oInsertButton,"click"),this.oApp.exec("SET_SCHARACTER_LIST",[this.charSet]);for(var t=0;t"),this.bIE?(t=jindo.$("