뭘 이런걸..

Posted
Filed under Tech/프로그래밍
한 2달은 지난일이지만, 공유하는 것도 괜찮을 듯 해서 작성합니다.

회사에서 Game 의 version.ini 다운로드시에 cache 의 문제로 웹서버에서 강제로 NoCache header 를 출력하도록 한 적이 있습니다.

setenv.add-response-header = ( "Expires" => "Thu, 01 Jan 1970 00:00:00 GMT", "Cache-Control" => "no-store, no-cache, must-revalidate, post-check=0, pre-check=0", "Pragma" => "no-cache" )


위와 같이 lighttpd 에서 설정을 한 후에, test 까지 마치고 귀가를 했었는데, 새벽에 난리가 나고 말았습니다. 새벽부터 전화가 불같이 오더군요. 직감적으로 어제 설정한 no-cache 가 문제가 된것 같아서 일단, 설정을 rollback 하고나니 역시나 문제가 해결이 되었습니다.

황당한 에러메시지

문제 해결후, 출근을 해서 장애 리포트도 작성할 겸 도대체 왜 문제가 되었는지 검증을 하던 중, 황당함에 어쩔 수 없는 사실을 발견하게 됩니다. IE 또는 WinInet API 로 다운로드를 받을 경우, ini 확장자가 no-cache header 를 받을 경우 WinInet API 차원에서 좌측과 같은 에러 메세지를 출력을 하는 겁니다.

다른 browser 에서는 모두 정상적으로 받아지는데 왜 IE 에서만 이런 문제가 발생할까 고민을 하고 검색을 하다가, 로그를 봐도 200 코드 반환을 했고, 믿을 수가 없어서 packet dump 를 떠 보았는데, 서버측에서도 정상적으로 파일 내용을 보내고 있었고, 심지어는 client 에서도 파일을 받았음에도 불구하고 IE (WinInet API) 만 유독 이런 처리를 하는 것으로 보아서, WinInet 자체적으로 이런 짓거리를 한다고 밖에 단정할 수 없겠더군요. --; 그래서 설정 값을 하나씩 제거하면서 테스트를 해 본바, no-cache 값이 들어갈 경우에만 발생을 하고 있었습니다.

MSDN 의 WinInet 의 Cache 관련 문서를 찾아봐도 이런 언급은 없었는데, 검색을 하다가 http://support.microsoft.com/kb/323308 문서를 발견하게 됩니다. 물론 상관은 없지만 HTTPS protocol 에서의 WinInet API 의 이상 작동에 관한 기술 문서더군요. 순간.. 버그가 또 있었구나.. 하는 암울한 생각만.. T.T 결국에는 장애 리포트만 쓰고선, 다음 부터는 꼭 IE 에서 테스트 하자는 결의만 다지고 허탈함을 달랠길이 없더군요.

혹시라도, Game 관련 회사의 Download Server 를 운영하신다면, Cache-Control header 에 no-cache 를 출력해서 저같은 경우를 당하지 말기를 바라면서 포스팅을 해 봅니다.
2006/12/18 00:45 2006/12/18 00:45
김정균

흠.. 간만에 이 이슈로 google 신께 질문하다가.. 얻은 답..

Expires: 0

으로 하면 IE 에서 됩니다. _--;

Posted
Filed under Tech/프로그래밍
http://css-validator.kldp.org 를 접속해 보셨던 분들은 아시겠지만, 일주일 전 부터 design 과 결과가 달라진 것을 아실 수 있을 겁니다. 현재 KLDP CSS validator 는 http://jigsaw.w3.org/css-validator/ 보다 훨씬 새 버전으로 많은 변경 사항이 있습니다. (물로 보이는 것은 외부적인 변화가 더 크지만..)

이번 update 에서는 완전 한글화에 중점을 두었으며, 이전에 처리를 하지 못하던 부분을 완료하였습니다. 일단, 내부적인 메세지 번역은 이전 버전에 해 두었지만 각종 문서들의 번역은 이루어지지 않았는데, 이전의 일본어 번역 페이지뿐 아니라 이번에는 중국어 번역페이지가 추가된 것에 자극을 받아, 한국어 번역 페이지까지 모두 작성하게 되었습니다.

또한,
"유효한 CSS 정보"
에서 css 에 한글이 들어가 있을 경우 (예를 들어 폰트 이름.. 등) 한글이 깨져서 나오는 문제를 해결을 했습니다. css-validator 가 내부적으로 UTF8 로 처리를 하는데, 이 경우 multi-byte 환경을 고려하지 않는 문제점이 있더군요. 대략적으로 문서가...

1. EUC-KR일 경우
  1. EUC-KR -> ISO-8859-1
  2. ISO-8859-1 -> UTF-8
2. UTF8 문서일 경우
  1. EUC-KR -> ISO-8859-1


와 같이 변환하여 print 를 하는 문제가 있습니다. 제가 java 를 모르는 관계로, 몇가지 patch 를 한것 외에는 이것까지 하려니 너무 막막해서, php wrapper 를 이용하여

function iconv_callback ($m) { global $u; $c = iconv ("utf8", "iso-8859-1", $m[3]); if ( ! $u->is_utf8 ($c) ) $c = iconv ("euc-kr", "utf-8", $c); return $m[1] . $c; }


꽁수를 사용하여 KLDP CSS Validator 에서는 정상적으로 나오도록 처리하고 있습니다.

마지막으로 중요한 것은... 이 메세지 번역과 기타 한글 관련 패치, 그리고 multi-byte 환경에서의 오작동 부분을 reporting 을 하는 것이 맞으려나.. 메일링 리스트 가입을 하지 않으면 투고할 곳이 없고, 그렇다고 메일링 리스트를 가입하여, 그 메일들을 받고 싶은 생각도 없고, 또.. 영어도 못하는 관계로.. 결국에는 main stream 으로의 진입은.. 또 다시 좌절 입니다. ^^;

다만, 한국어 버전으로 설치를 하고 싶으신 분은..

http://css-validator.kldp.org/howto/

를 참고 하시면, 제가 CSS Validator 를 설치하기 위한 닥질의 내용이 적혀 있습니다. 이번 업데이트된 버전은 예전 버전과 달리 문서가 많이 없데이트 되었고, 공식적인 설치 문서는

http://css-validator.kldp.org/DOWNLOAD.html

를 참고 하시면 됩니다. 다만, 전자가 좀더 자세할 겁니다. :-)
2006/09/29 17:21 2006/09/29 17:21

http://jigsaw.w3.org/css-validator 가 드디어 업데이트 되었습니다. 그동안 http://css-validator.kldp.org 가 개발 버전으로 운영되어 오다 보니 디자인이 달라서 이거 뭐에요 하는 질문을 많이 받았었는데, 이제 디자인도 동일해진 관계로 이런 질문은 더이상 오지 않을 듯 싶군요. 한국어 버전을 사용하면 좋은 점은 일단 한글 폰트가 들어가 있을 때 에러가 발생하지 않는 다는 점과 속도가 빠르다는 점이죠. 아..

Posted
Filed under Tech/프로그래밍
얼마전 올렸던 usermap patch 의 버그 수정입니다. 이전 패치에서 usermap 파일이 없을 경우 에러가 발생하는 문제가 있었습니다. 파일이 없으면 CVS_FOPEN 이 에러가 발생할 것이라는 엄청난 착각을 한 결과이네요. 이런저런 경우의 수를 다해서 테스트를 했다고 생각했는데..

diff -urNp cvs-1.11.17.org/src/server.c cvs-1.11.17/src/server.c --- cvs-1.11.17.org/src/server.c 2006-09-13 17:35:21.000000000 +0900 +++ cvs-1.11.17/src/server.c 2006-09-13 18:07:24.000000000 +0900 @@ -5785,7 +5785,56 @@ handle_return: It might or might not be the same as host_user. */ CVS_Username = xmalloc (strlen (username) + 1); strcpy (CVS_Username, username); - } + + if ( ! strcmp (username, host_user) ) { + char filename[256] = { 0, }; + FILE *op; + int userlen = strlen (username); + char *linebuf = NULL; + size_t linebuf_len; + struct stat mapfile; + sprintf (filename, "%s/%s/usermap", repository, CVSROOTADM); + + //syslog (LOG_DAEMON | LOG_NOTICE, "oops: %s", filename); + + if ( CVS_STAT (filename, &mapfile) > -1 ) { + if ( (op = CVS_FOPEN (filename, "r")) != NULL ) { + while ( getline (&linebuf, &linebuf_len, op) >= 0 ) { + if ( (strncmp (linebuf, username, userlen) == 0) + && (linebuf[userlen] == ':') ) { + char *mapuser = NULL; + char *ws = NULL; + char mapuserlen = 0; + + mapuser = strchr (linebuf, ':'); + if ( (ws = strchr (mapuser, ' ')) ) + mapuser[ws - mapuser] = 0; + else if ( (ws = strchr (mapuser, '\t')) ) + mapuser[ws - mapuser] = 0; + else if ( (ws = strchr (mapuser, '\r')) ) + mapuser[ws - mapuser] = 0; + else if ( (ws = strchr (mapuser, '\n')) ) + mapuser[ws - mapuser] = 0; + + mapuserlen = strlen (mapuser) - 1; + if ( mapuserlen > 0 ) { + free (host_user); + host_user = xstrdup (mapuser + 1); + } + break; + } + } + } + if (linebuf) free (linebuf); + + if ( ferror (op) ) + error (0, errno, "cannot read %s", filename); + + if ( fclose (op) < 0 ) + error (0, errno, "cannot close %s", filename); + } + } + } return host_user; }
2006/09/13 19:47 2006/09/13 19:47
Posted
Filed under Tech/프로그래밍
요즘 다시 IP 를 가지고 할 일이 생겨, 간만에 KRISP 2.0.0을 업데이트 했습니다. 딱히 성능이 좋아졌다거나 무언가 변화가 되었다기 보다는, GeoIP 를 가지고 일을 하다보니, GeoIP extension 이 추가될 경우 (상용..) 이를 활용할 수 있도록 지원을 해 보았습니다.

추가된 기능은 다음과 같습니다.

1. GeoIP City or GeoIP Lite City database 가 존재할 경우 도시 정보 contorl 2. GeoIP ISP database 가 존재할 경우, krisp 의 database 에 없는 IP 에 대해서 GeoIP ISP database 를 이용


즉, 고로 GeoIP 의 상용 database 를 사용할 수 있을 경우, krisp 에서도 역시 그 database 를 지원하도록 하는 것에 촛점을 맞춘 것 입니다. 대충 사용해 보니, GeoIP ISP 의 경우에는 품질이 괜찮은 반면, GeoIP City 의 경우 우리나라 환경에서는 영 맞지 않는 듯 싶네요.

krisp API 가 업데이트 됨에 따라, pear_krisp (with mod_geoip), mod_krisp (php extesion), KRISP perl module 모두 따라서 1.1.0 으로 업데이트 되었습니다.
2006/09/08 00:41 2006/09/08 00:41
Posted
Filed under Tech/프로그래밍
cvs 를 이용해서 프로젝트를 할 때 가장 귀찮은 것이 퍼미션/소유권 관리입니다. 이를 위해서 여러가지 꽁수를 쓰는데,

1. 유저들을 공통 그룹으로 묶고 umask 와 setgid 를 이용해서 퍼미션과 그룹권한을 유지시키는 방법
2. CVSROOT/passwd 를 이용하여 CVS passwd 의 User map 을 이용하는 방법
3. CVSROOT tree 의 모든 파일들에 주기적으로 w 권한을 주는 방법

등등 여러가지 형태로 운영이 되는데, 이를 근본적으로 해결할 길이 없을까 찾다가 그냥, 패치를 해 보았습니다. 원래는 2번의 방법을 애용했었는데, 이번에 개발서버들을 AD + winbind 를 이용하여 Active directory
를 이용하여 통합 인증을 구현하다 보니, 2번의 방법이 상당히 번거로와 졌는데, 결국 이를 해결하기 위해, cvs 1.12 의 pam pactch (1.11 을 위한 패치는 Fedora 5 의 cvs 에 들어 있습니다.) 와 아래의 usermap patch 를 만들게 되었네요.

요즘은 SVN 을 많이 사용하는 것 같은데, CVS data 가 너무 많아서 SVN 으로 가기는 힘들거나 귀찮고, user mapping 이 필요한 경우에는 사용하시면 유용할 것 같습니다. 설정은.. CVSROOT/usermap 파일을 생성하시고, loginuser:mapping_user 와 같이 한라인에 하나씩 지정 하시면 됩니다. mapping_user 는 system 에 존재하는 계정이어야 합니다.

diff -urNp src.org/server.c src/server.c --- src.org/server.c 2006-08-21 18:47:02.000000000 +0900 +++ src/server.c 2006-08-21 20:17:57.000000000 +0900 @@ -5785,7 +5785,53 @@ handle_return: It might or might not be the same as host_user. */ CVS_Username = xmalloc (strlen (username) + 1); strcpy (CVS_Username, username); - } + + if ( ! strcmp (username, host_user) ) { + char filename[256] = { 0, }; + FILE *op; + int userlen = strlen (username); + char *linebuf = NULL; + size_t linebuf_len; + sprintf (filename, "%s/%s/usermap", repository, CVSROOTADM); + + syslog (LOG_DAEMON | LOG_NOTICE, "oops: %s", filename); + + op = CVS_FOPEN (filename, "r"); + if ( op != NULL ) { + while ( getline (&linebuf, &linebuf_len, op) >= 0 ) { + if ( (strncmp (linebuf, username, userlen) == 0) + && (linebuf[userlen] == ':') ) { + char *mapuser = NULL; + char *ws = NULL; + char mapuserlen = 0; + + mapuser = strchr (linebuf, ':'); + if ( (ws = strchr (mapuser, ' ')) ) + mapuser[ws - mapuser] = 0; + else if ( (ws = strchr (mapuser, '\t')) ) + mapuser[ws - mapuser] = 0; + else if ( (ws = strchr (mapuser, '\r')) ) + mapuser[ws - mapuser] = 0; + else if ( (ws = strchr (mapuser, '\n')) ) + mapuser[ws - mapuser] = 0; + + mapuserlen = strlen (mapuser) - 1; + if ( mapuserlen > 0 ) { + free (host_user); + host_user = xstrdup (mapuser + 1); + } + break; + } + } + } + if (linebuf) free (linebuf); + + if ( ferror (op) ) + error (0, errno, "cannot read %s", filename); + if ( fclose (op) < 0 ) + error (0, errno, "cannot close %s", filename); + } + } return host_user; }
2006/08/21 21:24 2006/08/21 21:24

얼마전 올렸던 usermap patch 의 버그 수정입니다. 이전 패치에서 usermap 파일이 없을 경우 에러가 발생하는 문제가 있었습니다. 파일이 없으면 CVS_FOPEN 이 에러가 발생할 것이라는 엄청난 착각을 한 결과이네요. 이런저런 경우의 수를 다해서 테스트를 했다고 생각했는데.. diff -urNp cvs-1.11.17.org/src/server.c cvs-1.11.17/src/server.c --- cvs-1.11.17.org/src/s..

Posted
Filed under Tech/프로그래밍
프로그래밍을 하다 보면 coredump file 을 남겨서 segfault 에 대한 debugging 을 원할 때가 있습니다. 하지만 Redhat Linux 는 전통적으로 기본으로 coredump file 을 생성하지 못하도록 되어 있습니다. 더군다나, init script 에서도 이렇게 남기지 않게 되어 있 곤란을 겪을 때가 있습니다.

그래서 RH 에서 coredump 를 남기기 위한 작업을 기술해 봅니다.

1. /etc/profile

대략 26라인 즈음에 보면

ulimit -S -c 0 > /dev/null 2>&1


이라는 설정으로 core 를 남기지 않도록 되어 있습니다. 암울 합니다. --;

ulimit -c unlimited >/dev/null 2>&1


와 같이 수정해 줍니다. 시스템 파일을 건드리고 싶지 않다면, ~/.bash_profile 이나 ~/.bashrc 에 설정 합니다.

2. /etc/sysctl.conf

커널 파라미터 역시 기본으로 core 를 남기지 않도록 되어 있습니다. /etc/sysctl.conf 에 아래 설정을 추가합니다.

kernel.suid_dumpable = 1 kernel.core_uses_pid = 1


설정을 한 후에, sysctl.conf 의 변경 사항을 커널에 반영합니다.

[root@www SPECS]# sysctl -p


여기까지는 시스템에서 기본적으로 coredump 를 남기도록 하는 겁니다.

RH 의 경우에는 한술 더 떠서, init script 로 실행하는 모든 데몬에 대해서 core 를 남기지 않도록 initscripts package 에서 관리하고 있습니다. 그러므로, /etc/init.d/httpd 를 실행했을 때 core
를 남기도록 하려면..

1. /etc/sysconfig/init

DAEMON_COREFILE_LIMIT='unlimited'


를 추가해 줍니다.

2. 위의 설정은 init script 로 실행된 모든 스크립트에 영향을 줍니다. 각 init script 에서 /etc/init.d/functions 를 호출하기 전에

DAEMON_COREFILE_LIMIT='unlimited'


를 넣어 주시면 반영이 됩니다.

참조: http://kbase.redhat.com/faq/FAQ_80_7935.shtm
2006/08/10 16:08 2006/08/10 16:08
Posted
Filed under Tech/프로그래밍
Neowiz 는 시스템 설치를 PXE 와 kickstart 의 post script 를 이용하여 자동 관리를 하고 있습니다. 회사에서는 이 시스템을 P.I.P.E (본 뜻은 까먹었음. 그냥 파이프라고 함) 라고 칭합니다.

이번에 pipe system 을 migration 을 하고 있는데, 다음주 즈음 대략 몇백대를 동시에 설치할 일이 있어서, web daemon 을 apache 에서 lighttpd 로 변경을 했습니다.

centos 를 테스트 할 때까지만 해도 좋았는데.. redhat 9 의 anaconda 에서 lighttpd 기반에서 kickstart 파일을 받아오지 않는 난감한 사태가 발생을 하더군요. apache 로 가도 상관이 없지만, 몇백대씩 설치를 하려면 apache 로는 1대로는 버틸수가 없다는 문제가 발생을 합니다. 또한, pipe 의 특성상 설치를 하면서 시스템 내부에서 작업을 많이 하게 되는데, apache 로 몇백대를 설치할 경우에는 시스템이 과부하가 걸리게 됩니다.

그래서 고민하다가, 그래 한번 해결해 보자는 오기가 생기더군요. 원래 제가 이 바닥에서 뽀로꾸로 시작해서 오직

안되면 될 때까지 !!!


라는 신념으로 버텨온지라.. 이번에도 누가 이기나 한번 해 보자는 "자포자기"식으로 도전을 하게 되었습니다.

먼저.. 그럼 뭐가 문제일까.. 하고선 lighttpd 를 debug symbol 을 줘서 빌드한 후에 debugging 도 해 보았지만 뚜력한 이유를 알수가 없었고, 그럼 패킷이 어떻게 지나가나 보자.. 하고선 dump 를 떠 보았지만.. 시간만 속절없이 흘러가더군요. 그러다가.. 제대로 되는 패킷과 안되는 패킷을 비교하는 도중 아래의 붉은 글자 부분의 차이를 발견하게 됩니다.

* 400 Bad Request 경우
0x0000: 4510 0069 52fc 4000 4006 e980 7f00 0001 E..iR.@.@....... 0x0010: 7f00 0001 886f 0050 9443 d892 9435 6606 .....o.P.C...5f. 0x0020: 8018 0040 fe5d 0000 0101 080a 92a6 8da3 ...@.].......... 0x0030: 92a6 8a69 4745 5420 2f70 726f 6669 6c65 ...iGET./profile 0x0040: 2f64 6566 6175 6c74 2e72 6564 6861 742e /default.redhat. 0x0050: 392e 6933 3836 2f70 6970 652e 6b73 2048 9.i386/pipe.ks.H 0x0060: 5454 502f 312e 3009 0a TTP/1.0..


* 200 정상적인 경우
0x0000: 4510 0069 52fc 4000 4006 e980 7f00 0001 E..iR.@.@....... 0x0010: 7f00 0001 886f 0050 9443 d892 9435 6606 .....o.P.C...5f. 0x0020: 8018 0040 fe5d 0000 0101 080a 92a6 8da3 ...@.].......... 0x0030: 92a6 8a69 4745 5420 2f70 726f 6669 6c65 ...iGET./profile 0x0040: 2f64 6566 6175 6c74 2e72 6564 6861 742e /default.redhat. 0x0050: 392e 6933 3836 2f70 6970 652e 6b73 2048 9.i386/pipe.ks.H 0x0060: 5454 502f 312e 300d 0a TTP/1.0..


해당 자리는 carrige return (\r) 이 들어가야 할 자리인데.. 대체 09 가 무야 하고 찍어보니.. tab (\t) 를 찍고 있는 것입니다. 이제껏.. query 를 던지면서 왜 똑같은데 안되지 하고 있었는데.. RH9 anaconda 는

GET http://domain.com/uri\t\n


을 찍고 있었던 겁니다. 그러니 될 턱이 없지요 --; 이것 땜시 anaconda 소스와 lighttpd 의 소스를 까보면서 헛되이 시간을 보내고 있었던 것이었습니다. 알고나자 허탈함이 밀려 오면서.. (속으로는 이런 "씹x"...) 여기서 포기해야 하는가 하다가, 들인 시간이 아까와서 다시

안되면 될 때까지 !!!


의 정신으로, lighttpd 가 저 쿼리를 받아들일 수 있도록 수정해 보자는 말도 안되는 결심을 하게 됩니다. 그렇게 한참을 뒤져서 다음의 패치가 나오게 됩니다.

diff -urNp lighttpd-1.4.11.org/src/connections.c lighttpd-1.4.11/src/connections.c --- lighttpd-1.4.11.org/src/connections.c 2006-07-21 00:27:44.000000000 +0900 +++ lighttpd-1.4.11/src/connections.c 2006-07-21 00:26:47.000000000 +0900 @@ -910,15 +910,21 @@ int connection_handle_read_state(server /* check if we need the full package */ if (con->request.request->used == 0) { buffer b; + char *_bptr; b.ptr = c->mem->ptr + c->offset; b.used = c->mem->used - c->offset; + /* fixed redhat 9 anaconda bug */ + _bptr = strstr (b.ptr, "\t\n"); + if ( _bptr != NULL ) *_bptr = '\r'; + + //log_error_write(srv, __FILE__, __LINE__, "ss", "request header1:", b.ptr); if (NULL != (h_term = buffer_search_rnrn(&b))) { /* \r\n\r\n found * - copy everything incl. the terminator to request.request */ buffer_copy_string_len(con->request.request, b.ptr, h_term - b.ptr + 4);


간단하게, \t\n 을 찾아서 \t 를 \r 로 바꾸는 거죠. ^^; 이렇게 하다가 갑자기 포인터로 구현을 해 보고 싶더군요. 전 앞에서 밝혔다 시피 뽀로꾸와 수많은 닥질의 경험으로 오늘날의 바탕을 마련했는데, C 역시 그냥 마구잡이로 소스를 써내려간 막가파로서, 포인터에 대한 이해가 전혀 없이 사용해 왔는데 갑자기 포인터가 이해가 되는 듯한 느낌이 들었습니다. 그래서 별 소용은 없지만 다음과 같은 코드도 만들게 됩니다.

diff -urNp lighttpd-1.4.11.org/src/connections.c lighttpd-1.4.11/src/connections.c --- lighttpd-1.4.11.org/src/connections.c 2006-07-21 00:27:44.000000000 +0900 +++ lighttpd-1.4.11/src/connections.c 2006-07-21 00:26:47.000000000 +0900 @@ -910,15 +910,31 @@ int connection_handle_read_state(server /* check if we need the full package */ if (con->request.request->used == 0) { buffer b; + char *_bptr; b.ptr = c->mem->ptr + c->offset; b.used = c->mem->used - c->offset; + /* fixed redhat 9 anaconda bug */ + if ( strchr (b.ptr, '\t') != NULL ) { + _bptr = b.ptr; + while ( *_bptr != 0 ) { + if ( *_bptr == '\t' ) { + if ( *(_bptr+1) == '\n' ) { + *_bptr = '\r'; + break; + } + } else *_bptr++; + } + } + /* fixed redhat 9 anaconda bug */ + + //log_error_write(srv, __FILE__, __LINE__, "ss", "request header1:", b.ptr); if (NULL != (h_term = buffer_search_rnrn(&b))) { /* \r\n\r\n found * - copy everything incl. the terminator to request.request */ buffer_copy_string_len(con->request.request, b.ptr, h_term - b.ptr + 4);


누워서 침뱉기 일지는 모르겠지만.. 포인터를 사용하면서 한번에 이렇게 써 내려간 적은 처음인 듯 싶습니다. 예전에 기타를 칠때도 한동안 안 늘다가 어느날 갑자기 못치던 것을 치게 되는 경우가 있었는데, 마치 오늘 위의 코드가 그런 경우인 듯 싶습니다. 스스로가 감탄스럽더군요. (저는 가끔 제멋에 뻑 갈때가 종종 있습니다. ^^)

RH9 의 말도 안되는 request query 덕분에, 고생도 엄청 했고, 저런 것까지 처리를 해 주고 있는 apache 에 대해서 새삼스럽게 존경을 하게 되었으며 (괜히 apache 라고 하는게 아니구나..), 이런 코드를 한번만에 만들어 낸 자신에게 감탄도 하고.. (워낙 설계라는 것 없이 하나 보니, 한번에 쓰는 경우는 정말 드물었죠..), 금방 위치를 찾아낸 것도 감탄 스럽고.. 몸은 힘들었지만, 마음은 그대로 나름대로 뿌듯합니다.

처음에는 google 신에게 구걸을 하려고 시도를 했으나, 결국에는 찾지를 못하여.. 이 글로 내가 했던 고생을 좀 덜 수 있으면 다행이라 생각하고 후기를 남깁니다.
2006/07/21 04:01 2006/07/21 04:01
비밀방문자

관리자만 볼 수 있는 댓글입니다.

김정균

ㅎㅎ 버그가 맞네요. \t\n 을 \r\n 으로 하는 것이 목적인데, 제 코드는 \t\r 을 만들고 있었네요. ㅋㅋ 오류 알려 주셔서 감사합니다.

뭐 어차피 이 코드는 실제 패치에 사용한 코드가 아니라 그냥 심심해서 만들어본 코드였으니 상관은 없습니다만..

그리고 요즘 버전은 이 패치가 맞지 않습니다. 그래서 패치 자체도 바뀌었죠. 요즘은..

+ /* if rh9 support flag on, convert \t\n to \r\n */
+ if ( srv->config_storage[0]->rh9support ) {
+ //log_error_write (srv, __FILE__, __LINE__, "s", "RH9 Support flag on";);
+ if ( ch == '\\t' && b.ptr[i+1] == '\n' )
+ b.ptr[i] = '\\r';
+ }

이정도로 처리가 되고 있네요 :-)

popori

역쉬 뽀로꾸 마왕.. 그거땜시 내 점심이 날아간겨?

박정욱

이야.. 그때 그놈이군요.. 당황케했던.. 결국 발견.. @.@

Posted
Filed under Tech/프로그래밍
openlook.org 의 장혜식님 블러그를 보다보니, blog 의 trackback 의 인코딩때문에 (요즘 utf8 이 대세로 가는 분위기라..) 이런 저런 코드들이 나오고 있습니다.

그래서 저도 잊어 버릴까 만든 코드를 기록해 높습니다. (예전에 만들어 놓았다가 찾느라고 힘들었습니다. T.T)

다른 분들의 코드들이 대부분 iconv 나 언어에서 제공하는 charset encoding/deconding 함수를 이용하는 반면, 제 코드는 직접 까 봐서 이놈이 정말 맞는지 여부를 확인하는 코드 입니다.

<?php // // +----------------------------------------------------------------------+ // | PHP Version 4 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997-2003 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 2.02 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/2_02.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Author: JoungKyun Kim <http://www.oops.org> | // +----------------------------------------------------------------------+ // // $Id: eSystem.php,v 1.2 2005/07/11 05:58:11 oops Exp $ require_once 'PEAR.php'; /** * PEAR's eSystem:: interface. Defines the php extended system mapping function * and any utility mapping function * * @access public * @version $Revision: 0.1 $ * @package Unicode */ class Unicode extends PEAR { function chr2bin ($c, $shift = '') { $c = ord ($c); if ( $shift && preg_match ('/^([<>]+)[\s]*([0-9]+)/', $shift, $match) ) : switch ($match[1]) : case '>>' : $c = $c >> $match[2]; break; case '<<' : $c = $c << $match[2]; break; case '<' : $c = $c < $match[2]; break; case '>' : $c = $c > $match[2]; break; endswitch; endif; return decbin ($c); } function is_utf8 ($str) { $_l = strlen ($str); $_not = 0; for ( $i=0; $i<$_l; $i++ ) : #$_first = $this->chr2bin ($str[$i]); # if 7bit charactior or numeric, skipped #if ( strlen ($_first) != 8 ) # continue; # if single byte charactors, skipped if ( ! (ord ($str[$i]) & 0x80) ) : continue; endif; $_first = $this->chr2bin ($str[$i], '>>4'); switch ( $_first ) : case 1111 : $b = 3; break; # 4byte case 1110 : $b = 2; break; # 3byte default : return 0; # not utf8 endswitch; for ( $j=1; $j<$b; $j++ ) : if ( substr ($this->chr2bin ($str[$i+$j]), 0, 2) != 10 ) return 0; endfor; break; endfor; return $_not ? 0 : 1; } } /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ ?>


코드는 Pear 코드로 작성이 되었으며, 사용법은

<? require_once 'Unicode.php'; $_f = 'usage_200509.html'; $_ff = 'bb.html'; $u = new Unicode; if ( file_exists ($_ff) ) unlink ($_ff); $_t = file ($_f); foreach ( $_t as $_v ) : $_v = trim ($_v); if ( $u->is_utf8 ($_v) ) putfile_lib ($_ff, utf8decode_lib ($_v, 'cp949'), 1); else putfile_lib ($_ff, $_v, 1); endforeach; ?>


와 같이 사용할 수 있습니다.

단, euc-kr 과 utf8 만 구분이 됩니다.
2006/03/31 15:55 2006/03/31 15:55

트랙백은 HTTP GET 으로 간단한 파라미터들을 함께 넘기면 단순히 받아 저장하는 기능에 불과하므로 보내는쪽의 인코딩이 무엇인지 파악하기가 어려운 점이 있습니다. 물론 향상된 트랙백 규약에는 트랙백을 POST로 보내고 인코딩 정보도 함께 전송하도록 확..

문서의 Charset 을 detecting 하는 library 로는 IBM 이 지원하는 International Components for Unicode (ICU Project) 의 ICU library 와 Mozilla Browser 에서 이용하는 Universal Chardet library 가 있습니다. ICU 의 경우에는 charset detect 가 포함된지 꽤 되었음에도 불구하고, php 5.3 부터 기본 포함되는 intl extensi...

이창일

putfile_lib ($_ff, utf8decode_lib ($_v, 'cp949'), 1);
위에서 없는 함수를 사용 했네요;;
앞의 putfile_lib 파일에 쓰는 함수 인것 같고
utf8decode_lib 는 변환 같은데 PEAR.php 에도 엇는 함수네요

김정균

음 깜빡 했군요. 해당 함수들은 http://devel.oops.org 에서 배포하는 korean extension 에 포함되어 있습니다. 그리고 해당 함수들이 사용된 것은, 그냥 예제일 뿐이죠. 해당 부분에 님이 필요하신 코드를 적어 주시면 됩니다.

Posted
Filed under Tech/프로그래밍
굴림체가 너무 마음에 들어서 죽 고집을 하고 있었는데, 굴림체를 사용하는 사람들은 공통된 요구사항이 있었나 봅니다.

http://crizin.net/index.php?pl=306&ct1=3&ct2=10

에서 CrizinCode 라는 굴림체 변형 폰트를 발표했는데, 굴림체를 사용하면서 이점은 이랬으면 하는 모든 사항이 반영이 되었습니다. 만들어 주신분 정말 고맙습니다.

내가 원하던 글꼴의 조건은,

1. 고정폭 글꼴일 것
2. I,l,1,O,0의 구분이 명확할 것
3. 굴림체에 버금가는 가독성을 보일 것
4. 역슬래시를 \ 모양으로 표시해줄 것
5. 9pt 에서 Anti-aliasing 없이 출력될 것
6. 한글은 굴림 9pt로 출력될 것


감사히 잘 쓰겠습니다. :-)
2006/02/02 21:35 2006/02/02 21:35
Posted
Filed under Tech/프로그래밍
hanterm-xf 는 utf8 을 지원하지 않습니다. RH 가 utf8 로 default charset 을 변경한 이 후 부터, hanterm-xf 가 utf8 을 지원하지 않는 다는 이유로 꼬박 euc-kr 을 고집해 오고 있었습니다만.. 아무래도 대세에 밀리는 기분이 들어서 utf8 환경으로 변경을 해 보고자 작업을 하게 되었습니다.

처음에는 original hanterm 이 utf8 을 지원하는 까닭에 hanterm 을 cygwin 에서 난관끝에 빌드를 하고, utf8 이 지원됨을 확인하고 뿌듯했으나, 곧, 창을 resize 했을 경우, 원 size 의 화면만 출력이 되는 문제를 해결하지 못해.. 포기하고, termcap 의 문제인가 살펴 보았지만 알수 없는 암호만 가득해서 결국에는 소스를 열어 보고 이리저리 해 보았지만 해결을 못했습니다.

그래서 안되면, xterm 이 utf8 을 지원하니, xterm 의 utf8 기능을 hanterm-xf 에 반영을 하자고 hanterm-xf 의 소스를 열었으나.. 역시 define 의 엄청난 압박에 포기하고, iconv 를 이용해서 출력과 입력에만 처리하기로 하고 patch 를 작성 했습니다.

비록 요즘 gnome 이나 kde 의 library 를 이용한 term 들이 기본으로 한글을 지원하면서 hanterm(-xf) 의 필요성이 점점 없어지면서, 별로 사용을 하고 있지 않지만, cygwin 이나 기타 hanterm 에 대한 애정 때문에 사용하시는 분들은 아래의 패치를 이용하시면 utf8 걱정은 덜 수 있을 듯 싶습니다.



이 패치는 hanterm-xf 2.0.5-177 (현재 cvs version) 에 기반한 패치이며, 2.0.5 에서는 아마 적용이 가능할 것이며, 2.x 의 경우 수작업으로 패치를 하시면 사용이 가능 할 겁니다.

euc-kr mode

utf8 mode



잠깐, hanterm 과 hanterm-xf 는 뭐가 틀리나요?

hanterm 과 hanterm-xf 는 엄연히 뿌리가 다릅니다. hanterm 은 현재 XL 레이싱을 개발하고 있고, 리니지를 개발한 송재경씨가 X11R5 기반의 xterm 을 기반으로 작성을 했으며, 여러 OS 에서 포팅이 가능하다는 장점을 가지고 있는 반면에, hanterm-xf 는 ami, gau 등을 제작한 미지의 황치덕씨가 X11R6 기반의 xterm 에 hanterm 의 패치가 반영하여 작성을 했습니다. 그래서 여러가지 면에서 hanterm 보다 미려하기는 하지만 utf8 이 지원되지 않은 단점등 여러가지가 있습니다. 현재, hanterm 과 hamter-xf 의 개발은 중단된 상태나 다름이 없습니다.
2006/01/04 23:46 2006/01/04 23:46
김정균

utf8 patch 가 hanterm-xf 에 merge 가 되었습니다. hanterm-xf 2.0.6-177 부터 반영이 되었으니, 참고하세요.

badung

오!! 감사드립니다 잘 되는군요 그런데 utf-8모드로 따로 실행하거나 단축키는 없나요? 지금은 [완성]을 마우스로 찍어서 utf-8로 변환하고 있는데요..

김정균

$HOME/.Xdefaults 라는 파일을 생성하고, 이 파일에

Hanterm*hangulCode: 2

라고 지정해 주면 됩니다. 또는, hanterm 의 설정 파일 (여기에 지정해 주는 건데, 설치시에 따라 위치가 달라져서..), 저의 경우에는 /etc/X11/app-defaults/Hanterm 에

*hangulCode: 2

라고 지정을 해 주시면 됩니다. 폰트 설정을 하셨을테니, 폰트 설정을 하는 설정 파일에 해 주시면 됩니다.

badung

방법에 대해서 조금 질문 드릴게요 사용배포판은 젠투이구요 hanterm-xf-2.0.5-173.tar.gz 를 풀었고 그 디렉토리에서 patch -p1 <han...patch 를 했습니다. 그리고 ./configure 후에 make를 했는데


badung hanterm-xf-2.0.5-173 # make
gcc -I. -I. -DHAVE_CONFIG_H -D_GNU_SOURCE -I./composer -D_DEBUG_root_ -DHANTERM_PKGNAME=\"hanterm-xf\" -DHANTERM_VERSION=\"2.0.5\" -DKEYBOARD_DIR=\"/usr/local/share/hangul_keyboard\" -g -O2 -c ./charproc.c
./charproc.c: In function `VTInitialize':
./charproc.c:4997: error: `C_UTF8' undeclared (first use in this function)
./charproc.c:4997: error: (Each undeclared identifier is reported only once
./charproc.c:4997: error: for each function it appears in.)
./charproc.c: In function `from_utf8':
./charproc.c:6926: warning: passing arg 2 of `iconv' from incompatible pointer type
./charproc.c: In function `to_utf8':
./charproc.c:6984: warning: passing arg 2 of `iconv' from incompatible pointer type


이렇게 나오네요. 방법이 틀린건가요? 아니면 더 첨부해야 할 파일이 있을까요?

김정균

한글 관련 옵션을 주셔야 합니다. 그러지 않으면 xterm 과 동일하게 됩니다. 대략적으로

--x-includes=/usr/X11R6/include \
--x-libraries=/usr/X11R6/lib --with-x \
--enable-doublechars --enable-i18n \
--with-libiconv --enable-freetype \
--disable-input-method --enable-wide-chars \
--enable-chat --enable-now-chat \
--enable-boxchar --enable-ansi-color \
--with-own-terminfo=/usr/share/terminfo

정도는 주셔야 할겁니다.