Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package flash.swf;
import flash.swf.Dictionary;
import flash.swf.actions.*;
import flash.swf.debug.DebugModule;
import flash.swf.debug.LineRecord;
import flash.swf.tags.*;
import flash.swf.types.*;
import flash.util.IntMap;
import java.io.*;
import java.net.*;
import java.util.*;
/**
* Represents SWF metadata, which should not be confuses with AS3
* metadata.
*/
public final class MovieMetaData extends TagHandler
{
public MovieMetaData(byte[] swf, byte[] swd)
{
this(new ByteArrayInputStream(swf), new ByteArrayInputStream(swd));
}
public MovieMetaData(InputStream swf, InputStream swd)
{
try
{
init();
TagDecoder p = new TagDecoder(swf, swd);
parse(p);
}
catch (IOException ex)
{
}
}
public MovieMetaData(String u)
{
try
{
init();
URL url = new URL(u);
InputStream in = url.openStream();
TagDecoder p = new TagDecoder(in, url);
parse(p);
}
catch (MalformedURLException ex)
{
}
catch (IOException ex)
{
}
}
private void init()
{
actions = new IntMap();
modules = new IntMap();
functionNames = new IntMap();
functionSizes = new IntMap();
functionLines = new IntMap();
preciseLines = new IntMap();
mxml = new HashMap();
pool = null;
skipOffsets = new ArrayList();
}
private void parse(TagDecoder p) throws IOException
{
p.setKeepOffsets(true);
p.parse(this);
Collections.sort(skipOffsets);
className = null;
}
private Dictionary dict;
private Header header;
// given an offset, what's the bytecode?
public IntMap actions;
// given an offset, what debug module it's in?
public IntMap modules;
// given an offset, what function it's in?
public IntMap functionNames;
public IntMap functionSizes;
public IntMap functionLines;
public IntMap preciseLines;
// MXML DebugModule
public Map mxml;
// offsets that we don't want to profile
public List skipOffsets;
// temporarily store AS2 class name...
private String className;
private String[] pool;
public DebugModule getDebugModule(int offset)
{
DebugModule d = (DebugModule) modules.get(offset);
if (d == null)
{
return null;
}
else
{
return d;
}
}
public String getFunctionName(int offset)
{
return (String) functionNames.get(offset);
}
public Iterator getFunctionLines()
{
return preciseLines.iterator();
}
public Integer getOpCode(int offset)
{
return (Integer) actions.get(offset);
}
protected Integer getFunctionLineNumber(int offset)
{
return (Integer) functionLines.get(offset);
}
protected boolean isFunction(int offset)
{
String s = getFunctionName(offset);
return (s != null);
}
public void setDecoderDictionary(Dictionary dict)
{
this.dict = dict;
}
public void header(Header h)
{
header = h;
}
public void defineButton(DefineButton tag)
{
String[] temp = pool;
collectActions(tag.condActions[0].actionList);
pool = temp;
}
public void doAction(DoAction tag)
{
String[] temp = pool;
collectActions(tag.actionList);
pool = temp;
}
public void placeObject2(PlaceObject tag)
{
collectClipActions(tag.clipActions);
}
public void placeObject3(PlaceObject tag)
{
collectClipActions(tag.clipActions);
}
public void defineButton2(DefineButton tag)
{
collectCondActions(tag.condActions);
}
public void defineSprite(DefineSprite tag)
{
collectSpriteActions(tag.tagList);
}
public void doInitAction(DoInitAction tag)
{
if (header.version > 6 && tag.sprite != null)
{
String __Packages = idRef(tag.sprite);
className = (__Packages != null && __Packages.startsWith("__Packages")) ? __Packages.substring(11) : null; // length("__Packages.") = 11
if (isRegisterClass(tag.actionList))
{
DebugModule dm = new DebugModule();
// C: We actually want the class name here, not the linkage ID.
dm.name = "<" + __Packages + ".2>";
// C: We want the class name as the second input argument. Fortunately, we don't
// really do anything with the source, so it's okay.
dm.setText("Object.registerClass(" + __Packages + ", " + __Packages + ");");
dm.bitmap = 1;
LineRecord lr = new LineRecord(1, dm);
int startOffset = tag.actionList.getOffset(0);
dm.addOffset(lr, startOffset);
tag.actionList.insert(startOffset, lr);
modules.put((int) (Math.random() * Integer.MAX_VALUE), dm);
}
}
String[] temp = pool;
collectActions(tag.actionList);
pool = temp;
className = null;
}
private static final int[] regClassCall9 = new int[]
{
ActionConstants.sactionPush, // class name
ActionConstants.sactionGetVariable,
ActionConstants.sactionPush, // linkage id
ActionConstants.sactionPush, // 2
ActionConstants.sactionPush, // Object
ActionConstants.sactionGetVariable,
ActionConstants.sactionPush, // registerClass
ActionConstants.sactionCallMethod,
ActionConstants.sactionPop
};
private static final int[] regClassCall10 = new int[]
{
ActionConstants.sactionConstantPool, // constant pool
ActionConstants.sactionPush, // class name
ActionConstants.sactionGetVariable,
ActionConstants.sactionPush, // linkage id
ActionConstants.sactionPush, // 2
ActionConstants.sactionPush, // Object
ActionConstants.sactionGetVariable,
ActionConstants.sactionPush, // registerClass
ActionConstants.sactionCallMethod,
ActionConstants.sactionPop
};
// TODO: Use an evaluation stack to figure out the Object.registerClass() call.
public static final boolean isRegisterClass(ActionList actionList)
{
if (!hasLineRecord(actionList))
{
int[] opcodes;
if (actionList.size() == 9)
{
opcodes = regClassCall9;
}
else if (actionList.size() == 10)
{
opcodes = regClassCall10;
}
else
{
return false;
}
for (int i = 0;i < opcodes.length;i++)
{
if (actionList.getAction(i).code != opcodes[i])
{
return false;
}
else
{
// TODO: need to check the PUSH values...
}
}
return true;
}
return false;
}
String idRef(DefineTag tag) { return idRef(tag, dict); }
public static String idRef(DefineTag tag, Dictionary d)
{
if (tag == null)
{
// if tag is null then it isn't in the dict -- the SWF is invalid.
// lets be lax and print something; Matador generates invalid SWF sometimes.
return "-1";
}
else if (tag.name == null)
{
// just print the character id since no name was exported
return String.valueOf(d.getId(tag));
}
else
{
return tag.name;
}
}
private static final boolean hasLineRecord(ActionList c)
{
if (c == null || c.size() == 0)
{
return true;
}
boolean result = false;
for (int i=0; i < c.size() && !result; i++)
{
Action action = c.getAction(i);
switch (action.code)
{
case ActionConstants.sactionDefineFunction:
case ActionConstants.sactionDefineFunction2:
result = result || hasLineRecord(((DefineFunction) action).actionList);
break;
case ActionList.sactionLineRecord:
result = true;
break;
}
}
return result;
}
private void collectSpriteActions(TagList s)
{
String[] temp;
int len = s.tags.size();
for (int i = 0; i < len; i++)
{
Tag t = s.tags.get(i);
switch (t.code)
{
case TagValues.stagDoAction:
temp = pool;
collectActions(((DoAction) t).actionList);
pool = temp;
break;
case TagValues.stagDefineButton2:
collectCondActions(((DefineButton) t).condActions);
break;
case TagValues.stagDefineButton:
temp = pool;
collectActions(((DefineButton) t).condActions[0].actionList);
pool = temp;
break;
case TagValues.stagDoInitAction:
temp = pool;
collectActions(((DoInitAction) t).actionList);
pool = temp;
break;
case TagValues.stagDefineSprite:
collectSpriteActions(((DefineSprite) t).tagList);
break;
case TagValues.stagPlaceObject2:
collectClipActions(((PlaceObject) t).clipActions);
break;
}
}
}
private DebugModule findDebugModule(ActionList c)
{
MFUCache modules = new MFUCache();
for (int i=0; i < c.size(); i++)
{
Action a = c.getAction(i);
DebugModule temp = null;
switch (a.code)
{
case ActionConstants.sactionDefineFunction:
case ActionConstants.sactionDefineFunction2:
temp = findDebugModule(((DefineFunction) a).actionList);
break;
case ActionList.sactionLineRecord:
if (((LineRecord)a).module != null)
{
temp = ((LineRecord)a).module;
}
break;
}
if (temp != null)
{
modules.add(temp);
}
}
// ActionList may have actions pointing to more than one debug module because of #include, etc.
// The majority wins.
return modules.topModule;
}
private static Integer[] codes = new Integer[256];
static
{
for (int i=0; i < 256; i++)
{
codes[i] = new Integer(i);
}
}
private void collectActions(ActionList c)
{
// assumption: ActionContext c is always not null! try-catch-finally may be busted.
if (c == null)
{
return;
}
// interprets the actions. try to assign names to anonymous functions...
evalActions(c);
DebugModule d = findDebugModule(c);
String emptyMethodName = null;
// loop again, this time, we register all the actions...
for (int i=0; i < c.size(); i++)
{
int ioffset = c.getOffset(i);
Action a = c.getAction(i);
if (emptyMethodName != null && emptyMethodName.length() != 0)
{
functionNames.put(ioffset, emptyMethodName);
emptyMethodName = null;
}
if (a.code == ActionList.sactionLineRecord)
{
LineRecord line = (LineRecord) a;
if (line.module != null)
{
d = line.module;
if (d.name.endsWith(".mxml"))
{
mxml.put(d.name, d);
}
}
continue;
}
if (a.code >= 256)
{
// something synthetic we don't care about
continue;
}
actions.put(ioffset, codes[a.code]);
modules.put(ioffset, d);
switch (a.code)
{
case ActionConstants.sactionDefineFunction:
case ActionConstants.sactionDefineFunction2:
DefineFunction f = (DefineFunction) a;
Integer size = new Integer(f.codeSize);
if (f.actionList.size() == 0)
{
emptyMethodName = f.name;
}
else
{
Integer lineno = null;
// map all the offsets in this function to the function name
for (int j=0; j < f.actionList.size(); j++)
{
int o = f.actionList.getOffset(j);
Action child = f.actionList.getAction(j);
if (child.code == ActionList.sactionLineRecord)
{
// also find out the first line number of this function
if (lineno == null)
lineno = new Integer(((LineRecord)child).lineno);
preciseLines.put(o, new Integer( ((LineRecord)child).lineno ));
}
functionNames.put(o, f.name);
functionSizes.put(o, size);
}
// map all the offsets in this function to the first line number of this function.
for (int j=0; j < f.actionList.size(); j++)
{
int o = f.actionList.getOffset(j);
functionLines.put(o, lineno);
}
}
collectActions(f.actionList);
break;
}
}
}
private void collectCondActions(ButtonCondAction[] actions)
{
for (int i = 0; i < actions.length; i++)
{
collectActions(actions[i].actionList);
}
}
private void collectClipActions(ClipActions actions)
{
if (actions != null)
{
Iterator it = actions.clipActionRecords.iterator();
while (it.hasNext())
{
ClipActionRecord record = (ClipActionRecord) it.next();
collectActions(record.actionList);
}
}
}
private static Object pop(Stack