Home

日記
trac拡張探訪 BlogEdit

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にコピーしたら動いた。

Published At2006-02-14 00:00Updated At2006-02-14 00:00

日記
trac拡張のセキュリティEdit

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文法仕様的にできることが限られているとか)

単純に拡張のソースを見て、そこで対策を何もしてなさそうならばイントラ向けだ(公開して使うな)と考えるべきなのかなー。

*1 やっぱりsprintf相当だった。http://www.python.jp/doc/release/lib/typesseq-strings.html

Published At2006-02-14 00:00Updated At2006-02-14 00:00

日記
.egg系pluginを使う場合は前準備が必要だったEdit

tagsが動かなかったのは、TracPluginsに書かれているように、あらかじめsetuptoolsをインストールしていなかったのが原因だった。

setuptoolsをインストールしたら、tags(をはじめ、.egg系拡張機能)もちゃんと動くようになった。

Published At2006-02-14 00:00Updated At2006-02-14 00:00

日記
trac拡張探訪 AccountManagerPluginEdit

.egg系拡張なんで、これもsetuptoolsをあらかじめインストールしておく必要がある。あとこれはソース配布されているんで、自分でpython setup.py bdist_eggしてから、dist/*.eggをpluginディレクトリにコピーする。

で、説明通りにパスワードファイルの位置と書式をtrac.iniに書くと、ナビゲーション部分に

  • ログイン済みの場合は、自分のパスワードを変更する機能へのリンクが追加される
  • 未ログイン(anonymous)の場合は、自分のアカウントを追加する機能へのリンクが追加される(らしい。テスト環境の都合で実際に試してない。ソースを読んだだけ)

って、2番目の機能はちょっとうれしくないなー。管理者のみ新規アカウントを追加できるとかだと、いろいろ使えるんだけど。いやでも、権限設定いかんでは、それでもなんとかなるかなー。場合によっては、これを参考に自前の権限管理拡張を作った方がいいかも。

Published At2006-02-14 00:00Updated At2006-02-14 00:00

日記
trac拡張探訪 WebAdminEdit

これも.egg系なのでsetuptools必須。.egg形式で配布されているので、バージョンのあったものをpluginディレクトリに入れるだけで動く。

内容としては、TRAC_ADMIN権限を持つユーザーがアクセスすると、ナビゲーションに「Admin」というリンクが用意され、そこから

  • General - 一般設定
    • Basic Settings - プロジェクト名とかURLとか
    • Logging - ログ種別やファイル名
    • Permissions - アカウント、グループに対する権限設定
    • Plugins - 拡張機能のインストール(.eggファイルをアップロードする)・削除(権限が許せば無効化もできる)
  • Ticket System - チケット設定
    • Components - 以下は説明いらないよね
    • Priority
    • Seberities
    • Ticket Types

あたりが設定できる。あると便利そう。

Published At2006-02-14 00:00Updated At2006-02-14 00:00

日記
trac拡張探訪 AuthzWebadminPluginEdit

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……。

Published At2006-02-14 00:00Updated At2006-02-14 00:00

日記
trac拡張探訪 GraphvizPluginEdit

Graphvizで図が描けるプラグイン。もちろんGraphvizが必要。trac.iniの[graphviz]セクションに、作成した図の画像ファイル置き場(cache_dir)とそこにhttpでアクセスする際のパス(prefix_url)、Graphviz関連バイナリのパス設定が必要。

プラグイン自体は動いたんだけど、図中に日本語を使うために試行錯誤中。なんとなくgdの再コンパイルからやらないといけない気配なんだけど、今のところあまり必要としていないから、そこまで試さないかも。

Published At2006-02-15 00:00Updated At2006-02-15 00:00

日記
trac拡張探訪 WikiNotifyScriptEdit

Wikiの更新をメールで通知してくれる、という概要を読んで入れようと思ったんだけど、よく見たらこれはtracの拡張ではなく、tracのdbを直接読んでデータを取得する、独立したpythonスクリプトなのね。cronで定期的に回して使うような使い方の。

まあそれはそれで便利なんだろうけど、trac以外のところで管理しなければならないものはあまり使いたくないなー。というわけで試してない。

Published At2006-02-15 00:00Updated At2006-02-15 00:00

日記
trac拡張のセキュリティ 2Edit

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:

みたいにした方がいいってことだね。まあコード全部見てないんで、この部分以外がどうなのかは知らないけど。

Published At2006-02-16 00:00Updated At2006-02-16 00:00

日記
参照を持つオブジェクトや配列の比較 解決編Edit

参照を持つオブジェクトや配列の比較で書いた、

$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のどこかのバージョンで、参照を含むオブジェクトや配列のシリアライズが正常に動作するようになったはず。古いバージョンだとダメかもしれないけど。

Published At2006-02-16 00:00Updated At2006-02-16 00:00