2006-02-01 [長年日記]
_ PocketBloglinesでときどきネットワーク接続ができなくなる件
原因が分かった気がする。なんか腐ったDNSに当たって名前解決自体ができなくなっているっぽい。WILLCOM任せで自動で割り当てられたDNSサーバーの中に、おかしな情報を返してくるやつが混ざってない? 試しにDNSサーバーをWILLCOM任せにせずに、別プロバイダのDNSサーバーを使うように設定を変えてみたら、今のところ上記の症状が発生していない。
ちなみにそれに気づいたのは、その状態の時にIEで、かなり昔にサーバーを切り替えたサービスにアクセスしようとしたところ、もうキャッシュ期間もとっくに過ぎているはずなのに、切り替え前の古いサーバーにアクセスしにいったから。
2006-02-02 [長年日記]
_ 今度から車で行こう
昨日は福岡からオクサンが子供二人連れて帰ってくるのを空港まで迎えに行ったんだけど、地震の影響で飛行機が1時間ほど遅れ、さらに電車(京浜東北線)もぐだぐだになっていて、非常にぐったりと疲れる帰り道になった。行きの場合は飛行機の出発時間に遅れるわけにいかないから電車を使うのもありだろうけど、今度から帰りの迎えには必ず車で行くことを決意。あるいは、うちの近所で乗り捨てOKなレンタカーを空港で借りるってのが一番いい気もするな。今度調べておこう。
2006-02-03 [長年日記]
_ Webアプリとバッチで共通に扱うデータファイルの権限
Webアプリ(Apacheモジュールで動作するphp=httpd権限)とバッチ(コマンドラインアプリ)で共通に扱う(書き込み権限が必要な)データファイルがある場合、どのように取り扱うのが一番いいんだろう。
- ファイルを作成するときに誰でも書き込み可にする
- ファイルを作成するときにグループ書き込み可にして、httpdユーザーとコマンド実行ユーザーのグループをあわせる
- コマンド実行ユーザーは、httpdユーザーにsudoしてコマンドを実行する
- (シェル利用可能な)コマンド実行ユーザー=httpdユーザーにする
- コマンドはrootで実行しちゃえ!
キャッシュとかは1だったんだけど、キャッシュ以外のファイルを扱う場合は3かなー。2はやったことないけど、うまく設計すれば使いやすいだろうか? 外部ライブラリに依存していて、データファイルの権限を(ライブラリの中をいじらないと)コントロールできない場合も3だろうな。4は危険すぎるんで却下と思いつつも、ユーザー権限を適切に絞れるならばそれもありか? 5は緊急避難用?
2006-02-04 [長年日記]
_ Log_mailが飛ばない
PEAR Log_mailが動かないんで、おかしいなーとずっと調べていて、ようやく原因を見つけた。Log 1.9.3ではLog::factoryが生成したオブジェクトのリファレンスを正しく返してくれていないんで、shutdown functionでflushするタイミングでメール送信しているLog_mailでは、shutdown functionがflushするインスタンスと、ログをためているインスタンスが異なるものになってしまって、メールが飛ばないんだった。明示的に$logger->flush();したらメールが飛んだんでようやく気がついた。bug report
2006-02-06 [長年日記]
_ ブログサービスの XSS 脆弱性対策はいらない
不勉強なのでわからないのだけれど、何らかの理由で、はてなでは管理画面のドメイン変更がスクリプト制限に神経を遣うより高コストなのかな?
たいていのblogサービスではいわゆる管理機能のみでユーザー認証(のCookieによる継続)を利用しているけど、はてなの場合は「管理機能」だけではなく、一般ユーザーレベルの閲覧操作でも「ユーザー認証」されていることを活用し、SNS的な機能(閲覧ユーザー権限による分岐。たとえばプライベートモードとかはてなグループとか)を実現している。だからはてなでは、管理機能だけを別扱いにするだけでは、XSS(によるユーザー認証の乗っ取り)対策にはならない。はてなのSNS的な機能をオフにするか、現在とはまったく違った(閲覧ユーザー認証が乗っ取られたときの危険性を許容範囲まで下げるような)システムデザインで実装し直すか、する必要がある。
ちなみに今はクリティカルな部分(ポイントの扱いとか退会処理とか)は別認証になったから、ずいぶん認証が乗っ取られたときの危険性は下がったけど、昔(住所登録騒動が起こる前)はクリティカルな操作も同じ認証で行っていた。逆に言うと、現在は分離されているクリティカルな操作に関する認証以外の部分は、はてなのサービス全体の設計およびユーザービリティ的に分離できない部分なんだと思う。というのは憶測。
2006-02-07 [長年日記]
_ ブログサービスの XSS 脆弱性対策はいらない その2
しかし、いくつかの仕組みを変更すれば、なりすましの回避とスクリプトの利用許可は両立できるはずなのです。
技術的にどういう問題があるのか理解した上でそういう主張をするのならば、それはそれでありだと思う*1。ただ、はてなはもちろん初めからそういう技術的な知識を元に検討を行った上で、現在のシステムデザインを採用しているわけだろうし、「ユーザビリティを下げたら対応できる」的な話は、デザインの好み(どれもそれなりに妥当な選択肢のうちのどれを選ぶか)の問題だからなー*2。
ちなみにCookieを盗難されたくなければ、別にドメインごと換えなくたって、パスで有効範囲を絞ったっていいんで、たとえばドメイン「d.hatena.ne.jp」+パス「/ishinao/edit」で範囲を絞ったCookieを発効すれば、http://d.hatena.ne.jp/ishinao/edit以下でしか有効でない(XSSで盗難されない)認証を処理したりもできる。ドメインを換えることは必須ではない*3。
*1 レンタルサーバーとは全然違うんで、それを並立させて比べるのは論外。あと認証盗難がありうる場におけるXSS対策においては、ブラクラとかの話は基本的に関係ない。何もJavaScriptを使わなくてもブラクラを作ったり危険な外部リンクを踏ませたりできるわけだし
*2 ちなみに俺は現在のはてなのシステムデザイン(一つの認証ですべてのサービスが利用できる=複数サービスを連携した仕組みが作りやすい)の方が、認証範囲を狭く区切り必要に応じていちいちログインするような仕組みよりも、好み。ただ俺ならそういうデザインでユーザーに自由なHTML+CSS入力を許可しないけど
*3 ドメイン保持者にとって、ドメインCookieというものがセキュリティ的に非常に重要なポイントであることは確かだけど
2006-02-08 [長年日記]
_ 徳保さんのはてなXSS関連の認識の間違い
あるいは「ブログサービスの XSS 脆弱性対策はいらない その3」。
徳保さんはセキュリティ関係の知識が足りていないんで、きちんと勉強するまではXSSなどのセキュリティ関係の用語を使わないで語った方がいい。というか誤解を広げめられると迷惑だ。
「d.hatena.ne.jp 以下のコンテンツでスクリプトの悪用はありません、なぜならはてなが特別に許可したスクリプト以外は使用が制限されているからです」という安心感を売り物にしようとしている
はてなはCookieによるユーザー認証を利用しており、ユーザーに自由なJavaScriptを許すと、認証情報の盗難・悪用が可能になるから、ユーザーのJavaScript利用を禁止している。それは「安心感を売り物にしている」というレベルではなく、ユーザー認証を利用したサービスを提供しているサービス提供者の最低限の義務であり、それを行わずに被害がでた場合は、サービス提供者が責任を負わされるだろう。
その提供しているサービス内容に付随する義務としてのセキュリティ対策の話と、認証の仕組みを換えれば(ユーザビリティや根本的なサービスのデザインを換えれば)、ユーザーがJavaScriptを利用できるサービスは実現可能だ、というのような、提供するサービス内容自体を変更可能であるという議論とは次元が違う話である。
私がこのサイトにはてなアカウントにログインしているユーザ向けのトラップを仕掛けることは可能です。みなさんは、ただ私を信じているだけでしょう。
現在はたまたまCSSXSSというIEの致命的なセキュリティの欠陥が修正されないまま放置されており、それによって本来サービス外部からは成功しないはずの攻撃が成功してしまう。しかし、これはCSSXSSという非常にたちの悪い欠陥が放置されていることに原因があり、それがなければサービス外部からCSRFによって攻撃することはできないはずだ。
また、外部に攻撃コードが置かれた場合と、サービス内部に攻撃コードが置かれた場合とでは、サービス提供者にかかる責任の重さは圧倒的に違う。特にサービス内部(認証Cookieが読める場所)に攻撃コードが仕掛けられた場合は、認証情報の盗難というリスクがあり、外部からの攻撃とは攻撃の質がまったく異なる。
利用する楽観的なユーザーが実際に被害に遭う前にどう思うかは関係なく、なんらかの攻撃が成功した場合に、サービス提供者にかかる責任はどのくらい重いのか、が対策するべきかどうかの指標だろう。認証Cookieが読める場所でユーザーのJavaScript利用を許可していた場合、既知の攻撃に対して対策をしていなかったことになり、サービス提供者の責任は重くなる。
ちなみに、はてながCSSXSS対策をするべきかどうかについては、議論が分かれる部分だが、私は以前メモで書いたとおり、
CSSXSSはサーバー側のコーディングで対応できるレベルを超えた穴なんで、ブラウザ(IE)側で対処するべきだと思う。CSSXSS対策まで含めてWebアプリを作るとなると、安全を考えれば設計からやり直しになっちゃうし。
と考えている。CSSXSSは(もしそれへの対策が必須と言われた場合)既存のWebセキュリティに関する常識を覆すほど、大きな影響が出る問題だ。
「はてなダイアリーにはいいユーザも悪いユーザもいます。悪いユーザは退会させます」これでいいと思う。
全然よくない。というか、徳保さんははまちやさんの仕掛けるわかりやすいデモンストレーションのようなものが、XSSの代表例だと思っているのではないか? あれはあくまでもわかりやすいデモンストレーションであって、本来のXSSによる攻撃の危険性はああいうものにはない。
悪質な(本来警戒すべき)XSSによる攻撃は、認証情報を盗み、それを利用して認証情報で保護されたはずの情報を盗み、あるいは認証情報で保護されたはずの機能を利用し、それでいて利用者にはそのようなことが起こっていることをまったく気づかせない、というものだ。そのような攻撃はそう簡単には発覚せず、発覚しない間に被害は広がっていく。そのような攻撃でも、(攻撃が見つかったら)その仕掛けたユーザーを排除すればそれで対策は十分?
文章が修正されました
徳保さんの「ブログサービスの XSS 脆弱性対策はいらない」は「ブログサービスの設計思想とユーザ側の制約」というタイトルに代わり、XSSなどのセキュリティ用語をほとんど使わない内容に変更されました。変更後の文章表現ではもともとの文章にあった問題(セキュリティ関連の用語の使い方の間違いやその意味あいに対する誤解)がなくなっており、私が当初挙げた問題点は一掃されていると思います。
2006-02-09 [長年日記]
_ 脆弱性と攻撃と対策
閲覧者の安全はほどほどに守れば十分だの方にもちょっと反応しておこう。
ブラウザの脆弱性を突いて行われる攻撃については、「その通り」と回答します。
一方、ブラウザが仕様通りの動作を行っても、サービスの設計のまずさゆえに可能となってしまう攻撃に関しては、(私の価値観においても)なるほど許容範囲外だと思いました。
念のために書いておくと、あの部分の文章はあくまでも「XSSの攻撃は、はまちやさんの仕掛けるようなすぐに攻撃の存在が発覚するそれほど実害が大きくないものなんだから、攻撃者はすぐ特定できるし、見つけたら攻撃者を排除するだけで十分なのに、なんではてなはあんなに一生懸命XSS対策をしているの? 不要でしょ? っつーか俺たちにJavaScriptを使わせろや!」という徳保さんのもともとの主張(だと私が読み取ったもの)全体に対して、それは徳保さんが根本的にXSSというものを理解していなかったから、そう思ったんじゃないの?と問いかけているのであって、「対策は十分だと思うか、思わないか」の答えを直接的に聞いているわけではないので。いや別に答えてもいいけど。
ここからはかなり余談。
対策するべきかどうかを考えるときに、原因となる脆弱性が「ブラウザの実装にある」のか「サービスの実装にある」のか、という二つのみを並列させて論じることには、あまり意味がない*1。攻撃は、ブラウザもしくはサーバーの何らかの脆弱性を利用するものが多いが、ブラウザもしくはサーバーの脆弱性(ここでは特にプログラムレベルでの不具合)を利用しない攻撃もある。
まず、基本的にフリーテキストを解釈して処理を行うブラウザにおいては、実装側の自由度はかなり高く、それが脆弱性なのかブラウザの仕様なのか、明確には区別できないので、何らかの怪しげな挙動があったとしても、それが脆弱性であると言い切れない*2。あまり一般的ではないけど、実はこういうこともできるんだよ、というだけの話かもしれない*3。
特にJavaScriptに関して言えば、もともとがただのプログラミング言語なわけだから、そこで実現できることの自由度は非常に大きい。単に「攻撃」というだけならば仕様の範囲内でも非常に多様なことが可能だ。いわゆるJavaScriptによるブラクラなんて少しも脆弱性とは関係ない。信頼できないActiveXコントロールをインストールしたらキーロガーが常駐した、などというのも脆弱性とは関係なく、ブラウザの仕様通りの挙動だ。
また、ブラウザの脆弱性が発見された場合、もちろんその脆弱性を修正できるのはブラウザ制作者であって、サービス提供者がブラウザを修正するなんてことはできない。できるのは、その脆弱性を利用したなんらかの攻撃に対して、対策を取ることだけだ。
そして、ブラウザの脆弱性を利用した攻撃のすべてに、サービス提供者側で対策できるものではない。脆弱性の内容によっては、サービス提供者側では対応できないものもあるだろう。たとえばCSSXSSに関しては、それを利用したいくつかの攻撃に対策することは不可能ではないが、それはあくまでも場当たり的な対処であり、本質的な対策*4は不可能であると考えているので、サービス側での対応はされなくても仕方がないと考える*5。
逆に、ブラウザの脆弱性を利用した攻撃だとしても、それへの対策はサービス側でも容易に実現でき、しかもその脅威が十分に高いのならば、サービス側はブラウザ側の対策を待たずに対応した方がいいだろう。
サービスの実装に原因がある脆弱性を利用した攻撃は、対策しなくていい理由は思いつかないなー。まあ脅威の度合いが低ければ、すぐに対策する必要はないだろうけど、必ずいつかは対策するべきだよね。
|
要するに ある攻撃の 大元の原因が ブラウザにあるか サービスにあるか よりも その攻撃の 危険性 緊急性 その攻撃への対策が 可能かどうか の方が 重要 ってこと |
_ プラグイン追加
|
tDiaryに category_to_tagと bigpresenを 追加した でも 白文字 テーマだと 文字が 読めないんで bigpresen.rbの 71行目の styleに color:blackを 追加した |
*1 考慮するべき要素は、その2択では代表されない
*2 CSSXSSのようなものは、過去のWebセキュリティに対する各所の取り組みの経緯から考えて、本来そのようなことがあってはならない挙動だから、IEのセキュリティに関する不具合の一つだと言い切ることができるけど
*3 腐ったHTMLを適当に読み替えてくれたり、サーバーは画像データだと言っているのにHTMLとしてレンダリングしようとしたり
*4 CSSXSSに本質的に対策しようと考えるならば、GETアクセス可能なセキュリティで保護された領域に、セキュリティで保護されていることを前提とした情報を出力してはならない、となってしまう
*5 もちろんはてなのXSS対策自体も場当たり的と言えば言えるが、はてなのXSS対策はある程度収束した状況においての「場当たり的」であり、まったく収束していない状況に置ける「場当たり的」とは意味が異なる
2006-02-10 [長年日記]
_ bigpresenいいなー
ぐだぐだ長文を書いたあとに、まとめをbigpresenで書いておくというスタイルは、結構使えそう。場合によっては、まずbigpresenで概要を書いてから、詳しい話を後に書いた方がいいかもね(本文を読まない人が増えそうだけど)。
_ tracに日記インターフェースがあれば
CodeBlogを見ていて思ったんだけど、tracにWeb日記インターフェースがついていたらプログラマー系Webサイト構築にすごい便利じゃねー? バックエンドは標準のWikiシステムでいいんだけど、あれに、
- 日付をキーにしたテキストを手軽に書くためのインターフェース
- そのページ群のインデックスをわかりやすくまとめるインターフェース
を追加して、FrontPage相当がその表示になればそれでいい。tracの拡張機能を書けるようになるために、まずpythonを勉強するべきか……。
_ 参照を持つオブジェクトや配列の比較
こんな感じのコードが、
$foo =& new stdclass();
$foo->foo =& $foo;
if ($foo === $foo) {
echo 'equal';
} else {
echo 'not equal';
}
無限再帰になってしまうのは、仕様なんだろうか?(PHP 4.4.0/Windows、4.4.1/Linux) var_dumpとかはちゃんとRECURSIVEを見つけて止めてくれるのに。
→解決編へ
_ オブジェクトを含む配列にin_array
ついでにもう一つ。
$foo =& new stdclass();
$array = array(
$foo,
);
if (in_array($foo, $array)) {
echo 'found';
} else {
echo 'not found';
}
みたいなコードは、Wrong datatype for first argumentになるのも仕様なのか。まあちゃんとエラーメッセージが出るから仕様なんだろうけど、
Note: In PHP versions before 4.2.0 needle was not allowed to be an array.
とは書いてあるけど、objectはダメとは書いてないんだよな。
っつーかまあさっきの問題とこれとは同根で、オブジェクト同士の比較がうまくいかない(場合がある)から、in_arrayでオブジェクトが指定できないんだろうな。
せめてis_referenceとかができるなら、自前で実装できるんだけど、ある変数がリファレンスかどうかを判別する方法(別の変数と比較して同じシンボルテーブルを差しているかどうかがわかる、あるいは、そのシンボルテーブルを差す変数が複数存在するかどうかがわかる。)ってないよね。var_dumpのソースを見ればやり方は分かるんだろうけど。
2006-02-11 [長年日記]
_ bigpresenのBloglines対応
Bloglinesだとbigpresenで出力している部分が読めないんで、JavaScriptなしだと内容をホワイトスクリーンに初めから表示しておくようにしてみた(ついでにちょっとだけメッセージも変えてある)。
Index: bigpresen/trunk/bigpresen.rb
===================================================================
--- bigpresen/trunk/bigpresen.rb (revision 1)
+++ bigpresen/trunk/bigpresen.rb (revision 2)
@@ -48,5 +48,5 @@
else {
t#{scriptID} = 0;
- document.getElementById("#{scriptID}").innerHTML="《REPLAY》";
+ document.getElementById("#{scriptID}").innerHTML="《CLICK to REPLAY》";
document.getElementById("#{scriptID}").style.fontSize='100%';
}
@@ -69,8 +69,13 @@
<tr>
<td width="#{width}" height="#{height}" onClick="#{scriptID}()" valign="middle" align="center" bgcolor="#ffffff">
-<span id="#{scriptID}" style="line-height:100%; color:black;">《START》</span>
+<span id="#{scriptID}" style="line-height:100%; color:black;">#{str.tr('/', ' ').split(/\|/).join('<br>')}</span>
</td>
</tr>
</table>
+<script type="text/javascript">
+<!--
+document.getElementById("#{scriptID}").innerHTML = "《CLICK to START》";
+-->
+</script>
HTML
end
なんで
splitしてjoinしているんだろう? tr("|", "<br>")でいいのに。何をやろうとしていたんだっけ。
2006-02-13 [長年日記]
_ trac関連のメモ
複数tracプロジェクトは同じディレクトリ(/path/to/tracprojects/tracs)に配置した方がいい*1。同一ディレクトリ下のプロジェクト群を、tracdはまとめて管理してくれる。
関連するsubversionレポジトリについても、レポジトリ同士*2は同じディレクトリ(/path/to/tracprojects/svns)に作っておけば、mod_dav_svnでSVNParentPathとAuthzSVNAccessFileを組み合わせて、そのディレクトリ内のレポジトリをまとめて管理できる*3。
また、tracdもmod_dav_svn経由のsubversionも、同じhtpasswd互換のパスワードファイルを使って認証することができるので、tracとsubversionで共通のアカウント管理が可能。
tracプロジェクトの管理ユーザーの追加(*4)は、
trac-admin /path/to/tracproject permisson add [adminuser] TRAC_ADMIN
ただし、すべての管理をWeb経由でできるわけではないので、ある程度trac-adminあるいは/path/to/tracproject/conf/trac.iniをいじる必要がある(WebAdminPluginを要チェック)。
ネットワーク的にオープンな場所でクローズドなtracプロジェクトを運用するためには、tracを完全認証制(未ログイン者は閲覧アクセスもできない)にする設定方法があるのかどうか探す必要がある(anonymousからあらゆる権限をremoveすればいいのかな?)。
標準のCSS(文字が小さい)が気に入らない人は、/path/to/tracproject/templates/site_css.csをいじる。たとえば、
<?cs
##################################################################
# Site CSS - Place custom CSS, including overriding styles here.
?>
body {
font-size: 1em;
line-height: 1.5em;
}
とか*5。
SVNParentPathを使ってマウントしたsubversionレポジトリ(http://example.com/[someproject])に対して、svn co http://example.com/[someproject]ができないな*6。svn co file:///path/to/[someproject]はできるんだけど。これは仕様なのかな? それとも俺の設定がどこかおかしいのかな?
デザイナーとかと共同作業をする際に、subversion(というかバージョン管理システムという概念)を説明しないままに、そこそこの恩恵を受けてもらおうというアプローチ案。smbで適当なディレクトリをマウント(/path/to/someproject/smb)し、そこにある時点のexportをコピーする。デザイナーにはそこをマウントして作業してもらう。そして、別にcoしたディレクトリ(/path/to/someproject/work)を用意し、そこに作業ディレクトリの内容を定期的にsync*7&commit*8すると、作業履歴がsubversionに残る*9。こうすることで、.svnディレクトリの存在とかに気を遣わずに、自由に編集ができる。ただこの方法と、ふつうのsubversionの使い方とは相容れないんで、作業ディレクトリの切り方とかを考えておく必要がある*10
とか書きながらsubversion関連のドキュメントをながめていたら、subversion 1.2以降ではWebDAVの自動バージョン化なんて機能が使えるようになっていたらしい。デザイナーとの共同作業とかで使うならこっちの方がいいかな? でもWebDAVディレクトリってsmbと比べると微妙に不便なんだよなー。
全部の権限を削除したらエラーが出た
trac-admin remove /path/to/project permission remove anonymous BROWSER_VIEW LOG_VIEW FILE_VIEW CHANGESET_VIEW TICKET_VIEW TICKET_CREATE TICKET_APPEND TICKET_CHGPROP TICKET_MODIFY TICKET_ADMIN MILESTONE_VIEW MILESTONE_CREATE MILESTONE_MODIFY MILESTONE_DELETE MILESTONE_ADMIN ROADMAP_VIEW ROADMAP_ADMIN REPORT_VIEW REPORT_SQL_VIEW REPORT_CREATE REPORT_MODIFY REPORT_DELETE REPORT_ADMIN WIKI_VIEW WIKI_CREATE WIKI_MODIFY WIKI_DELETE WIKI_ADMIN TIMELINE_VIEW SEARCH_VIEW CONFIG_VIEW
ってやったら*11、tracdの該当のプロジェクトにアクセスすると
Oops...
Trac detected an internal error:
iteration over non-sequence
Traceback (most recent call last):
File "/usr/lib/python2.3/site-packages/trac/web/standalone.py", line 303, in _do_trac_req
dispatch_request(path_info, req, env)
File "/usr/lib/python2.3/site-packages/trac/web/main.py", line 139, in dispatch_request
dispatcher.dispatch(req)
File "/usr/lib/python2.3/site-packages/trac/web/main.py", line 80, in dispatch
req.perm = PermissionCache(self.env, req.authname)
File "/usr/lib/python2.3/site-packages/trac/perm.py", line 276, in __init__
self.perms = PermissionSystem(env).get_user_permissions(username)
File "/usr/lib/python2.3/site-packages/trac/perm.py", line 132, in get_user_permissions
for perm in self.store.get_user_permissions(username):
File "/usr/lib/python2.3/site-packages/trac/perm.py", line 218, in get_user_permissions
for user, action in rows:
TypeError: iteration over non-sequence
というエラーが出るようになった。権限が一個もなくなると、きっと権限チェックをiterationで回しているあたりでエラーが出るんだろうな(ソース未確認)。権限が空でも動くように直せばいいのかな?
ちなみに権限を適当に一個addしておけばエラーは出ず、ほとんどの機能はつぶれてくれる(WIKI_VIEWもつぶれるんで、主要な情報は何も表示されなくなる)んだけど、ヘッダ・フッタ回り+ユーザー設定メニューが見えちゃうんで、ちょっと気持ち悪いんだよな。本当はヘッダ・フッタ回りも完全に消えて、/loginを直接叩かないと何も見えない方がいいんだけど。
tracdとCGI起動の重さの違い
日常的に負荷状況が高いサーバーで、tracd(+Apache2リバースプロキシ)と(Apache2)CGI起動のtracを同時に動かしてみたところ、tracd経由の方が圧倒的に軽かった。っつーかCGI起動は重すぎだな。mod_pythonって手もあるけど、手軽さからいうとtracdを基本にした方がいいかな。トップページの表現力に難があるが。
_ えいご漬け
オクサンが買ったんでやらせてもらったけど、なかなかいい感じ。
今やっている範囲では、高校生レベル程度までの簡単な英語しか出てきてないけど*12、ほどよく忘れかけている単語や言い回しを思い出させてくれる。あと文章として読まれたときの聞き取りって学校ではほとんどやってなかったから、そこかしこに新しい発見(と慣れ)がある*13。これをしばらくやっていたら、単文の聞き取りはだいぶうまくなりそう。
ただ、さほど難しくない単語で構成された単文に関しては、もともと聞き取るのは難しくないんだよな。問題は、沢山の文章を連続して聞き取ろうとしているときに、一カ所でも意味を把握できない場所が出てくると、その後の文章がなし崩しに全部聞き取れなくなっちゃったりするところなんだけど、英語の聞き取りに慣れてきたら、そういうのもなんとかなるのかな。
そういやこのゲームをやっていて思ったんだけど、プログラムを日々書いていると、結構幅広い英単語を使っているんだなー。変数名とか関数名とかクラス名とかで使われる英単語(人のつけたもの、自分でつけるもの)って、いわゆる技術系単語以外にもいろいろあるから、結構沢山の英単語の意味と綴り方をちゃんと覚えていた。漢字なんかはもうほとんど覚えていないのに。
_ labelがあった方がいいよね
tDiaryでは、管理機能のチェックボックスにlabelが指定されていないけど、あった方が便利だよね*14。ということで、自分が使っている範囲のところに追加してみた。
でもこういうことは、場当たり的にやらずにちゃんと網羅的にやった方がいいんだろうな。あとlabel for="[ID]"を使うとinput type="checkbox"にidが必要になるんだけど、他の場所とのidの重複が怖いんで、専用のネームスペース(っつーかprefix)を使った方がいいかもしれない。
update.rhtml
*** update.rhtml.org 2006-02-13 18:05:49.000000000 +0900
--- update.rhtml 2006-02-13 18:22:31.637861952 +0900
***************
*** 38,44 ****
<input type="submit" tabindex="999" accesskey="A" name="<%%= submit_command %>" value=" <%%= submit_label %> ">
</span>
<span class="checkbox hidediary">
! この日の日記を隠す<input type="checkbox" name="hide" value="true" <% unless @diary.visible? then %>checked <% end %>tabindex="1000" accesskey="H">
</span>
</div></form>
</div>
--- 38,44 ----
<input type="submit" tabindex="999" accesskey="A" name="<%%= submit_command %>" value=" <%%= submit_label %> ">
</span>
<span class="checkbox hidediary">
! <label for="hide">この日の日記を隠す</label><input type="checkbox" name="hide" id="hide" value="true" <% unless @diary.visible? then %>checked <% end %>tabindex="1000" accesskey="H">
</span>
</div></form>
</div>
***************
*** 59,68 ****
@diary.each_comment( 100 ) do |comment| %>
<div class="commentator">
<span class="checkbox">
! <input class="checkbox" type="checkbox" tabindex="<%=2000+idx%>" name="<%= idx += 1 %>" value="true"<% if comment.visible? then %> checked<% end %>>
</span>
<span class="commentator"><%= CGI::escapeHTML( comment.name ) %><%= CGI::escapeHTML( " <#{comment.mail}>" ) unless comment.mail.empty? %></span>
<span class="commenttime"><%%=comment_date( Time::at( <%=comment.date.to_i%> ) )%></span>
</div>
<p><%= comment.body.make_link.gsub( /\n/, "<br>" ).gsub( /<br><br>\Z/, '' ) %></p><%
end
--- 59,70 ----
@diary.each_comment( 100 ) do |comment| %>
<div class="commentator">
<span class="checkbox">
! <input class="checkbox" type="checkbox" tabindex="<%=2000+idx%>" name="<%= idx += 1 %>" id="cid_<%= idx += 1 %>" value="true"<% if comment.visible? then %> checked<% end %>>
</span>
+ <label for="cid_<%= idx %>">
<span class="commentator"><%= CGI::escapeHTML( comment.name ) %><%= CGI::escapeHTML( " <#{comment.mail}>" ) unless comment.mail.empty? %></span>
<span class="commenttime"><%%=comment_date( Time::at( <%=comment.date.to_i%> ) )%></span>
+ </label>
</div>
<p><%= comment.body.make_link.gsub( /\n/, "<br>" ).gsub( /<br><br>\Z/, '' ) %></p><%
end
ping.rb
*** ping.rb.org 2006-02-13 18:14:32.000000000 +0900
--- ping.rb 2006-02-13 18:17:43.915602384 +0900
***************
*** 84,91 ****
def ping_edit_proc
r = <<-HTML
<div class="ping">
! <input type="checkbox" name="plugin_ping_send" value="true" checked tabindex="400" />
#{@ping_label_send}
</div>
HTML
end
--- 84,93 ----
def ping_edit_proc
r = <<-HTML
<div class="ping">
! <input type="checkbox" name="plugin_ping_send" id="plugin_ping_send" value="true" checked tabindex="400" />
! <label for="plugin_ping_send">
#{@ping_label_send}
+ </label>
</div>
HTML
end
makerss.rb
*** makerss.rb.org 2006-02-13 18:18:15.032871840 +0900
--- makerss.rb 2006-02-13 18:18:49.595617504 +0900
***************
*** 301,308 ****
checked = @cgi.params['makerss_update'][0] == 'false' ? ' checked' : ''
r = <<-HTML
<div class="makerss">
! <input type="checkbox" name="makerss_update" value="false"#{checked} tabindex="390" />
#{@makerss_edit_label}
</div>
HTML
end
--- 301,310 ----
checked = @cgi.params['makerss_update'][0] == 'false' ? ' checked' : ''
r = <<-HTML
<div class="makerss">
! <input type="checkbox" name="makerss_update" id="makerss_update" value="false"#{checked} tabindex="390" />
! <label for="makerss_update">
#{@makerss_edit_label}
+ </label>
</div>
HTML
end
*1 シンボリックリンクを使ったりする手もあるけど
*2 「tracプロジェクトと同じ」ではないよ
*3 snvserveは使ったことがないので、そっちを使うとどういうことができるのか未検討
*4 最初TRAC_ADMINに気づかずにWIKI_ADMIN、TICKET_ADMINとかいちいち追加してたよ
*5 ひな形テンプレートを書き換えようと思ったんだけど、/usr/share/trac/templatesにはsite_css.csがないなー。どこにあるんだろう
*6 /に対してPROPFINDすると301 Moved Permanentlyが返って終了になるみたい。subversion 1.3.0
*7 rsync -r --delete --exclude="*.svn" /path/to/someproject/smb /path/to/someproject/work
*8 svn commit /path/to/someproject/work -m "auto commit" -q
*9 これだけだと削除したファイルがレポジトリから消えないんで、その辺は別途svn deleteする処理をかます必要がある
*10 デザイン系ディレクトリは上記方法にして、プログラム系ディレクトリはふつうにcommitするとか。あるいは自動コミットの処理をもうちょっと頭よくして対応できるかな?
*11 ちなみに上記はTracPermissionsからコピっただけで、不要なエイリアスとかも混ざってる
*12 その後難しい単語が出てくるのかどうかは知らない
*13 設定で、日本語訳は答えが出た後に表示するようにしないと、聞き取りではなく、単に日本語を英文に翻訳してしまって、聞き取りの練習にならない
*14 チェックボックス自体をクリックしなくても、その説明文とかをクリックしてチェックボックスのオン・オフを切り替えることができるようになる
2006-02-14 [長年日記]
_ trac拡張探訪 tags
tracのWikiページにタグ入力と、タグ一覧・タグクラウドなどの表示をするためのマクロを追加するらしい。
けど、http://muness.textdriven.com/trac/wiki/tags/Setupを見ながらセットアップしようとしても認識してくれない。eggとcsテンプレートを追加して、trac-admin [project] upgradeしてもno upgrade necessaryになる。よくわからん。
まああまり使い勝手が良さそうでもないんで、使えないなら使わなくてもいいかも。
動いた
setuptoolsをあらかじめインストールしておかないと、.egg系拡張は動かないということだった。
で、実際に使ってみたんだけど、ページ入力時にいちいち別枠でタグを入力しなければならないってのと、TagListとかTagCrowdsとかに、現在使われているタグ(その回数)が表示されるのはいいけど、そこからのリンク先が単にタグ名のWikiページ(通常は用意されていない)になってるのはつまらないなー。そのタグを利用しているページ一覧とかにリンクされているのがふつうだと思うんだけど。どこかで設定すればそうなるのかな?
_ trac拡張探訪 AddCommentMacro
Wikiページにコメント欄を追加するマクロ。wiki-macrosに突っ込むだけで動く。プレビュー付きの本文+投稿者フォームが表示され、投稿するとフォームの上に投稿内容が追加されるというシンプルな作り。
これは用途によっては結構使えそう。コメント本文でWiki記法がフルに使えるのも便利。
_ trac拡張探訪 FootNoteMacro
脚注マクロ。zipを展開し、tracのバージョンにあわせた.pyをwiki-macrosにコピーするだけで動く。
[[FootNote(脚注の文章)]]で脚注を書いていくと、そこが連番数値リンク付き表示に変わる。んでもって、文末なんかに[[FootNote]]と書くと、そこが実際の脚注文章のリンク先になる。
便利は便利だけど、tDiaryのfnみたいに[[FootNote]]がなければ、自動的にページ末に脚注を表示してくれると楽なのになー。
_ trac拡張探訪 WikiCalendarMacro
一月分のカレンダーを表示し、各日に対して指定した書式のWikiページへのリンクを張る。簡単に日付をタイトルの一部として使ったページへのナビゲーション(編集&閲覧)を用意することができるので、後で紹介するBlogマクロと組み合わせると、日記風の使い方が可能になる。
_ trac拡張探訪 Blog
Blogという名前が付いているけれども、いわゆるBlog機能を持っているわけではなく、
- 特定の名前パターン(たとえば「Blog/%」とか)を持つWikiページを、更新が新しい順にまとめて表示する
- だから、blog的な内容は特定の名前パターン(たとえば「Blog/2006/02/14」とか)で書くようにしておけば、その最新の内容がまとめて表示される
- WikiCalendarMacroと組み合わせて、[[WikiCalendar(Blog/%Y/%m/%d)]][[Blog(Blog/%)]]とかしておけば、カレンダーナビゲーション+Blog風表示が実現できる
といった感じのもの。
Blog.2.pyの方をダウンロードして、Blog.pyという名前でwiki-macrosにコピーしたら動いた。
_ trac拡張のセキュリティ
Blogマクロのソースをちらっとながめていたんだけど、pythonって、
blogPattern = blogPattern.strip() sql = "SELECT DISTINCT name from wiki where name like '%s' order by time desc" % blogPattern
なんて感じで、Prepared SQLみたいなことができるのかな? それとも単なるsprintf(エスケープなし)かな? 多分「%」って演算子で%sのところにblogPatternが埋め込まれているんだよね。stripは単なるtrimみたいだし。*1
Blogマクロに限らないんだけど、tracの拡張全般に関して、セキュリティ的にどうなっているんだろう? 上記のような処理だと、ふつうに考えればマクロの呼び出し側でいろいろできちゃいそうだよね。
tracレベル、あるいはpythonライブラリレベルで何か対応されているのかな?(ある程度のセキュアさが保たれる仕組みを持っているとか) あるいはDB(sqlite)レイヤーで何か対応されている?(コアのテーブルとは権限が分離してあるか、あるいはsqliteのSQL文法仕様的にできることが限られているとか)
単純に拡張のソースを見て、そこで対策を何もしてなさそうならばイントラ向けだ(公開して使うな)と考えるべきなのかなー。
_ .egg系pluginを使う場合は前準備が必要だった
tagsが動かなかったのは、TracPluginsに書かれているように、あらかじめsetuptoolsをインストールしていなかったのが原因だった。
setuptoolsをインストールしたら、tags(をはじめ、.egg系拡張機能)もちゃんと動くようになった。
_ trac拡張探訪 AccountManagerPlugin
.egg系拡張なんで、これもsetuptoolsをあらかじめインストールしておく必要がある。あとこれはソース配布されているんで、自分でpython setup.py bdist_eggしてから、dist/*.eggをpluginディレクトリにコピーする。
で、説明通りにパスワードファイルの位置と書式をtrac.iniに書くと、ナビゲーション部分に
- ログイン済みの場合は、自分のパスワードを変更する機能へのリンクが追加される
- 未ログイン(anonymous)の場合は、自分のアカウントを追加する機能へのリンクが追加される(らしい。テスト環境の都合で実際に試してない。ソースを読んだだけ)
って、2番目の機能はちょっとうれしくないなー。管理者のみ新規アカウントを追加できるとかだと、いろいろ使えるんだけど。いやでも、権限設定いかんでは、それでもなんとかなるかなー。場合によっては、これを参考に自前の権限管理拡張を作った方がいいかも。
_ trac拡張探訪 WebAdmin
これも.egg系なのでsetuptools必須。.egg形式で配布されているので、バージョンのあったものをpluginディレクトリに入れるだけで動く。
内容としては、TRAC_ADMIN権限を持つユーザーがアクセスすると、ナビゲーションに「Admin」というリンクが用意され、そこから
- General - 一般設定
- Basic Settings - プロジェクト名とかURLとか
- Logging - ログ種別やファイル名
- Permissions - アカウント、グループに対する権限設定
- Plugins - 拡張機能のインストール(.eggファイルをアップロードする)・削除(権限が許せば無効化もできる)
- Ticket System - チケット設定
- Components - 以下は説明いらないよね
- Priority
- Seberities
- Ticket Types
あたりが設定できる。あると便利そう。
_ trac拡張探訪 AuthzWebadminPlugin
WebAdminプラグインに、subversionのAuthzファイルの編集機能(単にtextareaで更新)を追加するプラグインらしいんだけど、動かない。
.eggを作ってpluginディレクトリに突っ込み、trac.iniの[trac]セクションにauthz_file = "/path/to/authz"して見たんだけど、(ソースを見る限りは出てくるはずの)GeneralにAuthz Controlが追加されないなー。
Oh! No!
動かない原因が分かった。
authz_file = "/path/to/authz"
じゃなくて、
authz_file = /path/to/authz
だったよorz……。
*1 やっぱりsprintf相当だった。http://www.python.jp/doc/release/lib/typesseq-strings.html
2006-02-15 [長年日記]
_ trac拡張探訪 GraphvizPlugin
Graphvizで図が描けるプラグイン。もちろんGraphvizが必要。trac.iniの[graphviz]セクションに、作成した図の画像ファイル置き場(cache_dir)とそこにhttpでアクセスする際のパス(prefix_url)、Graphviz関連バイナリのパス設定が必要。
プラグイン自体は動いたんだけど、図中に日本語を使うために試行錯誤中。なんとなくgdの再コンパイルからやらないといけない気配なんだけど、今のところあまり必要としていないから、そこまで試さないかも。
_ trac拡張探訪 WikiNotifyScript
Wikiの更新をメールで通知してくれる、という概要を読んで入れようと思ったんだけど、よく見たらこれはtracの拡張ではなく、tracのdbを直接読んでデータを取得する、独立したpythonスクリプトなのね。cronで定期的に回して使うような使い方の。
まあそれはそれで便利なんだろうけど、trac以外のところで管理しなければならないものはあまり使いたくないなー。というわけで試してない。
2006-02-16 [長年日記]
_ trac拡張のセキュリティ 2
trac拡張のセキュリティで疑問に思った件については、TracDev/DatabaseApiにその辺の話が書いてあった。
At any cost, try avoiding the use of string formatting to get values into the SQL statement. The database automatically escapes values you pass using execute() arguments, the same is not true if you use string formatting. If you absolutely cannot avoid it, be sure to apply the sql_escape function in trac.util to all parameters you're passing in, to avoid possible SQL injection attacks:
具体的には、
cursor.execute("SELECT author,ipnr,comment FROM wiki WHERE name=%s", [thename])
だとDBライブラリが正しくエスケープしてくれるけど、自前で%演算子とか使って結合するんだったら、明示的にsql_escape関数を使ってエスケープしなきゃダメよ、という話。
だから、前に例に出したBlogマクロだったら、
*** Blog.py.org 2006-02-16 09:15:06.000000000 +0900
--- Blog.py 2006-02-16 09:16:54.053072208 +0900
***************
*** 49,57 ****
for blogPattern in args.split(','):
blogPattern = blogPattern.strip()
! sql = "SELECT DISTINCT name from wiki where name like '%s' order by time desc" % blogPattern
csName = db.cursor() # the matched wiki name
! csName.execute(sql)
while 1:
rowName = csName.fetchone()
if rowName == None:
--- 49,57 ----
for blogPattern in args.split(','):
blogPattern = blogPattern.strip()
! sql = "SELECT DISTINCT name from wiki where name like %s order by time desc"
csName = db.cursor() # the matched wiki name
! csName.execute(sql, [blogPattern])
while 1:
rowName = csName.fetchone()
if rowName == None:
みたいにした方がいいってことだね。まあコード全部見てないんで、この部分以外がどうなのかは知らないけど。
_ 参照を持つオブジェクトや配列の比較 解決編
参照を持つオブジェクトや配列の比較で書いた、
$foo =& new stdclass();
$foo->foo =& $foo;
if ($foo === $foo) {
echo 'equal';
} else {
echo 'not equal';
}
というコードが実行できない件、PHPコードレベルでの解決策を思いついた。
$foo =& new stdclass();
$foo->foo =& $foo;
if (serialize($foo) === serialize($foo)) {
echo 'equal';
} else {
echo 'not equal';
}
なら動作する。確かPHPのどこかのバージョンで、参照を含むオブジェクトや配列のシリアライズが正常に動作するようになったはず。古いバージョンだとダメかもしれないけど。
2006-02-21 [長年日記]
_ PHP+fastcgiでPATH_INFO
lighttpd+fastcgi+PHP 4.4.1で、php.iniでcgi.fix_pathinfoを有効にしてPATH_INFOが使えるようにしたところ、http://example.com/foo.php/http://example.com/みたいなPATH_INFOを渡しても、PATH_INFOとしてhttp://example.com/ではなくhttp:/example.com/(「//」が「/」になる)が返ってくるんだけど、これって設定で何とかならないのかなー。
2006-02-22 [長年日記]
_ 納税証明書がない
車検の季節がやってきて、また納税証明書が見あたらない。ということで、久しぶりに永福の杉並区出張所に行ってきた。ああだりい。
_ 1470.netリニューアル計画
長々やってきたストレスの溜まる仕事が一区切りついたんで、1470.netの全面リニューアル計画に着手することにした。ひとまず周辺ライブラリを地味にそろえて実験しながら、方向性を固めていこう。
_ どっちがましだろう
Trackback vs Pingbackを読んだだけで、元文章はどっちも読んでいないんだけど、ひとまずtrackbackとpingbackを比べてみると、
- trackback
- いいところ
- 実装・利用例が多く、すでにデファクトスタンダード化している
- (URLのみやりとりするping backと比べると)得られる情報量が多い
- 悪いところ
- 仕様レベルでノーセキュリティ。SPAM対策が難しい。
- trackback ping URLの仕様うざ。機械専用の情報を人間様に入力させようとは、何事か。
- auto discoveryの仕様もうざ。ないよりはましだし、動くことは動くけど。
- trackback ping URLのせいで、リンク先URL、通知先(ping)URLを二重管理しなければならない。しかもその二つを結ぶラインは、auto discoveryという非常に弱いラインしかない。
- 文字コード問題には現行仕様では対応している(結局初期の頃にshiroさんが言っていた仕様になったってことか)けど、実装レベルで対応しているところはほとんどなさそう。仕様のアップデートに関するアナウンスよわっ。
- いいところ
- pingback
- いいところ
- シンプル&スマート。逆に言うと、必要最低限。
- 人間は単にリンクするだけでOK(どこにどうやって送信するかなんて意識しなくていい)。
- URLと受信するサーバーとが切り離されている(HEADなどに受信サーバーURL(固定)を入れておくだけでいい。trackbackもある程度は切り離せるけど、エントリー単位の情報は共有する必要がある)
- 悪いところ
- ほとんど使われていない。
- これも特にセキュリティはないな。利用例が少ないからターゲットになっていないだけだろう。
- 情報量が少ない(URL情報しか持っていない)。
- いいところ
ちなみにpingbackは2、3年前に調べて以来全然見ていないから、現行仕様では何か変わっているのかもしれない(けど、きっと変わってないと思う)。
とか書いていて思ったけど、trackbackはWindowsライクな仕様(リッチだけど穴を塞ぐのが難しい設計)で、pingbackはUNIXライク(シンプルなツールを、外部と(パイプで)つないで使いこなしてね)な仕様、なんてイメージが重なるな。
現行trackbackの利点って、すでにデファクトスタンダード化しているところだけって気もするし、いろいろ問題点を解消しようとした結果、現行仕様と互換性がなくなったりするようならば、何もtrackbackにこだわる必要はないよなー、とは思う。
っつーか今更URLをキーにつながるなんてチープなことは考えずに、みんなHyper Estraierの全文検索機能を持って、P2P連携を使って全文検索でつながっちゃったほうが話が早いじゃん、ってのはどうだろう。まあP2P連携もそんなに大量のノードはつなげられないだろうから(ってHyper EstraierのP2P連携機能は使ったことないけど)、動的ノード解決の仕組みを考える必要があるかな。
ってなんだかずいぶん話が発散したな。
_ script.aculo.usにすることにした
そろそろAJAX関連も実用レベルで使い始めなきゃなーって感じなんだけど、たくさんあるライブラリ群を調べる気力がない(し、高度なJavaScriptライブラリたちを正しく評価する能力もない)んで、雰囲気でscript.aculo.usを基本ライブラリとして使うことに決めた。これってスクリプタキュラスって読むの?
フレームワーク的な部分とユーティリティ的な部分を(script.aculo.usの一部として使われる)prototype.jsに任せ、基本的なエフェクト処理をscript.aculo.usに任せる、ってイメージでいいのかな? あとYahoo!のUIライブラリあたりを部品として使いたいんところだけど、JavaScriptレベルでバッティングとかしちゃわないかな?
_ サーバーとクライアントでテンプレートを共有したい場合
データとテンプレートの配置 その3で書いたように、同じURL引数違いで出力フォーマットを変えるインターフェースを、作ったり使ったりして試してみている。基本的な方向性は悪くなさそう。
- データ層 - ここは好きにやる
- 汎用データ取得層 - ここは汎用クラスとして一般的なインターフェースを持たせる
- アプリケーション用データ取得処理 - アプリケーション内で共用するインターフェースとして作る(キャッシュとかはここでかます)
- データ出力層 - HTML、XML、JSON、TXTなどリクエストに応じて、形式を変えて出力する
なんて感じで作ってみている。
で、そういう作り方をしていると、データ出力層では出力形式に合わせて複数のテンプレートを使い分けたりするわけだけど、どうせならばHTML形式の場合に、リクエスト側でHTML展開する時に使うテンプレートファイルを指定できるようにしておけば、それでいいんじゃないかって気がしてきた。
JavaScriptでがりがり出力したい場合は、
http://example.com/path/to/resource?format=json
とかやって、JSON形式で受け取ったデータをJavaScript側でDOM操作なりJavaScriptテンプレートエンジンなりを使って出力してやればよく、たいていの場合はその方法を使うことになるんだろう。その場合の流れは、
- クライアント - サーバーにリクエストを投げる
- サーバー - データをJavaScriptが扱いやすいフォーマットで返す
- クライアント - 受け取ったデータをJavaScriptネイティブな変数に展開する
- クライアント - DOM操作やJavaScriptテンプレートを使って、データを出力する
どうしてもサーバーサイドにあるテンプレートを使いたい場合は、
http://example.com/path/to/resource?format=html&template=templatename
とかやって、必要に応じてサーバーサイドで部品レベルのテンプレート展開処理をしてもらい、その結果を受け取ればいい。その場合の処理は、
- クライアント - サーバーにリクエストを投げる
- サーバー - データを指定されたテンプレートで展開したHTMLとして返す
- クライアント - 受け取ったHTMLをそのまま表示する
ただしこういうやり方は、サーバーサイド実装者とクライアント実装者が同じ場合にはやりやすいけど、そうじゃない場合(たとえば別管理者が公開しているリソースを利用したい場合)はそう簡単にはいかない。
けど、その場合はクライアント実装者が、自前のサーバーに簡単なプロキシ(+テンプレート展開エンジン)を用意すればいいだろう。その場合の流れは、
- クライアント - プロキシにリクエストを投げる
- プロキシ - リソース提供サーバーにリクエストを投げる
- リソース提供サーバー - プロキシにリソースデータを返す
- プロキシ - 受け取ったリソースデータとローカルのテンプレートを使ってHTML展開処理を行う
- プロキシ - 展開したHTMLをクライアントに返す
- クライアント - 受け取ったHTMLをそのまま表示する
なんて感じか。
ひとまずそういう方向でいろいろ実験してみる。
2006-02-23 [長年日記]
_ だりぃ&ねみぃ
今日は、寝不足+車のバッテリー上がり+子供のお遊戯会で保育園まで徒歩で2往復+重いバッテリーを買って歩いて帰る+気の重い打ち合わせ、が重なり、非常にだりぃ&ねみぃと書いていたら、頭の中で「Darry and Nemmyの二人が大活躍! カートゥーンネットワークでこの後すぐ!」というCMが流れた。デクスターとディディ姉弟みたいなキャラクターが主役で、話の内容はエドエッドエディみたいな感じ。5年後くらいに新番組として始まったら、これはただの妄想ではなく、予知妄想だったってことになるでしょう。っつーか眠い。
2006-02-24 [長年日記]
_ しょうがない、認めてやろうじゃないか
一昨日あたりから急激に来ていたんだけど、もしかして風邪でもひいちゃったかな、なんて自分をごまかしていたりしたんだけど、そろそろごまかしきれないんで、認めてやろうじゃないか。今年も花粉がばりばり来てますよ! 病院行ってこよう。
2006-02-27 [長年日記]
_ 早くも開幕戦
土曜日には早くも草野球の今シーズン開幕戦だった。最近いろいろ忙しくてスポクラにもろくにいけていない状態だったんで、体力的にはかなりぐだぐだ。でもまあピッチングは4回2失点ですんだんで、そんなに悪くなかった。バッティングは全然だめ。4打席で3三振1内野フライだったかな? なんかバットが全然思ったところに振れない。当てにいっても芯に当たらないし、振りにいったらかすりもしない。ボールは見えているつもりなのになー。で、翌日からは予想通りの筋肉痛となり、現在老人のような動きしかできません。
_ ひどい状態キープ
金曜日に病院に行こうと思っていたんだけど、打ち合わせが長引いていけなかった。しょうがないんで土、日は市販の鼻炎カプセルでごまかしていたんだけど、あれを飲むと眠くなりすぎて何もできない。でも、飲まないでいると鼻水と目のかゆみで何もできないしなー。今日はとっとと病院に行ってこよう。
_ 病院に行ってきた
いつもと同じタリオン錠10mgを3週間分と、緊急用にポララミン錠2mgを5日分。タリオン錠が聞き始まるまでは5日くらいかかるんで、それまでは抗ヒスタミン薬のポララミンで症状を抑えるがよろし、とのこと。ポララミンの方は眠気が出るらしいんで、仕事の時は使わない方が良さそうだな。
_ 今更C++でcgiなんて
書くはめになるとは思ってなかったよ。でもsqliteのおかげでデータ管理はだいぶ楽できそう。


Before...
_ ishinao [プログラマとかです。]
_ a [大学院卒プログラマですか?]
_ ishinao [いいえ。]