URL 인코딩시 함수나 프로그래밍 언어에 따라 공백을 %20 또는 + 로 변경할 수 있는데,
사실 URI 스펙 상으로 + 는 reserved word 이고 공백은 %20 이다.
https://tools.ietf.org/html/rfc3986#section-2.2
javascript encodeURI()/encodeURIComponent() URL 인코딩에서도
공백은 %20 으로 처리한다.
테스트 코드
https://github.com/ysoftman/test_code/blob/develop/js/encoding.html
libapreq2(apr_util.h) apreq_escape() 로 URL 인코딩을 하면 공백을 + 로 처리하기 때문에 별도로 + 를 %20 으로 변경하는 작업이 필요하다.
테스트 코드
https://github.com/ysoftman/test_code/blob/develop/apr_test/apr_test.cpp
access log - get null 400 에러
# tomcat 에러 중 다음과 같이 path 부분이 null 이 찍히는 경우가 있다.
# 참고로 로그는 apache httpd mod_log_config 를 사용한다.
# https://httpd.apache.org/docs/2.4/ko/mod/mod_log_config.html
# /var/lib/tomcat8/conf/server.xml 에서 로그 포맷 설정
# %{Foobar}i - Foobar 헤더
# %h - 원격 호스트
# %l - 원격 identid가 제공한 로그인명, 기본값(-)
# %u - 원격 auth가 제공한 사용자명, 기본값(-)
# %t - 표준 영어 시간
# %r - 요청 첫번째 줄
# %s - 상태코드
# %b - http 헤더를 제외한 전송 바이트 수
# %h %l %u %t "%r" %s %b 포맷
# tomcat access log 확인
sudo tail -f /var/log/tomcat8/localhost_access_log.2019-01-31.txt
# 브라우저에서 '아이유' 요청하면 URL 인코딩 되고 다음과 같이 정상 동작(로깅)
127.0.0.1 - - [31/Jan/2019:18:15:30 +0900] "GET /%EC%95%84%EC%9D%B4%EC%9C%A0 HTTP/1.1" 404 1110
# curl 로 다음처럼 한글이 URL인코딩 없이 요청하는 경우 null 로 되고
# tomcat server.xml 의 protocol 기본 설정이 HTTP/1.1 로 돼있어
# HTTP/1.0 을 사용해도 로그에 HTTP/1.1 로 기록된다.
curl "http://localhost:8080/아이유" --http1.0 -s > /dev/null
# path 가 null 로 되어 처리할 수 없게 된다.
127.0.0.1 - - [31/Jan/2019:18:15:30 +0900] "GET null HTTP/1.1" 400 800
# tomcat 에러 로그를 확인을 위해 모든 로그를 확인해보자.
sudo vi /var/lib/tomcat8/conf/logging.properties
java.util.logging.ConsoleHandler.level = ALL
# tomcat 재시작
sudo service tomcat8 restart
# 에러 로그를 확인해보면
sudo tail -f /var/log/tomcat8/catalina.out
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
# 관련 내용을 구글링 해보니 tomcat 7.0.73, 8.0.39, 8.5.7 이상에서 발생하고
# http connector 에 relaxedQueryChars 를 설정하라고 한다.
# https://stackoverflow.com/questions/41053653/tomcat-8-is-not-able-to-handle-get-request-with-in-query-parameters
# tomcat 버전 확인하면 8.5.30.0 이다.
sudo bash /usr/share/tomcat8/bin/version.sh
# 다음과 같이 특수문자를 처리해봤지만 한글 utf8코드는 처리 되지 않았다.
sudo vi /var/lib/tomcat8/conf/server.xml
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" relaxedQueryChars="[]|{}^\`"<>" />
# relaxedQueryChars 특수문자는 명시할 수 있지만 non-alphabet 범위의 문자코드는 어떻게 명시할 방법이 없어, client 가 URL 인코딩을 해줘야 한다.
# 참고로 로그는 apache httpd mod_log_config 를 사용한다.
# https://httpd.apache.org/docs/2.4/ko/mod/mod_log_config.html
# /var/lib/tomcat8/conf/server.xml 에서 로그 포맷 설정
# %{Foobar}i - Foobar 헤더
# %h - 원격 호스트
# %l - 원격 identid가 제공한 로그인명, 기본값(-)
# %u - 원격 auth가 제공한 사용자명, 기본값(-)
# %t - 표준 영어 시간
# %r - 요청 첫번째 줄
# %s - 상태코드
# %b - http 헤더를 제외한 전송 바이트 수
# %h %l %u %t "%r" %s %b 포맷
# tomcat access log 확인
sudo tail -f /var/log/tomcat8/localhost_access_log.2019-01-31.txt
# 브라우저에서 '아이유' 요청하면 URL 인코딩 되고 다음과 같이 정상 동작(로깅)
127.0.0.1 - - [31/Jan/2019:18:15:30 +0900] "GET /%EC%95%84%EC%9D%B4%EC%9C%A0 HTTP/1.1" 404 1110
# curl 로 다음처럼 한글이 URL인코딩 없이 요청하는 경우 null 로 되고
# tomcat server.xml 의 protocol 기본 설정이 HTTP/1.1 로 돼있어
# HTTP/1.0 을 사용해도 로그에 HTTP/1.1 로 기록된다.
curl "http://localhost:8080/아이유" --http1.0 -s > /dev/null
# path 가 null 로 되어 처리할 수 없게 된다.
127.0.0.1 - - [31/Jan/2019:18:15:30 +0900] "GET null HTTP/1.1" 400 800
# tomcat 에러 로그를 확인을 위해 모든 로그를 확인해보자.
sudo vi /var/lib/tomcat8/conf/logging.properties
java.util.logging.ConsoleHandler.level = ALL
# tomcat 재시작
sudo service tomcat8 restart
# 에러 로그를 확인해보면
sudo tail -f /var/log/tomcat8/catalina.out
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
# 관련 내용을 구글링 해보니 tomcat 7.0.73, 8.0.39, 8.5.7 이상에서 발생하고
# http connector 에 relaxedQueryChars 를 설정하라고 한다.
# https://stackoverflow.com/questions/41053653/tomcat-8-is-not-able-to-handle-get-request-with-in-query-parameters
# tomcat 버전 확인하면 8.5.30.0 이다.
sudo bash /usr/share/tomcat8/bin/version.sh
# 다음과 같이 특수문자를 처리해봤지만 한글 utf8코드는 처리 되지 않았다.
sudo vi /var/lib/tomcat8/conf/server.xml
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" relaxedQueryChars="[]|{}^\`"<>" />
# relaxedQueryChars 특수문자는 명시할 수 있지만 non-alphabet 범위의 문자코드는 어떻게 명시할 방법이 없어, client 가 URL 인코딩을 해줘야 한다.
Linux Oracle 11g 설치시 한글깨짐 현상 해결 방법
Oracle 11g 설치시 ./runinstaller 를 실행시켰을때 글자자 네모상자로 깨져 나올 경우
export LANG=C
export LC_ALL=C
를 실행후
./runinstaller
export LANG=C
export LC_ALL=C
를 실행후
./runinstaller
Eclipse 로 생성한 ant build.xml 인코딩 설정하기
Eclipse 에서는 기본적으로 Java 프로젝트를 ant 빌드파일(build.xml)을 export 하여 생성할 수 있다.
하지만 생성된 build.xml 에는 컴파일시 인코딩 옵션이 빠져있다.
.java 파일이 utf-8 로 인코딩 된경우, build.xml 로 ant 를 실행하면 "unmappable character for encoding MS949... " 과 같이 컴파일시 인코딩 에러가 발생할 수 있다.
[해결방법]
build.xml 에서 아래와 같이 javac 속성에 encoding 을 추가한다.
... 생략
<javac encoding="utf-8" debug="true" debuglevel="${debuglevel}" destdir="bin" source="${source}" target="${target}">
... 생략
하지만 생성된 build.xml 에는 컴파일시 인코딩 옵션이 빠져있다.
.java 파일이 utf-8 로 인코딩 된경우, build.xml 로 ant 를 실행하면 "unmappable character for encoding MS949... " 과 같이 컴파일시 인코딩 에러가 발생할 수 있다.
[해결방법]
build.xml 에서 아래와 같이 javac 속성에 encoding 을 추가한다.
... 생략
<javac encoding="utf-8" debug="true" debuglevel="${debuglevel}" destdir="bin" source="${source}" target="${target}">
... 생략
Java Tomcat Servlet 인코딩 설정
1. 톰캣 서버 환경파일 server.xml 의 Connector 태그 속성에 URIEncoding 을 추가한다.
톰캣홈/conf/server.xml 에서
<Connector port="8080" .... URIEncoding="EUC-KR">
2. 서블릿 소스(.java)에서 setCharacterEncoding() 을 사용한다.
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
request.setCharacterEncoding("EUC-KR");
response.setCharacterEncoding("EUC-KR");
}
톰캣홈/conf/server.xml 에서
<Connector port="8080" .... URIEncoding="EUC-KR">
2. 서블릿 소스(.java)에서 setCharacterEncoding() 을 사용한다.
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
request.setCharacterEncoding("EUC-KR");
response.setCharacterEncoding("EUC-KR");
}
Unity3D Standalone 환경에서의 ArgumentException: Encoding name 'euc-kr' not supported 오류 해결방법
[문제]
Unity 에서 C# System.Text.Encoding.GetEncoding("euc-kr") 으로 한글 인코딩을 사용하였을 경우
Unity Editor 상에서 플레이하면 잘 작동하지만 Emulator 나 Device 의 standalone 환경에서는
다음과 같은 오류가 발생한다.(Eclipse Logcat 으로 확인)
INFO/Unity(499): ArgumentException: Encoding name 'euc-kr' not supported
[해결방법]
C:\Program Files (x86)\Unity\Editor\Data\Mono\lib\mono\2.0\I18N.CJK.dll
을 프로젝트에 복사해 포함시키면 standalone 환경에서도 정상 작동한다.
한글이외의 문자셋을 사용한다면 I81N.west.dll I18N.rare.dll 등을 사용하면 된다.
Unity 에서 C# System.Text.Encoding.GetEncoding("euc-kr") 으로 한글 인코딩을 사용하였을 경우
Unity Editor 상에서 플레이하면 잘 작동하지만 Emulator 나 Device 의 standalone 환경에서는
다음과 같은 오류가 발생한다.(Eclipse Logcat 으로 확인)
INFO/Unity(499): ArgumentException: Encoding name 'euc-kr' not supported
[해결방법]
C:\Program Files (x86)\Unity\Editor\Data\Mono\lib\mono\2.0\I18N.CJK.dll
을 프로젝트에 복사해 포함시키면 standalone 환경에서도 정상 작동한다.
한글이외의 문자셋을 사용한다면 I81N.west.dll I18N.rare.dll 등을 사용하면 된다.
C/C++ MultiByte 문자를 Wide 문자로 바꾸기
// 20100607 ysoftman
// MultiByteToWideChar() 나 WideCharToMultiByte() 는 코드페이지 값을 파라미터러 받지만
// mbstowcs() 나 wcstombs() 코드페이지를 파라미터를 전달 할 수 없어 setlocale 로 미리 코드페이지를 설정해야한다.
// 윈도우에서 wchar_t 2바이트
// 리눅스에서 wchar_t 4바이트
// utf-8은 한문자가 1(8bit)~4(32bit)바이트의 크기를 가질 수 있다.
// 이런 가변길이에 대응하기 위해서는 리눅스의 wchar_t 를 사용한다.
// 한국,일본,한자 는 utf-8에서 3byte를 차지하여 리눅스에서만 변환된다.
// 따라서 ko_KR.UTF-8 나 ja_JP.UTF-8 로 로케일을 지정한다
if (bUTF8_Encoding == true)
{
//setlocale(LC_ALL, "ja_JP.UTF-8");
setlocale(LC_ALL, "ko_KR.UTF-8");
fprintf(stderr, "Type : UTF-8 encoding\n");
}
else
{
//setlocale(LC_ALL, "ko_KR.EUC-KR");
//setlocale(LC_ALL, "korean");
setlocale(LC_ALL, ""); //현재 PC에 설정된 지역으로 사용
}
// 20100607 ysoftman
// multibyte 단위의 문자열를 mbstowcs() 를 사용해 wide 단위 문자열로 바꾼다.
//readChars = mbsrtowcs(m_pXArr, &cpRecog, mX, NULL);
readChars = mbstowcs(m_pXArr, cpRecog, mX);
mX = readChars;
fprintf(stderr, "Input length = %d\n", readChars);
// MultiByteToWideChar() 나 WideCharToMultiByte() 는 코드페이지 값을 파라미터러 받지만
// mbstowcs() 나 wcstombs() 코드페이지를 파라미터를 전달 할 수 없어 setlocale 로 미리 코드페이지를 설정해야한다.
// 윈도우에서 wchar_t 2바이트
// 리눅스에서 wchar_t 4바이트
// utf-8은 한문자가 1(8bit)~4(32bit)바이트의 크기를 가질 수 있다.
// 이런 가변길이에 대응하기 위해서는 리눅스의 wchar_t 를 사용한다.
// 한국,일본,한자 는 utf-8에서 3byte를 차지하여 리눅스에서만 변환된다.
// 따라서 ko_KR.UTF-8 나 ja_JP.UTF-8 로 로케일을 지정한다
if (bUTF8_Encoding == true)
{
//setlocale(LC_ALL, "ja_JP.UTF-8");
setlocale(LC_ALL, "ko_KR.UTF-8");
fprintf(stderr, "Type : UTF-8 encoding\n");
}
else
{
//setlocale(LC_ALL, "ko_KR.EUC-KR");
//setlocale(LC_ALL, "korean");
setlocale(LC_ALL, ""); //현재 PC에 설정된 지역으로 사용
}
// 20100607 ysoftman
// multibyte 단위의 문자열를 mbstowcs() 를 사용해 wide 단위 문자열로 바꾼다.
//readChars = mbsrtowcs(m_pXArr, &cpRecog, mX, NULL);
readChars = mbstowcs(m_pXArr, cpRecog, mX);
mX = readChars;
fprintf(stderr, "Input length = %d\n", readChars);