Aug 26, 2004

SQLiteをMovable Typeで使ってみる

「Movable Typeのマイナー機能を使ってみる」シリーズ第二弾。第一弾は「Ogawa::Buzz: mt-view.cgiを使ってみる」。

あまり知られていないことですが、MT3.1の「テンプレートごとに管理可能なダイナミックPHPページ生成」機能はBerkeleyDBでは動作しません。3.1でこの機能を使いたい人はMySQLかPostgreSQLかSQLiteにとっとと移行する必要があります。

3.1ではMySQLでないと駄目のようです。PostgreSQLとSQLiteには順次対応するとのこと。

このうち、MySQL、PostgreSQLは三層Webアプリケーション構築においてはごくメジャー(かつ安価)なソリューションである一方、計算機に親しみ切れていない人々にとっては取っ付きの悪いのも事実です。そこで考えてみたいのは、やはりSQLiteっていうのは何なのかということです。

SQLite home page

PHP5に標準でバンドルされるようになったのでご存知の方も多いとは思いますが、SQLiteはデータベースサーバではありません。構造データの操作をSQL言語で行うためのユーザーレベルライブラリです。MySQLのようなクライアント・サーバー型のDBサーバとは異なり、別のサーバプロセスを起動したり設定したりする必要もないため、非常にお手軽です。自分のソフトウェアにDB機能を組み込んで配布するのにも向いています。例えば、POPFile(POPFile - Automatic Email Classification)などにもSQLiteが組み込まれています。

また、SQLiteではデータベース単位に一個のイメージファイルが作成されます。テーブル単位でファイルが複数作られるBerkeleyDBや、dumpに少しワザ(Ogawa::Buzz: Lolipopの MySQL データベースを簡単バックアップするCGIスクリプト)が必要なSQLサーバに比べると、より容易にバックアップできます。

また、SQLite Database Speed ComparisonにあるようにMySQLやPostgreSQLよりかなり高速に動作するようです。この比較には実はtrickがあるのですが、それに関しては後で触れます。

前説はこのくらいにして以降では使い方などについて述べます。

インストール

mt-check.cgiでDBD::SQLiteモジュールが見つからなければインストールする必要があります。CPAN(search.cpan.org: Matt Sergeant / DBD-SQLiteからダウンロードできます。また、SQLite home pageからは何もダウンロードする必要はありません。DBD::SQLiteモジュールにすでにバンドルされているためです。

注意する点としては、現状最新の1.0.4(SQLite 3.0.4beta相当)はMovable Typeからうまく使えないので、0.3.1(SQLite 2.8.12相当)をインストールしなくてはならないということです。インストール方法は、Techknow Movable Type: CPANモジュールのインストール方法の「CPAN シェルを使わずにインストールする」を参考にしてください。CPAN Shellで「install DBD::SQLite」とかやってしまうと、最新版がインストールされてハマること請け合いです。

2005-02-26にDBD-SQLite 1.08(SQLite 3.1.3相当)がリリースされ、Movable Typeから正常に使えるようになりました。

レンタルサーバへのインストール

最近のLolipopのレンタルサーバでは、DBD-SQLiteはインストール済みのようです。その場合には下記のファイルは不要です。

通常、レンタルサーバにはDBD-SQLiteはインストールされていないようです。Lolipopで使いたい場合には以下のいずれかのzipファイルをダウンロードしてください。

Lolipop-DBD-SQLite-0.31.zip (182KB)
Lolipop-DBD-SQLite-1.08.zip (195KB)

このzipファイルを展開すると得られるSQLite.soを$MT_DIR/extlibに、SQLite.pmを$MT_DIR/extlib/DBDに、それぞれコピーすると使えるはずです。ロリポップ以外でも環境によっては利用できると思います。

設定方法

mt.cfgで以下のように設定します。DBUser、DBHost、またmt-db-pass.cgiは設定する必要がありません。

ObjectDriver DBI::sqlite
Database mtdb
# DBUser <database-username>
# DBHost localhost

Databaseで指定するのはDBイメージのファイル名です。上記のように単に「Database mtdb」と指定するとmt.cfgがあるディレクトリにmtdbというイメージファイルが作られます。「Database db/mtdb」とするとdbディレクトリの中にmtdbというイメージファイルが作られます。

あとはTechknow Movable Type: Movable Type のインストールなどを参照して適宜インストールするだけです。

性能

SQLite Database Speed Comparisonの計測結果にも関わらず、SQLiteの処理速度(特にINSERT、UPDATE)はそれほど高くはないと言われています。端的に言うと、SQLite(およびDBD-SQLite)の既定の動作(AutoCommitモード)では、書き込みを伴うSQLオペレーション一個ごとにグローバルロックを獲得し、物理ファイルイメージ上での処理が完了する(ありていに言ってfsyncが返るまで)まで離さないのです。したがって連続するINSERT/UPDATEは、非常に効率が悪くなります。上記URLにあるような一般的なSQLサーバに対する優位性を主張するのはやや強引と言えるでしょう。

もちろん、ユーザライブラリの実装としては、通常オペレーション発行後プログラムが異常終了する可能性を考えたら当然の選択です。その代わりに明示的にトランザクション区間を定義すれば、Commit時にのみ反映されるようになって効率は劇的に改善します。

Satoshi's Blog : SQLite の INSERT は遅いのか?
【特集】生まれ変わるPHP - Zend Engine 2、SQLiteの実力は? (8) MySQLとSQLiteの比較 - 大量のデータの書込みでは? (MYCOM PC WEB)

Movable Typeではと言うと、常にAutoCommitしています。そこで、仮にCGIの実行一回を一個のトランザクション区間とみなすように改造したもの(SQLite-trans)を用意して、ちょっとした比較実験を行ってみました。

2004.08.28追記: やっぱり「CGIの実行一回を一個のトランザクション区間とみなす」というのは無理があったようです。Rebuildなんか長時間ロックを取ってしまうので、裏でコメントしたりトラックバックしたりできなくなってしまいます。「Multiple-readers or a single writer」をまじめに実現しないと実用になりません。

実験環境は、SUSE Linux 9.1(ReiserFS) on VMware 4.5.2ですのでDisk I/Oが通常のサーバーより相当ショボイものと考えてください(下記の結果では使うDBによって性能差が非常に大きいですが、実際にはもっと差がない場合が多いということです)。

以下のグラフは、25個(445Kbytes)、200個(3564Kbytes)のエントリ(中身はGNU Public License)をBerkeleyDB版、MySQL版、SQLite版、SQLite-trans版でそれぞれimportするのにかかる時間をTime::Elapseモジュールを使って計測したものです。

こちらはBenchmarkモジュールでCPU Timeを計測したもの。

オリジナルのSQLite版は、BerkeleyDBと同等以上の性能でしかなく、率直に言ってショボイです。しかし、トランザクション機能を使えば、MySQL版以上の性能が出るようです。それにしても...、PerlのCPU Timeって謎。なんでこんなにSQLiteのSystem Timeが小さいのだろう。

どうやらファイルシステムの影響が大きいようなので、同じ実験をFedora Core 2(Ext3) on VMware 4.5.2でもやってみました。

思いがけずSQLite、SQLite-transが速いです。ReiserFSもExt3もJournaling Filesystemなのですが、fsyncしたときに物理ファイルにちゃんと反映するか、単にJournaling logに反映されるだけかと言う、システムコールの振る舞いの違いが関わっていそうです。

Aug 23, 2004

King-sized Bed Project

ベッドを無印の脚付きマットレスからBo Conceptのキングサイズベッドに買い換えました。

先月末注文したのですが、ようやく土曜日にヘッドボードを除く部品が揃って納品されました。ヘッドボードは(発注ミスがなければ)今デンマークあたりからどんぶらこ、どんぶらこと運ばれている最中で、最低あと1ヶ月は待たないと届かないでしょう。完成予定図は↓(脚は微妙に異なる部品)。

BoConcept Products

今回ちょっと頑張ったのはマットレスをSealy Posturepedicの、しかもフォーシーズンズで使われているクラスのものにしたということです。ちなみに椿山荘のマットレスは「椿山荘スペシャル」らしいので、私のような庶民の目に付くところ(家具屋の抱き合わせ)では売られていないのではないかと思われます。それにしても快適なマットレスです。今までのが酷過ぎました。

Sealy Japanホームページへようこそ!

あとキングサイズで困るのは、ベッドパッドやシーツが近所のショッピングセンターなどでは売っていないこと(少なくとも三軒茶屋の西友にはない)。東急ハンズ渋谷本店でもシーツは2種類しかなく、ベッドパッドは置いてありません。専門店に行けばあるにはあるのですが妙に割高なのです。しかたがないので、東急ハンズでシーツを買い、ベッドパッドはベッドパッド用キルティング生地から作ってもらうことにしました。それでも専門店の半値以下とはこれ如何に。

Aug 21, 2004

Application-level Callbacks in MT3.1

Movable Type 3.1(日本語版じゃなくて英語版)は現在beta testフェーズにあります。このバージョンで追加された機能はこの辺り(Movable Type 日本語版サイト: Movable Type 3.1の主な新機能について)で確認できますが、私にとってはアプリケーション・レベルのコールバック機能の追加が一番重要な変更で、それ以外は枝葉末節でしかありません。

ではこの機能がどのようなことに使えるかというと、例えば今流行っている「日本語を含まないコメントはSpamとしてRejectする」などの改造は、以下のようなごく簡単なプラグインとして実現できてしまいます(自分でこのプラグインを使うつもりはありませんけれど…)。このプラグインを拡張してルールを追加・変更するのも簡単でしょう。

spamfilter.pl

0.01(2004.08.20): 初版公開。

また、Ogawa::Buzz: Trackbackの脆弱性で話題になっていたような改造も以下のようなごく簡単なプラグインとして実現できてしまいます。この種の脆弱性は時々刻々と発見され、対処する必要がある性質のものですから、プラグインの形でincrementalに対策できるメリットは大きいと思われます。

tbexploit.pl

0.01(2004.08.20): 初版公開。

サンプルプラグインを作ってみて分かったのは、結構強力な機能だということです。もちろん、CommentFilterやTBPingThrottleFilterなどと言った有用なコールバック用のフックがアプリケーション側でちゃんと定義されていることが肝なのですが。

念のため断っておきますと、Movable Type 3.01以前のバージョンでは動作しません。まだ公開されていない3.1以上のバージョンが必須です。ベータテストに参加していない方は、3.1公開まで素直に待ちましょう。

Aug 18, 2004

アジアンボウル@三軒茶屋

突然ですが、

猛烈に草を摂取したくなることがあります。

そう、草ですよ、草。Grass。ありませんか?

例えば、夏の休日、遅い朝食を素麺で済ませてだらだらプログラミング、3時くらいになって腹減ったなー、ありもので済ますかって感じでパスタを食べた、その一時間後。

例えば、夜中、明日締め切りのパワポを作るために徹夜して仕事中、3時ごろに無性にカップ焼きそばが食べたくなり、なぜか(買い置きされているので)手を伸ばしてしまい、分かっていたこととは言え、自然に胃がもたれてしまい、それを解消するのを口実にコンビニにアイスクリームを買いに行き、それも平らげた、その一時間後。

いいから俺に草を食わせろ~!!!

って感じになります。もう苛々して仕方がなくなるのです。小麦粉が忌々しくて仕方がなくなるのです。もう葱でも胡瓜(草じゃない!)でも大根(草じゃないって!!)でもいいからとにかくBARIBARIやりたくなるのです。

さて、本題のASIAN BOWLですが、池尻大橋に一号店があり(マイナーな筋では結構知られていて人気です)、その二号店がうちのごく近所にできました。メニューはフォーやパカパオなどの東南アジア飯中心というかオンリーで、テイクアウトもでき、二店舗目にも関わらず店舗デザインが妙にパッケージ化されている(ドトールグループか寿がきや(スガキコ)グループなんじゃないかと思ったくらい)、というファーストフード感あふれるお店です(しかし、ビールが630円なのが解せん)。

味は割と良いです。盛り付けもきれいなもんです。ファーストフードなので過大な期待は禁物ですが。そんなことより、この店の意義は気楽に思う存分「草」を食む食むできるということに尽きます。特にパカパオは葱だく、パクチーだく、バジルだくが基本。我ら「パクチージャンキー」党員も大満足の一品です。

場所はこのあたり。
Google マップ - 東京都世田谷区三軒茶屋2-20-11

Aug 16, 2004

MT-I18N Plugin

MT3.0日本語版のMT::I18Nの機能をコンテナタグやグローバルフィルタとして使えるようにするプラグインを公開します。

MTI18N_Plugin - ogawa - Google Code

機能的には、milanoさんのmt-jfold pluginのスーパーセットになります。また、Movable Type日本語版の3.0以降のバージョン以外では動作しません。

何となくMovable Type 3.0 のプラグイン API : NDO::Weblogに触発されたので、私もMT3.0のPlugin APIを使ってみました。

Aug 14, 2004

MT3.01D 日本語版「勝手にパッチパッケージ」Release 1

Movable Type 3.01D日本語版に対するパッチも結構溜まってきたのでそろそろ「勝手にパッチパッケージ」Release 1をリリースします。

MT-3.01D-ja-p01.zip (13,361bytes)

修正内容は下記のエントリにある(1)~(7)と、ほんの気持ちだけ+αしたものです。

Ogawa::Buzz: Movable Type 3.01D 日本語版・修正案

このパッチは、Movable Type 3.01D日本語版に対するパッチ(UNIX汎用、Windows用)です。これ以外のバージョンには適用できません。

パッチの当て方

UNIX汎用パッチ
MT-3.01D-full-lib-jaディレクトリ(フル・パッケージ版)、またはMT-3.01D-update-jaディレクトリ(アップデート版)に、上記のZipアーカイブに含まれているMT-3.01D-ja-p01.diffをコピーし、以下のようにパッチを当ててください。
patch -p1 < MT-3.01D-ja-p01.diff
Windows用パッチ
MT-3.01D-full-lib-jaディレクトリ、またはMT-3.01D-update-jaディレクトリに、上記のZipアーカイブに含まれているMT-3.01D-ja-p01.EXEをコピーし、ダブルクリックして実行してください。

あとは通常通りWebサーバーにファイルをアップロードするだけです。Techknow Movable Type: Movable Type のインストールなどが参考になるでしょう。

すでにセットアップが済んでいる場合、このパッチパッケージはlib以下のファイルしか変更しませんので、libディレクトリのみアップロードして上書き(またはインストール済みのlibを削除してコピー)すれば済みます。また、テンプレートなどは一切修正しませんので、セットアップ済みのBlogのテンプレートを変更する必要もありません。

注意

このパッチパッケージは自己責任で使用してください。SixApart日本法人から有償ライセンスを購入して使用している場合、パッチ適用後のシステムは一般的にはサポート対象外になります。...なりますが、もしサポートが適切に行われるのならば、このパッケージと同様の修正をSixApartに要求することができるはずで、したがってその当然の結果として修正後のコードを入手することも、さらにはそのサポートを受けることもまた同様にできるはず、というのが私の考えです。

このエントリの引用・リンクなどはもちろん自由に行っていただいて構いません。が、このエントリに含まれるパッチパッケージの再配布、またこのエントリに含まれることを明記せずにパッチパッケージに直接リンクすることはお控えください。

Aug 9, 2004

mt-sql2db.cgi: mt-db2sql.cgiの逆変換 CGIスクリプト

コネタが続きますが、このエントリでは、MySQLなどに保存しているMovable TypeのデータをBerkeleyDBにコピーするための自作CGIスクリプト(mt-sql2db.cgi)を紹介します。

mt-sql2db.cgi

0.01(2004.08.09): 公開。

レンタルサーバなどでMySQLなどを使っている場合、どうしてもデータをロストする危険を感じないわけにはいきません。実際廉価なレンタルサーバでのSQLサーバ利用は「at your own risk」と明記されている場合が非常に多く、サービスの継続性にも不安を感じます。

一方で、Movable TypeはBerkeleyDB形式で作ったデータをSQLに変換する機能は提供しますが、その逆の機能は提供しません。確かに一旦SQLに変換してしまえば、Ogawa::Buzz: LolipopのMySQLデータベースを簡単バックアップするCGIスクリプトに書いたようにSQLデータをバックアップすること自体は簡単です(しかもreadableだし、portableだし、だし)。が、そうして取ったバックアップからリカバリーしたい場合、リカバリー側環境でSQLサーバが無事に使えれば問題はないですが、そうでなければMovable Typeを継続して使うことができないということになります。

こうした事情もあり、最近頓にトラブルの多いBerkeleyDBからMySQLに移行したいがBerkeleyDBに戻せないのは困るという理由で二の足を踏んでいる、という人は割に多いのではないでしょうか? そんな人の背中を押すのがこのスクリプトの目的です。

このスクリプトは、端的に言ってMovable Type 3.0に付属のmt-db2sql.cgiの逆変換機能を提供します。mt.cfgでDBI ObjectDriverを指定しているときに、データベースに格納してあるすべてのMT Objectを読み込んではDBM形式で保存していく、というただそれだけのスクリプトです。

使い方

基本的な使い方は以下の通りです。

  1. 上記リンクよりCGIスクリプトをダウンロードして、mt-sql2db.cgiという名前で保存します。
  2. mt.cgiなどが置かれているディレクトリにアップロードし、mt.cgiなどと同様に実行権限を与えます。
  3. mt.cfgでObjectDriver、Database、DBUser、DBHost、(BerkeleyDBが使用するディレクトリを指定する)DataSourceが適切に設定されていることを確認してください。また、DataSourceで指定したディレクトリを作るのも忘れずに。
  4. ブラウザからmt-sql2db.cgiにアクセスしてCGIを実行してください。SQLサーバのデータがDataSourceで指定したディレクトリにBerkeleyDB形式でダンプされるはずです。
  5. 無事に済んだら、mt.cfgのObjectDriverの行をコメントアウトしてBerkeleyDBでの動作確認をしてください。

このツールはもう少し応用的な使い道もできます。

megu's blogのmeguさんにコメント欄でご示唆いただいたように、異なるSQLサーバ間のデータ形式変換にも使えます。例えば、MySQLで作ったデータを一旦BerkeleyDB形式に変換(このエントリのmt-sql2db.cgi)し、次にBerkeleyDB形式のデータをPostgreSQL形式に変換(MT3.0付属のmt-db2sql.cgi)することで、MySQL→PostgreSQLの移行ができます(vice versa)。

もちろん両スキーマ間の変換をする方が確実かつ高速なのは言うまでもないですが、この方法ならSQLの知識なしに(あるいはそれ専用のツールを使うことなしに)変換できるというメリットがあります。

注意点

  • エントリーの数が増えると非常に時間がかかるようになります。所要時間はおおよそエントリー数の2乗に比例すると考えてください。辛抱が肝心です。
  • レンタルサーバなどではスクリプトの実行時間が長くかかり過ぎると途中終了する場合があります。その場合にはこのツールは使えません。ちなみにLolipopではこのブログはバックアップできませんでした
  • BerkeleyDBへのバックアップは、mt.cfgのDataSourceで指定しているディレクトリに行います。すでにこのディレクトリにバックアップが存在する場合上書きされます
  • Known bugですが、Link this template to a file(このテンプレートにリンクするファイル)を指定しているテンプレートがあるとスクリプトが失敗することがあります。これはBerkeleyDBにsaveしようとする際に対象ファイルへのアクセスが発生するためです。原因は分かっていますが、面倒なので対処しません。
  • MySQLとPostgreSQLとSQLiteで動作することを確認しています。
  • MT2.6X~MT3.1Xでしか動作確認しておりません。
  • ご利用は計画的におながいいたします。念には念を入れてバックアップしてください。

Aug 6, 2004

Trackbackの脆弱性

誰もが気が付きまくっている、性善説に基づいて設計されたとしか思えない、あのTrackbackの自明な脆弱性。Exploitも超簡単です。

Trackback の脆弱性についての勧告: blog.bulknews.net

以下のようないい加減なHTMLをデバッグ用・動作試験用に使っていたのですが(exploitに使われる可能性を鑑みて削除)、ついに使えなくなってしまう日が来てしまいますか。何やら寂しいような…。

私は宮川さんのエントリにあるような修正をlib/MT/App/Trackback.pmに施しています。が、実際のところこの修正の有無に関わらずDDoS攻撃に対して脆弱なのは変わりません。この修正はどちらかというと単にSpam対策ですね。mod_rewriteによる修正の方がより本質的だと思います。

ちなみにレンタルサーバーなどではApacheのMultiViewsオプションが標準で有効になっていることがしばしばあるので(少なくともlolipopはそうなっている)、Trackbackスクリプトはmt-tb.cgiだけでなくmt-tbでも実行できてしまいます。したがって、mod_rewriteで対処する場合には、以下のいずれかにしておく必要があります(赤字は宮川さん版からの変更部分)。

RewriteEngine On
RewriteCond %{REQUEST_METHOD} POST
RewriteCond %{REQUEST_URI} mt-tb\.cgi
RewriteCond %{REQUEST_URI} mt-tb(\.cgi)?
RewriteCond %{HTTP_REFERER} .+ [OR]
RewriteCond %{HTTP_USER_AGENT} ^Mozilla/
RewriteRule (.*) - [F,L]
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_METHOD} POST
RewriteCond %{REQUEST_URI} mt-tb\.cgi
RewriteCond %{HTTP_REFERER} .+ [OR]
RewriteCond %{HTTP_USER_AGENT} ^Mozilla/
RewriteRule (.*) - [F,L]

それにしてもApacheのRewriteRuleって分かりにくいです。例えば、上のRewriteRuleを/mt/.htaccessに書いたとします。すると、/.htaccessに書いておいたRewriteRuleが無効になってしまいます(気のせい?)。したがって、/mt/.htaccessにルールを書くのをやめて/.htaccessに一緒に記述するか、/mt/.htaccessに/.htaccessで書いたルールを改めて記述する必要があります。何か納得行きませんね。

mt-resave-entries.cgi: basenameを正しく設定するためのCGIスクリプト

このエントリでは、MT 2.6X利用時に作成したエントリのbasename(通常NULLになっているはず)を設定するための自作CGIスクリプト(mt-resave-entries.cgi)を紹介します。

mt-resave-entries.cgi

0.01(2004.08.06): 公開。
0.02(2004.08.09): entry_idでソートするのを忘れてました。

このスクリプトは、basenameがNULLになっているエントリをidの若いものから順番にloadしてはsaveしていくことでbasenameを再設定します。なぜこのツールが必要なのかについては、Ogawa::Buzz: Movable Type 3.0のIndividual Entry Archiveの命名方式の問題点で説明していますのでご参照ください。

エントリの作成時刻は元のままですが、更新時刻はCGIを実行したときのものに更新されます。これは仕様です。ご利用はくれぐれもノークレーム、ノーリターンでおながいします。

使い方

  1. 上記リンクよりCGIスクリプトをダウンロードして、mt-resave-entries.cgiという名前で保存します。
  2. mt.cgiなどが置かれているディレクトリにアップロードし、mt.cgiなどと同様に実行権限を与えます。
  3. ブラウザからmt-resave-entries.cgiにアクセスしてCGIを実行してください。basenameがNULLのエントリがあれば再保存して新しいbasenameを付与していきます。

Advancedな使い方

このCGIはついうっかり設定されてしまったbasenameを再設定する目的にも使えます。例えば、英語版を使っていて意味不明のbasenameを付けられてしまった場合や暫定的に付けたタイトルを元に不本意なbasenameを付けられてしまった場合などは、この方法で対処できます。ただし作業は高度になりますので腕に覚えのない方は止めておくべきです。

まず、対象のエントリのbasenameを一旦NULLに変更します。ここではMySQLを使用しているものと仮定します。以下のSQL文をコマンドラインインタフェースないしphpMyAdminを使って実行します。

UPDATE mt_entry SET entry_basename=NULL WHERE entry_id=XXX

XXXは対象のエントリのIDです。すべてのエントリを再設定したいのであれば、WHERE節を記述する必要はありません。UPDATEが無事済んだら(1秒もかからないと思います)、
次にmt-resave-entries.cgiを実行すればbasenameを再設定することができます。

Aug 2, 2004

Movable Type 3.0のIndividual Entry Archiveの命名方式の問題点

Movable Type 3.0になってIndividual Entry Archive(個別のアーカイブ)のファイル名の命名規則が変わったことは知られていますが、このエントリではこの命名方式にまつわる問題点を述べたいと思います。

MT3.0になって各エントリのレコードにbasenameというフィールドが追加されました。これはIndividual Entry Archiveを生成するときのファイル名(のベースネーム)を決定するためのもので、「一つのエントリに一つのファイル名を対応させる」ために個々のエントリにuniqueな文字列が設定されます(MT::Util::make_unique_basename)。基本的にはタイトルを元に生成され、すでに存在するエントリと同一のbasenameになってしまう場合には_1、_2、...と接尾辞を付けることでuniquenessを実現しています。

このbasenameはMT 2.6X以前には存在しませんでしたから、MT 2.Xからアップグレードした場合には(MT 2.Xのエントリを一旦ExportしてからImportしている場合は該当しません)、既に存在するエントリではNULLになっています。また、MT 3.0ではエントリを「最初に」作成した時点でこのbasenameが決定されてエントリの情報と共に保存されます。タイトルを入力せずに暫定的にエントリを保存した場合には、本文からbasenameを生成します。

実はこのbasenameの決め方やbasenameがNULLのときのMT3.0の振る舞いにはかなり疑問を感じなくはありません。

  1. 初回作成時以降にエントリのタイトルを追加したり変更したりしてもそれがbasenameに反映されることはありません。暫定的なタイトルを付けた場合、あるいはタイトルを入力せずに暫定的に保存した場合に、それを変更できないのではDraft(下書き)の意味がありません。エントリの内容や作成時刻はいつでも変更できるのですから、basenameを再設定する機能や、元となる情報をキーワードなどでいつでも指定できる機能があってもよいと考えられます。

  2. タイトルを入力しなかった場合には、本文の先頭10文字をdirifyしたものを元にbasenameが決定されます。しかし、このとき使われるlib/MT/I18N.pmのfirst_n_textは改行文字を除去しないため、basenameに改行を含んだ文字列が設定される可能性があります。つまり生成されるファイル名が「hoge[改行][改行].html」「hoge[改行][改行]_1.html」のような困ったものになる可能性があります。

    これはI18N.pmのイージーなバグですので簡単に直すことができます。修正方法はOgawa::Buzz: Movable Type 3.01D 日本語版・修正案に述べています。また、3.11日本語版などではこの修正が取り入れられています。が、すでに異常なbasenameを設定してしまっているエントリを修正することは、1.に書いた通りできません。

  3. basenameがNULLの時(つまりMT2.Xからアップグレードした場合など)の振る舞いに問題があります。この場合、個別のアーカイブの名前はどのように作られるかというと、タイトルがあればタイトルをdirifyしたもの、なければ本文の先頭10文字をdirifyしたものをそのままファイル名に使用します(MT::Util::archive_file_for)。つまり、(MT3.0で)エントリ生成時にユニークなbasenameが付与される時とは異なり、一つのエントリに一つのファイル名という原則が成り立ちません。

    このことは重大な状況を容易に引き起こし得ます。同じ月に同じタイトルのエントリを2個以上作っていた場合、複数のエントリが同じファイル名を持つことになり、どれか一つしか生成されないことになります。また、すべて日本語のタイトルを付けていた場合、ファイル名は「.html」「.php」だけになってしまいますし、すべて日本語のタイトルを持つ複数のエントリを同月に作っていた場合には(ごく一般的な状況ですが)より一層悲惨なことになることが容易に想像されます。

3. に関しては、実はNULLになっているbasenameをMT 3.0の枠組みで設定することができます。basenameがNULLの状態でエントリを保存し直そうとすると、そのエントリのタイトルや本文を元にを新たにuniqueな文字列を生成して設定してくれるのです。したがって片っ端からエントリを保存し直せばbasenameは設定されます。

それが面倒ならOpen power-editing mode(一括編集モード)でエントリの一覧を表示して何も変更せずに保存すれば、まとめて再保存したことになります。ただし要注意なのは、この方法では新しいエントリから順に設定がなされるということです。例えば、すべて日本語のエントリが5個しかないという状況を仮定します。これを一度に再保存すると、古いものから順にpost_4、post_3、...と名前が付き、一番新しいエントリにpostというbasenameが付けられてしまいます。次に新しいエントリを作るとpost_5となります。とてつもなく気持ち悪いですね。

要するに、basenameがNULLのエントリを古いものから読み込んでは再保存する簡単なツールがあれば結構楽ができそうです。と言ってもまだ作ってもいないのですが...。作ってみました(以下参照)。

Ogawa::Buzz: mt-resave-entries.cgi: basenameを正しく設定するためのCGIスクリプト

また、このツールがあれば1.や2.の問題に起因する異常なbasenameを再設定する機能を実現するのも比較的容易になるはずです。つまり、一旦エントリのbasenameをNULLにした後にこのツールを適用するとbasenameを再設定できるわけです。

About Me

My Photo

つくばで働く研究者

Total Pageviews

Amazon

Copyright 2012 Ogawa::Buzz | Powered by Blogger
Design by Web2feel | Blogger Template by NewBloggerThemes.com