삽질하는플머

php-xmlrpc 에서 시간함수 문제

탐구생활/WEB 관련

상황은 이렇다. 


델파이로 만든 XMLRPC 클라이언트에서 "시간값"을 인자로 PHP로 만든 XMLRPC 서버의 함수를 실행하고

이 값을 MySQL의 타임스탬프 필드에 저장하자. 


xml-rpc 의 시간표시는 iso 8601 에 따라 다음과 같이 표시된다.

  • 2011-08-24T00:00:00

xmlrpc.inc 에는 이 형식과 유닉스 타임스탬프 사이의 변환을 위해 iso8601_encode, iso8601_decode 함수가 정의되어있다. 
이렇게 변환한 유닉스 타임스탬프값을 MySQL에 집어넣기 위해 MySQL 내장함수인 FROM_UNIXTIME() 을 사용해 봤는데
클라에서 전송한 시간보다 +9 시간 더 나오는 문제가 발생. iso8681_decode의 두번째 인자에 1을 주어 UTC로 풀어도 마찬가지.

RPC 테스트중인 윈도의 PHP는 현재시간이 UTC로 설정되어있다. 그런데 시스템시간은 한국. 그래서 생기는 문제인 듯. 
실제로 다음과 같은 코드로 타임존을 설정하면 제대로 처리된다.


date_default_timezone_set("Asia/Seoul");


NAS, 또는 우분투의 PHP에서 echo date_default_timezone_get(); 을 찍어보면 Asia/Seoul 이 잘 출력되는 것을 보아 윈도용 WAMP의 PHP에서 시스템의 설정을 읽지 못하는 문제로 보인다. 그렇다고 코드에 저걸 무조건 박아넣기도 골룸.


date로 문자열 꾸미기도 시도해 봄. 


1 $tt = iso8601_decode($ExpireDate);
2 $ts = date("Y-m-d G:i:s", $tt);

하지만 iso8601_decode 내부에서 gmmkttime, 또는 mktime 을 실행시키면서 타임존 문제가 생김. 


뭐가 어쨌건 시스템의 날짜 설정과 무관하게 델파이에서 전송한 시간값을 MySQL에 입력하기만 하면 되므로...
iso8601_decode 의 앞부분을 흉내내 이렇게 만들어 봄. 

1 function iso8601_time_to_mysql($idate) {
2     if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $idate, $regs)) {
3         return sprintf("%s-%s-%s %s:%s:%s", $regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6]);
4     } else
5         return NULL;
6 }    


요는, php의 시간변환 함수를 사용하지 말자는 것. 
비슷한 요령으로 역변환도 만들어 둠. 

1 function mysql_time_to_iso8601($idate) {
2     if (preg_match('/([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})/', $idate, $regs)) {
3         return sprintf("%s%s%sT%s:%s:%s", $regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6]);
4     } else
5         return NULL;
6 }


이제 델파이에서 의도한 시간값이 PHP를 거쳐 MySQL로 제대로 꽂힌다. .



여담으로, date('Z') 로 얻어낸 값에는 현재 설정된 타임존과 UTC 사이의 분단위 시간차이가 들어있다.
GetTimeZoneInformation() 으로 얻어낸 TimeZhoeBias 값과 동일. 그냥 까먹을까봐 적어둠. 




쓰레드에 이름 달아주기

탐구생활/Delphi

쓰레드 코딩을 하다보면... 디버깅창에 줄줄이 나타난 쓰레드가 어디서 만든 뭐하는 녀석인지 궁금할 때가 있다. 

이 때 각 쓰레드마다 이름을 붙여둔다면 심적으로나마 편안함을 얻을 수 있지 않을까... 


물론 디버깅에서만 유효하지만, 좋은 내용이 있어 공유한다. 


http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx

http://blogs.msdn.com/b/stevejs/archive/2005/12/19/505815.aspx


const

  MS_VC_EXCEPTION = $406D1388;

  

type

  TThreadNameInfo = record

    dwType: DWORD;      // Must be 0x1000.

    szName: PAnsiChar;  // Pointer to name (in user addr space).

    dwThreadID: DWORD;  // Thread ID (-1=caller thread).

    dwFlags: DWORD;     // Reserved for future use, must be zero.

  end;


procedure SetThreadName(aThreadID: DWORD; const aThreadName: PAnsiChar);

var

  tmi: TThreadNameInfo;

begin

  if (DebugHook = 0) then Exit; 


  tmi.dwType := $1000;

  tmi.szName := aThreadName;

  tmi.dwThreadID := aThreadID;

  tmi.dwFlags := 0;

  try

    RaiseException(MS_VC_EXCEPTION, 0, sizeof(tmi) div sizeof(LongWord), PDWORD(@tmi));

  except

  end;

end;



사용법은 다음과 같이. 


procedure TForm1.FormCreate(Sender: TObject);
begin
  SetThreadName(GetCurrentThreadID, 'Main thread'); 
end;


IDE의 디버깅창을 들여다보면, 예쁘게 이름이 붙은 쓰레드를 확인할 수 있다 . 



키보드 타입 3 에서 컨트롤+스페이스 사용하는 법

탐구생활/Delphi



맥북에어를 데려왔다. 가볍고 빠르다. 좋다. 

윈도를 올려봤다. 응? 한영키가 없네? 어차피 키보드 타입 3를 쓰니까 패스!

터보델파이를 깔았다. 컨트롤+스페이스가 안먹는다. 우측 컨트롤키가 없으니 좌컨트롤+우컨트롤+스페이스 신공도 안통한다. 

영문 입력기를 추가하고 알트+쉬프트를 며칠 써보니... 익숙치 않은 키입력 때문에 손가락이 꼬이는 느낌이다. 


타입 3 키보드에서 컨트롤+스페이스는 한자변환키이다. 

가만히 생각해보니 IME모드가 영문일 때 이 키는 별로 필요가 없다. 

그렇다면? 입력 포커스를 가진 윈도가 한글입력 상태가 아닐 때 이 한자변환키를 무력화하고

좌컨트롤+우컨트롤+스페이스 키스트로크를 조립해주면 되겠군. 


그래서 탄생한 물건이 이 놈. 



KbdT3Help.7z




한글 IME 에서 영문모드일 때 컨트롤+스페이스 입력을 좌컨트롤+우컨트롤+스페이스 로 변환해준다. 

한 번 실행시키면 동작하고 다시 실행시키면 정지한다. 






이제 좀 살만하네~~


------------



터보델파이로 만든 32비트 어플이지만, DLL을 침투시키지 않기 때문에 64비트 프로세스에서도 잘 돌아간다. 

64비트 윈도7에 띄운 64비트 라자루스에서도 동작함. 

DLL 만들기 귀찮아서 게으름을 피웠는데... 의도하지 않은 "사이드 이펙트"... 훗~!

귀차니즘은 역시 프로그래머의 가장 큰 미덕이다. 


관리자모드로 실행시킨 어플에서도 동작하게 하려면, 이 유틸리티도 관리자모드로 띄울 것. 







2014.3.14. 

PHPer 님의 의견대로, 아무 파라미터나 지정되면 메시지박스를 띄우지 않도록 수정. 

새로 받으세요~~ 





2017.02.16

차일피일 미루다 이제야 github에 등록함. 

https://github.com/oranke/kbd-type3-helper


구글 네이티브 클라이언트 돌려보기

탐구생활/WEB 관련

구글 네이티브 클라이언트는 네이티브 바이너리를 크롬 웹브라우저 내에서 실행시키는 개념으로, 

처음 들었을 때는 "뭐야 이거! 액티브엑스의 크롬버전이잖아???!!!" 라고 현기증부터 났었는데... 

찬찬히 뜯어보고 나니 실행되는 바이너리의 권한을 보안이 강화된 샌드박스 내로 제한함으로서 

나름 지옥문이 열리지 않도록 이것저것 신경쓴 물건 되시겠다. 


OpenGL ES 2.0 기반의 3D 가속도 지원하고 크롬이 실행되는 환경이라면 윈도건 리눅스건 맥이건 가리지 않고 굴러간다. 

또다른 게임 플랫폼으로서 살펴볼만한 가치가 충분하다는 이야기. 


도대체 어떤 물건인지 궁금하니 일단 돌려보자. 

https://developers.google.com/native-client/?hl=ko


윈도에서 Cygwin과 Python 2.6.8을 이용해 테스트하다 실패했다. 역시 이런 거 할 때는 리눅스가 甲이다. 

파이썬 2.6.5 가 깔려있는 우분투 10.04 서버에서 다음과 같이 따라해보자. 

먼저 설치부터. 


$ wget http://commondatastorage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/nacl_sdk.zip

$ unzip nacl_sdk.zip

$ cd nacl_sdk

$ ./naclsdk list

... 뭐라뭐라뭐라...

$ ./naclsdk update

... 현재 안정화버전인 "후추_19" 가 내려온다. NaCL... 소금과 후추라니 네이밍센스 끝내주네!!



설치가 끝났으니 예제를 하나 골라잡이 돌려봐야지. 


$ cd pepper_19/examples/tumbler/

$ make

$ make RUN



5103 포트에 현재 작업 디렉토리에 대한 웹서버가 구동된다. 크롬으로 접속하기 전에 Native Client 설정을 켜주자. 

주소창에 about:flags 입력하고 네이티브 클라이언트 항목을 찾아 체크해준 뒤 제일 밑에 재시작 버튼을 눌러 크롬을 재구동한다. 




이제 우분투 서버의 5103 포트에 접속해 tumbler.html 을 클릭하자. 





오늘은 일단 여기까지. 




우분투 10.04 + phpLiteAdmin 에서 SQLCipher 사용.

탐구생활/Others

phpLiteAdmin 은  sqlite 의 웹 어드민 툴로서 phpMyAdmin 에 익숙하다면 눈이 번쩍 뜨일만한 물건이다. 

이름부터 비슷하다. 사용법도 아주 유사하다. 

게다가 단일 php파일 하나로 되어있어 별다른 설치 없이 웹서버에 올리고 디렉토리에 쓰기 권한만 설정하면 동작한다. 


SQLCipher sqlite3 위에 OpenSSL 기반의 암호화를 지원하는 라이브러리이다. 

PRAGMA key = 'password' 명령을 실행한 뒤 이후 입력되는 테이블, 필드 정보는 모두 인코딩되어 저장된다. 

설정된 암호의 변경은 PRAGMA rekey = 'newpassword' 명령으로 처리할 수 있다. 


문제는, 기존에 만들어진 암호화되지 않은 DB파일에 암호를 설정하는 기능이 없다는 것. 

때문에 phpLiteAdmin 같은 sqlite 어드민 툴에서 작업한 내용을 적용하려면, 적절한 형식으로 출력한 뒤 다시 암호화된 DB파일에 밀어넣어주어야 한다. 적어도 기본 암호라도 설정할 수 있게 해주면 이후 이 파일의 키값만 새로 지정하는 방식으로 작업할 수 있을텐데... 


뭐 DB설계에 경험이 많다면야 이런 도구 없이도 좋은 스키마를 쭉쭉 뽑아내겠지만, 눈으로 봐야만 뭔가 만들 수 있는 나같은 놈에겐 다른 나라 이야기. 


안되면 되게 한다. 삽질은 그래서 의미를 가지지. 



먼저 우분투의 php5에서 sqlite 를 사용할 수 있게 하자. 


# sudo apt-get install php5-sqlite phpt-sqlite3



phpinfo()로 찍어보면 pdo_mysql, pdo_sqlite 가 설치되며 sqlite3 는 따로 설정되어있는 것을 볼 수 있다. 


PDO

PDO supportenabled
PDO driversmysql, sqlite, sqlite2

pdo_mysql

PDO Driver for MySQLenabled
Client API version5.1.61

pdo_sqlite

PDO Driver for SQLite 3.xenabled
SQLite Library3.7.10

........

SQLite

SQLite supportenabled
PECL Module version2.0-dev $Id: sqlite.c 293036 2010-01-03 09:23:27Z sebastian $
SQLite Library2.8.17
SQLite EncodingUTF-8

DirectiveLocal ValueMaster Value
sqlite.assoc_case00

sqlite3

SQLite3 supportenabled
SQLite3 module version0.7
SQLite Library3.7.10

DirectiveLocal ValueMaster Value
sqlite3.extension_dirno valueno value



phpLiteAdmin은 PDO, SQLite3, SQLiteDatabase 세종류의 모듈을 지원한다. 

이 드라이버의 설정은 phpLiteAdmin.php 의 130번째 줄 근처의 


define("FORCETYPE", false);


이 부분을 다음과 같이 수정해 강제로 설정할 수 있다. 


define("FORCETYPE", "PDO");


또는 


define("FORCETYPE", "SQLite3");



그런데 무슨 이유에서인지 이 부분을 SQLite3 로 설정하면 제대로 동작하지 않는다. 

PDO 모듈을 써서 생성된 파일을 메모장에서 열어보면 다음과 같다. 




앞부분에 보이듯 sqlite3 형식인 것으로 보아 PDO의 sqlite 가 sqlite3 를 기본으로 하는 것 같은데... 

좀 더 확실히 하기 위해 ldd로 pdo_sqlite.so 의 dependency 를 살펴보자. 


# cd /usr/lib/php5/20090626+lfs

# ldd pdo_sqlite.so

        linux-gate.so.1 =>  (0x00bfe000)

        librt.so.1 => /lib/tls/i686/cmov/librt.so.1 (0x007d5000)

        libsqlite3.so.0 => /usr/lib/libsqlite3.so.0 (0x00a98000)

        libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x002f4000)

        libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0x0045e000)

        /lib/ld-linux.so.2 (0x00e93000)

        libcrypto.so.0.9.8 => /lib/i686/cmov/libcrypto.so.0.9.8 (0x00110000)

        libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0x00eb7000)

        libz.so.1 => /lib/libz.so.1 (0x006ca000)



예상대로 libsqlite3.so 를 참조하고 있다. 

phpLiteAdmin이 SQLite3 모듈로 잘 동작했다면 sqlcipher 를 기반으로 php5의 모듈을 재빌드해 올리기만 하면 될텐데 싶지만... 

그래도 그나마 다행이다. 


일단 sqlcipher 를 빌드하자. 


# sudo apt-get install tcl tcl-dev libssl libssl-dev

# git clone git://github.com/sqlcipher/sqlcipher.git

# cd sqlcipher

# ./configure --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC" LDFLAGS="-lcrypto"

# make

# sudo make install



윈도에서 빌드는 개삽질인데, 리눅스에서는 TCL만 깔아주면 한방에 끝나네~~
이제 pdo_sqlite.so 가 참조하는 라이브러리를 /usr/local/lib 에 생성된 libsqlite3.so.0.8.6 로 바꿔주면 되는데, 

어차피 sqlcipher는 sqlite3의 모든 기능을 가지고 있고 테스트머신에 이런저런 신경쓰기도 귀찮아서 그냥 /usr/lib 에 복사해 버렸다. 


# sudo cp /usr/local/lib/libsqlite3.so.0.8.6 /usr/lib/



내친김에 기존의 sqlite3 모듈도 새로 만들어 넣어두자. sqlcipher 홈페이지에 잘 설명되어있으니 그대로 따라하면 된다. 

다만 php-5.4.0/ext/sqlite3 소스에 config.m4 파일이 config0.m4 로 되어있으니 phpize 전에 이 이름을 바꿔주는 것만 신경쓰자. 

이렇게 만들어진 sqlite3.so 를 apt-get 으로 설치한 /usr/lib/php5/20090626+lfs/sqlite3.so 와 교체해주고 아파치를 재구동하면 완료. 




남은 문제는 phpLiteAdmin에서 언제, 어떻게 기본 암호를 설정해주느냐 하는 것. 

여기저기 살펴보니 660줄 근처에 Database class 에 정의된 쿼리에 대한 래퍼함수가 눈에 띈다. 이 함수 도입부분에 다음 코드를 추가하자. 


        ........

//generic query wrapper

public function query($query, $ignoreAlterCase=false)

{

$this->db->query("PRAGMA key = '1234';");

if (strtolower(substr(ltrim($query),0,5))=='alter' && $ignoreAlterCase==false) // ......

        ........



이제 수정된 phpLiteAdmin을 우분투의 아파치에서 접근할 수 있게 해주고 DB파일을 만들어보자. 


 



생성된 DB파일을 열어보면 알아볼 수 없도록 암호화되어 저장된 것을 알 수 있다. 




스키마 설계 및 기본정보 입력이 마무리된 파일은 나중에 "PRAGMA rekey" 명령으로 새 암호를 할당해 배포하면 됨. 



phpliteadmin.7z