代码之家  ›  专栏  ›  技术社区  ›  Simon Groenewolt

handle verifyerror:error 1014使用as3加载SWF时

  •  1
  • Simon Groenewolt  · 技术社区  · 14 年前

    我们正在开发一个系统,该系统为应用程序提供一个主SWF,并从单独的SWF中加载单独的工具——在那里 因为独立的SWF来自CMS(特别是现在我们还在开发,但将来其他开发人员可能会创建一个不兼容的工具),所以将来会出现版本控制问题。我正在尽可能地阻止它们,但我真的希望能够在加载不兼容的SWF时向系统用户显示一条消息。

    这意味着我们需要捕获那个verifyerror,或者至少确定由于某种原因加载失败——目前我不知道如何处理这个问题。我怀疑有可能使用10.1和未捕获错误系统,但我们目前的目标是Flash播放器10。有人有好主意吗?(我们已经在处理ioErrorEvent.io_错误)

    更新:我已经构建了一个解决方案,在导入前扫描字节码,看起来可以工作。我稍后再发布解决方案。

    5 回复  |  直到 12 年前
        1
  •  1
  •   Rad'Val    14 年前

    最好的方法是使用不丹建议的一个图书馆。我用过 senocular's 下一个例子。 此外,由于seniomer的库只为解析的swf提供基本操作,因此您可能需要swf格式规范(adobe.com/devnet/swf/pdf/swf_file_format_spec_v10.pdf)来从加载的swf中获取所需的信息。

    下一个示例列出了加载的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
    
       }
      }
     }
    

    }

        2
  •  1
  •   9re    14 年前

    我确实误解了你想做什么。

    好吧,实际上,我想没有验证错误的处理程序,要检测错误,您必须使用字节代码。

    顺便说一下,我有一个想法,这不是你问题的答案,但可能对你有所帮助。

    第三方SWF依赖于应该在我的SWF中的类——如果缺少该类,我会得到verifyerror。

    从这一点上,我可以建议,如果您将“缺少的类”链接到SWF,并将第三方SWF加载到applicationdomain.currentdomain或new applicationdomain(applicationdomain.currentdomain),则可以避免“验证错误”。 (这是因为Flash播放器将在父SWF中找到丢失类的差异。)

    这是我的示例代码,它加载带有验证错误的SWF( http://teionclub.com/test/xml/main.swf )

    Avoiding VerifyError - wonderfl build flash online
        3
  •  0
  •   Simon Groenewolt    14 年前

    我认为有办法解决这个问题。

    1. 使用Urlloader或 将数据流转换为字节数组。
    2. 使用任何开放源代码库来分析类似SWF二进制的 this this .
    3. 检查它是否验证整个字节数组是否表示有效 SWF文件。
    4. 如果上述测试成功,则使用 LoadBytes方法。
    5. 否则,向用户显示这不起作用。

    免责声明: 一个二进制文件可以是一个有效的SWF,但它仍然可能无法呈现,但通过这种方式,您可以放弃所有无效的SWF或扩展名更改为SWF的任何其他格式。

        4
  •  0
  •   9re    14 年前

    我以前使用过这种应用程序,但我认为修复加载的SWF比处理VerifyError更好。VeriyerRor指示加载的SWF已损坏或格式不正确。

    很自然,SWF本身是畸形的,而不是在传输过程中SWF被破坏。我猜你是想加载png或其他名为“.swf”的格式,或者swf是由flex编译器或flash以外的软件生成的,比如swfmill(在后一种情况下,软件中会有一个bug)。

        5
  •  0
  •   Simon Groenewolt    12 年前

    为了最终回答我自己的问题,这是我用来检测可能错误的实用程序类。我将SWF作为字节数组加载,并在将其作为实际movieclip加载之前扫描内容。

    正如您所看到的,我的代码很大程度上依赖于 com.segfaultlabs.swfutils package

    重要提示:我已经停止使用这种防止错误的方法,而是选择更手动的方法,通过实际尝试加载文件并查看它们是否工作来检查文件。这是因为实用程序不完整,而且我目前对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;
            }
        }
    }
    
    推荐文章