blog/2007-01-17


Total: 4271 / Today: 1 / Yesterday: 1

MabinogiWebAvatarRenderer Classの謎

Web素材/PukiWiki/mabi_avatar.inc.phpで公開している#mabi_avatarを開発する上で参考にしたサイトは、まびらぼである。このサイトでは、マビノギのキャラクター画像を表示したり、生成したりしている。普通考えるならば、マビノギのキャラクター画像を表示しているActiveX(MabinogiWebAvatarRenderer Class)は、Web上に表示する以上、ほかのページに持ってきていても同じように動作するはずである。しかしながら、実際は公式サイトでのみ表示可能で、ほかのサイトからActiveXを呼び出しても通常は表示されないようになっている。

この問題はさておき、まず自分のキャラの3D画像はどのように表示されているだろうか?公式サイトでログインしてソースを読み、どこでアバダー画像を表示しているかを探していると以下の部分が目にとまった。

<SCRIPT LANGUAGE="JavaScript">
<!--
	avatarserver	 = "http://avatar.mabinogi.jp"
	antialias = "2"
	usercode = "4p6NgM4PtWKQA2nB070C"
	code = "gPqQX9aM0BGNET7RzvWCdJLMG;6RFka;ydaMFEqP0ga;Q8n;yPaQGN6NNIq;D:6R:cE3X1KML5rNArKRV578mP6Qn9aMGtkO1k6P8B2NET7RzvWCdJLMG;6RFka;ydaMFEqP0ga;JUq;hFKMNkq;udaMjK3QjG3ALXHAIj7RI4n;C9KNmTXA57IBV5KMaBbO8Ib;UC0R"
//-->
</SCRIPT>
<script language="javascript" src="/5th/js/swf_avatar.js"></script>

で、swf_avatar.jsの中身

document.write('<OBJECT ID="avatar" CLASSID="CLSID:7623BE59-D4CF-4379-ABC4-B39E11854D66" WIDTH=128 HEIGHT=256 CODEBASE="'+avatarserver+'/3drender/renderer/mabiweb.2006.5.19.cab#version=2006,5,19,0">');
document.write('<PARAM NAME="antialias" value="'+antialias+'">');
document.write('<PARAM NAME="bgcolor" value="ffffff">');
document.write('<PARAM NAME="camera" value="-15 15 0.75">');
document.write('<PARAM NAME="onactive" value="0">');
document.write('<PARAM NAME="usercode" value="'+usercode+'">');
document.write('<PARAM NAME="code" value="'+code+'">');
document.write('</OBJECT>');

これから、わかることは単純に前者の内容をMabinogiWebAvatarRenderer Classに渡しているだけと取れる。従って、同じ画像を表示させたいのであれば、

<object id="avatar" classid="clsid:7623BE59-D4CF-4379-ABC4-B39E11854D66" codebase="http://avatar.mabinogi.jp/3drender/renderer/mabiweb.2006.5.19.cab#version=2006,5,19,0" width="128" height="256" >
 <param name="antialias" value="2" />
 <param name="bgcolor" value="FFFFFF" />
 <param name="camera" value="-15 15 0.75" />
 <param name="onactive" value="0" />
 <param name="usercode" value="4p6NgM4PtWKQA2nB070C" />
 <param name="code" value="gPqQX9aM0BGNET7RzvWCdJLMG;6RFka;ydaMFEqP0ga;Q8n;yPaQGN6NNIq;D:6R:cE3X1KML5rNArKRV578mP6Qn9aMGtkO1k6P8B2NET7RzvWCdJLMG;6RFka;ydaMFEqP0ga;JUq;hFKMNkq;udaMjK3QjG3ALXHAIj7RI4n;C9KNmTXA57IBV5KMaBbO8Ib;UC0R" />
</object>

と入れればすむハズである。しかしながら、このままでは、ログインしてからの一定期間だけしか表示されない。そこで、まびらぼでは、どのようにキャラクター画像を表示しているかをソースを見て読んでみる。すると、

<object width="0" height="0" classid="clsid:bfbc3059-9c61-5ba1-2075-85c8b6ecfc07"></object>

という行が加えられていることがわかる。これが、jmwfreの正体である。このjmwfreのページを読めばわかるとおり、何らかの処理をしてアバダー画像を呼び出していることがわかる。実際、この行を追加することでクライアントサイドにjmwfreをインストールしてある場合に限って、アバダー画像が表示されるようになった。

avatar.executeの謎

しかし、謎は残る。このまびらぼのabout?http://mabinogi.or.tp/about/のページのソースを読むと、以下のようなものに気づくだろう。

  1. <param>要素のcode属性が含まれていない
  2. ヘッダー内にavatar.executeというものがある

このavatar.executeは、先ほどログインした公式サイトで探してみると

function bbc(bb) 
    {
          switch(bb)
			{
				case "4" : 
					submenu_0101.style.display = "none"
	                document.all.area1.innerHTML = document.avachange.imging.value
					break;
				case "0" :
					if (document.avachange.avaornot.value != "not")
					   {
							submenu_0101.style.display = "block"
							document.all.area1.innerHTML = "";
							avatar.execute =  document.avachange.oravaing.value;

というように書かれている。で、bbc(bb)がどこで呼び出されているかを探していると、

<select style='width:100%;margin-top:4px;' name="motionabc" onChange="bbc(this.value)">	
		   <option value='4' >2D ログアウトポーズ</option>
		   <option value='0' selected>3D ログアウトポーズ</option>
		   <option value='1' >3D 歩き</option>
	       <option value='2' >3D 走り</option>
		   <option value='3' >3D 立ち</option>
	  </select>

という箇所が目にとまった。つまり、ポーズの体位変更にたとえば、<option value='1' >3D 歩き</option>を選択したときに、先ほどのcodeに加えてgTqIVlKEQ8KPakKOVN78UV6Pという命令を送っていることになる。(function bbc(bb) の27行目付近参照)onchange属性が使われていることを考えるとPOST命令を送るなどの複雑な処理をしているわけでなく、単純にDHTMLの一種と考えられるだろう。

それだけならば、DHTMLでMabinogiWebAvatarRenderer Classを呼び出している<object>タグごと書き換えればすむ話である。しかし、このような小細工がしてある上に瞬時に効果が発動することを考えると、上書きに近い形でActiveXを叩いているとが考える事ができる。先ほどDHTMLで書き換えると書いたが、その場合、その中に含まれる<object>要素で呼び出したActiveXを0から呼び出す必要が出てくる。

つまり、avatar.executeを使って、上書きで命令を送ることができるといえる。おそらく、これは、リロード時間短縮のためにMabinogiWebAvatarRenderer Class側で用意された配慮だろう。従って、<param>要素のcodeの値とavatar.executeは、等価であるといえる。

そもそもcodeはなんぞや

次に謎に思うのは、まびらぼのabout画面である。先ほど、自分のアバダー画像のコードは

code = "gPqQX9aM0BGNET7RzvWCdJLMG;6RFka;ydaMFEqP0ga;Q8n;yPaQGN6NNIq;D:6R:cE3X1KML5rNArKRV578mP6Qn9aMGtkO1k6P8B2NET7RzvWCdJLMG;6RFka;ydaMFEqP0ga;JUq;hFKMNkq;udaMjK3QjG3ALXHAIj7RI4n;C9KNmTXA57IBV5KMaBbO8Ib;UC0R"

であることがわかったが、まびらぼのaboutのページに記載されているまびらぼ管理人のコードは

avatar.execute = '1k6P8B2NET7RzvWC:8KPboKOKcqNK5rPDC7RdJLMG;6RP8r;UfaQD27Rb5KM6SLRdJLMG;6Re3qQwALO';

と非常に短い。つまり、余計なオーバーヘッドがあることがわかる。

とりあえず、;で区切って比較してみよう。まずは、先ほどの自分のキャラクター画像のコードである。

gPqQX9aM0BGNET7RzvWCdJLMG;
6RFka;
ydaMFEqP0ga;
Q8n;
yPaQGN6NNIq;
D:6R:cE3X1KML5rNArKRV578mP6Qn9aMGtkO1k6P8B2NET7RzvWCdJLMG;
6RFka;
ydaMFEqP0ga;
JUq;
hFKMNkq;
udaMjK3QjG3ALXHAIj7RI4n;
C9KNmTXA57IBV5KMaBbO8Ib;
UC0R

で、こっちは同じサーバーのサブキャラ

これに対し、まびらぼ管理人の場合

1k6P8B2NET7RzvWC:8KPboKOKcqNK5rPDC7RdJLMG;
6RP8r;
UfaQD27Rb5KM6SLRdJLMG;
6Re3qQwALO

4つの要素だけである。また、参考までにまびらぼトップページのコードを見ると

1k6P8B2NET7RzvWC:8KPboKOKcqNK5rPDC7RdJLMG;
6RP8r;
UfaQD27REn6R60a;
dRLMn3bQUfaQ0C2R

これも4つである。しかも、上の2行が一致している。つまり、下の2行だけで表示されるアバダーが決まっている。言い換えれば、キャラクターの画像を示すのに必要な要素は2つだけということになる。

ついでなので、自分の別キャラの場合を見てみる。

gPqQX9aM0BGNET7RzvWCdJLMG;
6RFka;
ydaMFEqP0ga;
Q8n;
yPaQGN6NNIq;
D:6R:cE3X1KML5rNArKRV578mP6Qn9aMGtkO1k6P8B2NET7RzvWCdJLMG;
6RFka;
ydaMFEqP0ga;
JUq;
hFKMNkq;
udaMjK3QjG3AQvJBjT7SZr6A82XBpW3AVx6EudaMiK3QIj7R

ある法則性のようなものに気がつくであろう。

gPqQX9aM0BGNET7RzvWCdJLMG;
6RFka;
ydaMFEqP0ga;
Q8n;
yPaQGN6NNIq;
D:6R:cE3X1KML5rNArKRV578mP6Qn9aMGtkO1k6P8B2NET7RzvWCdJLMG;
6RFka;
ydaMFEqP0ga;
JUq;
hFKMNkq;

の10行は、キャラが異なっても同一である。

結局どこまでがキャラを指す要素なのか、まだ調べてみる必要がありそうだ。

まびらぼに学ぶAjaxによるコードの隠蔽

さて、ここまでわかると、まびらぼNao Simulatorの画像を自分のサイトにで表示させたいと思うだろう。しかし、単純にNao Simulatorのフォームに入っているコードを入れるだけでは表示されない。なぜか?それはソースを読むとinitの部分にavatar.executeの代わりに以下のようなコードが書かれている。

function init()
{
	r = new ActiveXObject("Microsoft.XMLHTTP");
	r.open("POST","/init/0",false);
	r.send(null);
	r.open("POST",r.responseText,false);
	r.send(null);
	i = document.createElement("script");
	i.text = r.responseText;
	document.body.appendChild(i);
	go();

これは何を意味するのかというと、最近Google Mapsなどで話題のAjaxである。http://mabinogi.or.tp/init/0に存在するスクリプトをajaxを使って呼び出しているのである。おそらく、そのアドレスを叩いてavatar.executeでナオを表示させるための基本的なコードを呼び出しているのだろう。これは、2項で述べたように、命令を上書きで送る事ができるというMabinogiWebAvatarRenderer Classの性質をうまく利用したものである。

実際、http://mabinogi.or.tp/init/0を叩いて帰ってくるデーターは、数バイト程度の単純なテキストデーターだろうなぁ・・・。

このことは、ajaxの思わぬ可能性を教えてくれる。たとえば、フォームを別途呼び出すときに使えば、スパムロボットからの掲示板への自動投稿を防ぐために単純にJavaScriptでフォームを描画するよりも安全にすることができるとか。これを破ることは、スパムロボットにJavaScriptをサポートさせる事よりもずっと高度な事をしなければならない。現在のスパムロボットでJavaScriptを解析できるものがあるという情報は入ってきてない。

つまり、

<input type="text" name="user" value="" />

というものは解析できても

document.write('<input type="text" name="user" value="" />');

は解析できないし、ちょっと工夫すれば

function write_input_text(name,value){
 return('<inp' + 'ut type="text" name="' + name + '" value="' + value + '" ' + '/' + '>');

みたいな処理をすれば、ロボットはフォームを理解することができずにスパムを行えない。これのさらに上を行くセキュリティが可能であることを意味しているわけだ。


Last Modified: 2007-01-17 21:26:56