PHP+モバイルFLASHにて無理矢理ながら画像の差し替え | ~人生はプログラミングだ Web Programmer Openβ~

PHP+モバイルFLASHにて無理矢理ながら画像の差し替え

最初にふと思ったのだが前参考にしたコードって
http://libpanda.s18.xrea.com/

こちらサイトのなのかな。
前回あげたまとめサイトはリンク先がばらばらだったし、そんな気がしてきた(汗
「すみません!気づかずに直リンクさせてもらいました><」って後で言わないと(汗

ここから本題-------------------------------------------------
かなり条件は限定されているが、swfの画像をPHPで差し替える事が出来たのでちょいとまとめ
(と言うより、忘れないようにメモ)

まず、前回話していたswf4の仕様書は結局見つけてないという。
その代わりに良いツールを見つけた。

■お勧めツール[swfdump]
SWFTOOLS


欲しい方はSWFTOOLSをダウンロード。

使い方は、コマンドプロンプトから使用。swfdumpのフォルダまで行き下記を入力


C:\>[リンク先]>swfdump 

これで見れるヘルプ見ると早いかも。
一番簡単な使い方は下記を入力。

C:\>[リンク先]>swfdump xxxx.swf

これだけでバイナリの流れを見るだけでも楽しめる(笑
また、どのバイナリデータが何処を表すかを見ることも可能。
この流れを知れるようになっただけで、だいぶ楽になった。
ちなみに、これを見る前に試していた方法が、


replaceにより画像を文字列として読込み、無理矢理画像をreplaceで入れ替える

…力技とかいわないで><
いやまあ、力技なんだけど。
この力技だけだと上手くいかない。バイナリエディタで違いはわかるんだけど理由が解らない状態に。
そこでこのswfdumpの-dを使い、バイナリデータを検証。
すると、画像の記述はこんな感じになっているのを気づく。

7F 05 xx xx [画像情報そのまま]

7F 05が画像の定義らしい(JPEGしか試してないからJPEGだとそうなのかも。何とも言えない)
次のxx xx の部分が入れるファイルを変更すると変わる。つまり、ファイルサイズを指している事になる!

そんなわけで、16進数に変えた値とやはりreplaceの力技を使い書き換え。
コードにしたらこんな風になった。

//前回の記事のコードを改良
function h32($sizeint){
return pack("V",$sizeint);
}
function h16($sizeint){
return pack("v",$sizeint);
}

function calctaglen($dataarray){
$ret = 0;
foreach($dataarray as $key => $value){
$ret += strlen($key)+strlen($value) + 11;

}
return $ret+1;
}
function maketag($dataarray){
$tag = "\x3f\x03";
$taglen = calctaglen($dataarray);
$tag .= h32($taglen);

foreach($dataarray as $key => $value){
$tag .= "\x96".h16(strlen($key)+2)."\x00".$key."\x00";
$tag .= "\x96".h16(strlen($value)+2)."\x00".$value."\x00";
$tag .= "\x1d";
}
$tag .= "\x00";
return $tag;
}
//ホワイトイメージ(真っ白の画像)
$base_img="new_white.jpg";
$fbimg=fopen($base_img,"rb");
$fbsize=filesize($base_img);
$fb_imgtmp=fread($fbimg,$fbsize);
$fb_size_h="\x7F\x05".h16($fbsize+6);
$fb_imgtmp=$fb_imgtmp;
fclose($fbimg);


//新しいイメージ
$change_img="img.jpg";
$fcimg=fopen($change_img,"rb");
$fcsize=filesize($change_img);
$fc_imgtmp=fread($fcimg,$fcsize);
$fc_size_h="\x7F\x05".h16($fcsize+6);
$fc_imgtmp=$fc_imgtmp;
fclose($fcimg);

// フォームから渡ってきた変数代入文相当のアクションタグ生成
$doactiontag = maketag($HTTP_GET_VARS);
// ベースとなる SWF ファイル指定
$srcswf = "imgload.swf";
// 読み込み
$fr = fopen($srcswf,"rb");

// ヘッダ長さは可変なので途中まで読んでから確定させる
// 背景色設定タグよりも前に DoActionTag 挿入するとエラーでるので
// 便宜的にそいつもヘッダ扱い($headlen 計算の末尾の "+5" 部分)
$headtmp = fread($fr,9);
$rb = ord(substr($headtmp,8,1))>>3; // rectbit
$headlen = ceil(((( 8 - (($rb*4+5)&7) )&7)+ $rb*4 + 5 )/8) + 12 + 5;
$head = $headtmp.fread($fr,$headlen-9);

// 挿入によるファイルサイズ変更反映のためのヘッダ変更
$oldsize = filesize($srcswf);

$tail = fread($fr, $oldsize-$headlen);
$tail = str_replace($fb_imgtmp,$fc_imgtmp,$tail);
$tail = str_replace($fb_size_h,$fc_size_h,$tail);
$newsize = strlen($tail)+strlen($doactiontag)+strlen($headtmp);
$newhead = substr($head,0,4).h32($newsize).substr($head,8);
fclose($fr);


// ファイルに書きだす場合
$destswf = "out.swf";
$fw = fopen($destswf,"wb");
fwrite($fw,$newhead);
fwrite($fw,$doactiontag);
fwrite($fw,$tail);
fclose($fw);
print "<html><head></head><body><a href=\"$destswf\">$destswf</a></body>";


前の記事で紹介したページの内容がベース。
このコードの簡単な流れを書くと

置換する場所を判断する為に現在読み込んでる画像を読み込みますよ(画像サイズも計算)

新しい画像読込ますよ(こっちでも画像サイズ計算)

前の記事で紹介した変数入れ替えだよ

SWFを読み込んで、ファイルサイズと画像を置換

合計サイズをヘッダーに書き込んで書き出し

out.swfを出力

こんな感じに一応成功。テスト第一歩といった所。
問題は画像サイズが変更出来ないのと、いちいち画像サイズに合った空白画像を作らなければいけない事。
そして、一個しか画像ファイルが読み込めない事。
まあ、融通利かない(汗。

そこで、explodeを使い、空白画像部分に別の画像を入れてやるという方法を取ろうとしてますが(やはり力技)、何かファイル容量が合わない。
ファイル容量さえ合えば画像複数は何とかなりそう。

しっかし、他人のソースを利用しないと力任せなコードになるなぁ。
何とかしないと。