2

アプリケーション用のメイン SWF を持ち、個別の SWFS から個別のツールをロードするシステムを作成しています。個別の SWFS は cms から取得されるため、将来的にはバージョン管理の問題が発生するでしょう (特に現在はまだ開発中であるため、将来、他の開発者が互換性のないツールを作成する可能性もあります)。私はそれらを可能な限り防止しようと懸命に努力していますが、互換性のない swf がロードされたときに、システムのユーザーにメッセージを表示できるようにしたいと考えています。

これは、VerifyError をキャッチするか、何らかの理由で読み込みが失敗したと判断する必要があることを意味します。現時点では、それを処理する方法がわかりません。10.1 と uncaughtError システムを使えば可能かもしれませんが、現在は Flash Player 10 をターゲットにしています。(すでに IOErrorEvent.IO_ERROR を処理しています)

更新: インポートする前にバイトコードをスキャンするソリューションを構築しましたが、うまくいくようです。後で解決策を投稿します。

4

5 に答える 5

1

これを行う最良の方法は、bhupsが提案したライブラリの1つを使用することです。次の例では、senocularを使用しました。また、senocularのライブラリは、解析されたSWFの基本的な操作のみを提供するため、ロードされたSWFから必要な情報を取得するには、SWF形式仕様(adobe.com/devnet/swf/pdf/swf_file_format_spec_v10.pdf)が必要になる場合があります。

次の例では、ロードされたSWFのすべてのクラス名を一覧表示します。

package swf
{
 import flash.events.Event;
 import flash.net.URLRequest;
 import flash.net.URLStream;
 import flash.utils.ByteArray;
 import flash.utils.Endian;

 import swf.SWFReader;

 public class GetSWFInfo
 {

  private var swfInfo:SWFReader;

  public function GetSWFInfo()
  {
   var urlRequest:URLRequest = new URLRequest("theswf.swf");
   var loader:URLStream = new URLStream();   
   loader.load(urlRequest);
   loader.addEventListener(Event.COMPLETE, onComplete);
  }


  public function onComplete(e:Event):void {
   var recivedByteArray :ByteArray = new ByteArray();
   URLStream(e.currentTarget).readBytes(recivedByteArray);


   //create a new instance of SWFReader
   swfInfo = new SWFReader();
   //readTag it's a callback function that will be called when a tag is read during the SWF parse process.
   //read more on tags in the SWF specification document
   swfInfo.tagCallback =  readTag;
   //start parsing
   swfInfo.parse(recivedByteArray); 
  }



  public function readTag(tag:uint, bytes:ByteArray):void {


   //76 it's the tag type for SymbolClass tag
   //read more in the SWF specification document
   if (76 == tag) {


    var classesArray:Array = new Array();
    var symbolsNumber:uint = 0;
    var currentId:uint = 0;

    bytes.endian = Endian.LITTLE_ENDIAN;

    //read the symbols Number
    //again read more in the SWF specification document
    symbolsNumber = bytes.readShort();

    bytes.position = 4;

    while (true) {

     var i:uint = bytes.position;

     //every string name ends with a null byte
     //again read more in the SWF specification document
     while(bytes[i] != 0) i++;

     var readAmount:uint = i - bytes.position;

     classesArray.push(bytes.readUTFBytes(readAmount));

     //the last ID is always the base class Id, and it's 0
     currentId=bytes.readUnsignedShort();

     bytes.position++;     

     if (currentId==0) {
      break;
     }
    }

    //this two should be equal
    trace(classesArray.length + 1);//the number of elements in the classesArray
    trace(symbolsNumber);//the number of classes retrived from the SWF

    //list the names
    var name:String;
    for each (name in classesArray) {
     trace(name);
    }

    //now you have an array with all the class names that you can use to compare

   }
  }
 }

}

于 2010-07-23T05:19:06.137 に答える
1

私はあなたがやろうとしていることを誤解しました。

まあ、実際にはベリファイ エラーのハンドラはないと思いますが、それを検出するには、バイト コードと戦わなければなりません。

ところで、あなたの質問に対する答えではないかもしれませんが、役立つかもしれないと思います。

サードパーティの SWF は、自分の SWF にあるはずのクラスに依存しています。そのクラスが見つからない場合、VerifyError が発生します。

この時点から、「不足しているクラス」を SWF にリンクし、サードパーティの SWF を ApplicationDomain.currentDomain または新しい ApplicationDomain(ApplicationDomain.currentDomain) にロードすると、「検証エラー」を回避できるとアドバイスできます。(これは、Flash Player が親 swf で不足しているクラスの定義を見つけるためです。)

これは、検証エラーのあるswfをロードする私のサンプルコードです( http://teionclub.com/test/xml/main.swf )。

VerifyError の回避 - wonderfl build flash online
于 2010-07-26T07:27:03.603 に答える
0

最後に私自身の質問に答えるために、これは私が起こりうるエラーを検出するために使用してきたユーティリティクラスです。SWFをバイト配列としてロードし、実際のMovieClipとしてロードする前にコンテンツをスキャンします。

ご覧のとおり、私のコードはcom.segfaultlabs.swfutilsパッケージに大きく依存しています

重要:エラーを防ぐこの方法の使用をやめ、実際にファイルをロードして機能するかどうかを確認することにより、ファイルをチェックするより手動のアプローチを選択しました。これは、ユーティリティが完全ではなく、ABC形式に関する私の現在の知識が、常に正しいチェックを開発できることを確認するのに十分ではないためです。

私のコードを、それを突き刺したい他の人のための出発点としてここに投稿してください:-)

package nl.ijsfontein.utils
{
    import com.segfaultlabs.swfutils.ABC.ABCCPool;
    import com.segfaultlabs.swfutils.ABC.ABCClass;
    import com.segfaultlabs.swfutils.ABC.ABCInstance;
    import com.segfaultlabs.swfutils.ABC.ABCMethodInfo;
    import com.segfaultlabs.swfutils.ABC.ABCMultiname;
    import com.segfaultlabs.swfutils.ABC.ABCParser;
    import com.segfaultlabs.swfutils.ABC.ABCTraitConstSlot;
    import com.segfaultlabs.swfutils.ABC.ABCTraitsInfo;
    import com.segfaultlabs.swfutils.ABC.ABCinfo;
    import com.segfaultlabs.swfutils.SWFDataInput;
    import com.segfaultlabs.swfutils.SWFFile;

    import flash.system.ApplicationDomain;
    import flash.utils.ByteArray;

    /**
     * utility to see which classes a swf uses, but doesn't contain itself 
     * - this can be used to detect possible VerifyErrors before they happen.
     */
    public class SwfDependencyUtil
    {
        public function SwfDependencyUtil()
        {
        }

        // return null if ok, or name of needed class if external depencendy
        private static function resolveSuper(abc:ABCinfo, superClass:String):String
        {
            //if (superClass.indexOf("flash.") == 0 || superClass.indexOf("*") == 0 || superClass.indexOf("Object") == 0)
            if (superClass.indexOf("*") == 0)
            {
                trace('  super: ' + superClass + " (ignore)");

            }
            else
            {
                var superClassClass:ABCClass = null;
                for each ( var c:ABCClass in abc.classes )
                {
                    if (c.name == superClass)
                    {
                        superClassClass = c;
                    }
                }
                if (superClassClass)
                {
                    trace('  super: ' + superClass + " (resolved internally)");
                    return resolveSuper(abc, superClassClass.iref.base);

                }
                else
                {
                    trace('  super: ' + superClass + " (NOTFOUND)");
                    return superClass;
                }
            }

            return null;
        }

        /*
         * checks: classes, superclasses, static variables, member variables
         * TODO: function arguments
         * won't check: method bodies
         *
         * TODO: refactor to multiple methods
         */
        public static function getDependencies(swfBytes:ByteArray):Array /* of String */
        {
            var result:Array = [];
                swfBytes.position = 0;
                var swfr:SWFFile = new SWFFile(swfBytes);
                var arr:Array;
                if ( swfr.compressed )
                {
                    swfr.dataInput = swfr.uncompress();
                    swfr.readHeader();                  
                };
                arr = swfr.parseTags();
                if ( arr[82] != null )
                {
                    var abc:ABCinfo = new ABCinfo();
                    var cpool:ABCCPool = new ABCCPool();
                    var abcparse:ABCParser = new ABCParser();

                    abcparse.readMethodBytes = true;
                    abcparse.readExceptions = false;
                    for ( var j:int = 0; j < arr[82].length; j += 1 )
                    {
                        swfr.dataInstance.position = arr[82][j].position;
                        try
                        {
                            abcparse.parse( swfr.dataInput as SWFDataInput, abc, cpool, new FakeLogger() );
                            for each ( var c:ABCClass in abc.classes )
                            {
                                trace('class:', c.name);
                                var superClass:String = c.iref.base;
                                var dependency:String = resolveSuper(abc, superClass);
                                if (dependency)
                                {
                                    result.push(dependency);
                                }
                                for each (var mn:ABCMultiname in c.iref.interfaces)
                                {
                                    var interfaceName:String = mn.nsset[0] != "" ? mn.nsset[0] + "::" + mn.name : mn.name;
                                    var interfaceDependency:String = resolveSuper(abc, interfaceName);
                                    if (interfaceDependency)
                                    {
                                        result.push(interfaceDependency);
                                    }
                                }
                                for each (var ti:ABCTraitsInfo in c.traits)
                                {
                                    if (ti is ABCTraitConstSlot)
                                    {
                                        var constName:String
                                        if (QName(ABCTraitConstSlot(ti).type).uri)
                                        {
                                            constName = QName(ABCTraitConstSlot(ti).type).uri + "::" + QName(ABCTraitConstSlot(ti).type).localName
                                        }
                                        else
                                        {
                                            constName = QName(ABCTraitConstSlot(ti).type).localName
                                        }
                                        var constDependency:String = resolveSuper(abc, constName);
                                        if (constDependency)
                                        {
                                            result.push(constDependency);
                                        }
                                    }
                                    else if (ti is ABCMethodInfo)
                                    {
                                        trace('method', ABCMethodInfo(ti).name);
                                    } else
                                    {
                                        trace(ti);
                                    }
                                    // trace(ti.type.localName);
                                }

                                // const (static?) members: c.traits
                            }

                            for each ( var i:ABCInstance in abc.instances )
                            {
//                              trace(i);
                                for each (var instanceTi:ABCTraitsInfo in i.traits)
                                {
                                    if (instanceTi is ABCTraitConstSlot)
                                    {
                                        trace('instance:', createClassNameFromQname(ABCTraitConstSlot(instanceTi).type));
                                        var csdep:String = resolveSuper(abc, createClassNameFromQname(ABCTraitConstSlot(instanceTi).type));
                                        if (csdep)
                                        {
                                            result.push(csdep);
                                        }
                                    }
                                    else if (instanceTi is ABCMethodInfo)
                                    {

                                    }
                                    else
                                    {
                                        trace('unexpected trait type');
                                    }
                                }
                            }

                            abc.dispose();
                        } 
                        catch ( e:Error ) 
                        { 
                            trace( "  Error  ",e.getStackTrace() );
                        };                          
                    };
                    cpool.dispose();
                }
                else
                {
                    trace("No DoABC block... ;(");
                }
            return result;
        }

        private static function createClassNameFromQname(qn:QName):String
        {
            var result:String
            if (qn.uri)
            {
                result = qn.uri + "::" + qn.localName
            }
            else
            {
                result = qn.localName
            }
            return result;
        }

        public static function getUnsatisfiedDependencies(swfBytes:ByteArray):Array /* of String */
        {
            var result:Array = [];
            var dependencies:Array = SwfDependencyUtil.getDependencies(swfBytes)
            for each (var dependency:String in dependencies)
            {
                if (ApplicationDomain.currentDomain.hasDefinition(dependency))
                {
                    trace('ok: ', dependency);
                }
                else
                {
                    trace('ERROR: unsatisfied dependency: ', dependency);
                    result.push(dependency);
                }
            }
            return result;
        }
    }
}
于 2012-06-10T20:04:39.750 に答える
0

過去にその種のアプリケーションを使用したことがありますが、VerifyError を処理するよりも、読み込まれた SWF を修正する方がよいと思います。VeriyError は、ロードされた SWF が破損しているか、形式が正しくないことを示します。

また、転送中に SWF が破損するのではなく、SWF 自体の形式が正しくないのは当然です。png や ".swf" という名前の他の形式を読み込もうとしているか、SWF が Flex コンパイラや Flash 以外のソフトウェア (swfmill など) によって生成されていると思います (後者の場合、そのソフトウェアにバグがある可能性があります)。

于 2010-07-18T06:29:36.190 に答える
0

この問題を回避する方法があると思います。

  1. URLLoader または URLStream を使用して ByteArray に swf をロードします。
  2. thisまたは thisのような SWF バイナリの解析には、任意のオープン ソース ライブラリを使用します。
  3. バイト配列全体が有効な SWF ファイルを表していることを検証するかどうかを確認します。
  4. 上記のテストが成功した場合は、loadBytes メソッドを使用して、この ByteArray をローダーにロードします。
  5. それ以外の場合、これが機能していないことをユーザーに示します。

免責事項:バイナリ ファイルは有効な SWF である可能性がありますが、レンダリングできない可能性がありますが、これにより、すべての無効な SWF または拡張子が swf に変更されたその他の形式を破棄できます。

于 2010-07-21T06:31:06.223 に答える