2009/04/25

client-hello ie firefox RSA SHA1 MD5

SSL の暗号スイートは誰が決めてるのよ? って話になって
この話するの 2 度目なはずなんだけど曖昧な記憶
なので SSL について検索したらサーバが決めてました
client hello でクライアントが使えるリストを提示して
server hello で「じゃぁこれね」ってサーバが選んでるそうです

「じゃぁ、ブラウザは何を提出してるわけ?」って知りませんよねぇ
まぁパケットキャプチャーすれば分かるしサーバいじってもいいのかと思ったら
wireshark で全て解決ということが分かってはいおしまい

というわけにもいかなかったのですが
まぁこんだけ道具揃ってれば絶対誰か調べてるはずなので
ググったらちゃんといらっしゃいました
Tatsuyoshi tech diary
やぁ、すばらしい

ブラウザによってバラバラですね
勉強になりました

2009/04/24

csv python

csv から tsv にしようと思いました
たまに csv だとダメだけど tsv なら平気っていうことに出会ったり
そもそも csv より tsv の方が好きです
ググりました
一杯出てきます

object 指向だと思うともう少しちゃんと書いた方がいいのかしら?と思いつつ
import csv
import fileinput
import sys

tsv = csv.writer(sys.stdout,csv.excel_tab)

for row in csv.reader(fileinput.input()):
tsv.writerow(row)
まぁ簡単でいいや、という気分。
ほんとに変換すればいいんなら
tsv.writerows(csv.reader(fileinput.input()))
でいいのかもしれないけど自重

mod_wsgi

mod_wsgi を使って Django の project を deploy しようとしました
でも WSGI のことは
WSGIとPythonでスマートなWebアプリケーション開発を:第1回 WSGIの概要|gihyo.jp … 技術評論社
で復習しないと曖昧にしか理解できてません、middleware とか
昔一度読んでるのであとは勘が頼りです

apache に mod_wsgi を読ませると wsgi-script という Handler が登録されるみたい
ConfigurationGuidelines - modwsgi - Basic configuration guide for mod_wsgi. - Google Code によると
The WSGI application contained within the code file specified should be called 'application'.

なので
wsgi-script として呼ばれた file に application という関数が定義されていれば
あとは server に渡して動かしてくれます

どうやって wsgi-script だと認識させるかというと
AddHandler, SetHandler, WSGIScriptAlias などを用います
WSGIScriptAlias は ScriptAlias と同じだと思えば OK なはず
これさえ設定してやれば
mod_wsgiでDjangoを動かすまでを淡々と記録する - スコトプリゴニエフスク通信
にあるような sample script はもぉ動くはず
あとは urls.py とか settings.py いじると Django も動く、tryl & error で

でも、これ 1 つの url で動くようになるけど
urls.py にある沢山の URL には対応しない??
試しに沢山ファイル作ったら動いたけどそれじゃ格好悪いし
1 つのファイルで全部受けることにしてあと PATH_INFO っぽい感じでっていうと
AddHandler だと /mysite/index.wsgi/vote/3 とかなるし、格好悪いし
(つうか本当は PATH_INFO ではないと思うんだけど、PATH_INFO って何だ?)
で〜、沢山検索しました
あー、何で ".htaccess" なんて入ってるかっていうと
どうも最初に system の設定 file をいじってるような説明があったので
local で何とかならないかなと思ったからなんですけど

で、結局どうしたかっていうと
SetHandler で拡張子無しで wsgi-script と思わせることにしました
え〜
でもまぁ、仕方ないですよね
Rails のときは lighttpd をサーバにして apache からそれを呼んだんだけど
Django でもそういうのできるのかな?
何かそっちの方がシンプルな気がしてきてるんだけど
また後日ググりましょう

2009/04/23

new.instancemethod

Python で既存クラスに instance method 足せないの? と思ったので
調べてたら結局 new.instancemethod に辿りつきまして検索すると
クラスの挙動まとめ #2 - 大カフェインに辿りつきました
やぁ、ありがたい

#1 があるので #1 から読むと良いですよね
とりあえず、function が class とか instance に対応付けられると (これも束縛と言うの?)
instance method に返信するっていうのが分かりました
あと、class の定義に新旧あるのも知れたので良かったです

小学生の日記みたいになってるな

"recompile with -fPIC" mod_python

Django も勉強したのでデプロイだーと思って
Django のデプロイを見てみたら mod_python を使ったらと
コンパイルしちゃうぞーと思ってコンパイルしてみたら通らない

"recompile with -fPIC" って言われたから検索してみたら
Agile Testing: Compiling mod_python on RHEL 64 bit を発見
Python の Makefile をいじって make install してからやり直したら無事にコンパイルできました
CFLAGS に -fPIC 足しました

mod_wsgi も同様にエラーが出たのだけど同様の方法で解決

にしても blog の記事が 2007/10 なら
何か対応しといてくれても良い気がするんだけど
これは 64bit RHEL 固有の問題なんでしょうか

2009/04/22

数字 変換 python

昨日せっかく n 進表示な str を int に変換したのに
今日はそれをもう一度 str に戻したくなりました
ググりました
とりあえず 16 進でいいよ、と思ったら結局
3.6.2 文字列フォーマット操作でいけました
$ python
Python 2.5.2 (r252:60911, Jan 4 2009, 17:40:26)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> "%o %x %X" % (59, 59, 59)
'73 3b 3B'

Python 2.6 以降? なら
$ python
Python 2.6.1 (r261:67515, Apr 19 2009, 02:16:57)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print format(59, 'b')
111011
>>> print format(59, 'o')
73
>>> print format(59, 'x')
3b
>>> print format(59, 'X')
3B

こんなんもいけるみたい
でも、int みたいな柔軟さのあるのは無いのかなぁ

2009/04/21

16進数 python

Python の OpenSSL のバインディング? っていうと
OpenSSLの本にも載っている M2Crypto
でもこれ SWIG を入れなきゃいけなかったりしてちょっとインストールが面倒
他にも SWIG 使ってる package 使いたいってんならいいんだけど、そうでもないし
SWIG 使ってる何か良いパッケージあるんでしょうか

で、簡単にインストールできるのが pyOpenSSL
これは easy_install でサクっと入ってくれたりするんだけど非力
何が例えば困ったかっていうと
  • X.509 の署名アルゴリズムが取れない
  • SSL で繋いだときのサーバが提示するサーバ証明書以外の証明書が取れない
  • 公開鍵のパラメータが取れない
とかまぁ、ニッチな要望なんですけど

で、patch でも書くかと思っていじっていたんですが
RSA っていうと大きな素数を使います、2 つ
しかも掛け算して 1024bit とか 2048bit でないと表現できないような数字を使うので
OpenSSL は BIGNUM とかって多倍長? って言うんでしょうか、型が用意されていて
その型で計算しています、桁溢れちゃうからね!!
で、pyOpenSSL はどうも BIGNUM をバインドしてくれていない、ひどい

ひどい! と思ったんですがそこで諦めてはいかんと思い
かといって BIGNUM を実装というのは踏み込んではいけない世界な気がして
OpenSSL: Documents, bn(3) を良く眺めてみると
char *BN_bn2hex(const BIGNUM *a);
とある、これは BIGNUM を char で 16 進表示してくれるようでした
string までもってったら Python の int にもできるだろうと思って検索
2-36進数の文字列をint型に変換する - スコトプリゴニエフスク通信にありました
>>> int("0101", 2)
5
>>> int("nishio", 36)
1422284208
おぉ〜

で、これを C で書かないといけないので include/python2.6/intobject.h をチェック
PyAPI_FUNC(PyObject *) PyInt_FromString(char*, char**, int);
名前からして何かこれっぽいけど、何だこの第二引数は、ということで更に "PyInt_FromString" で検索
7.2.1 (通常)整数型オブジェクト (plain integer object)
素晴しい、日本語だ
で、どうも NULL で良いらしいので NULL にしたら無事大きな数字が出てきました

NULL ってのはアドレス 0 を挿すポインタのことらしい
要するに 0?

結局どうなったかっていうと
static PyObject *
crypto_PKey_params(crypto_PKeyObj *self, PyObject *args)
{

PyObject *params;

if (!PyArg_ParseTuple(args, ":params"))
return NULL;

params = PyDict_New();

if (self->pkey->type == EVP_PKEY_RSA) {
if (self->pkey->pkey.rsa->n != NULL)
PyDict_SetItem(params, PyString_FromString("n"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.rsa->n), NULL, 16));
if (self->pkey->pkey.rsa->e != NULL)
PyDict_SetItem(params, PyString_FromString("e"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.rsa->e), NULL, 16));
if (self->pkey->pkey.rsa->d != 0)
PyDict_SetItem(params, PyString_FromString("d"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.rsa->d), NULL, 16));
if (self->pkey->pkey.rsa->p != NULL)
PyDict_SetItem(params, PyString_FromString("p"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.rsa->p), NULL, 16));
if (self->pkey->pkey.rsa->q != NULL)
PyDict_SetItem(params, PyString_FromString("q"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.rsa->q), NULL, 16));
if (self->pkey->pkey.rsa->dmp1 != NULL)
PyDict_SetItem(params, PyString_FromString("dmp1"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.rsa->dmp1), NULL, 16))
;
if (self->pkey->pkey.rsa->dmq1 != NULL)
PyDict_SetItem(params, PyString_FromString("dmq1"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.rsa->dmq1), NULL, 16))
;
if (self->pkey->pkey.rsa->iqmp != NULL)
PyDict_SetItem(params, PyString_FromString("iqmp"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.rsa->iqmp), NULL, 16))
;
} else if (self->pkey->type == EVP_PKEY_DSA) {
if (self->pkey->pkey.dsa->p != NULL)
PyDict_SetItem(params, PyString_FromString("p"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.dsa->p), NULL, 16));
if (self->pkey->pkey.dsa->q != NULL)
PyDict_SetItem(params, PyString_FromString("q"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.dsa->q), NULL, 16));
if (self->pkey->pkey.dsa->g != 0)
PyDict_SetItem(params, PyString_FromString("g"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.dsa->g), NULL, 16));
if (self->pkey->pkey.dsa->priv_key != NULL)
PyDict_SetItem(params, PyString_FromString("priv_key"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.dsa->priv_key), NU
LL, 16));
if (self->pkey->pkey.dsa->pub_key != NULL)
PyDict_SetItem(params, PyString_FromString("pub_key"), PyInt_FromString(BN_bn2hex(self->pkey->pkey.dsa->pub_key), NULL
, 16));
}

return params;
}
こんなんになっちゃったんだけど、何か格好悪くない?
誰かに直して欲しい、あと、unittest の書き方も教えて欲しい
つか先ず BIGNUM をバインドしてほしい

あ、ちなみに、Ruby の source を中々参考にしました。

python query_string parse

Django でとある API を叩こうとしたんですが
その返事が改行で区切るか application/x-www-form-urlencoded っぽいのかの二択
まぁ前者は面倒だろうから後者で、と思って検索しました
21.16. urlparse — Parse URLs into components — Python v2.6.2 documentation
Python はもお 2.6.2 が出てるんですねぇ、でも Unicode で少しバグがあるとか
Python 2.6.2 リリース && 日本人に取っては割とキツいバグ混入 - methaneの日記
気をつけたい

$ python
Python 2.6.1 (r261:67515, Apr 19 2009, 02:16:57)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import urlparse
>>> urlparse.parse_qs('a=1&b=2&a=3&c=%E3%81%82')
{'a': ['1', '3'], 'c': ['\xe3\x81\x82'], 'b': ['2']}
>>>
うん、何かまぁ、良さそう

"TEMPLATE_DIRS"

Django のチュートリアル? を読みまして
その分かり易さにいたく感動したので
というわけでなく元々何か作ろうと思っていたからですが
何か自分で作るべと思いました

ミニマリストですからなるべく小さな環境を構築したいと思います
なので認証など不要かと思われるものは削ってみたり
で、「カップリングを無くすのだ!!」と書いてある割に
チュートリアルでは template は Django の project で持っていたので
application 毎に持てるに違いないと思って検索しました

議論されてまとめられてて言うことなし

settings.py の INSTALLED_APPS に application が登録してあれば
その application の directory 下の templates は捜してくれるってことでした
TEMPLATE_DIRS は空でも問題なしでした
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
)

INSTALLED_APPS = (
# 'django.contrib.auth',
# 'django.contrib.contenttypes',
# 'django.contrib.sessions',
# 'django.contrib.sites',
'mysite.polls'
)
何ならここまで削っても OK

あと、絶対パスで書いてね、ってのが何か気持ち悪かったんだけど
ROOT_PATH = os.path.dirname(__file__)

ってが書いてあるのを見て少し気分が良くなりました

2009/04/19

latex packate "line number"

他人と LaTeX の修正をしようとしていて
pdf 化したものの「p.5, l.3 の the は」とかいうともぉ気が狂いそう
で、確か行数を表示する package があったよなと思ったら、ありました
lineno ってのがあるらしい

debian (lenny) 使ってるので
$ auto-apt search lineno
usr/share/texmf-texlive/tex/latex/lineno/ tex/texlive-humanities
usr/share/doc/texlive-doc/latex/lineno/ doc/texlive-humanities-doc

texlive-humanities を入れてプリアンブルに
\usepackage{lineno}
\pagewiselinenumbers

って書いたら行数出ました
\linenumbers でもいいらしいです

openCRX sugarcrm

openCRX っていう CRM ソフトの名前を聴いたので少し調べました
で、まぁ対抗馬は SugarCRM なのかなと思って比較とか捜すと
エンタープライズ・オープンソース[ベスト・セレクション]第1回:業務アプリケーション : オープンソース
他にも沢山のオープンソースな CRM が紹介されてました

以前 SugarCRM を少し真面目に調べてたことがあったんだけど
帳票とかの機能があったりして素敵だなと思ったりしても
どうも日本語の対応が怪しい感じを受けたりして見送ってしまいました
あれ、Module Builder の日本語対応があんま好みでなかったんだっけな?
でもそれは対応方法が書いてあったような気が、あれ? 結論は何だったっけ?

日本語対応バッチリを望むってことなら salesforce なんでしょうけどねぇ...

つか、この連載がちょっと面白そうかな?

openCRX は openCRX Users Japan ってのができたみたいだし
デモもあるみたいなので興味倍増中