OpenSSL SEED 패치

대표적인 오픈소스 보안 툴킷인 OpenSSL에 금융전산쪽에서 강제적으로 쓰도록 하고 있어서 국내에서 굉장히 많이 쓰이고 있는 SEED (RFC4009) 지원을 넣은 패치를 만들었습니다. (<- “패치”를 누르면 다운로드)

원래는 재작년 쯤에 OpenSSL에 SEED넣는 프로젝트를 소프트웨어진흥원이 발주해서 i모 보안회사와 ㄱ모 대학이 같이 진행한 것이 있었습니다. 이 결과물을 자세히 보면 소스의 원저작자의 저작권을 무시한 심각한 문제가 있고, 업스트림을 바로 하기에는 부족한 점이 꽤 있습니다. 그래서, 저작권 문제를 해결하고, 업스트림을 할 수 있도록 OpenSSL에서 이전에 새로운 싸이퍼가 들어갔을 때의 상황과 거의 똑같은 범위의 작업을 했습니다. 그리고, NexG사에서 지원해 준 x86 어셈블리 구현도 추가해서 속도도 400% 정도로 향상시켰습니다. 🙂 (민수형/미쓰옹 감사합니다! -O-)

이제, 오픈소스에서 가장 중요한 작업인 정치적 문제가 남았는데.. 마침 OpenSSL 홈페이지가 다운됐는지 접속이 전혀 안 돼서 보낼 수가 없군요.. 흐흐. 언제 살아나면 0.9.8b나 0.9.9부터는 SEED를 볼 수 있도록 힘 좀 써 봐야겠습니다. -O-

OpenSSL API에 익숙한 분들께서는 꼭 테스트를 한번씩 해봐주세용; 제가 SSL에는 익숙하지가 않아서 이게 제대로 도는지 알 수가 없네요. 크흐 _-_

Io 파이썬 바인딩

으흐흐.. Io가 주류 언어들에 비해서 워낙 라이브러리가 부실하다보니 뭔가 하려고 하면 항상 꼭 몇개씩 발목잡는 부분이 있었습니다. 파이썬의 str에 해당하는 Sequence와 String같은 경우에도 대충 다 있는 것 같이 보이면서도, 꼭 뭔가 하려면 한 개씩 없고.. List나 Map도 참 답답할 때가 많고.. 그래서 그냥 파이썬 브릿지가 있으면 어떨까 생각하다가 우선 파이썬 바인딩을.. 🙂 한 30줄 짜니까 금방 되네요~

Io 20060104
Io> Python

==>  Python_0xa4f380:
  runString = CFunction_0xa49500

Io> Python runString("import sys\nprint sys.platform\nfor i in 1,2,3:\n print 'yay!'")
Running
freebsd6
yay!
yay!
yay!

==>  Python_0xa4f380:
  runString = CFunction_0xa49500

Io>

이제 오브젝트 매핑도 좀 하고, 브릿지 역할을 할 수 있게, Io 객체도 파이썬에 그대로 넘겨줄 수 있게 여러가지 수정을 해 봐야겠습니다. ^_^;

답글 남기기 방법 변경

많은 분들이 오픈룩을 RSS 리더로 읽으시기는 하지만, 그래도
가끔 홈페이지에 웹브라우저로 직접 들어오시는 분들의 편의를
위해서 답글 남기는 방법을 다른데서 보통 유행하는 방식으로
바꿔봤습니다. 목록 화면에서도 [답글] 버튼을 누르면 화면
안에서 현재 답글 목록이 나오고 거기서 바로 쓸 수 있는
방식으로요~

리프레시나 다른 페이지로의 이동 없이 답글을 남길 수 있기 때문에
좀 더 쉽게 답글을 쓰실 수 있지 않을까 생각이 됩니다. 아하하; -ㅇ-;
그리고 버튼 순서를 약간 바꾸었고, 메일과 홈페이지 입력하는
칸은 평소에는 숨겨뒀다가 버튼을 누르면 나오게 했습니다.

대체적으로 자바스크립트가 작동하지 않거나 텍스트 브라우저인
경우에도 동작하도록 고려를 했는데, 혹시나 쓰시는 브라우저에서
제대로 안 보이시는 경우에는 알려주세요~ (이 글에다가 답글 테스트를.. 🙂 — 그나저나 이것하느라 coreblog 프러덕트에 직접 무식한 패치를 해버리는 바람에 업그레이드가 골치아프게 생겼군요;;

파이썬은 왜 빌트인 타입의 메쏘드를 못 바꾸는가

Io의 asString, asCharacter 같은 것 덕분에 앞뒤로 왔다갔다 하지 않고도 계속 쓸 수 있다는 점이 참 와닿아서, 파이썬에서는 그렇게 할 수 없을까 하다가, 전에 어떤 분이 파이썬에서 왜 베이스 타입에서는 메쏘드를 못 갈아치우냐 하시길래, “엇 안되나! (뻘쭘)” 했던 기억이 나서 좀 더 연구를 해 보았습니다. 으흐흐

파이썬의 타입 오브젝트의 플래그 중에 Py_TPFLAGS_HEAPTYPE이라는 것이 있는데 이것은 힙에 할당된 타입에만 들어가는 플래그라서, 즉, 런타임에 상속된 타입들은 이 플래그가 설정이 되지만, 컴파일할 때 스택에 할당된 타입 객체들은 이 플래그가 설정되어 있지 않아서 결국 “can’t set attributes of built-in/extension type”라는 에러를 뱉어냅니다. 그런데, 파이썬은 타입 오브젝트가 비록 스택에 있긴 하지만 const가 아니기 때문에 실제로 딕셔너리도 할당을 하는 등 변조를 하고 gc로 관리까지 하고 있어서 변경한다고 문제가 생길 것은 없었습니다. 그래서 그 부분을 패치해서 실험해 보면, (Object/typeobject.c의 type_setattro함수의 첫 if 블럭을 주석처리)

>>> object.asInt = lambda x: int(x)
>>> object.size = lambda x: len(x)
>>> [1,2,3].size()
3
>>> 'hehehee'.size()
7
>>> '123'.asInt()
123

요렇게 잘 돌아갑니다~

과연.. 잘 되는데 왜 파이썬에서는 막아놓은 것일까!
그 이유는 메일링리스트를 한참 뒤져본 결과 귀도의 적극적인
의도
로 막아놓은 것인데, 귀도의 설명에 따르면
빌트인 타입 오브젝트들은 여러 쓰레드에 걸친 것 같은
공유되는 컨텍스트에서 같이 사용되는 경우가 많기 때문에
문제를 발생시킬 소지가 높은 핵이라서 이런 걸 공식적으로
허용해 줄 수가 없다고 하네요.
뭔가 수긍이 가는 것 같기도 하면서도.. 파이썬의 다른 면들은
과연 그렇게 깨끗했나 의심이.. 흐흐흐.. -O- 하여간 약간
아쉽군요~

한글로 Io 프로그래밍

요즘 Io로 시간날 때 이것 저것 장난치며 놀고 있는데, 모든 것이 다 교체가 가능하다는 말에, 한글로 프로그래밍도 제법 가능할까 하는 생각이 들어서, 한번 쑥 바꿔봤습니다. 흐흐. 우선, 기본적으로 Io는 한글이 식별자로 쓰이지 못하기 때문에 패치를 해야하는데, IoLexer.c에서 글자 읽는 부분을 패치를 했습니다. (아직은 임시로 테스트해보기 위한 흉악한 패치입니다. =3)

그래서 이제 코드가 어떻게 보일지 무척 궁금해서 얼마 전에 코드 레이스 관객 문제를 Io로 풀었던 것을 고쳐 봤습니다. 우선, 원래의 Io코드는 이렇게 됐습니다. (창준형이 수정해 줌)

Sequence applyByGroup := method(msg,
    rechar := self at(0)
    repeats := 0
    self asMutable append(0) foreach(ch,
        if(rechar != ch,
            msg(rechar, repeats)
            repeats = 0; rechar = ch)
        repeats = repeats + 1
    )
)

current := "1"
(Lobby args at(0) asNumber - 1) repeatTimes(
    next := Sequence clone
    current applyByGroup(block(ch, repeats,
        next appendSeq(ch asCharacter, repeats asString)))
    current = next
)
current linePrint

이제 한글로 프로그래밍하려면, 기본 객체들이나 메쏘드들 이름을 일일이 바꾸는 초기화 루틴이 필요한데, 그 부분을 이렇게 넣어 봤습니다.

// 기본 오브젝트 메쏘드
슬롯 := getSlot("getSlot")
만약에 := 슬롯("if")
메쏘드 := 슬롯("method")
복사 := 슬롯("clone")
코드뭉치 := 슬롯("block")

// 오브젝트
연속열 := Sequence do(
    의 := 슬롯("at")
    추가 := 슬롯("append")
    하나씩 := 슬롯("foreach")
    숫자로 := 슬롯("asNumber")
    덧붙이기 := 슬롯("appendSeq")
    한줄로출력 := 슬롯("linePrint")
    변경가능하게 := 슬롯("asMutable")
)
입구 := Lobby do(
    인자 := 슬롯("args")
)
숫자 := Number do(
    번반복 := 슬롯("repeatTimes")
    글자로 := 슬롯("asCharacter")
    문자열로 := 슬롯("asString")
)
목록 := List do(
    의 := 슬롯("at")
)

// 지역객체
Locals 자신 := 메쏘드(self)

번역은 대충 일단 간단하게만.. 흐흐;; 그러면 위의 개미수열 소스가 이렇게 됩니다.

연속열 같은것끼리 := 메쏘드(추가명령,
    반복글자 := 자신 의(0)
    반복횟수 := 0
    자신 변경가능하게 추가(0) 하나씩(글자,
        만약에(반복글자 != 글자,
            추가명령(반복글자, 반복횟수)
            반복횟수 = 0; 반복글자 = 글자)
        반복횟수 = 반복횟수 + 1
    )
)

개미 := "1"
(입구 인자 의(0) 숫자로 - 1) 번반복(
    다음개미 := 연속열 복사
    개미 같은것끼리(코드뭉치(코드, 반복횟수,
        다음개미 덧붙이기(코드 글자로, 반복횟수 문자열로)))
    개미 = 다음개미
)
개미 한줄로출력

이히히. 아무래도 대/소문자 구분이 없다보니 약간 코드가독성이 떨어지는 것 같기도 하고.. 한데, 나름대로 교육용 언어로는 괜찮을 것 같기도 하고… 띄어써야 할 부분이 문법과 다른 게 좀 거시기하고… (애매하군요 -.-;;)

Mono CP949 코덱 무려 2년 묵은 버그 수정

2003년 10월에 Mono에 CP949
코덱을 넣고서는 C# 문법도 다 까먹고 그냥 무관심하게 있었는데,
얼마 전에 어떤 한국분이 영어로 잘 안 돌아간다고 메일을 보내셔서
2년만에 오래간만에 C# 코드를 좀 보게 되었습니다.

아직 디버거에 익숙하지 않아서 그냥 System.Console.WriteLine 으로
열심히 돌아다녀보니까, 으하하하. copy & paste 버그를 하나
발견했습니다. Mono CJK 코덱들은 공유 dll에 들어가 있는 정적 바이트
배열 데이터를 가지고 디코드를 하는데, 한국어 코드페이지인 CP949는 데이터를 쓰는 영역이
KSX1001 영역, UHC 레벨 1 영역, UHC 레벨 2 영역 이렇게 3가지로
나뉘어 있습니다. 그런데, UHC 레벨 2 영역이 첫 번째 바이트가
0xA1로 시작하는 것으로 돼 있는데, 코드 안에서는 레벨 1 것을
붙여넣기 해서 수정하다보니 0x81에서 시작하는 계산식이
그대로 남아있어서;; -ㅇ-;;;

아마 그때 테스트해 봤을 때는 인코딩 하는 것은 열심히 다
테스트를 했는데, 디코드는 확장완성형 부분은 글자가 터미널에서
안 써져서 귀찮아서 테스트를 안 했더니만 이렇게 돼 버렸네요;;
흐흐.. 그래서 방금 패치를 제출했습니다.
간단한 문제이니까 Mono 다음 버전에는 아무래도 고쳐지겠죠?

참, 그리고 11월 1일에 지미안의 에노모토 아쯔시씨가 CP949에서
EUC-KR도 제대로 지원하게 수정했더군요~ 다음 버전엔 EUC-KR도
쓸 수 있게 되었습니다. 🙂

collections.rbtree

2004년 여름쯤에 파이썬 2.4가 릴리스되기 전에 collections 모듈에
타입이 1개 밖에 없는데 이름이 복수로 붙어서, 피보나치 힙을
넣자는 얘기가 있을 때 한 3주일 고민을 해서 피보나치 힙을 구현
했었습니다. 그런데, 피보나치 힙이 워낙 괴짜스러운 자료구조라서 복잡하고
편리한 것들을 추가하기에는 영 불편해서 결국은 그냥 중단했었습니다.

올해 초에는, 피보나치힙과 비슷한 용도에 사용할 수 있지만,
바이너리 트리의 특징을 유지하고 있기 때문에, 구현이 훨씬 쉬운
레드블랙 트리를 한번 구현을 해 볼까 생각을 했었습니다. 그런데~ 훈련소
다녀오고 나니까 머리가 안 돌아가서.. 이히히 ^_^;;
결국은 한참을 벼르던 레드블랙 트리 구현을 마침 숙제하기가
너무 귀찮기도 하고 파이썬 2.5도 곧 피쳐프리즈가 되지 않을까 해서 밀어넣어보려고 한번 집중해서 구현해 봤습니다. 기본적으로
제공되는 메쏘드는

  • T.insert(v): 값을 트리에 넣음
  • T.remove(v): 값을 트리에서 뺌
  • T.clear(): 트리를 비움
  • T.has_key(k): 키가 있는지 검사
  • T.values(): 값의 리스트를 리턴
  • T.keys(): 키의 리스트를 리턴
  • T.items(): (키, 값) 페어의 리스트를 리턴
  • T.nfirst(n): 작은 값부터 순서대로 n개를 리턴
  • T.nfirstitems(n): 작은 값부터 순서대로 n개를 (키, 값) 페어의 리스트로 리턴
  • T.nlast(n): 큰 값부터 순서대로 n개를 리턴
  • T.nlastitems(n): 큰 값부터 순서대로 n개를 (키, 값) 페어의 리스트로 리턴
  • T.popleft(v): v보다 작은 값을 모두 빼내고 리스트로 리턴
  • T.popleftitems(n): v보다 작은 값을 모두 빼내서 (키, 값) 페어의 리스트로 리턴
  • T.popright(v): v보다 큰 값을 모두 빼내고 리스트로 리턴
  • T.poprightitems(n): v보다 큰 값을 모두 빼내서 (키, 값) 페어의 리스트로 리턴
  • 그 외에 __setitem__, __getitem__, __len__, __contains__ 이 지원됩니다.

아무래도 레드블랙트리나 피보나치힙류는 세션 테이블같이 정렬 순서에 따라서 빠르게 작업을 해야 하는 경우에 프리어러티 큐로 활용하는 것이 가장 대표적인 용례인데, 피보나치힙으로 구현을 한다면 순위를 뽑으려고 할 때 매번 extractmin을 해야하는 반면에, 레드블랙트리는 그냥 트리에서 돌아다니는 것으로 구할 수 있다는 것이 장점이라고 할 수 있겠습니다. (속도는 완전한 C 타입으로 구현하면 피보나치힙이 훨씬 빠르지만, 파이썬의 비교연산 특성상 파이썬 확장 모듈이 되면 별 차이가 안 납니다.)

소스는 오픈룩 trac 작업실안에도 있고, 소스포지 패치 리뷰 트래커에 Patch #1324770으로 올렸습니다. 이히히. 잘 돼서 파이썬 2.5에 들어가면 좋겠군요.

시간표 정도는 자동으로

복학 준비를 하면서, 어제 신촌으로 이사도 하고 준비가 착착 되어가고 있습니다~
이제 내일부터는 수강신청인데, 항상 할 때마다 과목끼리 충돌 검사도 하고, 주4를 만들려면 어떻게 해야하나 항상 고민을 하는게 참 귀찮았습니다. 그래서, 아무래도 이런 작업은 사람이 할 일이 아닌 것같아서 자동으로 선호도를 입력하면 시간표를 만들어 주는 스크립트를 하나 만들었습니다. 으흐흐~

우선 입력값으로 들어가는 것은, 후보 과목들의 기본 정보들과 각 수업의 대체 그룹 (같은 그룹에서는 1과목만 신청하게)을 CSV로 지정해서 그것을 프로그램에서 읽어옵니다. 그리고, 그 외의 정보로 따로 들어오는 것은

  • 신청 학점 (최소, 최대)
  • 주4일 선호 가중치
  • 주3일 선호 가중치
  • 학교에 있는 시간 가중치 (-로 주면 가급적이면 공강을 줄임)
  • 이른 아침 시작 가중치 (-로 주면 아침 수업을 피함)
  • 저녁 수업 가중치 (-로 주면 저녁 수업을 피함)
  • 과목별 선호도 (학점에 곱함)
  • 수업 과집중 가중치 (-로 주면 수업이 너무 많이 몰리는 것을 피함)

으흐흐 그래서 시간표를 몇 개 뽑아 봤더니 직접 손으로 짠 것보다 만족스러운 것이 몇개 나오는군요~ 수강신청 하다가 몇개 꽉 찼을 때도 대안 시간표를 쉽게 새로 생성이 가능!

CSV 파일 형식은 이런 식으로 입력합니다. (그룹,가중치…,학점 순)

C,0.8,ENG1104-01-00,수치해석,"화1/목3,4(화5)",공A004/공A019(과232),서보윤,3

소스는 snippets/aratt에 있습니다. (프로그램 이름은 Arranger for the Relaxed Assembly of TimeTable 에서 따왔습니다. -_-;) 라이선스는 언제나 그렇듯 libpng/zlib license를 적용합니다.

메가박스 취소표를 노려 보자

최근에 BeautifulSoup이 정말 HTML에서 부분 뜯어내기에 좋다는 소리를 듣고, 오늘 영화 예매를 하려고 보던 차에, 주기적으로 취소표 보기가 너무 귀찮은 나머지 아름다운 수프를 마셔버렸습니다. 꿀꺽~ 역시 이름대로 생각보다 훨씬 쉽게 잘 만들었네요.

$ python boxwatch.py
0) 로봇 - 더빙
1) 로봇 - 디지털
... (중략) ...
15) 친절한 금자씨
16) 친절한 금자씨 - 한글자막
17) Mr.and Mrs. 스미스

>> 15
== Available ==
        13:50 (9관)     16:15 (9관)     18:40 (9관)     21:05 (9관)
... (중략) ...
== Unavailable for now ==
        08:00 (3관)     08:20 (1관)     09:00 (9관)     10:25 (3관)
... (중략) ...
        20:25 (1관)
>> 17:15 17:40 18:00
polling...
polling...
polling...

대략 이렇게 나오다가 표가 뜨면 예매 페이지를 웹 브라우저로 띄워줍니다. (파이썬의 webbrowser 모듈에서 지원하는 브라우저이거나 cygwin이면 제대로 뜹니다.)

므흐흐.. 소스는 여기서 받으실 수 있고, 늘 그렇듯 libpng/zlib 라이선스입니다. (파일 인코딩이 euc-kr이니, 소스 브라우저에서는 약간 깨져서 보입니다.

사내 상용 솔루션을 위한 빌드

제가 다니고 있는 회사에서는 조엘식 분류에서 “사내 소프트웨어”에 들어가는, 중규모 솔루션을 주로 만듭니다. 고객사에서 원하는 대로 플랫폼도 바뀌고, 소스 1줄을 수정하려고 해도 고객사에 작업내역서를 보내고 승인받은 뒤에 직접 들어가서 작업을 해야하는데다가 일요일 새벽에만 작업이 가능한 곳도 있고, 문제가 생기면 손해배상도 들어오고 그러다보니, 아무래도 디펜던시가 우찌됐건간에 시스템 기본 라이브러리를 빼고는 모두 직접 옵션 조절해서 컴파일한 것을 깔게 됩니다. 리눅스에서만 돌던 소프트웨어를 갑자기 AIX에서 돌려보자고 하루 전에 연락이 오기도 하고 -_-; 하여간~ 흐흐

그냥 빌드해 놓고 그냥 tar을 들고 댕기던 시절에는, 빌드도 다 손으로 해야하다보니, 밤마다 자동빌드는 커녕, 업그레이드 한번 하려고 해도, 수시간씩 걸리고, 새 플랫폼이 나와도 포팅하는데 하루종일 별의 별 삽질을 다 하게 됩니다. 그래서, 상태를 좀 개선해 보고자 새로 하는 프로젝트에서는, POSIX 플랫폼이면 무난하게 돌아가는 형태의 빌드를 구성해 봤습니다. 흐흐흐.

처음엔 GNU make 기반의 makefile 문법으로 하려고 했었는데, GNU make에서는 for루프와, target 함수 같은 것을 제공하지 않아서, 아무래도 m4같은 것의 도움 없이는 10개 이상의 디펜던시가 있는 패키지를 모두 한꺼번에 빌드하는 게 꽤 힘들었습니다. 그래서 결국은 NetBSD pkgsrc에서 BSD make를 가져다가 자동 빌드하고 그걸로 프로젝트를 빌드하는 방식으로 바꿨는데.. 이러쿵 저러쿵 만들다 보니까 결국은 포트같이 돼 버렸습니다. 그러니까.. 으흐흐. 예를 들면 이렇게~

# Berkeley DB build
# $Id: dep.bsddb.mk 864 2005-06-17 07:22:34Z perky $

NAME=           bsddb
FANCYNAME=      BerkeleyDB
VERSION=        4.3.28
SITE=           http://downloads.sleepycat.com/
DISTFILE=       db-${VERSION}.tar.gz
SRCDIR=         ${WRKDIR}/db-${VERSION}/build_unix

CONFIGURE_SCRIPT=../dist/configure
CONFIGURE_ARGS= \
        --prefix=${PREFIX} \
        --disable-cxx \
        --disable-debug \
        --disable-java --disable-mingw \
        --disable-tcl --enable-static \
        --disable-shared

NO_INSTALL=     yes

.include "submodule.mk"

요걸로 프로젝트를 매일 밤과 점심시간에 자동으로 빌드해서 에러가 나면 메일로 알려주도록 세팅해 두었습니다. 이제 기능을 좀 추가해서, 바이너리 인스톨러 스냅샷 만드는 것과 인스톨 스크립트로 자동으로 인스톨해서 유닛테스트 돌리는 것도 해보려고 합니당. 지금까지 만든 것은 여기에 올려 두었습니다. 디펜던시도 많고 플랫폼도 많은 내부 프로젝트 관리하는 분은 써 보세요. 🙂