ExtJS GridPanel の cellclick イベントを使う

マニュアルどおりでうまくいかなかったのでメモ。
ExtJS 3.1 で動作確認。

var grid = new Ext.grid.GridPanel({
  // 中略
  listeners: {
      cellclick: function( grid, rowIndex, columnIndex, e) {
        var record = grid.getStore().getAt(rowIndex); // rowIndex番目のレコード取得
        var fieldName = grid.getColumnModel().getColumnId(columnIndex); // columnIndex番目のフィールド名取得
        var data = record.get(fieldName); // 指定座標のセルの内容を取得。
        alert(data); // 表示。
      }
  }
});

参考:
ExtJS GridPanel

HTTP – Locationヘッダには相対URLを使ってはいけない

HTTP の仕様(RFC2616)では、 Location ヘッダは絶対URIでなければならないと今更知りました。
Hypertext Transfer Protocol — HTTP/1.1(日本語) 14.30:

Location = “Location” “:” absoluteURI

ちなみに絶対URI(absolute URI)とはRFC2396によるとスキームから始まるURIのみを指します。
スラッシュ(“/”)から始まる URL が絶対URLと言われることがありますが、正確には絶対パス(absolute path)指定の相対URLであり、絶対URLではありません。

absoluteURI = scheme “:” ( hier_part | opaque_part )
hier_part = ( net_path | abs_path ) [ “?” query ]
relativeURI = ( net_path | abs_path | rel_path ) [ “?” query ]
net_path = “//” authority [ abs_path ]
abs_path = “/” path_segments

 
ただ、ほとんどのブラウザで相対URLへのロケーションを寛容に解釈してくれます。
lynx では警告が出るようですが、一般向けには携帯でさえ(mova など余程古いものを除けば)意図通りにリダイレクトしてくれるようになり、仕様違いでも問題がほぼなくなってしまいました。
 
相対URLが便利なのも事実。なのでもしかしたら HTTP 2.0 ができるときには相対URI可、なんてことになるかもしれませんね。

SWFObject – IE で Flash から fscommand が実行できない対策

IE で Flash ムービー(foo.swfなど)を innerHTMLなどで動的に埋め込むと, VBスクリプトでイベントを取れなくなるのが原因のようです。
 
対策は、SWFObject FAQに書かれているように

5.なぜ動的なパブリッシュを行うとインターネットエクスプローラーで fscommand が動かなくなるのか。
Adobe は fscommand をインターネットエクスプローラーで動作させるため、
FSCommand 呼び出しを受け取り JavaScript に転送するための VBScript を追加するように推奨しています。
ですが SWFObject の動的なパブリッシュメソッドで行っているように、
innerHTMLや outerHTML などを使って Flashムービーを挿入する場合には VBScript は全く動作しません。
 
運がいいことに、VBScript の代わりに JavaScript を使っても fscommand の呼び出しを受け取る方法があります。
このちょっと下にあるコードではプロプライエタリ(訳注:専用の?)属性(を、あなたのコードをおかしくさせないために、さらに条件分岐コメントで括ったもの)を使っています。
 
例として、下のVBScriptは、

<SCRIPT LANGUAGE=VBScript>
on error resume next
Sub myCom_FSCommand(ByVal command, ByVal args)
  call myCom_DoFSCommand(command, args)
end sub
</SCRIPT>

次のように置き換えることが可能です。

<!–[if IE]>
<script type=”text/javascript” event=”FSCommand(command,args)” for=”myCom”>
  myCom_DoFSCommand(command, args);
</script>
<![endif]–>

 
注意:Flash 8 以上でパブリッシュしている場合、JavaScript – ActionScript間の通信には fscommand() を利用するよりも ExternalInterface が推奨されています。
 
コードの例は SWFObject のテストスイートでも見つけることができます。

参考:
FlashとJavaScriptの連携
SWFObject v2.0 ドキュメント日本語訳
Why doesn’t fscommand work in Internet Explorer with dynamic publishing ?(SWFObject FAQ)
ExternalInterface(ActionScript 3.0 コンポーネントリファレンスガイド)

PHPでDBレコードをソートする

レコード…連想配列の配列…は、MDB::fetchAll() や DB::getAll() の結果の書式で見られるように一般的なデータ構造書式です。
たまにはコードを上げてみよう、ということで汎用関数としてレコードソート関数を作ってみました。実装コードおよびサンプルは下のほうにあります。
特に著作権等は主張しませんのでご自由にお使いください。
 
書式:

int sort_records(&$records, $key, $descent = false);


実装コード:

/**
 * DBなどのレコードを任意のキーでソートする。
 * PHP 4.4.9, PHP 5.2.8 で動作確認。
 *
 * @author ecoop.net
 * @access public
 * @param array &$records DBなどレコードの配列
 * @param string $key ソートの基準にするカラムの名前。省略時は第一カラムでソート。
 * @param boolean $descent true なら降順で結果を返す。省略時は false
 * @return bool 成功なら true を返す
 */
function sort_records(&$records, $key = null, $descent = false){
  if(!$records || !is_array($records)){ return false; }
   
  // $key が省略された場合は第一レコードの第一カラムを名前を取得
  if(is_null($key)){
    $t = array_values($records);
    $t = array_keys($t[0]);
    if(!$t){ return false; }
    $key = $t[0];
  }
  // —-
  $map = array();
  foreach($records as $i => $v){
    if(!is_array($v) || !isset($v[$key])){ return false; }
    $map[$v[$key] .’_’. $i] = $v;
  }
  
  if($descent){
    $res = krsort($map);
  }else{
    $res = ksort($map);
  }
  $records = array_values($map);
  return $res;
}

利用例:

// 元データ
$records = array(
array(‘age’ => 24, ‘name’=>’john’),
        array(‘age’ => 33, ‘name’=>’george’),
        array(‘age’ => 56, ‘name’=>’bill’),
        array(‘age’ => 50, ‘name’=>’steven’),
);
// name カラムでソート
sort_records($records, ‘name’);
print_r($records);

結果:

Array
(
    [0] => Array
        (
            [age] => 56
            [name] => bill
        )
    [1] => Array
        (
            [age] => 33
            [name] => george
        )
    [2] => Array
        (
            [age] => 24
            [name] => john
        )
    [3] => Array
        (
            [age] => 50
            [name] => steven
        )
)

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);
            }
        }
    }
}

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>