2007/05/10

[技術系]   MovableTypeエクスポートログ形式は腹を切って死ぬべきだ

at 08:31JST
 
MovableTypeエクスポートログ形式の問題点 : ひろ式めもちょう
http://memo.hirosiki.jp/article/41294601.html

のつづき。

MTのエクスポート結果って、
属性: 属性値
属性: 属性値
  :
BODY:
本文内容
----- ←項目区切り
ほかデータ列
  :
------- ←エントリ区切り

って感じで羅列になっているテキストファイルなわけだが。

ということは、これはどんな素人が見ても、
「本文中に ----- とか ------- とかが
 単独行で入ったらマズいな」
とわかる。通常、こういうものは何らかの方法でエスケープするものだ。

たとえば、いにしえのUNIX mbox形式では、メールメッセージの区切りが
From nantoka@nantoka

となっているわけだが、一般にメッセージ中行先頭の
From

は、
>From

でエスケープする慣習となっている。相互運用性にはやや混乱があるが、
http://man.qmail.jp/jman5/mbox.html
きわめてまっとうな方法で、これで20年は戦ってきた。

シェアの高いMTだし、当然このあたりは何か対応しているんだろうと思って確認してみると、

・エクスポートされるデータ
 →まったくエスケープされない

というのがわかった(V3.3)。

…正気か?

さらにさらに。

・エスケープされていないデータをインポートした場合
 →壊れたエントリが生成される

ということも確認できた。

…えー!?
マジですか…。

いくらMTのエクスポート画面で
「これは完璧なバックアップ手法じゃありません」
とうたってても、こりゃないだろ! というか、問題はバックアップではなく(バックアップならMySQLをダンプしておけばいい話)エクスポートが正常にできないということだ。相互運用性が確保されないという問題だ。

というか、大げさに言えばこれはセキュリティホールにも近い問題だ。なぜなら、上記のような形式で出力される中には「コメント」「トラックバック」のデータも含まれるから。
「お。気に入らないやつみっけー。
 こいつ、もうまともにエクスポートできないように、
 コメント欄に - を5つ書いといてやれ!」
と攻撃のネタにすることもできる。これだけで攻撃対象は自分のMTを簡易バックアップすることが不可能になるうえ、ほかのblogシステムへの移行もできなくなる。

ちなみに、いったんこの形式でエクスポートされたデータは機械的に問題点をチェックすることはできない。目視で修正するしかない!(検索すりゃ手間が多少省けるけど、コメントだけで1万件近いようなサイトを運営してる身には地獄だ)


そもそもMTがきちんとエスケープしないでエクスポートしている背景には、この機能がMTのテンプレート機能を転用して実装された簡易なものだということがあるようだ。

Movable Type Knowledge Base: Customized Exports
http://www.sixapart.com/movabletype/kb/imports/customized_expo.html

にはエクスポート形式の詳細のほか、いろいろなエクスポートの方法が書かれているが、あくまでMTのテンプレートを使った方法だけが紹介されている。まあ、言っちゃ悪いがテヌキだよね。


で、こんな簡単な問題はもちろんぼくじゃなくてもすぐわかるわけで、知ってる人はけっこういるみたいなんだけど、あんまり問題視されてないんだな…。おまけに、ご丁寧にほかのMT互換サービスも、このMTと同じ弱点をそのままマネしている。Seesaa BLOGもそう! -----のエスケープの必要を考えず、そのままエクスポートしている。おーい…。

唯一対応しているらしいのが

開発者ブログ MovableType形式と忍者形式のログエクスポートやログインポート
http://samurai.blog.shinobi.jp/Entry/111/

「忍者ブログ」だ。ここは
5つ以上の連続したハイフンと改行は5つの連続したハイフンと改行の間に半角スペースを入れます。

というAd Hocなやり方で対応している。忍者はいつもひと味違うサービスをやってるが、えらいな…。

忍者ブログは
「何らかの方法でエスケープしても、
 インポート側がアンエスケープできなければ意味がない」
という事情からこの方式を考え出したのだろう。行末に半角スペースが入っていても誰も気づかない。しかし、本来的には

エクスポート側
・行頭に-がある場合は「- 」を挿入する
インポート側
・行頭に「- 」がある場合はこれを削除する

という、より単純で明確な運用を普及させる必要があると思う。

とはいえ人に対応してもらうのを待っているわけにもいかないしな…。
いくつか方策を考えた。

・エクスポート側
 - MTでまっとうにエクスポートできるよう、プラグインを作る
  (とりあえず、ぼくは今「インポートする側」なので後回し)
 - XML-RPC APIを介して、MT互換blogから正常に“吸い出す”スクリプトを書く
  (…トラックバックとコメントって吸い出せたっけ?)
 - MT Perl API経由でバックエンドのDBからデータを吸い出すスクリプトを書く

・中間
 - MTエクスポートデータ中、怪しい「-----」を見つけて
  エスケープする支援スクリプトを書く

・インポート側(- エスケープ対応)
 - MTでまっとうにインポートできるようパッチを書く

※追記
エクスポート、インポートともにパッチを書いてみた↓

MTでまっとうにエスケープしたエクスポート/インポートをできるようにするパッチ : ひろ式めもちょう
http://memo.hirosiki.jp/article/41339889.html


めんどくさ…。

もうさー、とにかくこの
・まともにエスケープもしていない
・ファイル名(permlink URL)の保全もできない
MT形式を標準扱いするのはやめようよー。


追記:
…これ、コメント部分のインポート時パースにも問題ないか?
lib/mt/importexport.pm l.320から
my @lines = split /\r?\n/, $piece; 
my($i, $body_idx) = (0) x 2;
COMMENT:
for my $line (@lines) {
$line =~ s!^\s*!!;
my($key, $val) = split /\s*:\s*/, $line, 2;
if ($key eq 'AUTHOR') {
$comment->author($val);
} elsif ($key eq 'EMAIL') {
$comment->email($val);
} elsif ($key eq 'URL') {
$comment->url($val);
} elsif ($key eq 'IP') {
$comment->ip($val);
} elsif ($key eq 'DATE') {
my $date = $class->_convert_date($val) or next;
$comment->created_on($date);
} else {
## Now we have reached the body of the comment;
## everything from here until the end of the
## array is body.
$body_idx = $i;
last COMMENT;
}
$i++;
}
これだと、コメントの先頭に「(EMAIL|URL|IP|DATE):」な行があるとパースされてしまうよね。…URLのところがヘンにサニタイズをすり抜けたりしなきゃいいんだけど…。

別にケチつけたくて調べてるわけじゃないんだが、これならJUGEMかどっかみたいにXML形式でエクスポートしてくれたほうがいいなあ。もともとMTはXML関連モジュールを使用しているのだから、インポート/エクスポートに利用できないことないのに。



関連しそうな過去記事:
さらに過去の記事
2009/04 (1)   2008/12 (3)   2008/11 (9)   2008/10 (10)   2008/09 (20)   2008/08 (2)   2008/07 (23)   2008/06 (16)   2008/05 (22)   2008/04 (11)   2008/03 (21)   2008/02 (20)   2008/01 (21)   2007/12 (32)   2007/11 (37)   2007/10 (46)   2007/09 (63)   2007/08 (33)   2007/07 (41)   2007/06 (81)   2007/05 (173)   2007/04 (168)   2007/03 (113)   2007/02 (123)   2007/01 (92)   2006/12 (111)   2006/11 (185)   2006/10 (20)  
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。