windymelt / p2p2ch

2ch like p2p bbs by Scala
BSD 3-Clause "New" or "Revised" License
11 stars 1 forks source link

書き込み時に文字コードの変換に失敗している場合がある #2

Closed hangingman closed 10 years ago

hangingman commented 10 years ago

例えば「テストテスト」はURLエンコードされて「%83e%83X%83g%83e%83X%83g」でPOSTされる。しかし、内部処理の影響なのか、書き込み後に表示されるスレッドでは文字化けした文字列が表示されることがある。

windymelt commented 10 years ago

多くの2ch専用ブラウザはShift-JISで投稿をエンコードし、投稿しています。 しかしながらPlay frameworkではHTTP POSTの受け入れエンコードとしてUTF-8がハードコードされています。 このためP2P2chのZIPに内蔵しているPlayは、私が独自にこの部分を改変しています。したがってGitHubからP2P2chをダウンロードする場合、これを動作させるPlayはパッチを当てる必要があります。

もしかすると2chはエンコードを解析し、自動的に変換を行なっているのかもしれません。 そうであるならばP2P2chにもそのような機能が必要であるかもしれません。

HTTPプロトコルの解析が必要かもしれません。できるだけ、2chのそれに似せる必要があるかも。

chirauraNoSakusha commented 10 years ago

デコード関数がパーセントエンコーディングの

Shift_JISの2バイト目など、バイトが非予約文字に対応するなら、その文字をそのまま使用しても良い。 (http://ja.wikipedia.org/wiki/%E3%83%91%E3%83%BC%E3%82%BB%E3%83%B3%E3%83%88%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0 より)

に対応していない可能性はありませんか? 私はこれに引っ掛かりました。

windymelt commented 10 years ago

パーセントエンコーディング関連の部分は調査が必要かもしれません。

@Hiroyuki-Nagata しかし、状況を再現できる文字列が無いことには手の付けようがないので、おねがいします。

追記:このソフトウェア中においてPlayのPOSTのデコードのメソッドなりクラスなりをoverrideすることで、Playそのもののソースコードは改変せずにすむかもしれません。

hangingman commented 10 years ago

自分のScala + play flameworkの知識の無さのせいで、解析はすすんでいません ローカルネットワークでp2p2chって使えるのかな?

windymelt commented 10 years ago

ローカルではポートを変更して起動すれば大丈夫です。

Playを別にインストールしているとき

$ /path/to/play/play -Dhttp.port=9001 -Dp2pakka.akka.remote.netty.tcp.port=22224

ZIPを落としてきたとき

$ bin/p2p2ch -Dhttp.port=9001 -Dp2pakka.akka.remote.netty.tcp.port=22224

Playにかんしては「Scala逆引きレシピ」に少し情報が載っています。Scalaの参考書としても有能です。(宣伝)


追記:Playはjava.net.URLDecoderをパーセントエンコーディングのデコードに利用しているみたいです。

chirauraNoSakusha commented 10 years ago

それです。私が引っ掛かったのは。 ドキュメントを読み直したところ、URLDecoderは http://ja.wikipedia.org/wiki/%E3%83%91%E3%83%BC%E3%82%BB%E3%83%B3%E3%83%88%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0 の「application/x-www-form-urlencoded」に対応したデコードを行っているようです(文字列なのでバイナリデータ云々は無視して良さそう)。2chブラウザは「概要」の方でエンコードするのでおかしなことになります。

windymelt commented 10 years ago

Mac OSXで動作する2chブラウザ "Thousand" では、application/x-www-form-urlencodedで送信されているようです。POSTメソッドではapplication/x-www-form-urlencodedを使うようなので、ブラウザが間違っているのかもしれません。

@Hiroyuki-Nagata ブラウザの名前が分かれば書いておいてください。

chirauraNoSakusha commented 10 years ago

私の環境では、ブラウザがHTTPのContent-Typeの指定を間違っているように思えます。 navi2chでは "てすと テスト" を "%82%C4%82%B7%82%C6%20%83e%83X%83g" とエンコードしました。 JaneDoe Viewも同じでした。これは前述の「概要」の方に対応します。 しかし、どちらもHTTPのContent-Typeにはapplication/x-www-form-urlencodedを指定していました。 ちなみに、URLEncorderでエンコードすると "%82%C4%82%B7%82%C6+%83%65%83%58%83%67" になりました。 "Thousand" ではどうでしょうか?

推測ですが、http://www.monazilla.org/index.php?c=6-20 を見るとPOST時のContent-Typeについては特に記述がないので、本来,中身は決め打ちでContent-Typeの指定は必要無いところに、てきとうにapplication/x-www-form-urlencodedを指定するのが慣習になっているのではないでしょうか?

windymelt commented 10 years ago

パケットキャプチャの結果、"Thousand"ではapplication/x-www-form-urlencodedでスペースに"%20"を使用しています。つまり間違った挙動です。


http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4によれば、POSTのためにはすくなくとも

をサポートする必要があるようです。

chirauraNoSakusha commented 10 years ago

Content-Typeの指定が間違っているんでしょう。

ユーザエージェントはapplication/x-www-form-urlencodedとmultipart/form-dataをサポートしなければならない。他はここでは定義しない。 (訳)

と書いてあるので、他の形式を使うことは問題無いはずです。

本当はContent-Typeに2chの投稿形式であることを示す名前を入れるべきところに、似たようなapplication/x-www-form-urlencodedを入れているだけでしょう。 もしくは、これはHTTPではなく2chプロトコルである、と考えた方が良いのかもしれません。

windymelt commented 10 years ago

もしくは、これはHTTPではなく2chプロトコルである、と考えた方が良いのかもしれません。

そうだといえそうです。

さて、こちらで現象を再現できないのでそもそもの問題の解決のしようがないのですが、いかがいたしましょう。"Thousand"では、_エセx-www-form-urlencoded_でも問題無く動作します。

chirauraNoSakusha commented 10 years ago

他の2chブラウザを試せば再現できるかもしれません。

ThousandではShift_JISの2バイト目も確実に符号化するようにしているのではないでしょうか。 実験したらURLDecorderは%20を半角スペースに変換したので、Shift_JISの2バイト目も符号化されていれば、URLDecorderでもデコードできるはずです。

hangingman commented 10 years ago

@windymelt

とりあえず手元のJDとWineで起動したJaneStyleで同じ現象を確認しました。 JD http://jd4linux.sourceforge.jp/ JaneStyle http://janesoft.net/janestyle/

現象としては、カタカナがほとんど文字化けします。 漢字はなぜか化けません。Shift_JISのカタカナに何か共通点があるのかもしれません。

現象 「テスト」で投稿すると 「?e?X?g」で表示される

hangingman commented 10 years ago

V2Cでも登録を試行してみましたが、外部板としての登録ができませんでした。 http://v2c.s50.xrea.com/

BathyScapheは正常動作です http://bathyscaphe.sourceforge.jp/

今のところMacではうまく行くというところですか

Monazillaの書き込みに関する資料はここです http://www.monazilla.org/index.php?e=199

追記: 新しいバージョンのp2p2ch(P2P2ch-1.03.zip)をVPSで起動させています、試験用にどうぞ http://183.181.8.23:9000/bbs/

windymelt commented 10 years ago

@Hiroyuki-Nagata ありがとうございます。さて、何度もお願いして申し訳ないのですが、JD/JaneStyleから発信されたHTTP/POSTをWireSharkなどのパケットキャプチャで捕獲して、投稿した文字列の部分を(Gistなどで)示していただけないでしょうか?当方Windows環境が無いので、できたらよろしくお願いします。

新しいバージョンのp2p2ch(P2P2ch-1.03.zip)をVPSで起動させています、試験用にどうぞ http://183.181.8.23:9000/bbs/

なんらかのエラーが発生しているようです。

hangingman commented 10 years ago

JDで書込した際のパケットキャプチャのログ https://gist.github.com/Hiroyuki-Nagata/7888696

JaneStyleで書込した際のパケットキャプチャのログ https://gist.github.com/Hiroyuki-Nagata/7888788

便利なサイト http://www.tagindex.com/cgi-lib/encode/url.cgi

hangingman commented 10 years ago

まあ、おそらくこの現象でしょう http://d.hatena.ne.jp/srkzhr/20091104/1257352836

上記の出力結果は文字化けを起こしてしまいます。
「Q」の部分は本来「%51」のようにencodeされた状態であるべきところですが、
ASCIIコード内の1byte文字としてdecodeされた状態になっているためです。
これはリファラを設定してくる各サイトの実装依存なので制御できませんから、
受け手側での対応が必要になってきます。

Shift_JIS文字列の「キ」をエンコードすると「%83L」 L部分はASCIIの文字列としてそのまま残されてる。

試しにC++でURLEncodeを書く http://melpon.org/wandbox/permlink/tDRVFwQkgcE3YDh8

hangingman commented 10 years ago

Javaのcommons-codecのほうではShift_JISで符号化されてないASCII文字を使用しても ちゃんとデコードできるようです。 http://www.good-approach.com/urlEncode.html

対処としては上のリンクのようにちょっとコードを足してplay側でURLのデコード処理を修正したほうが簡単に見えます。java.net.URLDecoderをcommonsのものに変えるのはなんだか難しそうなので。

windymelt commented 10 years ago

playにはcommons codecが標準で付属してるようなので、playを修正することにします。

ここに色々と有用な情報がありました。

Playframeworkでガラケーサイト

commons-codecのURLCodecがPlayのlibに最初から入っています。

windymelt commented 10 years ago

diff作りました。 playのデコードに使うクラスをcommons-codecに変更します。

https://gist.github.com/windymelt/7893820

旧来のパッチと統合してあります。

windymelt commented 10 years ago

また、サイトに置いてあるzipもバージョンアップがてらパッチ済みの新しいplayに変更させました。

hangingman commented 10 years ago

さっそくP2P2ch-1.04.zipを使用して書き込みテストを実施しましたところ 文字化けせず書き込めております。ありがとうございます。 というわけでクローズさせていただきまっす