タイミングのよいことに、11日の日記の「Winny可視化のため、WebブラウザにWinnyプロトコルハンドラを」に対して、「高木版Winnyプロトコルハンドラは妙だ」という反応があった。
それを言うなら winnytp://a272e2d2e7a6844d97ab5fd9619be1d6 というURIで、ネットワークのどこかにある a272e2d2e7a6844d97ab5fd9619be1d6 というハッシュのファイルを指すのが自然なんじゃないかと。
高木版Winnyプロトコルハンドラは妙だ, blog.fuktommy.com, 2006年6月25日
べつにそれに限定される理由はない。両方があり得るというだけのことだ。 URL (Uniform Resource Locator) として、場所を指定してリソースを指定する方法「winnytp://HOSTNAME:PORT/[FILE_ID]」もあれば、 URN (Uniform Resource Name) として、場所に依存しない形でリソースを指定する方法「winny:FILE_ID」もあり得るという理解でよい。*1
私は単に、後者の実装には興味がない。
実装の面からいうとWinnyプロトコルには自分の公開ファイルの一覧を出力する機能はなかったと思うんですけど。 Apacheでいえば Options -Indexes と設定しているようなもんでしょ。ということは winnytp://192.168.2.1:7743/foo.jpg はありえても winnytp://192.168.2.1:7743/ はないんじゃないですか。
高木版Winnyプロトコルハンドラは妙だ, blog.fuktommy.com, 2006年6月25日
べつに全ファイルが表示される必要はない。そのサイトから受信したコマンド13から、そのサイトについてのエントリを抽出する実装でよいのであって、「Options -Indexes」されているわけじゃない。
じつは言い出した当初、それができるかどうかいささか不確かに感じていた。そこで、ちょうど昨日から、実際に作って試していたところだった。
Javaのjava.net.URLConnection用のストリームハンドラを軽く書いてみた。使い方は次のような感じになる。Javaで書いたため一般のWebブラウザに組み込むことはできそうにないが(HotJavaにならできるけども)、ここではテキストベースのHTMLブラウザをJavaで書くケースを想定している。(ダウンロード機能はまだ書いていないので「[FILE_ID]」部分は指定しても無視される。)
import java.net.URL; import java.io.*; public class Nynx { static final String usage = "Usage: java Nynx url"; public static void main(String[] args) { if (args.length != 1) { System.err.println(usage); System.exit(1); } String url = args[0]; URL.setURLStreamHandlerFactory(new WinnytpURLStreamHandlerFactory()); // ハンドラの組み込み try { java.net.URLConnection uc = new URL(url).openConnection(); InputStream is = uc.getInputStream(); BufferedReader buf = new BufferedReader(new InputStreamReader(is)); while (true) { String line = buf.readLine(); if (line == null) break; System.out.println(line); } } catch (IOException e) { System.err.println(e.toString()); } } } class WinnytpURLStreamHandlerFactory implements java.net.URLStreamHandlerFactory { public java.net.URLStreamHandler createURLStreamHandler(String protocol) { if (protocol.equals("winnytp")) { return new WinnytpURLStreamHandler(); } else { return null; } } } class WinnytpURLStreamHandler extends java.net.URLStreamHandler {...} class WinnytpURLConnection extends java.net.URLConnection {...}
実行してみると次のようになる。図1は実装途中の確認テストで実行した際の様子で、受信したコマンド13のエントリを削らずに表示した様子だ。
ここから、HOST_NAME部分がアクセス先サイトと一致するエントリ(図1の矢印部分)だけを残して表示すればよく、実行すると図2のようになった。(リンクのhref属性は、相対URLになるので「winnytp://HOSTNAME:PORT/」部分を省略している。)
このとき、こちらからサーバ(Winnyノード)へは何らコマンドもデータも送信していない(Winnyプロトコル冒頭の暗号キーおよびコマンド0〜3も送っていない)。実装の最初のテストでそのことに気づいたのだが、単にこちらから TCP接続しただけで、応答ストリームにコマンド13などを返してくるようだ。受信したデータをWinnyプロトコルにしたがってデコードしただけで、このような表示ができた。
昨日(土曜日)の夕方から書き始めたところ、今日(日曜日)の朝にはこの程度に動くものに仕上がった。このことからしても、今や誰でも、公開されている資料をもとにこうしたプログラムを作成できる状況にあることがわかる。実際、5月15日のCMU日本校のカンファレンスの席でも、会場からの質問で「(情報漏洩対策として)うちでも作っている」という声が出ていた。
Winnyについてこれまでに考えを記した日記:
*1 そのためわざわざ「tp」を付けて区別しておいた。