PHPのsession_regeneration_id とセッションフィクシエーション対策

CSRF 対策のうち、セッションフィクセーションを避けるために使われる
session_regenerate_id() 関数について、ITProで間違い(になる場合がある)記事を見つけたのでメモ。
 
関数の知られざる引数(print_r関数、session_regenerate_id関数)[より

同じように、PHP 5.1からはsession_regenerate_id関数にも第1引数が指定されました。第1引数をtrueに指定すると、古くなったセッションは削除されるようになります。
 
もともとセッション固定攻撃を防ぐために用意された関数ではなく、PHP 5.1 までの同関数には古いセッションファイルを削除する機能が無かったため、セッション固定攻撃への対策としては不十分でした。
 
今後は、session_regenerate_id関数の引数に必ずtrueを指定することを忘れないようにしましょう。また、それまでのPHPで使う場合は、以下のコードを使うことで、セッション固定攻撃を防ぐことができます。

のように、session_regenerate_id() の第一引数に true を常に指定すべきと書かれていますが、session_regenerate_id(true) はむやみに使ってはなりません。
 
ショッピングカートなど限定的な用途でセッションを使っている場合は問題ないのですが、常にログインが必要なサイトなどで非同期で複数のリクエストを実行する可能性がある場合、古いセッションが削除されると問題になりことがあります。
 
たとえば同じ HTML 内に認証が必要な画像などの埋め込みコンテンツが複数あったり AJAX で認証が必要なデータにアクセスする場合、一つのセッションIDで複数のリクエストを行うため、2リクエスト目以降も古いセッションで認証することになるからです。
 
代替案として、session_regenerate_id(false) と session_write_close() を組み合わせて古いセッションのみ有効期間を設定してやるとよい、とsession_regenrate_idのコメント欄に書かれていました。
 
実装例:

// ユーザがリクエストしたセッションIDからセッション情報をロードする。
session_start();
// —————————————————–
// 以下セッションフィクセーション対策
if(isset($_SESSION[‘expire’]) && $_SESSION[‘expire’] < time()){
    // 過去に session_regenerate_id() で置き換えられた古いセッションによるアクセス。
    // 有効期限を過ぎていればセッション情報をクリアする。
    $_SESSION = array();
}
 
// 古いセッションは2分間で消えるように設定。
$_SESSION[‘expire’] = time() + (2*60);
// 有効期限を記録するため、一旦明示的にセッションを閉じ、$_SESSION の中身を古いセッションIDで保存する。
session_write_close();
 
// 閉じたセッションを開きなおす。
session_start();
// セッションIDを更新し、$_SESSION を古いセッションIDから切り離す。
session_regenerate_id();
// 新しいセッションID は有効期限なし。
unset($_SESSION[‘expire’]);
// ——————————————-
// セッションフィクセーション対策ここまで。
// あとは通常通り。
$_SESSION[‘user_id’] = “1234”;

 
また、session_regenerate_id() だけではセッション所有者のリクエストによる XSRF は防ぐことはできないため、こちら(開発者のための正しいCSRF対策)を参考にワンタイムトークン等も適宜組み合わせましょう。

PHPで任意のファイルデスクリプタを開く

PHP には fdopen がないので、子プロセスについては /dev/fd/<FD番号> で代用してます。
PHP の機能ではありませんが。。

<?php
// child.php: 子プロセス(parent.php から実行される)
$fd = 4; // 親プロセスとのやり取りに使うファイルデスクリプタ(0:stdin, 1:stdout, 2:stderr)
$fdfile = “/dev/fd/$fd”;
if(!file_exists($fdfile)){
   die(“ファイルデスクリプタが開かれていません”);
}
 
$pipe = fopen($fdfile, “r”);
while(!feof($pipe)){
  echo fread($pipe, 1024);
}
fclose($pipe);

 

<?php
// parent.php: 親プロセス
$fd = 4; // 子プロセスとの通信に使うファイルデスクリプタ
$fp = proc_open(“php child.php”, array(
  $fd=>array(‘pipe’, r),
),$pipes);
 
fwrite($pipes[$fd], “Hello world!!”);
fclose($pipes[$fd]);
 
proc_close($fp);

 
FreeBSD の場合、標準では /dev/fd に 0,1,2 しかないため動作しません。
次のようにしてfdescfs を /dev/fd にマウントすればプロセスごとのファイルデスクリプタを自動作成してくれるようになります。

# echo “fdescfs /dev/fd fdescfs rw 0 0” >> /etc/fstab
# mount /dev/fd

または /dev/fd を使わない実装に置き換える事でも動作します。
この場合、ファイルデスクリプタが開いているかの確認には fstat [-p PID] を使うといいかもしれません。

// child.php: FreeBSD で devfs を使っている場合の代替実装。
$fd = 4;
$pipe = popen(‘cat < &'.$fd, 'r');
echo fread($pipe, 1024)
pclose();

PHPのproc_open の落とし穴

http://d.hatena.ne.jp/ichii386/20071116/1195153132
 
proc_open()の説明に書いてある例通りやると問題があるので [[stream_select()|]http://jp.php.net/manual/ja/function.stream-select.php] をあわせて使いましょう、という話。
一つのストリームを読み書きしてる間に他のストリームからの入力がたまるとバッファがいっぱいになってしまい、そこで書き出し側の処理がブロックしてしまう可能性がある。
stream_select を使うと、複数のストリームの中から入出力要求がきているストリームのみを選択して読み書きすることが出来ると。
 

// http://d.hatena.ne.jp/ichii386/20071116/1195153132 から引用:
$stdout = $stderr = ”;
while (feof($pipes[1])= false || feof($pipes[2]) = false) {
    $ret = stream_select(
        $read = array($pipes[1], $pipes[2]),
        $write = null,
        $except = null,
        $timeout = 1
    );
    if ($ret= false) {
        echo “error\n”;
        break;
    } else if ($ret
= 0) {
        echo “timeout\n”;
        continue;
    } else {
        foreach ($read as $sock) {
            if ($sock= $pipes[1]) {
                $stdout .= fread($sock, 4096);
            } else if ($sock
= $pipes[2]) {
                $stderr .= fread($sock, 4096);
            }
        }
    }
}

Windowsで「ファイル名を指定して実行」をランチャー化するカスタマイズ方法と起動コマンド一覧

http://it.kndb.jp/entry/show/id/146
 
4年くらい前から、この記事と同じようにファイル名を指定して実行(Windows+R)をランチャーとして使っています。
いちいちランチャーをインストールするより Windows の標準機能を使おうということで始めたもののこれが存外に便利。
「ファイル名を指定して実行」に慣れると Windows標準のコマンドも覚えられるし、引数対応のプログラムもフル活用できて一石二鳥、です。
 
既存のコマンドとかぶらないよう、自分ルールで頭に記号をつけたものをショートカットで作って使っています。
 
・ “+” から始まるものはディレクトリ(+bin でランチャー用ディレクトリ, +home でマイドキュメントなど)
・”@” から始まるものはプログラム短縮名(@f で firefox, @i で iexplorer(Internet Explorer), @e で Eclipse, @p で PuTTY, @n でテキストエディタ, @fz で FileZilla, @ooo で OpenOffice.org などなど)
 
とくにキーボード派にオススメです。おためしあれ。

FOMA Flashlite3.x をコピー禁止にする

DoCoMo 携帯では Flashlite 3.x からプロファイルでコピー禁止(転送禁止)を明示しないとファイル転送可能になりました。
 
SWFファイルの再配布を防止するには(携帯サイトを作ろう。)に詳しくまとめられています。
CS4 の場合は以下の手順で設定できるようです。

 (引用)
プロパティ→プロファイル→「編集」をクリック
FlashタブのSWF設定で「XMPメタデータを含める」にチェックが入っていることを確認し、「ファイル情報」をクリック
モバイルSWFタブの「フォーワードロック」にチェックを入れて「OK」をクリック

 
この記事では CS3 について詳しく書かれていませんが、CS3 の場合は標準ではXMPプロファイル設定ができないため、Adobe サイトから CDK をインストールする必要があります。
 
■ Flash CS3 Professional への Flashlite 3.0 CDK インストール手順
1. Adobe ダウンロードページから「Flash CS3 Professional 用 Flash Lite 3.0 アップデート」をダウンロードして fl_flashlite3_update.exe を実行し、プログラムに従ってインストールする。
 
2. Adobe Flash Lite for i-modeのウェブサイトから「Flash Lite 3.0 対応 NTT DoCoMo 携帯電話用 Adobe Flash CDK をダウンロード」を選択し、CDK(コンテンツ開発キット)をダウンロードする。
 →「Adobe モバイル デベロッパー プログラムに参加」のフォームが開きます。名前とメールアドレスが必須入力になっていますが、メール認証や会員登録もなく、ニュースレターの配信も任意なのでそれほど手間ではないです。適当にアドレスを入れて「続行」、を選択してください。この次のページでダウンロードできます。
 
3.ダウンロードしたファイル(flash_lite_3_0_image_cdk_jp.zip)を展開する。
この中に含まれるファイルのうち、「metadata_tool_readme_jp.pdf」が拡張機能の説明書、「モバイルメタデータ.swf」が拡張パネル本体です。
 
4.説明書の手順に従い「モバイルメタデータ.swf」を指定フォルダにインストールする。
swf を指定フォルダにコピーすることで、Flash CS3 Professional から拡張パネルとして利用できるようになります。
コピー先は OS によって異なり、それぞれ次のフォルダがコピー先になります。

■ Windows Vista PC:
…/Users/< ユーザ名>/AppData/Local/Adobe/Flash CS3/ja/Configuration/
WindowsSWF
■ Windows XP PC:
…/Documents and Settings/< ユーザ名>/Local Settings/Application Data/
Adobe/Flash CS3/ja/Configuration/WindowsSWF
■ Apple Mac:
…/Users/< ユーザ名>/Library/Application Support/Adobe/Flash CS3/ja/
Configuration/WindowsSWF

 
5.Flash CS3 Professional を開く。
既に開いている場合はインストールしたパネルを反映させるため、一度 Flash CS3 Professional を再起動してください。
 
6.Flash CS3 Professional で、コピー禁止させたい Flashlite 3.0 プロジェクトを開く。
インストールに成功していたら「ウィンドウ」メニューの「他のパネル」の項目に「モバイルメタデータ」が追加されています。
 
7.「ウィンドウ」メニュー→「他のパネル」→「モバイルメタデータ」を開く
「フォーワード・ロック」をチェック
 
8.右下の適用ボタン(レ点)を押して適用
 
9.Flashlite3.x としてパブリッシュ
 
以上です。

Flash SWFファイル仕様 – ActionScript の仕様詳細(SWF3,SWF4)

Flashlite 1.x で採用している ActionScript 1.0 (SWF3,SWF4) の SWF 仕様についてメモ。
シンプルなつくりですが、スタックなど後継の ActionScript2, AS3 の実装の根幹になる部分なので最新のバージョンの AS を理解する上でも参考になると思います。
 
これさえ読めばバイナリエディタや swfmill で ActionScript を1から記述できる、かもしれません。
 

SWF 仕様書ではチャンクの事をさして「タグ」と書いてあるのですが、XMLタグとの混同を避けるため、ここではチャンクと記述することにしました。
 
なお、swfmill で利用する際にタグ名とチャンク名で名前が変わっている場合があるため、swfmill で名前が変わるチャンクについては、End (swfmill:<EndAction>)のように、カッコ内にswfmillでのタグ名を表記しています。
 
 
■ アクション(ActionScript)はすべて DoAction チャンクの Actions フィールド(swfmill:<Actions>)に定義する。
SWF3, SWF4 では他の場所にアクションは書けません。
逆に DoAction の中にはアクションしか書けません。
分離されていて分かりやすいですね。
 
■ Actions フィールド(swfmill:<Actions>)は1バイトのヌル文字で終わる。
Actions フィールドはアクションの連続で構成され、0 個以上の任意の数のアクションを記述できます。
End フラグ(swfmill: <EndAction>)をあらわす1 バイトのヌル文字で終わります。
例:

DoAction チャンク(tag-type:12)
  Actions フィールド(0個以上のアクションを指定)
  {Action1}
  {Action2}
  {Action3}
  …
  End フラグフィールド(ヌル文字)

swfmill 例:

<DoAction>
 <Actions>
   <!– Action1 –>
   <!– Action2 –>
   <!– Action3 –>
   <!– : –>
   <EndAction />
 </Actions>
</DoAction>

 
■ アクションが実行されるのはフレームが表示される時。
どこで DoAction を定義したとしても、カレントムービークリップの現在のフレームが表示されるタイミングで実行されます。
つまり、DoAction で定義した時に処理されるわけではなく、その後最初に ShowFrame タグが現れた時にたまっていたアクションが一気に実行されます。
これはアクションスクリプト内でムービークリップ等を参照する場合、ShowFrame までに配置されていればよく、DoAction タグが現れた時点では何も存在してなくても問題ない、という事を意味します。
 
■ アクションは全てスタック方式で記述する。
SWF4 以降、アクション中の関数、式、およびそれらで使う式の左辺、式の右辺、関数の引数、メソッドの実行インスタンスなど全ての要素は LIFO(Last In First Out) のスタック方式で記述します。
例: 「 a=123; b = a + 15; 」 という2個の式を SWF4 のアクションチャンクで記述する。

DoAction
  ActionPush(Type:0) a // “a” をスタックに積む…stack1
  ActionPush(Type:0) 123 // “123” をスタックに積む…stack2
  ActionSetVariable // stack1,stack2 を取り出して stack1 = stack2 として評価( a = “123”;)
  ActionPush(Type:0) b // “b” をスタックに積む…stack1
  ActionPush(Type:0) a // “a” をスタックに積む…stack2
  ActionGetVariable // stack2 を取り出して変数 a の値を参照してスタックに積みなおす(a -> “123”) …stack2
  ActionPush(Type:0) 15 // “15” をスタックに積む…stack3
  ActionAdd // 直近の2スタック(stack2,stack3)を合算し、結果をスタックに積む(123 + 15 -> 138) … stack2
  ActionSetVariable // stack1, stack2 を取り出して stack1 = stack2 を評価(b = 138)
  End // アクション記述終了

swfmill の例:

<DoAction>
  <actions>
    <PushData>
      <items>
        <StackString value=”a”/>
      </items>
    </PushData>
    <PushData>
      <items>
        <StackString value=”123″/>
      </items>
    </PushData>
    <SetVariable/>
    <PushData>
      <items>
        <StackString value=”a”/>
      </items>
    </PushData>
    <PushData>
      <items>
        <StackString value=”b”/>
      </items>
    </PushData>
    <GetVariable/>
    <PushData>
      <items>
        <StackString value=”10″/>
      </items>
    </PushData>
    <AddCast/>
    <SetVariable/>
    <EndAction/>
  </actions>
</DoAction>

 
■SWF チャンク書式
SWF のチャンクはヘッダ部と本体から構成されます。
ヘッダ部は全てのチャンクで共通で、
・種類(Tag type)
・ヘッダを除くチャンクの長さ
の2要素からなります。
 
ヘッダを除いたチャンクの長さが63バイト以内の場合、以下の短縮書式で記述し、ヘッダのサイズは2バイトになります。
・種類(Tag type): 10ビット
・ヘッダを除くチャンクの長さ: 6ビット
 
ヘッダを除いたチャンクの長さが 64 バイトを越える場合、以下の書式で記述し、ヘッダのサイズは6バイトになります。
・種類(Tag type): 2バイト(UI16)
・ヘッダを除くチャンクの長さ: 4バイト(UI32)
 
■アクション書式
DoAction の Actions フィールド内に記述するアクションもチャンクの書式にならっていて、ヘッダ部とその他の部分に分かれています。
ヘッダ部の構成要素もチャンク同様
・種類(ActionCode/アクションコード): 1バイト(UI8)
・ヘッダを除くアクションの長さ: 2バイト(UI16)
の2要素からなります。ヘッダ部のサイズは 3バイトです。
 
ただしアクションコードが 0x80 未満のアクションはヘッダしか持たないため、長さを記述しません。
このときはヘッダのサイズは1バイトになります。
 


アクション一覧
 
■SWF3
SWF3 ではフレームの移動などムービークリップの基本操作が実装されました。
※SWF3 はスタック方式ではないため、引数が必要なアクションについてはフィールド部に記述します。
 
○ ActionNextFrame
次のフレームを再生後停止する。
ActionScript: nextFrame()
ActionCode: 0x04
 
○ ActionPreviousFrame
前のフレームを再生後停止する。
ActionScript: previousFrame()
ActionCode: 0x05
 
○ ActionPlay
現在の(次の)フレームから再生する。
ActionScript: play()
ActionCode: 0x06
 
○ ActionStop
現在のフレームの処理完了後停止する。
ActionScript: stop()
ActionCode: 0x07
  
○ ActionToggleQuality
表示品質を高⇔低に相互に切り替える。
ActionCode: 0x08
 
○ ActionStopSounds
再生している音をすべて停止する。
ActionScript: stopSounds()
ActionCode: 0x09
 
○ ActionGotoFrame
指定したフレームに移動する。
gotoAndPlay(), gotoAndStop() に数値を指定した場合に呼ばれる。
gotoAndPlay() と同じ動作を望む場合は ActionGotoFrame の後に ActionPlay を実行すればよい。
ActionScript: gotoAndPlay()
ActionCode: 0x81
Length: 2 固定
フィールド: frame=移動先フレーム番号(UI16)
 
○ ActionGotoLabel
指定したフレームに移動する。
gotoAndPlay() に文字列を指定した場合に呼ばれる。
ActionScript: gotoAndPlay()
ActionCode: 0x8C
フィールド: label=移動先フレーム名(文字列)
 
○ ActionWaitForFrame
ActionCode: 0x8A
Length: 3 固定
フィールド: フレーム番号(UI16), スキップするアクションの数(UI8)
 
○ ActionGetURL
指定したターゲットの内容を URL 先のデータに置き換える(HTML, SWF など)。
ActionScript: getURL()
ActionCode: 0x83
フィールド: URL(文字列), ターゲット(文字列)
 
○ ActionSetTarget
以降のすべてのアクションを指定したインスタンスで実行するよう変更する(例 SetTarget “../foo”)。
SetTarget “” のように空文字を指定すると現在のムービークリップに戻します。
ActionScript: tellTarget(){ … }
ActionCode: 0x8B
フィールド: ターゲット名(文字列)
 


■SWF4で追加されたタグ
SWF4 からスタック構造になり、条件分岐や演算子など基本的なプログラミング言語の機能が実装されました。
ただ型についてはまだまだ未実装な部分が多く、boolean は数値、数値は文字列として処理し、スタックに入れられます。文字列連結演算子が + ではなく add なのはこのためです。
 
□算術演算子
○ ActionAdd (swfmill:<AddCast>)
ActionScript: + 演算子
※SWF5 以降は ActionAdd2 (swfmill:<AddTyped>) に置き換え
 
○ ActionDivide (swfmill:<Divide>)
ActionScript: / 演算子
 
○ ActionMultiply (swfmill:<Multiply>)
ActionScript: * 演算子
 
○ ActionSubtract (swfmill:<Subtract>)
ActionScript: – 演算子
 
□関係演算子(数値比較)
○ ActionEquals
ActionScript: == 演算子
 
○ ActionLess
ActionScript: < 演算子
 
□論理演算子
○ ActionAnd
ActionScript: && 演算子
 
○ ActionNot
ActionScript: ! 演算子
 
○ ActionOr
ActionScript: || 演算子
 
□文字列操作
○ ActionStringAdd
※SWF5 以降は ActionAdd2 に置き換え
ActionScript: add 演算子
 
○ ActionStringEquals

○ ActionStringExtract
○ ActionStringLength
○ ActionMBStringExtract
○ ActionMBStringLength
○ ActionStringLess
 
□スタック操作
○ ActionPop
○ ActionPush
 
□型変換
○ ActionAsciiToChar
○ ActionCharToAscii
○ ActionToInteger
○ ActionMBAsciiToChar
○ ActionMBCharToAscii
 
□制御構造
○ ActionCall
 
○ ActionIf (swfmill: <BranchIfTrue>)
if 文の実装。条件に一致していたら指定バイト数アクション処理を飛ばす。
ActionScript: if( … ){ }
ActionCode: 0x9D
フィールド: BranchOffset=移動バイト数(-32768 から 32767 までの間の数値。ActionIf の次のアクションを0とする)
例: if( n < 5 ){ 処理1; }else{ 処理2 }; 処理3; をアセンブラで記述。

DoAction
  ActionPush “n”
  ActionGetVariable // 変数 n を展開
  ActionPush “5”
  ActionLess // n < 5 を判定し、結果をスタックに入れる
  ActionNot // スタックにいれた真偽値を「反転」
  ActionIf 123 // スタックに入れた値が真なら処理を ActionJump の次(123バイト先)まで飛ばす
  // (処理1 のアセンブラ) if(){ … } 内
  ActionJump 23 // 処理1の最後に到達する。ここにきたら処理2(23バイト分)を飛ばす。
  // (処理2 のアセンブラ) // else{ … } 内
  // (処理3 のアセンブラ) // 条件文の外の共通処理。
  End フラグ

例: swfmill での記述例

<DoAction>
 <actions>
  <PushData><items><StackString value=”n” /></items></PushData>
  <GetVariable/>
  <PushData><items><StackString value=”5″ /></items></PushData>
  <LessThanCast/>
  <LogicalNOT/>
  <BranchIfTrue byteOffset=”123″ />
  <!– 処理1 –>
  <BranchAlways byteOffset=”23″ />
  <!– 処理2 –>
  <!– 処理3 –>
  <EndAction/>
 </actions>
</DoAction>

 
○ ActionJump (swfmill:<BranchAlways>)
if 文のelse 部の実装。このアクションに到達した場合、無条件で指定バイト数アクション処理を飛ばす。
ActionScript: if .. else{ }
ActionCode: 0x99
フィールド: BranchOffset=移動バイト数(-32768 から 32767 までの間の数値。ActionJump の次のアクションを0とする)
 
 
□変数
○ ActionGetVariable
○ ActionSetVariable

Flash をxmlから作れる便利な swfmill でさらに Flash Lite 1 の swf を扱えるようにしてみた

Klab さんのパッチで swfmill simple を扱った時に文字コードエラーが出る件で、解決パッチを作ってみました。
 
参考…2009-06-05 / swfmill – メモ。cp932まわり
 
このエラーは swfmill simple で <clip import=”file.swf” /> として flash をインポートする時、 file.swf が flashlite 1.x であり、その swf 内に日本語を含む場合にのみ発生します。
 
swf のインポートを処理する swft_document() で swf->xml に変換する処理でテキストエンコーディングが効いていないのが原因でした。
アドホックではありますが -e で与えた文字コードをインポートするパッチを当てたところ、無事エラーなく動作するようになりました。
 
swfmill simple テキストエンコーディング対応パッチ
 
Klab さんのパッチとあわせて適用してください(パッチ順序は問いません)。

フリーのFlashコンパイラ swfmill のメモ。simple について

– XML の encoding に指定する文字コード(<?xml encoding=”…”?>)は日本語を使っていても UTF-8 でよく、XMLファイルの文字コードとあっていればよい(パッチ不要)。
– flash lite 1.1 で作る時は <movie version=”4″ compressed=”false”> という指定必須。swfmill は <movie> だけだとデフォルトで圧縮され、Flash 6 以降用にコンパイルされるため。
 
– <DoAction> を入れる時は、ActionScriptを入れたいフレームの<frame>〜</frame>の中に入れるとよい

swf file format spec v10 – SWF3 actions より引用:
DoAction
DoAction instructs Flash Player to perform a list of actions when the current frame is
complete. The actions are performed when the ShowFrame tag is encountered, regardless of
where in the frame the DoAction tag appears.
 
DoAction は現在のフレームが完了した時、Flash プレイヤーがどのアクションを実行すべきかを一覧で指示します。
DoAction がフレーム内のどこで定義されたとしても、ShowFrame タグが現れた時点でアクションが実行されます。

ちなみに swmill simple の <frame><!–フレーム内容–></frame> は XSLT での変換時に <!– フレーム内容 –><ShowFrame/> に置換されます。
 
– XMP 設定は<meta>タグに書く
メタデータの設定は次のように書きます。

<movie>
  <meta>
    <rdf:RDF xmlns:rdf=”http://www.w3.org/1999/02/22-rdf-syntax-ns#”>
      <!– 〜中略〜 –>
    </rdf:RDF>
  </meta>
</movie>

フリーのFlashコンパイラ swfmill のメモ。文字コードcp932まわり

パッチあてても外部 swf を読み込む時は -e cp932 指定が効かない様子。
 
Klab さんの cp932 パッチを使っているのですが
日本語を使っている Flash を flashlite 1.1 用にパブリッシュして、<clip> で組み込もうとすると, iconv エラーになってしまいました。
 
検証コード:

<?xml version=”1.0″ encoding=”cp932″?>
<movie compress=”false” version=”4″>
  <clip import=”cp932_problem_inc.swf” />
</movie>

実行コマンド:

swfmill -e cp932 simple cp932_problem.xml > out.swf

実行結果:

# Cygwin の場合
error : string is not in UTF-8
error : string is not in UTF-8
error : string is not in UTF-8
error : string is not in UTF-8
iconv failed: _等幅
iconv failed: はろーわーるど
 
# Linux の場合
error : xmlEncodeEntitiesReentrant : input not UTF-8
iconv failed: _ツ等幅
iconv failed: はろーわーるど

 
この結果として swf は出力されるものの文字化けしてしまいます。
 
ちなみに、clip に指定したのと同じ swf を “swfmill -e cp932 swf2xml” で実行してやった場合はもちろん正しく変換できます。
 
検証に使った swf/fla ダウンロード
 
参考:
swfmillでFlash Lite 1のswfを扱えるようにしてみた(Klab 株式会社)

フリーのFlashコンパイラswfmillのメモ。simple で扱う XML の書式とタグ一覧

swfmill の SWFML simple モードの基本的な使い方はここに書いているのですが、実際はもっと便利なタグがたくさんあります。

swfmill simple コマンドは swfmill xml2swf と同様、XMLからSWFを生成するコマンドですが、xml2swfより使いやすくなっています。


タグ一覧
■基本タグ
・<movie> (ルート要素)
SWFML simple の XML ルート要素です。
属性で swf のパブリッシュ用設定ができます。
 
全ての属性、および<frame>をのぞく子要素が省略可能です。
 
FlashLite 1.1 対応にする場合はFlashバージョン4(version=”4″),圧縮なし(compressed=”false”)にしなければなりません。
 
例: ステージサイズ240×320, フレームレート20fps, Flashバージョン4, 圧縮なしに設定

<?xml version=”1.0″ encoding=”UTF-8″?>
<movie width=”240″ height=”320″ framerate=”20″ version=”4″ compressed=”false”>
  <frame />
</movie>

 
・<meta> (親: <movie>)
swf のメタデータXMLを設定する。
 
例:携帯(DoCoMo)でメール転送禁止(フォワードロック)に設定する

<movie>
 <meta>
  <rdf:RDF xmlns:rdf=”http://www.w3.org/1999/02/22-rdf-syntax-ns#”>
   <rdf:Description rdf:about=”” xmlns:swf=”http://ns.adobe.com/swf/1.0/”>
     <swf:forwardlock>True</swf:forwardlock>
   </rdf:Description>
  </rdf:RDF>
 </meta>
</movie>

 
・<background> (親: <movie>)
背景色を設定する。
 
例: 背景色を黒にする

<movie>
  <background color=”#000000″>
  <frame />
</movile>

 
・<frame> (親: <movie>, <clip>)
ムービークリップのキーフレームをあらわす要素で、この中にインスタンスを配置する。
ムービークリップをあらわす<movie>と<clip>の子要素として記述し、これらを定義する時は最低でも1個必須です。
<frame>がなくても動作しますが、誤動作の原因になるため省略すべきではありません。
 
属性:
name … フレーム名(省略可)
 
例:2つのキーフレームからなるムービークリップを定義する。

<movie>
 <frame>
    <!– 1フレーム目 –>
  </frame>
 <frame>
    <!– 2フレーム目 –>
  </frame>
</movie>

 
・<stop> (親: <frame>)
そのフレームを描画後、次のフレームに移らないようストップする。

<movie>
  <clip id=”img1″ import=”1.png”>
  <clip id=”img2″ import=”2.png”>
 
  <frame>
    <!– img1 を表示し、このフレームで停止する –>
    <place id=”img1″ depth=”1″/>
    <stop />
  </frame>
  <frame />
  <frame />
 
  <frame>
    <!– img2 を表示 –>
    <place id=”img2″ depth=”1″/>
  </frame>
</movie>

 
・<call>
指定したクラスメソッドをエントリポイントにする(要SMC + α)。
手順については「Adding components]」を参照。
  
属性:
object … 実行クラス
method … 実行メソッド


■リソース定義
フォント、シンボルなどの定義。
 
・<library> (親: <movie>, <frame>, <clip>)
<library>内に定義した<clip>, <sound>, <font>などリソース定義をライブラリとしてエクスポートし、
外部からそのリソースを参照できるようにする。
 
例: シンボル foo, boo をライブラリに登録する。

<movie>
  <library>
    <clip id=”foo” import=”abc.jpg”/>
    <clip id=”boo” import=”def.jpg”/>
  </library>
</movie>

 
・<clip> (親: <movie>, <library>, <frame>)
画像(PNG, JPEG)やムービークリップ(SWF), SVG などリソースを組み込み、参照できるように定義する。
<clip import=””> で指定したファイルはコンパイル時に読み込まれて一緒にビルドされます。
 
属性:
 id … シンボル名(省略時は名前なし)
 import … 組み込むリソースのファイル名(省略可)
 class … ムービークリップとしてシンボル化するクラス名(省略可。子要素とimport を両方省略時は必須?)
例: 画像ファイル foo.jpg を読み込んでシンボル名 image1 として参照できるようにする。

<movie>
  <clip id=”image1″ import=”foo.jpg” />
</movie>

例2: 新規ムービークリップをシンボル myMovie として定義する。

<movie>
  <clip id=”myMovie”>
    <frame />
  </clip>
</movie>

 
・<font> (親: <library>)
TrueType フォントを組み込み、ActionScript からの参照用に定義する。
 
・<sound> (親: <library>)
mp3 などサウンドファイルを読み込み、ActionScript からの参照用に定義する。
例:

<library>
  <sound id=”sound1″ import=”music.mp3″/>
</library>

 
・<textfield> (親: <movie>, <library>, <frame>)
テキストを入れるラベルを定義する。
 
属性:
id … シンボル名
name … 同期する変数名
text … 表示するテキスト
x … X座標
y … Y座標
width …
height …
size …
leading …
wordWrap …
isHTML …
multiLine …
password …
readOnly …
autoSize …
notSelectable …
hasBorder …
useOutlines …
align …
leftMargin …
rightMargin …
indent” …


■インスタンスの配置
ムービークリップ内へのシンボル配置など。
 
・<place> (親: <frame>)
定義済みシンボルを配置する。
属性:
 id … インスタンス化するシンボルの名前(必須)。
 name … ActionScript での参照用インスタンス名(省略時は名前なし)
 x, y ・・・ 座標(ピクセル。省略時は (0, 0))
 depth … 深度(数値で表し、大きいほど手前)
 scale … 表示倍率(省略時は 1.0)
 
例: シンボル image1 をインスタンス化し、座標 (0,50) に等倍配置し、その上に座標 (25,30) にサイズ1/2で配置する。

<clip id=”image1″ import=”foo.jpg” />
<frame>
  <place id=”image1″ x=”0″ y=”50″ depth=”1″/>
  <place id=”image1″ x=”25″ y=”30″ scale=”0.5″ depth=”2″ />
</frame>

 
・<import>(親: <frame>)
任意の URL のムービーを動的に読み込み配置する。
ActionScript の loadMovie(url) と同様の動作。
例:

<frame>
  <import url=”http://example.com/foo.swf”></import>
</frame>


■その他
・swfmill だけで ActionScript を埋め込む
<movie> や <clip> 内の <frame>〜</frame> に <DoAction> 要素を入れると、
そのフレーム上のアクションスクリプトとして実行できます。
 
<DoAction>は SWF のアセンブラでの書き方になるため、別環境で作った swf ファイルを swf2xml で変換して <DoAction>以下を抽出するのが楽な方法です。
 
例: Flash lite 1.1 用 ActionScript を埋め込む。

<?xml version=”1.0″ encoding=”UTF-8″?>
<movie version=”4″ compressed=”false”>
  <frame>
   <!– ムービークリップインスタンス mc1 を配置(参照用) –>
   <clip id=”mc” import=”myMC.swf” />
   <place id=”mc” name=”mc1″ depth=”0″ />
   <!– 簡単な ActionScript を _root で実行 –>
   <DoAction>
    <actions>
      <!– _root.foo = 123; を実行。 –>
      <PushData>
        <items>
          <StackString value=”/:foo”/>
        </items>
      </PushData>
      <PushData>
        <items>
          <StackString value=”123″/>
        </items>
      </PushData>
      <SetVariable/>
   
      <!– mc1.msg = “Hello”; を実行 –>
      <PushData>
        <items>
          <StackString value=”mc1:msg”/>
        </items>
      </PushData>
      <PushData>
        <items>
          <StackString value=”Hello”/>
        </items>
      </PushData>
      <SetVariable/>
      <EndAction/>
    </actions>
   </DoAction>
   <!– ActionScript ここまで –>
  </frame>
</movie>


参考:
Using swfmill to create SWFs without Flash(公式)
swfmill Open Source Flash WiKi
SWFMLl DTD
swfmil の XML 書式定義