2010
7/29

IE+SWFのSSL領域との通信時に発生するトラブルについて

とある案件でちょっとハマったので備忘録がわりにメモ。まず今回のファイル構成は以下のとおり。

fig

処理の流れとしては、

(1)main.swfからSSLサーバのcrossdomain.xmlを読み込み。
(2)main.swfからdata_output.phpにアクセスし、読み込む画像のURL一覧を記載したXMLデータを取得。
(3)(2)で取得したXMLデータをもとに、個別の画像を読み込み。

・・・という、割とよくあると言えばよくある構成です。ポイントはやっぱりSSL領域とのクロスドメイン通信があること。ドメイン名が同じでも、非SSLのサーバとSSLサーバとでは別ドメインと判断されるんですよね。

で、一通り作ってサーバにアップしたところ、FirefoxやChromeやSafariでは動くのになぜかIEだけ画像が表示されない!crossdomain.xmlはきちんと記述できてるし、XMLデータを非SSL側のサーバに設置すればIEでも動くので、どこで止まってるんだろうと調べたところ、(2)のXMLデータ取得のところでポシャってることが判明。で、Google先生に尋ねて出てきたのが以下の記事:

つまりこれはIEに起因する問題で、非SSL領域のSWF(に限らず、Ajax通信などでも同じでしょう)からSSL領域のデータをリクエストした際、サーバからのレスポンスヘッダにPragma: no-cacheが含まれているとIE側で正しく処理ができないんだそうです。なんとご無体な・・・。

FirefoxでHttpFox使ってdata_output.phpのレスポンスヘッダを調べてみたところ、あったあったありましたよPragma:no-cacheが。ということで、php側に対応を依頼しました。

しかしこれ随分と前から存在する問題のようですけど、IE側では修正(変更?)する予定は無いんでしょうか・・・。


Filed under: ActionScript3,Troubles,WindowsComments (0)— tonpoo @ 4:22 PM

2010
7/2

Error calling method on NPObject

ss

製作中のとあるフルFlashサイト。ブラウザで普通に確認してる分には問題なく動作していたため全く気がつかなかったが、Firefoxのエラーコンソールを開いてみると「Error calling method on NPObject」というJavaScriptエラーが頻発!「なんじゃこりゃ」ということで早速調べてみたところ、原因がわかりました。

まず、今回のサイトは以下のような条件が揃っていました。

  • SWFファイルのドメインと、そのSWFファイルを埋め込んで表示するHTMLファイルのドメインが異なっている(SWFは http://www.hogehoge.home/movie.swf にあり、HTMLファイルは http://user.hogehoge.home/index.html にある、というような感じ)
  • マウスホイール対応のためにSWFWheelを使用
  • SWFファイルの埋め込みにSWFObjectを使用

そしてSWFWheelのサイトを見ていたところ、以下のような注意書きが:

その他

外部ドメインからの読み込み

SWFWheelを使ったswfファイルを、外部ドメインから読み込む場合、HTML側とActionScript側の両方でExternalInterfaceの動作を明示的に許可する必要があります。

  1. HTML側にて、paramタグ及びembedタグでallowScriptAccessの値にalwaysを指定する。
  2. ActionScript側にて、Security.allowDomain等で許可するドメインを指定する。

ビンゴですね。1.の方は対応済みだったんですが、2.の方が未対応でした。ところで今回のサイト、サブドメインの数が一定でなく、運用後に随時追加される可能性があります。ので、ワイルドカードを使って以下のようなコードを追加。

Security.allowDomain("*.hogehoge.home");

結果は・・・?ダメでした。まだエラーが出ます。うーん、もしかしてワイルドカードでサブドメインを指定するのは無理なのか?ということで、今度は以下のコードで実験。

Security.allowDomain("*");

成功!エラーがでなくなりました。全ドメインを対象にしてしまうのは危険といえば危険ですが、現時点ではこれが最善の策でしょうか。


Filed under: ActionScript3,SWFObject,SWFWheel,TroublesComments (0)— tonpoo @ 11:37 AM

2010
6/24

Flash Communication Server:プロキシサーバに関する問題

HTTPトンネリングの件に関連して、FCS関連でプロキシサーバを経由した場合の接続方法についての下記の記事も簡単に和訳しました。

Macromedia – Developer Center : Tunneling Macromedia Flash Communications through Firewalls and Proxy Servers. Page 3

例によって文書自体が古い上に意訳・適当な訳文ですが、HTTPトンネリングと同じく何かの参考までに。

※注:HTTPトンネリングの記事同様、こちらもリンク先が無くなってしまいました。アドビサイトにどこかに原文残ってないのかな・・・。


プロキシサーバに関する問題

内部のネットワークとインターネットとの中継役としてプロキシサーバを利用することで、組織のネットワーク環境をより安全にすることができる。WEBプロキシサーバというのは通常、ネットワークの通信料を削減するためのキャッシングサーバとして利用される。とはいえ、プロキシサーバの使い道は他にもある。

ネットワークレイヤーのファイヤーウォールとプロキシサーバを組み合わせることで、WEBへのアクセス自体は確保した上で、組織のネットワーク内にあるワークステーションから外部のネットワークに対して直接アクセスする必要がなくなる。ブラウザはリモートのサーバに対してWEBページのデータを直接要求するのではなく、プロキシサーバに対して要求しなければならない。ページのデータがキャッシュされていなかった場合には、プロキシサーバがリモートのサーバに対してリクエストを行ない、返ってきたデータをブラウザに戻すことになる。プロキシサーバが中継役として存在する場合、ファイヤーウォールは基本的にネットワーク内部から外部に対して直接送出されるリクエストは全てブロックするように設定されていることが多い―――たとえそれが80番ポートに対するものであったとしても。プロキシサーバだけが80番ポートを通じて外側の世界との接続を許されているのだ(図8を参照)。

HTTPトンネリングを使わない場合、プロキシサーバの内側にいて、インターネットへの直接接続が許可されていない環境にあるユーザーはコミュニケーションサーバへの接続ができない。HTTPトンネリングを使えばできるようになることがしばしばある。プロキシサーバからしてみれば、RTMPTを使った接続要求というのは通常のHTTPリクエストと同様に捉えられる。コミュニケーションサーバからのレスポンスもHTTPレスポンスと同様に判断される。このため、プロキシサーバはRTMPTリクエストの送出もコミュニケーションサーバからのデータ受信についても対応できるはずである。ところが、HTTPトンネリングがうまくいくかどうかは保証されていないのだ。プロキシサーバにはWEBページをキャッシュする中継役以上の機能がある。それは、外部のネットワークリソースに対するアクセスの制御ということだ。例えば、プロキシの管理者はアクセス禁止サイトのリストを作成し、プロキシサーバ内の全ユーザーに対して、それらのサイトへのアクセスを拒否することができる。プロキシサーバの中には、さらに詳細にデータの調査やフィルタリングが可能なものもある。例えば、特定のコンテンツや、text/thmlのようなMIMEタイプのみを許可することもできる。WEBサーバがWEBページのデータをブラウザに対して返す際、HTTPヘッダにはContentTypeというデータが含まれる。WEBサーバがWEBページのデータを送出する場合のHTTPヘッダの書式は以下のようになる:

HTTP/1.1 200 OK
Server: Netscape-Enterprise/6.0
Date: Sat, 24 May 2003 01:09:43 GMT
Content-type: text/html
Etag: "c96066c3-1-0-1e8"
Last-modified: Tue, 25 Jun 1996 19:11:18 GMT
Content-length: 488
Accept-ranges: bytes

また、画像データを送出する場合のHTTPヘッダの書式は以下のようになる:

HTTP/1.1 200 OK
Server: Netscape-Enterprise/6.0
Date: Sat, 24 May 2003 01:51:17 GMT
Content-type: image/gif
Etag: "782311ca-126-0-f1ae"
Last-modified: Mon, 06 May 2002 21:10:38 GMT
Content-length: 61870
Accept-ranges: bytes

Macromedia Flash Communication Serverが返すデータはテキストデータではないが、HTTPヘッダにはContent-typeの記述が含まれない。そして、Content-typeが記述されていない場合にはtext/htmlと判断されてしまう。このため、RTMPTのトラフィックであっても、全てのプロキシサーバを通過できるという保証は無いのである。プロキシサーバとアプリケーションレイヤのファイヤーウォールというものが、システムアドミニストレータの設定した幅広いバリエーションのルールに従ってコンテンツのフィルタリングを行うように作られているということを考慮すれば、これはおかしなことではない。ITセキュリティの部署が正規のHTML文書といくつかの画像フォーマット(image/GIFなど)のみを許可すると決定したならば、それを実現するための精巧なツールが開発されるということだ。もしRTMPT接続さえも通さないプロキシサーバの場合は、組織のファイヤーウォール担当の管理者に連絡を取り、プロキシサーバの例外設定が可能かどうか確認するといい。

fig08

図8.プロキシサーバとファイヤーウォール

注:各端末(Workstation)はインターネットに直接接続することはできず、必ずプロキシサーバを通してリソース要求を行うことになる。プロキシサーバはインターネットからリソースを取得し、それを各端末に転送する。各端末がファイヤーウォールを越えて外部のシステムにアクセスすることは決してない。

一度に複数のポートを利用する

Macromediaは先日、Flash Communication Server バージョン1.5のリリースとともに、Flash Communication Serverコンポーネントのアップデート版をリリースした。このアップデートの目玉のひとつが、Simple Connectコンポーネント内部に新規に追加されたコードである。このアップデートによって、デフォルトのRTMPポート(1935)経由で到達できないサーバへの接続時間を短縮するための機能が追加された。Simple Connectコンポーネントのアプリケーションディレクトリのパラメーターに「rtmp」が指定されていて、かつポート番号が指定されていない場合、Simple Connectコンポーネントは次のように動作する:

  1. NetConnectionオブジェクトを生成し、指定されたアドレスに対して、1935番ポートを使って通常の接続を試みる。
  2. 2つめのNetConnectionオブジェクトを生成し、250ミリ秒待機した後、サーバに対して80番ポートを使ったRTMPT接続を試みる。
  3. 先に接続が成功した方を受け入れ、もう片方のNetConnectionオブジェクトは接続を閉じてから破棄する。

厳密に言えばこのようなやり方は必要ない。FlashPlayerはデフォルトでまず1935番ポートを使ったRTMP接続を試み、その後443番ポート、80番ポートを試みる。その後、80番ポートを使ったRTMPT接続を試みるからだ。ただしこれらの試みは時間がかかる。はじめのRTMP接続が失敗した場合、250ミリ秒後に80番ポートを使ったRMTPT接続を試みることで、接続プロセスにかかる時間は劇的に短縮されるのだ。このコンポーネントの作りを理解するため、FCSimpleConnectClassのactualConnect()メソッドを見てみよう。すべての人がSimple Connectコンポーネントを使うわけではないので、以下に示すコードは本来のコードを少々編集したものになっている。ただし行っている処理はほぼ同じだ。筆者はこのコードをメインのタイムラインに記述したが、よりオブジェクト指向的なアプローチで書き換えることも可能である。

//接続に成功するとonConnectファンクションが実行される
function onConnect(nc) {
	_global.main_nc = nc;// グローバル変数に接続成功済みのNetConnectionオブジェクトを記録
	// 確認のためURIをtraceし、使用中のプロトコルを確認
	trace("onConnect> "+nc.uri);
	// 接続に成功したNetConnectionオブジェクトのためのonStatusハンドラを生成
	main_nc.onStatus = function(info) {
		//ここに各種のイベントをハンドルするためのコードを記述
		//以下のコードはinfoオブジェクトの内容を出力するもの
		trace("----main_nc.onStatus----");
		for (var p in info) {
			trace(p+": "+info[p]);
		}
	};
	//あとは他のコンポーネントに接続したりプログラムを初期化するなど・・・
}

//接続に失敗するとonConnectFailedファンクションが実行される
function onConnectFailed(info) {
	//infoオブジェクトを検証し、接続失敗の原因についてレポートする
	//以下のコードは単にinfoオブジェクトの内容をtraceしているだけなので、
	//各自でエラーハンドリングコードを書き換えること
	trace("----onConnectFailed----");
	//infoオブジェクトの全プロパティの分ループ処理
	for (var p in info) {
		trace(p+": "+info[p]);
		// If the application rejects the connection and passes back
		// and application object loop through all its properties too.
		if (p == "application") {
			var appObj = info.application;
			for (var q in appObj) {
				trace("   "+q+": "+appObj[q]);
			}
		}
	}
}

//RTMP接続用のNetConnectionオブジェクトを生成
rtmp_nc = new NetConnection();
//こちらの接続が先に成功した場合に、rtmpt_ncオブジェクトを破棄するための
//onStatusハンドラを生成
rtmp_nc.onStatus = function(info) {
	this.pending = false;
	if (info.code == "NetConnection.Connect.Success") {
		if (rtmpt_nc.pending) {
			rtmpt_nc.onStatus = null;
			rtmpt_nc.close();
			rtmpt_nc = null;
			clearInterval(connectionID);
		}
		onConnect(this);
	} else if (!rtmpt_nc.pending) {
		onConnectFailed(info);
	}
};

//RTMPT接続用のNetConnectionオブジェクトを生成
rtmpt_nc = new NetConnection();
//こちらの接続が先に成功した場合に、rtmp_ncオブジェクトを破棄するための
//onStatusハンドラを生成
rtmpt_nc.onStatus = function(info) {
	this.pending = false;
	if (info.code == "NetConnection.Connect.Success") {
		if (rtmp_nc.pending) {
			rtmp_nc.onStatus = null;
			rtmp_nc.close();
			rtmp_nc = null;
		}
		onConnect(this);
	} else if (!rtmp_nc.pending) {
		onConnectFailed(info);
	}
};

//どちらのNetConnectionオブジェクトについてもペンディングフラグを立てておく
rtmp_nc.pending = true;
rtmpt_nc.pending = true;

//rtmp接続を試みる
rtmp_nc.connect("rtmp://host.domain.com/myApp/myInstance",userName,password);

//rtmpt接続を400ミリ秒後に行うように設定
connectionID = setInterval(connectRTMPT, 400);

//このファンクションが実行されたらインターバルを破棄してRTMPT接続を試みる
function connectRTMPT() {
	clearInterval(connectionID);
	rtmpt_nc.connect("rtmpt://host.domain.com/myApp/myInstance",userName,password);
}
//80番ポートが使えず、8080番ポートを使う場合などのconnectRTMPTメソッドの記述例は以下のとおり
function connectRTMPT() {
	clearInterval(connectionID);
	rtmpt_nc.connect("rtmpt://myHost.myDomain.com:8080/myApp/myInstance",userName,password);
}

Filed under: ActionScript2,ActionScript3,TranslationComments (0)— tonpoo @ 1:22 PM

2010
6/15

Flash Communication Server:HTTPトンネリングプロトコルについて

諸事情からFlashCommunicationServerへのHTTPトンネリング接続の方法について調べる機会があり、下記のドキュメントを簡単に和訳してみました。

HTTP Tunneling protocols

※注:リンク先が無くなってしまいました・・・。げ、原文まだどっかに残ってないかな・・・。

旧Macromedia時代の文書で、例によってかなり意訳・適当な訳文ですが、何かの参考までに。


HTTPトンネリングプロトコル

RTMP、RTMPT、RTMPS

FlashPlayerはFlashCommunicationServerと通信する際、デフォルトではRTMPプロトコルを使い、1935番ポートに接続する。 失敗したら443番ポートと80番ポートでの接続を試みる。 ファイヤーウォールが設定されている場合、非標準のポートを経由したTCP/IP通信が許可されていないことがあるため。 これらの手法で、およそ96%のユーザーをカバーすることができるはず。

100%に近いユーザーをカバーするためには(もしあれば)プロクシを通すか、ファイヤーウォールのためにHTTP通信しかできない場合などはHTTPトンネリングを使ってHTTPプロトコル越しにRTMPパケットを送信することになる。

以前のFlashPlayerでは、サーバへの通信要求は常にRTMPプロトコルで行われ、オプションとしてポート番号を指定することが可能であった。以下のコードでは、RTMPを利用し、1935番、443番、80番の3つのポートを使った計3回の接続を試みる。

nc.connect("rtmp://mysite.com/myapp");

以下のようにしてポート番号を指定した場合には、指定されたポート番号を使った1回の接続のみを試みる。

nc.connect("rtmp://mysite.com:PORT/myapp");

現在のFlashPlayerでは、以下の3つのうちどれか一つのプロトコルを使った接続がサポートされるようになった。

  • RTMP(デフォルトポート:1935)
  • RTMPT(HTTPを経由したトンネリング。デフォルトポート:80)
  • RTMPS(HTTPSを経由したトンネリング。デフォルトポート:443)

コードの書式は以下のようになる。

  • nc.connect("rtmpt://flashteam.macromedia.com/myapp");
  • nc.connect("rtmps://flashteam.macromedia.com/myapp");

上記の場合、各プロトコルのデフォルトポートに対しての計1回の接続のみを試みる。

ポート番号を指定する場合の書式は以下の通り。

  • nc.connect("rtmp://flashteam.macromedia.com:PORT/myapp");
  • nc.connect("rtmpt://flashteam.macromedia.com:PORT/myapp");
  • nc.connect("rtmps://flashteam.macromedia.com:PORT/myapp");

上記の場合は、指定されたポートに対しての計1回の接続を試みる。

また、以下のような特殊な接続方法もある。

  • nc.connect("rtmp://flashteam.macromedia.com/myapp");

この場合、RTMP:1935を試みたあとにRTMPT:80(昔のHTTP:80に代わるもの)を試みる。

新しいFlashPlayerでは、これは「万が一の場合の代替手法」として機能している。もしデフォルトの方法が失敗した場合、FlashPlayerは80番ポートでの接続を試みる。おそらくこれがHTTPトンネリングのための最も一般的な手法であろう。

メモ:HTTPトンネリングはリアルタイムな音声・映像配信のパフォーマンスに影響をおよぼすことがある。


・・・結論としては、以下の方法がベスト、っていう認識でいいのかな。

nc.connect("rtmp://flashteam.macromedia.com/myapp");

Filed under: ActionScript2,ActionScript3,TranslationComments (0)— tonpoo @ 2:39 PM

2010
5/12

FlashDevelop3.1.1+FlashIDEでプロファイラは使えるのか?

昨日は第35回Flash OOP 勉強会『Flash OOP presents/Flash開発環境自慢大会!』に参加。そこでFlashDevelop担当の馬鹿全さんが紹介してくれた機能のうち、魅力的だったもののひとつがプロファイラデバッガ。もっとも、デバッガについては3.2.*から正式に実装されるということだったので、とりあえずはプロファイラから使ってみよう!・・・と思ったのはいいものの、FlashDevelop + FlexSDKじゃなくて、FlashDevelop + FlashIDEの組み合わせで果たして使えるのか?図々しくも馬鹿全さん本人に質問したところ「中を見る限りではFlexSDK側だった気がします」との回答が。むむ、それはちと寂しい・・・。ただ、馬鹿全さんも「実はまだ僕も試していません」とのことだったので、とりあえず試してみました。

まず、自分の環境はまだFlashDevelop3.1.0だったので、これを3.1.1にバージョンアップ。でもって起動すると、憧れの(?)プロファイラパネルが出現!まあでもパネルが出ただけで喜んではいけない。プロファイラパネルの目覚まし時計アイコンをクリックしてプロファイラを開始。次に通常通りにIDE(Flash CS3)の方でflaファイルを開き、FlashDevelopではプロジェクトファイルを開き、FlashDevelop側からプロジェクトをテスト!すると・・・
ss

おお、動いとる!
というわけで、どうやら全く問題なくプロファイラが使えるようです。すばらしい!

と思って安心して、しばらくしてからもう一度やってみると・・・動かない。

何故?と思いいろいろ試してみたのですが、どうも私の環境では

  1. まずFlashDevelopを起動する。
  2. プロファイラパネルの「プロファイラを開始」ボタン(目覚まし時計のアイコン)をクリックしてプロファイラを開始しておく。
  3. FlashIDEを起動する(この際、通常のFlashIDE起動より若干時間がかかる)。
  4. flaファイルを開いてテスト(パブリッシュプレビュー)を行う。

・・・という順番で作業を行った場合にプロファイラが作動しました。

うーん、なんなんでしょうね。FlashIDE側の設定か、あるいはFlashDevelop側の設定か、それとも他の何かか・・・。まあ、いずれにせよ、なんとかプロファイラが使えそうなので、しばらくこれで様子見てみます。

追記:

twitterでの馬鹿全さんやflabakaさんの発言などによると、どうも特に起動順とか関係なしにフツーに使えるらしい。むー、ウチの環境固有の問題ですかね・・・。

flabaka – FlashDevelop3.1.1のプロファイラを使ってみる

時間のあるときに別のマシンでも試してみます。


Filed under: FlashDevelopComments (1)— tonpoo @ 6:55 PM

2010
5/10

AlivePDFを使ってSWFからPDF出力

SWFから動的にPDFファイルを生成するためのライブラリであるAlivePDFをちょっと使ってみました。

alivepdf – Project Hosting on Google Code

AIRなら単体でのPDF出力も可能なようですが、SWFファイルからだと単体では無理で、サーバー側にファイル出力用(?)のphpプログラムを設置する必要があるようです。ただ、そのphpプログラムも提供されていたので、とりあえず単純なプログラムを組んで試してみました。
(続きを読む…)


Filed under: ActionScript3,alivepdfComments (0)— tonpoo @ 6:48 PM

2010
5/7

Jobs対Flashの戦いにOperaが参戦とな

TechRadarに、Apple(ジョブス)対Adobe(Flash)の論争にOperaが参戦したという記事が掲載されました。Operaのプロダクトアナリストの人にインタビューした内容ということですが、簡単に和訳してみました。いつも通り(?)、適当訳なので意訳・誤訳が満載です。正確な内容は元記事を当たってみてください。

Opera joins in Jobs v Flash argument | News | TechRadar UK

以下、和訳文です。「卵が焼ける」とはずいぶんですね・・・。

(続きを読む…)


Filed under: Flash,Topics,TranslationComments (0)— tonpoo @ 1:14 PM

2010
4/24

SWFWheelを使ってみる

AS3から実装された、マウスホイールを検知するMouseEvent.MOUSE_WHEELイベントはMacでは動作しない、というのは知っていて、その問題を解消するためのライブラリがあるという話も聞いていたのですが、実際に使ってみる機会に遭遇したので、備忘録もかねて導入までのフローをメモしてみました。ちなみに参考にしたのはfeb19さんの以下の記事:

feb19.jp blog – SWFWheelを使う

導入したライブラリはSWFWheelです。実際の導入フローは以下の通り:
(続きを読む…)


Filed under: ActionScript3,SWFWheelComments (0)— tonpoo @ 12:10 AM

2010
4/22

FlashDevelop3.1.0 RTM出た!!

twitterでも話題になってますが、FlashDevelop3.1.0 RTMが出ました。
(続きを読む…)


Filed under: Flash,FlashDevelop,Software,zen-codingComments (0)— tonpoo @ 10:51 PM

2010
4/6

Flashbugを導入したらFlashPlayerが落ちるようになった件とその解決策

今日、Flashbugの設定をちょっと変更した瞬間から、Flashコンテンツのあるページを表示させるとやたらとブラウザ(Firefox)が落ちるようになってしまった。これがFlashbugを無効化したり削除したりしても直らない上、Google Chromeでも発生したことから軽くパニクったんですが、結論からいうと、Flashbugの設定画面からFlashPlayerの設定を変更してしまったことが原因のようでした。

ss
ええ、仰るとおり、まさに"very easy to crash"でしたよ(涙)。上記のスクリーンショットのように、Undocumented Trace Log Settings欄のチェックを全て外したら、クラッシュせずに動くようになりました。

で、原因究明の過程でFirebugのオフィシャルページ(Flashbug – An extension for Firebug | Course Vector)の文章について簡単に翻訳してみた(してしまった)ので、備忘録をかねて参考までにアップしておきます。
(続きを読む…)


Filed under: Firefox,Flash,Software,Translation,TroublesComments (0)— tonpoo @ 1:10 PM