レ点腫瘍学ノート

Top日記2025年11月22日

Pukiwiki下書き機能実装の改良(v0.2)

pukiwiki pukiwiki_draft

PukiWiki 1.5.4に下書き機能を実装してみました。現在の最新の実装はv0.2になります。
ここ数週間、試行錯誤しながら進めてきたので、忘れないうちに記録しておきます。

GitHub - m0370/pukiwiki_draft: Mirror repository for pukiwiki_draft
Mirror repository for pukiwiki_draft. Contribute to m0370/pukiwiki_draft development by creating an account on GitHub.
https://github.com/m0370/pukiwiki_draft

背景

このサイトではPukiWikiを使っています。長い記事を書いている途中でブラウザがクラッシュしたり、通信が切れたりすると、それまで書いた内容が全部消えてしまいます。これが不便だったので、編集途中の内容を一時保存できる下書き機能を実装してみることにしました。

コードレビューで見つかった問題

先日、Pukiwiki 1.5.4をベースとして下書き機能を実装したものをリリースしていました。詳しくは下記の記事を参照してください。

Pukiwikiの下書き機能実装 - レ点腫瘍学ノート
pukiwiki pukiwiki_draft PukiWiki 1.5.4に下書き機能を追加してみたPukiwikiの下書き機能とは何か下書き機能の使い方下書きとして編集内容を保存する下書きから編集を再開する全ページの下書きを管理する下書き機能の仕組み下書き機能の活用シーン下書き機能の導入方法追加情報P
https://oncologynote.jp/?31fe03fea5

実装自体は既に行われていたのですが、本番環境で使う前に一通りコードを確認してみました。すると、いくつか気になる点が出てきました。

最も問題だったのはCSRF対策がなかったことです。下書きの保存や削除がトークン検証なしで実行されていたため、悪意あるサイトから不正なリクエストを送られる可能性がありました。また、XSS対策も完全ではなく、HTMLタグのエスケープ処理が不十分な箇所がありました。

そのほかにも、ファイル操作のエラー処理が甘かったり、使われていないコードが残っていたり、日本語と英語の両対応ができていなかったりと、細かい問題が複数見つかりました。これらをTODO.mdにまとめて、一つずつ対処していくことにしました。

セキュリティ対策の実装

CSRF対策として、セッションベースのトークンメカニズムを追加しました。PukiWiki本体にget_ticket()check_ticket()という関数がなかったので、lib/init.phpに追加しています。下書きの保存、削除、公開の各操作で、POSTリクエストとトークン検証の両方を確認するようにしました。

XSS対策では、JavaScriptのconfirm()メッセージ内で言語変数を使っている部分を、json_encode()htmlsc()でエスケープするように変更しました。

編集競合への対応

下書きを保存した後、他の人が本文を編集してしまうケースがあります。その状態で下書きを公開すると、新しい編集内容を上書きしてしまう可能性があります。

これを防ぐため、下書き保存時に本文のMD5ハッシュ値を記録しておき、公開時に現在の本文と比較するようにしました。ハッシュ値がない古い下書きについては、タイムスタンプで比較するフォールバック機構も用意しています。競合が検出された場合は、差分を表示して、本当に上書きしてよいか確認できるようにしました。

国際化対応

日本語と英語の両方で使えるよう、ja.lng.phpとen.lng.phpに言語変数を追加しました。「下書きが保存されました」などのメッセージは全て言語変数として定義してあります。英語の翻訳はネイティブチェックを受けていないので、不自然な部分があるかもしれません。

ファイル操作の改善

下書きデータはファイルとして保存されます。ファイル操作では、権限不足やディスク容量不足など、様々なエラーが発生する可能性があります。fopen()flock()fputs()の各関数でエラーが返された場合は、処理を中止するようにしました。また、複数のプロセスからの同時アクセスに備えて、読み取り時は共有ロック、書き込み時は排他ロックを使うようにしています。

ローカル環境でのテスト

macOS上にPHP 8.4とApacheを構築して、実際に動作確認をしました。最初はget_ticket()関数が見つからないエラーが出たり、PHPのヘレドック構文で変数展開がうまくいかなかったりと、いくつか問題がありました。一つずつ調べながら修正していきました。

pukiwiki.ini.phpの$line_break設定を0から1に変更して、テキスト内の改行が自動的に<br />タグに変換されるようにもしました。

残っている課題

自動保存機能は実装していません。技術的には可能ですが、実装が複雑になるため、今回は見送りました。また、古い下書きを自動削除する機能も実装していません。ユーザーが明示的に保存したデータを勝手に削除するのはリスクがあると判断しました。

追記


この記事に対するコメント

このページには、まだコメントはありません。

お名前:

更新日:2025-11-22 閲覧数:185 views.