Basic認証を越える方法
2010 年 2月 27 日 土曜日 kosuke前回エントリーの際に、Basic認証越えを試した時のメモ。
Basic認証を越える方法は、FLASH-JP.COM – フォーラム にスレッドが有名だと思います。
検索するとこれをAS3に置き換えた方法が沢山あったのですが、試してみて気づいたところがあります。それは送信メソッドがPOSTじゃないと認証されなかったことです。
例えば、以下だとリクエストヘッダで認証できませんでした。Base64エンコーダーはFlex SDKにインストールされているものを使っています。
var encoder:Base64Encoder = new Base64Encoder(); encoder.encodeUTFBytes( "ユーザー名" : "パスワード" ); var header:URLRequestHeader = new URLRequestHeader("Authorization", "Basic " + encoder.toString() ); var req:URLRequest = new URLRequest( "リクエストURL" ); req.requestHeaders.push( header ); navigateToURL( req ); |
こう書き直したら認証されるようになりました。
var encoder:Base64Encoder = new Base64Encoder(); encoder.encodeUTFBytes( "ユーザー名" : "パスワード" ); var header:URLRequestHeader = new URLRequestHeader("Authorization", "Basic " + encoder.toString() ); var req:URLRequest = new URLRequest( "リクエストURL" ); req.requestHeaders.push( header ); req.method= URLRequestMethod.POST; req.data = {}; navigateToURL( req ); |
変わっていることは、送信メソッドにPOSTを指定したことと、dataに空オブジェクトを加えたこと。リファレンスによれば、methodを指定してもdataが無いと自動的にGETで処理されるとあり、でダミーの値を入れておく必要があるようだ。ちなみにdataにオブジェクトを入れて、methodをGETにした場合も認証されませんでした。
FileReference
2010 年 2月 25 日 木曜日 kosukejpgやpng、mp3などをダウンロードさせたい時、navigateToURLで直接URLを指定するとブラウザのウインドウに表示さる。ブラウザのウインドウに表示せずダウンロードさせるにはFileReferenceが有効だ。
参考:FileReference – ActionScript 3.0 言語およびコンポーネントリファレンス
例:画像ファイルをダウンロードする
private function _onMouseDown(e:MouseEvent):void{ var req:URLRequest = new URLRequest( "http://blog.nipx.jp/wp-content/uploads/2009/09/ceocle.jpg" ); var file:FileReference = new FileReference(); file.download( req ); } |
先日、これを使ってつまづいたところをメモしておく。よく読めばリファレンスに記載があったのだが…。
・認証がある場合、ブラウザからでないとダウンロードできない。
認証がある場合、Flashでパブリッシュした後の画面やスタンドアローンプレイヤーではダウンロードが失敗する。ブラウザで表示している場合、認証の入力画面が表示され認証可能。
仕事の場合、開発用のサーバーには大抵Basic認証がかかっていますがいちいちブラウザで確認するのは手間なので、パブリッシュの画面からダウンロードできないか試してみたのだけどダメっぽい。Basic認証を抜けるにはリクエストヘッダを送る方法が知られているけど、FileReferenceでは追加したリクエストヘッダ自体が無視されるようだ。
リファレンス download()メソッドより引用
サーバーでユーザー認証が必要な場合、ブラウザ内で実行される、つまり、ブラウザプラグインまたは ActiveX コントロールを使用する SWF ファイルでのみ、認証用のユーザー名とパスワードをユーザーが入力できるダイアログボックスを表示できます。〜
〜 URLRequest オブジェクトの requestHeaders プロパティは無視されるため、カスタム HTTP リクエストヘッダはアップロードまたはダウンロードでサポートされません。
FileReferenceを使う場合、ダウンロード状況を表示する演出なんか入れることありそうなんで、開発上ちょっと面倒だなぁと思う。ところでこのFileReference、Player 10以上ではFlashで生成したデータを保存させることが出来る。AirならFileで出来ると知っていたがFlash PlayerでもFileReferenceで保存できるようになっていたんですね。saveのdata引数にはByteArrayが渡せるのでどんなファイル形式でも保存出来るようだ。
private function _onMouseDown(e:MouseEvent):void{ var file:FileReference = new FileReference(); file.save( "FileReferenceでテキストデータを保存。", "sample.txt" ); } |
executeのextra引数
2010 年 2月 23 日 火曜日 kosukeProgressionでコマンドを実行するexecuteメソッドには、extraという引数があります。
シーン遷移でコマンドを実行する場合、extraを使うケースはほとんどないと思いますので、あまり馴染みのない引数ですが、コマンドを単体で利用する場合、extraを使うと便利なこともあります。
コマンドリストを実行する際extraを渡すと、コマンドリストに登録された全てのコマンドは実行時に渡されたextraをリレーします。つまり、登録されたコマンドはすべて実行時にextraを利用できます。
たとえば、一連のアニメーションを登録したコマンドリストを実行し、最後の挙動だけ異なるようにしたい場合など、extraを渡して挙動を変更することが可能です。
例:同じコマンドリストを実行し、最後のコマンドでextraで渡した異なる色値に変更する。
btn0.label = "RED"; btn1.label = "GREEN"; btn2.label = "BLUE"; _comm = new SerialList( null, new Prop( ball, { x:450, y:130 } ), new Prop( ball.transform, { colorTransform:new ColorTransform() } ), [ new DoTweener( ball, { x:200, transition:"easeOutSine", time:3 } ), new DoTweener( ball, { y:350, transition:"easeOutBounce", time:3 } ) ], new Func( function():void{ var trans:ColorTransform = new ColorTransform(); trans.color = this.extra; ball.transform.colorTransform = trans; }) ); _comm.interruptType = CommandInterruptType.RESTORE; btn0.addEventListener( MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void{ if( _comm.state == ExecutorObjectState.EXECUTING ) _comm.interrupt( true ); _comm.execute( 0xFF0000 ); }); btn1.addEventListener( MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void{ if( _comm.state == ExecutorObjectState.EXECUTING ) _comm.interrupt( true ); _comm.execute( 0x00FF00 ); }); btn2.addEventListener( MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void{ if( _comm.state == ExecutorObjectState.EXECUTING ) _comm.interrupt( true ); _comm.execute( 0x0000FF ); }); |
Twitterの投稿欄に入力するリクエスト
2010 年 2月 18 日 木曜日 kosukeTwitterを全然利用しないので(特にFlasherには前から流行っているのは知ってるけどニガテなんす。この手のもの)知らなかったのだが、TwitterにstatusパラメータをつけたURLでリクエストすると自分の投稿欄にstatusの値が入力されるってことを最近知りました。
こんな感じ。
http://twitter.com/home/?status=aiueo
Twitterのアカウントを持っていてログインしているなら、投稿欄に「aiueo」と入力されるはず。
何も考えずにFlashからこれを使ったら、
var req:URLRequest = new URLRequest( "http://twitter.com/home/?status=aiueo" ); navigateToURL( req ); |
これで同様に投稿欄に入力されているので、ヨシッと思ったのですが、
//2バイト文字を含む var req:URLRequest = new URLRequest( "http://twitter.com/home/?status=あいうえお" ); navigateToURL( req ); |
とか、
//メタ文字を含む var req:URLRequest = new URLRequest( "http://twitter.com/home/?status=http://nipx.jp/#/nipx" ); navigateToURL( req ); |
だとうまくいきません。
これはURLエンコードされないのが原因。端折らずちゃんとURLVariablesで値を渡せば解消されます。(問題の文字列をエンコードするって手もありますが。)
var req:URLRequest = new URLRequest( "http://twitter.com/home/" ); var vers:URLVariables = new URLVariables(); vers.status = "あいうえお/#/かきくけこ"; req.data = vers; navigateToURL( req ); |
さらにTwitterに送る文字コードはUTF-8である必要があります。
なので、FlashでSystem.useCodePage = true;を使っている場合、送信前にフラグをおろす必要があります。
//文字コードはUTF-8で送る必要あり System.useCodePage = true; //useCodePage = trueにしている場合 var req:URLRequest = new URLRequest( "http://twitter.com/home/" ); var vers:URLVariables = new URLVariables(); vers.status = "あいうえお/#/かきくけこ"; req.data = vers; System.useCodePage = false; navigateToURL( req ); System.useCodePage = true; |
nipx Flash Wallpaper for Mobile Phone
2010 年 2月 16 日 火曜日 kosukeこれまでに掲載していた待ち受けFlashをまとめて、待ち受けFlashサイトを作りました。ブログを提供の場にするのは限界に感じていましたので。ダウンロードはDL-MARKETを試験的に使っています。待ち受けを探す方とこのブログの主な内容は一致しませんので、この方がより多くの方にみてもらえるかと。
待ち受けFlashは、プライベートワークとして今後も時間がある時に作っていきますのでご期待ください。といってもしばらく忙しそうですが…。
nipx 待ち受けFlash / MechanicalCube
2010 年 2月 12 日 金曜日 kosuke
|
自分による、自分の作品。いや、いままでのも自分の作品なんだが。
かわいい系の待ち受けばかりできてたので、シンプルなものを考えた。リアルなアナログ時計なら、カチッ、カチッと動く秒針が好き。その感じをデジタルの文字盤で出したいなぁと思った。
当初、都度、立方体を描画してみたのだけど、Device Centralでシュミレートすると全然厳しい感じだったので、AirとNative3Dを用いて全コマ画像ファイルに書き出したものを使い、ストップモーションで表現しています。時間にあわせて正しく回転させるのは意外に難しいと感じた。アニメーションに使う秒数があるので、今回の場合はフレームレート8以上が出る機種でないと回転しきる前に次の秒が来ちゃいます。
Flash Liteのミリ秒が怪しい
2010 年 2月 11 日 木曜日 kosukeFlash Lite の Date オブジェクトで、ミリ秒の取得・設定でおかしな部分があったので記録。
Flash Liteでミリ秒は正しく動かないのかもしれない。
具体的には試したことですが、以下のソースを実行するとローカルタイムがミリ秒で出力されますよね。
var _date:Date = new Date(); trace( _date.getTime() ); |
これはFlash Playerで期待通り動きました。
しかし、Flash Lite にして、Device Centralで確認すると出力にはミリ秒が切り捨て(?四捨五入?)られた値で表示されます。
//出力
1265814066000
1265814067000
1265814067000
1265814067000
1265814067000
1265814067000
1265814067000
1265814067000
まず、これが実機でももれなくそうなのか、エミュレートによるものなのか、よくわからない。
Device Centralでは、「デバイスステータス」のパネルで、任意の時間を試せるのですが、この「時間」にミリ秒を入力できないので、
このパネルに依存するものなのかもしれないし。
次に手もとの機種(WS007SH Flash Lite 2.1)で以下を試してみました。
_rootにプロット用のテキストフィールドを作ってミリ秒部分を繰り返し出力してみる。
debug.text += " / " + _date.getMilliseconds(); |
これを確認するとミリ秒は丸められることなく、0〜999の値が表示されました。つまりミリ秒は取得できると思ったわけです。この時点では。
で、最終的に僕が何をしたかったかというと、時計をつくるにあたり、数字が表示されるアニメーションを0.5秒で作った為、Dateで取得した時間を500ミリ秒進めて、実時間と数字がキメ状態になる際のラグを減らそうとしました。
var _date:Date = new Date(); _date = new Date( _date.getTime() + 500 ); |
そうしたら何故か正しく動かない。
500ミリ秒の加算がいけないのかと、試しに加算をやめて、秒とミリ秒を以下のソースでプロットし確認したところ、
debug.text += " / " + _date.getSeconds() + ":" + _date.getMilliseconds(); |
わかるだろうか。左の数字と見比べると、なぜか同じ秒でミリ秒が戻っている。44:992→44:64。
500ミリ秒加算した時は、さらに状況が悪くて、
ミリ秒どころか、秒が戻っている。(しかも複数フレームで。)
もう一台別の機種(WS011SH Flash Lite2.1)で試しても同様の状況だった。僕の環境だけの問題なのかもしれないのですが、Flash Liteでミリ秒は正しく得られるのか不透明な状況です。ひとまず、ミリ秒を使うことは諦めることにしました。この件、何かご存知の方は是非コメントいただきたくお願いします。
PreloadSWF
2010 年 2月 10 日 水曜日 kosukeProgression 4.0.1 Public Beta 1.3 ですが過去のバージョンに比べると、とても完成度が上がっていますね。Beta版ということで避けていた方もそろそろ手をだしていい時期と思いました。
先日とある案件で使ってみて、便利なところにいろいろ気づきましたので、いくつか記事にしようと思います。
今回はあらたに追加されたPreloadSWFコマンドについて。
このPreloadSWFを使うと任意のタイミングでプリロードを開始できます。
これがどう便利かというと、CastPreloaderクラスを使って子SWFを読み込む場合おおよそ以下の流れとなります。
1.読み込む直前。この時、atCastLoadStart にて非同期処理が可能。
2.読み込み。この時、atProgress でロード毎に処理が可能。(プログレスバーを進めるなど)
3.読み込み完了。この時、atCastLoadComplete にて非同期処理が可能。
通常、これでまったく問題ないのですが、プリローダーで子SWF以外にも外部ファイル(画像だったり、サウンドだったり、他のSWFだったり)を読み込み、プログレスバーを進行させたいこともあると思います。
この場合、Progressionのコマンドで行うなら、プログレスバーの進行度合いを管理しつつ、atCastLoadStart か、atCastLoadComplete 内で読み込む形になります。こうなるとプログレスバーの管理が若干面倒ですよね。PreloadSWFコマンド(とLoaderList)を使えば、これをとてもスマートに行えます。
例:atCastLoadStart で外部ファイルの読み込みとCastPreloaderの読み込みを実行。
override protected function atCastLoadStart():void{ addCommand( new LoaderList( { onProgress:function():void{ trace( this.percent + "%" ); } }, new LoadBitmapData( new URLRequest( "image1.jpg" ) ), new Trace( "image1 完了" ), new PreloadSWF( {} ), new Trace( "Preloader 完了" ), new LoadBitmapData( new URLRequest( "image2.jpg" ) ), new Trace( "image2 完了" ), new LoadSound( new URLRequest( "sound1.mp3" ) ), new Trace( "sound1 完了" ) ), new Wait( 3 ) ) } |
この場合、image1.jpg の読み込み後、CastPreloaderの読み込みが実行され、その後、image2.jpg、sound1.mp3 を読み込み、3秒後に atCastLoadStart が完了します。特に atCastLoadComplete を設定しなければ、この後、読み込んだCastDocumentの処理に移行します。
少し注意したいのは、atCastLoadCompleteは、PreloadSWFの完了ではなく、atCastLoadStart の完了後実行されることでしょうか。
この方法をとれば、プログレスバーは、LoaderListの onProgrss で進行させるだけですむようになります。
読み込むファイルの容量の差が大きく、プログレスバーの進行がスムーズでない時は、各読み込みコマンドのfactorプロパティを設定して相対的な重要度を設定します。
たとえば、
image1.jpg が 10Kbyte
index.swf が 10Kbyte
image2.jpg が 10Kbyte
sound1.mp3 が 30 Kbyte
なら、sound1.mp3を読み込むコマンドのfactorを3にすると、プログレスバーの進行の差が少なくなると思います。
nipx 待ち受けFlash / Shirokuma
2010 年 2月 10 日 水曜日 kosuke
|