SWF Binary Hacks ~ evalのいばら道 ~ Shibuya.JS Technical Talk#3 – Shibuya.es 竹迫 良範 <[email protected]> はじめに 2 謝罪 今日 Flex2 SDK を インストールしたばかりです 嘘言ってたらごめんなさい 3 eval の発音について eval イーヴァル eval イヴァル eval エヴァル の検索結果 約 4 件 の検索結果 約 11 件 の検索結果 約 12 件 eval イーバル eval イバル eval エバル の検索結果 約 13 件 の検索結果 約 13 件 の検索結果 約 28 件 ※某G調査機関による調べによる 4 JavaScriptでフォント名一覧を 取得する3つの方法 (1) IE限定 (2) LiveConnect (3) Flash利用 TAKESAKO @ Yet another CybozuLabs http://labs.cybozu.co.jp/blog/takesako/2007/03/javascript_getallfonts.html (1) Dialog Helper Object でフォント名一覧取得 <OBJECT id="dlgHelper" CLASSID="clsid:3050f819-98b5-11cf-bb82-00aa00bdce0b" width="0px" height="0px"> </OBJECT> function getAllFontsByDialogHelper() { var fontslist = ''; try { for (var i = 1; i < dlgHelper.fonts.count; i++) { fontslist += dlgHelper.fonts(i) + '\n'; } } catch(e) { fontslist = 'sorry, could not get fonts list.'; } return fontslist; } 6 7 ※動作するブラウザが激しくIEに限定される 8 (2) LiveConnect で Javaアプレットを操作 java.awt.GraphicsEnvironment#getAllFonts() function getAllFontsByLiveConnect() { var fontslist = ''; try { var fonts = java.awt.GraphicsEnvironment. getLocalGraphicsEnvironment().getAllFonts(); for (var i = 0; i < fonts.length; i++) { fontslist += fonts[i].getFontName() + '\n'; } } LiveConnect catch(e) { - Netscape3以降の仕様(JavaScript1.1) fontslist = 'sorry, could not get fonts list.'; - Firefox, Opera で動作 } return fontslist; JavaのオブジェクトをJavaScriptから操作 } 9 LiveConnectとは? できること JavaのオブジェクトをJavaScriptから操作できる その逆も 動作環境 Netscape3以降(JavaScript1.1)の仕様 Firefox, Opera で動作 使用できる条件 Javaアプレットの実行が許可されているとき 10 (3) Flash の TextField.getFontList() を利用 var user_fonts = TextField.getFontList(); user_fonts.sort(); getURL('javascript:fontList("‘ + escape(user_fonts) + ‘“)’, '_self'); こんな感じで .asファイルを作って getFontList.swf を作る 11 でも、いちいち swfファイルを 作るの面倒だよなぁ… Flash(ActionScript)で eval 使えたっけ? SWF Binary Hacks ~ evalのいばら道 ~ 斜め下から始める 初めてのFlash 13 FlashProxy.swf でFlash関数を動的実行 Collection & Copy - JavaScript用Flashプロキシ、 Javascript Sound Kit (id:brazilさん作) http://d.hatena.ne.jp/brazil/20060726/1153884951 <script type="text/javascript"> Sound.methods = "loadSound start stop getId3 getPan setPan getTransform setTransform getVolume setVolume getDuration setDuration getPosition setPosition getBytesLoaded getBytesTotal".split(" "); function Sound(){ return new FlashProxy("Sound", Sound.methods); } var sound = new Sound(); : みたいな感じで JavaScript から Flash の関数を動的に呼び出すことができる 14 FlashProxy.as のソースコード(id:brazilさん) import flash.external.ExternalInterface; class FlashProxy{ static var proxy; var target; function FlashProxy() { this.target = new (eval(_root.className)); ExternalInterface.addCallback("dispatch", this, dispatch); ExternalInterface.addCallback("addListener", this, addListener); } function dispatch(prop, args) { var obj = this.target[prop]; if (obj instanceof Function) { return obj.apply(this.target, args); } return obj; } function addListener(event) { this.target[event] = function(){ ExternalInterface.call("FlashProxy.onTrigger", _root.id, event, arguments); } } static function main(mc) { proxy = new FlashProxy(); } } 15 お、Flashでも evalできる? 16 17 なんかFlashにはいろいろ制限があるみたい import flash.external.ExternalInterface; class FlashProxy{ static var proxy; var target; function FlashProxy() { this.target = new (eval(_root.className)); ExternalInterface.addCallback("dispatch", this, dispatch); ExternalInterface.addCallback("addListener", this, addListener); } function dispatch(prop, args) { この方法だと var obj = this.target[prop]; if (obj instanceof Function) { TextField.getAllFonts() return obj.apply(this.target, args); } return obj; } や System.setClipboard みたいな スタティック関数の呼び出しができない (インスタンスを直接生成できない abstract クラスのメソッド) function addListener(event) { this.target[event] = function(){ ExternalInterface.call("FlashProxy.onTrigger", _root.id, event, arguments); } } static function main(mc) { proxy = new FlashProxy(); } } 18 次のバージョンでは eval 自体廃止されちゃうし 19 JavaScript から Flash の スタティック関数を evalっぽく実行したい! 20 例えば Ruby の場合… 3つのeval関数があるのに! 1. ふつうの eval 2. Object#instance_eval 3. Module#module_eval/class_eval → 空前のメタプログラミング期ブーム 21 それ Flashy.swf でできるよ 22 それFlashy.swf 使えばできるよ JavascriptからFlashの任意の静的関数を 呼び出すことができる <object id=“flashy” data=“Flashy.swf” /> <script language="JavaScript"> var flash = document.getElementById('flashy'); flash.setStatic('flash.system.IME.enabled', true); // IME オン </script> Kazuho@Cybozu Labs: JavaScript から Flash の便利な機能を使う方法 http://labs.cybozu.co.jp/blog/kazuho/archives/2007/03/flashy.php 23 Flashy.as のソースコード(奥一穂さん) package { スタティック関数の呼び出しを動的に import flash.display.*; import flash.external.ExternalInterface; (インスタンスを直接生成できない import flash.utils.getDefinitionByName; abstract クラスのメソッドも呼べる) public class Flashy extends Sprite { public function Flashy() { ExternalInterface.addCallback("getClass", getClass); ExternalInterface.addCallback("getStatic", getStatic); ExternalInterface.addCallback("setStatic", setStatic); ExternalInterface.addCallback("callStatic", callStatic); } public function getClass(expr:String):Object { return getDefinitionByName(expr); } public function getStatic(expr:String):Object { var m:Object = expr.match(/^(.*)\.(.*?)$/); return this.getClass(m[1])[m[2]]; } public function setStatic(expr:String, value:Object):void { var m:Object = expr.match(/^(.*)\.(.*?)$/); this.getClass(m[1])[m[2]] = value; } public function callStatic(expr:String, args:Array):Object { var m:Object = expr.match(/^(.*)\.(.*?)$/); return this.getClass(m[1])[m[2]].apply(m[1], args); } } } 24 Flashの関数を呼ぶだけじゃなく ASのコードを直接実行してみたい eval使えないけど、どうする??? JavaScript で SWF を動的生成すればできるよ! <body><embed width="0px" height="0px" type="application/x-shockwave-flash" flashvars="param=val" src="data:application/x-shockwave-flash;base64, Q1dTCbwDAAB42l1SQW/TMBS23a5uu5VtGqqGEFKlTaqE1CbtDmhVFzG1KxoHi uCCkCbqOm5j5iaR4y7dATEu/AROO8PP4IzEoTvwBzhx4R9wwE7G2mFF8nufv+ /zy3uegexPAO58BmAbgu7mPQDA+61vEIC2dEetF91eZTYRftTS2UHVUypsWVY cx/V4rx7IsdXY39+37KbVbNY0oxad+4rMan60U3USgy6LqOSh4oFfMTkZBlN1 UK1eu7r0xjScSpFYutRigk2YryKrUW9oI5e2RoGcEOWQMBScEmNnzWqRF9DTm Jyx2kiQyGtbC6LRKK4Ecw7dYMgqPcFmlWblcKFP2CnFkN1Foc7SbxKjrtNgYo UycKdU1zTSVol4WWIswulQ8Mhj0pn6p34Qp1csUMOhkhEV3Gb8w8y5IP54Ssb MOXqWnN3kSY1EMadp248se89q7qVFGKxt/dfra0SPzwHdjV+ZNuigj5dfXhf1 YJOFwKc3KIl+X95/t6nh78Uel5HqcEkFA1/vftCYYY8kmbAG2AB1gC4u/mCgw 9Ulainpfd3lUSjIee5lKLli+bEkocdpVBiyMfd7XIiiK0mcSjDzXQPliet2PC 7cXH/4llG1llqxMzP79SOzdbUtUVS3r9RNb0ipm8e+YpJQxc9YipRvnXcC/RC 5z+RKGZYz26i8CkoYIoyyGK5gmMMQY5jHsIBhEWfXMCphdAej9QxYXhCiQibp AkQQZiHQCcwXMnP7iYayqFBszO3KBfoxPwYn6CkCOrwaZWqwn4V6333+cLfdX 8nosJ8DJ/iqj6EWIu2V35nbDAzy9qBgD4r2YNUerNkDpL9X4EGyPEPd2DKXLw /msc7/AuHTEs4="></embed></body> 26 URI data:スキームでGIF画像を動的に生成 GIF画像をbase64でエンコード(RFC2397) <img id="icon_here"> <script> var data = ‘data:image/gif;base64,’+ ‘R0lGODlhAAEwAMQAAJ2M5Me98GRK1DoYyYBr3PHv・・・(中略)・・・ Pe99XO81Y50auc6PBkZEgpzbmt7HJa2I57CffgnMNqmWHAWNBwwGsKp KsrmJqltOOV69nuYxSkqpoTata18rWtrr1rTIIAQA7'; var icon_elem = document.getElementById("icon_here"); icon_elem.src = data; </script> http://www.kawa.net/works/js/data-scheme/base64.html Firefox, Opera で動作 残念ながら IE では動作しませんが・・・ 27 GIF SWF 28 SWFファイルフォーマットの仕様書 Adobe Player Licensing から入手可能 http://www.adobe.com/licensing/developer/ メールアドレス(Adobe ID)を登録 ライセンスに同意する必要がある Flash6以降の情報のみ Alexis' SWF Reference http://sswf.sourceforge.net/SWFalexref.html Flash6以前の情報についても書いてある 2001年からの蓄積 29 Alexis' SWF Reference : : : : http://sswf.sourceforge.net/SWFalexref.html 30 SWF File Header, SWF Tags… struct swf_header { unsigned char unsigned char unsigned long } f_magic[3]; 'FWS' or 'CWS' f_version; f_file_length; struct swf_header_movie { swf_rect unsigned short fixed unsigned short }; f_frame_size; f_frame_rate; f_frame_count; struct swf_csmtextsettings { swf_tag f_tag; /* 74 */ unsigned short f_text_id_ref; unsigned f_use_flag_type : 2; unsigned f_grid_fit : 3; unsigned f_reserved : 3; long float f_thickness; long float f_sharpness; unsigned char f_reserved; }; 31 SWFファイルを DISアセンブル しながら勉強したい… 32 swfdumpコマンドで DISアセンブル SWFTOOLS の swfdump コマンドを使うと SWFファイルの内容をダンプすることができる http://www.swftools.org/documentation.html > swfdump --full FlashProxy.swf [HEADER] [HEADER] [HEADER] [HEADER] [HEADER] [HEADER] [HEADER] [009] [027] [000] [038] File version: 8 File is zlib compressed. Ratio: 63% File size: 796 (Depacked) Frame rate: 20.000000 Frame count: 1 Movie width: 450.00 Movie height: 325.00 3 SETBACKGROUNDCOLOR (ff/ff/ff) 4 DEFINESPRITE defines id 20480 0 END 21 EXPORTASSETS exports 20480 as "__Packages.MTASC" [03b] 643 DOINITACTION adds information to id 20480 ( 206 bytes) action: Constantpool(22 entries) String:"FlashProxy" String:"_global" String:"target" String:"_root" String:"className" String:"dispatch" String:"flash" String:"external" 33 swfdumpはアクションレコードの抽出が苦手 ( : 8 bytes) action: unknown[8e] (remainder of 8 bytes:"\0\0\0\2)\0p\0") : アクションレコードの抽出に失敗 … orz 34 SWF::Parser (CPAN) なら・・・ dumpswf.plx dumpswf.plx Flash.swf > Flash.pl Flash.swf そのものを生成する Perlスクリプト「Flash.pl」を生成 http://www.nmt.ne.jp/~ysas/butaperl/swf/Parser.sjis.pod.html http://search.cpan.org/~YSAS/SWF-File/lib/SWF/Parser.pm 35 Sothink SWF Decompiler (試用期間30日) http://www.sothink.com/product/flashdecompiler/ 36 DISアセンブル結果(Sothink SWF Decompiler) 37 しかし、 URIデータスキームに 埋め込みのSWFは Flash Player 9 では動かない…orz Flash Player 8 では動いたのに(><) 38 Flash上で動く ECMAScriptの処理系 があればいいじゃね? Flash Lite 職人である鴨志田さんに聞いてみると そういう処理系があるらしい! 40 ScriptEngine.swf の特徴 バイトコードインタプリタ 一旦スクリプトをバイトコード的なものに変換してから 独自VM上で実行 ECMA-262 3rd Editionにほぼ準拠 +いくつかの拡張(コルーチンなど) ActionScript1 的な感じで記述が可能 詳しくはWebで http://www.be-interactive.org/?itemid=6 http://www.be-interactive.org/?itemid=194 41 Xelf(ゼルフ)の開発者 – 新藤さん(高校3年生) 名前の由来:Flexの逆でxleF http://bcnranking.jp/it_junior/21-00012742.html ゲームを製作しやすくしよ うプロジェクトの一環として、 ECMAScript +αの処理系 をFlash(AS)上に実装 期待age 42 まとめ 43 Flashでevalっぽいことをするには? JavaScript でできないことをプラグインで Javaアプレット + LiveConnect(IEでは使えない) Flash 使えばいろいろできる(クロスブラウザ) JavaScriptからFlashのコードを実行したい ActionScriptで任意の関数を呼ぶ方法 FlashProxy.swf Flashy.swf (id:brazilさん) (奥一穂さん) SWFファイルの動的生成(URIデータスキーム) Flash Player 9 以降ではもう使えない技…orz Flash上で動く ECMAScript+αの処理系あるよ これ最強! 新藤さんGJ 44 ご清聴ありがとうございました Special Thanks to: CybozuLabs 奥さん、鴨志田さん 45
© Copyright 2024 ExpyDoc