/* * JSwiff is an open source Java API for Macromedia Flash file generation * and manipulation * * Copyright (C) 2004-2005 Ralf Terdic (contact@jswiff.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.jswiff.xml; import com.jswiff.swfrecords.RegisterParam; import com.jswiff.swfrecords.actions.Action; import com.jswiff.swfrecords.actions.ActionConstants; import com.jswiff.swfrecords.actions.ConstantPool; import com.jswiff.swfrecords.actions.DefineFunction; import com.jswiff.swfrecords.actions.DefineFunction2; import com.jswiff.swfrecords.actions.GetURL; import com.jswiff.swfrecords.actions.GetURL2; import com.jswiff.swfrecords.actions.GoToFrame; import com.jswiff.swfrecords.actions.GoToFrame2; import com.jswiff.swfrecords.actions.GoToLabel; import com.jswiff.swfrecords.actions.If; import com.jswiff.swfrecords.actions.Jump; import com.jswiff.swfrecords.actions.Push; import com.jswiff.swfrecords.actions.SetTarget; import com.jswiff.swfrecords.actions.StackValue; import com.jswiff.swfrecords.actions.StoreRegister; import com.jswiff.swfrecords.actions.Try; import com.jswiff.swfrecords.actions.UnknownAction; import com.jswiff.swfrecords.actions.WaitForFrame; import com.jswiff.swfrecords.actions.WaitForFrame2; import com.jswiff.swfrecords.actions.With; import com.jswiff.util.Base64; import com.jswiff.util.StringUtilities; import org.dom4j.Element; import java.util.Iterator; import java.util.List; /* * Writes SWF actions to XML. */ class ActionXMLWriter { static void writeAction(Element parentElement, Action action) { int actionCode = action.getCode(); Element element; switch (actionCode) { case ActionConstants.ADD: element = parentElement.addElement("add"); break; case ActionConstants.ADD_2: element = parentElement.addElement("add2"); break; case ActionConstants.AND: element = parentElement.addElement("and"); break; case ActionConstants.ASCII_TO_CHAR: element = parentElement.addElement("asciitochar"); break; case ActionConstants.BIT_AND: element = parentElement.addElement("bitand"); break; case ActionConstants.BIT_L_SHIFT: element = parentElement.addElement("bitlshift"); break; case ActionConstants.BIT_OR: element = parentElement.addElement("bitor"); break; case ActionConstants.BIT_R_SHIFT: element = parentElement.addElement("bitrshift"); break; case ActionConstants.BIT_U_R_SHIFT: element = parentElement.addElement("biturshift"); break; case ActionConstants.BIT_XOR: element = parentElement.addElement("bitxor"); break; case ActionConstants.CALL: element = parentElement.addElement("call"); break; case ActionConstants.CALL_FUNCTION: element = parentElement.addElement("callfunction"); break; case ActionConstants.CALL_METHOD: element = parentElement.addElement("callmethod"); break; case ActionConstants.CAST_OP: element = parentElement.addElement("castop"); break; case ActionConstants.CHAR_TO_ASCII: element = parentElement.addElement("chartoascii"); break; case ActionConstants.CLONE_SPRITE: element = parentElement.addElement("clonesprite"); break; case ActionConstants.CONSTANT_POOL: element = writeConstantPool(parentElement, (ConstantPool) action); break; case ActionConstants.DECREMENT: element = parentElement.addElement("decrement"); break; case ActionConstants.DEFINE_FUNCTION: element = writeDefineFunction(parentElement, (DefineFunction) action); break; case ActionConstants.DEFINE_FUNCTION_2: element = writeDefineFunction2(parentElement, (DefineFunction2) action); break; case ActionConstants.DEFINE_LOCAL: element = parentElement.addElement("definelocal"); break; case ActionConstants.DEFINE_LOCAL_2: element = parentElement.addElement("definelocal2"); break; case ActionConstants.DELETE: element = parentElement.addElement("delete"); break; case ActionConstants.DELETE_2: element = parentElement.addElement("delete2"); break; case ActionConstants.DIVIDE: element = parentElement.addElement("divide"); break; case ActionConstants.END_DRAG: element = parentElement.addElement("enddrag"); break; case ActionConstants.ENUMERATE: element = parentElement.addElement("enumerate"); break; case ActionConstants.ENUMERATE_2: element = parentElement.addElement("enumerate2"); break; case ActionConstants.EQUALS: element = parentElement.addElement("equals"); break; case ActionConstants.EQUALS_2: element = parentElement.addElement("equals2"); break; case ActionConstants.EXTENDS: element = parentElement.addElement("extends"); break; case ActionConstants.GET_MEMBER: element = parentElement.addElement("getmember"); break; case ActionConstants.GET_PROPERTY: element = parentElement.addElement("getproperty"); break; case ActionConstants.GET_TIME: element = parentElement.addElement("gettime"); break; case ActionConstants.GET_URL: element = writeGetURL(parentElement, (GetURL) action); break; case ActionConstants.GET_URL_2: element = writeGetURL2(parentElement, (GetURL2) action); break; case ActionConstants.GET_VARIABLE: element = parentElement.addElement("getvariable"); break; case ActionConstants.GO_TO_FRAME: element = writeGoToFrame(parentElement, (GoToFrame) action); break; case ActionConstants.GO_TO_FRAME_2: element = writeGoToFrame2(parentElement, (GoToFrame2) action); break; case ActionConstants.GO_TO_LABEL: element = writeGoToLabel(parentElement, (GoToLabel) action); break; case ActionConstants.GREATER: element = parentElement.addElement("greater"); break; case ActionConstants.IF: element = writeIf(parentElement, (If) action); break; case ActionConstants.IMPLEMENTS_OP: element = parentElement.addElement("implementsop"); break; case ActionConstants.INCREMENT: element = parentElement.addElement("increment"); break; case ActionConstants.INIT_ARRAY: element = parentElement.addElement("initarray"); break; case ActionConstants.INIT_OBJECT: element = parentElement.addElement("initobject"); break; case ActionConstants.INSTANCE_OF: element = parentElement.addElement("instanceof"); break; case ActionConstants.JUMP: element = writeJump(parentElement, (Jump) action); break; case ActionConstants.LESS: element = parentElement.addElement("less"); break; case ActionConstants.LESS_2: element = parentElement.addElement("less2"); break; case ActionConstants.M_B_ASCII_TO_CHAR: element = parentElement.addElement("mbasciitochar"); break; case ActionConstants.M_B_CHAR_TO_ASCII: element = parentElement.addElement("mbchartoascii"); break; case ActionConstants.M_B_STRING_EXTRACT: element = parentElement.addElement("mbstringextract"); break; case ActionConstants.M_B_STRING_LENGTH: element = parentElement.addElement("mbstringlength"); break; case ActionConstants.MODULO: element = parentElement.addElement("modulo"); break; case ActionConstants.MULTIPLY: element = parentElement.addElement("multiply"); break; case ActionConstants.NEW_METHOD: element = parentElement.addElement("newmethod"); break; case ActionConstants.NEW_OBJECT: element = parentElement.addElement("newobject"); break; case ActionConstants.NEXT_FRAME: element = parentElement.addElement("nextframe"); break; case ActionConstants.NOT: element = parentElement.addElement("not"); break; case ActionConstants.OR: element = parentElement.addElement("or"); break; case ActionConstants.PLAY: element = parentElement.addElement("play"); break; case ActionConstants.POP: element = parentElement.addElement("pop"); break; case ActionConstants.PREVIOUS_FRAME: element = parentElement.addElement("previousframe"); break; case ActionConstants.PUSH: element = writePush(parentElement, (Push) action); break; case ActionConstants.PUSH_DUPLICATE: element = parentElement.addElement("pushduplicate"); break; case ActionConstants.RANDOM_NUMBER: element = parentElement.addElement("randomnumber"); break; case ActionConstants.REMOVE_SPRITE: element = parentElement.addElement("removesprite"); break; case ActionConstants.RETURN: element = parentElement.addElement("return"); break; case ActionConstants.SET_MEMBER: element = parentElement.addElement("setmember"); break; case ActionConstants.SET_PROPERTY: element = parentElement.addElement("setproperty"); break; case ActionConstants.SET_TARGET: element = writeSetTarget(parentElement, (SetTarget) action); break; case ActionConstants.SET_TARGET_2: element = parentElement.addElement("settarget2"); break; case ActionConstants.SET_VARIABLE: element = parentElement.addElement("setvariable"); break; case ActionConstants.STACK_SWAP: element = parentElement.addElement("stackswap"); break; case ActionConstants.START_DRAG: element = parentElement.addElement("startdrag"); break; case ActionConstants.STOP: element = parentElement.addElement("stop"); break; case ActionConstants.STOP_SOUNDS: element = parentElement.addElement("stopsounds"); break; case ActionConstants.STORE_REGISTER: element = writeStoreRegister(parentElement, (StoreRegister) action); break; case ActionConstants.STRICT_EQUALS: element = parentElement.addElement("strictequals"); break; case ActionConstants.STRING_ADD: element = parentElement.addElement("stringadd"); break; case ActionConstants.STRING_EQUALS: element = parentElement.addElement("stringequals"); break; case ActionConstants.STRING_EXTRACT: element = parentElement.addElement("stringextract"); break; case ActionConstants.STRING_GREATER: element = parentElement.addElement("stringgreater"); break; case ActionConstants.STRING_LENGTH: element = parentElement.addElement("stringlength"); break; case ActionConstants.STRING_LESS: element = parentElement.addElement("stringless"); break; case ActionConstants.SUBTRACT: element = parentElement.addElement("subtract"); break; case ActionConstants.TARGET_PATH: element = parentElement.addElement("targetpath"); break; case ActionConstants.THROW: element = parentElement.addElement("throw"); break; case ActionConstants.TO_INTEGER: element = parentElement.addElement("tointeger"); break; case ActionConstants.TO_NUMBER: element = parentElement.addElement("tonumber"); break; case ActionConstants.TO_STRING: element = parentElement.addElement("tostring"); break; case ActionConstants.TOGGLE_QUALITY: element = parentElement.addElement("togglequality"); break; case ActionConstants.TRACE: element = parentElement.addElement("trace"); break; case ActionConstants.TRY: element = writeTry(parentElement, (Try) action); break; case ActionConstants.TYPE_OF: element = parentElement.addElement("typeof"); break; case ActionConstants.WAIT_FOR_FRAME: element = writeWaitForFrame(parentElement, (WaitForFrame) action); break; case ActionConstants.WAIT_FOR_FRAME_2: element = writeWaitForFrame2(parentElement, (WaitForFrame2) action); break; case ActionConstants.WITH: element = writeWith(parentElement, (With) action); break; default: element = writeUnknown(parentElement, (UnknownAction) action); } String label = action.getLabel(); if (label != null) { element.addAttribute("label", label); } } private static Element writeConstantPool( Element parentElement, ConstantPool constantPool) { Element element = parentElement.addElement("constantpool"); List constants = constantPool.getConstants(); int id = 0; for (Iterator it = constants.iterator(); it.hasNext();) { String constant = (String) it.next(); Element constantElement = element.addElement("constant"); constantElement.addAttribute("id", Integer.toString(id++)); if (StringUtilities.containsIllegalChars(constant)) { constantElement.addElement("value").addAttribute("base64", "true") .addText(Base64.encodeString(constant)); } else { constantElement.addElement("value").addText(constant); } } return element; } private static Element writeDefineFunction( Element parentElement, DefineFunction defineFunction) { Element element = parentElement.addElement("definefunction"); element.addAttribute("name", defineFunction.getName()); String[] parameters = defineFunction.getParameters(); Element parametersElement = element.addElement("parameters"); for (int i = 0; i < parameters.length; i++) { parametersElement.addElement("parameter").addAttribute( "name", parameters[i]); } RecordXMLWriter.writeActionBlock(element, defineFunction.getBody()); return element; } private static Element writeDefineFunction2( Element parentElement, DefineFunction2 defineFunction2) { Element element = parentElement.addElement("definefunction2"); element.addAttribute("name", defineFunction2.getName()); element.addAttribute( "registercount", Short.toString(defineFunction2.getRegisterCount())); RegisterParam[] parameters = defineFunction2.getParameters(); Element parametersElement = element.addElement("parameters"); for (int i = 0; i < parameters.length; i++) { RegisterParam parameter = parameters[i]; Element paramElement = parametersElement.addElement("registerparam"); paramElement.addAttribute("name", parameter.getParamName()); paramElement.addAttribute( "register", Short.toString(parameter.getRegister())); } Element preloadElement = element.addElement("preload"); if (defineFunction2.preloadsArguments()) { preloadElement.addAttribute("arguments", "true"); } if (defineFunction2.preloadsGlobal()) { preloadElement.addAttribute("global", "true"); } if (defineFunction2.preloadsParent()) { preloadElement.addAttribute("parent", "true"); } if (defineFunction2.preloadsRoot()) { preloadElement.addAttribute("root", "true"); } if (defineFunction2.preloadsSuper()) { preloadElement.addAttribute("super", "true"); } if (defineFunction2.preloadsThis()) { preloadElement.addAttribute("this", "true"); } Element suppressElement = element.addElement("suppress"); if (defineFunction2.suppressesArguments()) { suppressElement.addAttribute("arguments", "true"); } if (defineFunction2.suppressesSuper()) { suppressElement.addAttribute("super", "true"); } if (defineFunction2.suppressesThis()) { suppressElement.addAttribute("this", "true"); } RecordXMLWriter.writeActionBlock(element, defineFunction2.getBody()); return element; } private static Element writeGetURL(Element parentElement, GetURL getURL) { Element element = parentElement.addElement("geturl"); element.addAttribute("url", getURL.getURL()); element.addAttribute("target", getURL.getTarget()); return element; } private static Element writeGetURL2(Element parentElement, GetURL2 getURL2) { Element element = parentElement.addElement("geturl2"); switch (getURL2.getSendVarsMethod()) { case GetURL2.METHOD_GET: element.addAttribute("sendvarsmethod", "get"); break; case GetURL2.METHOD_POST: element.addAttribute("sendvarsmethod", "post"); break; default: element.addAttribute("sendvarsmethod", "none"); } if (getURL2.isLoadTarget()) { element.addAttribute("loadtarget", "true"); } if (getURL2.isLoadVariables()) { element.addAttribute("loadvariables", "true"); } return element; } private static Element writeGoToFrame( Element parentElement, GoToFrame goToFrame) { Element element = parentElement.addElement("gotoframe"); element.addAttribute("frame", Integer.toString(goToFrame.getFrame())); return element; } private static Element writeGoToFrame2( Element parentElement, GoToFrame2 goToFrame2) { Element element = parentElement.addElement("gotoframe2"); element.addAttribute( "scenebias", Integer.toString(goToFrame2.getSceneBias())); if (goToFrame2.play()) { element.addAttribute("play", "true"); } return element; } private static Element writeGoToLabel( Element parentElement, GoToLabel goToLabel) { Element element = parentElement.addElement("gotolabel"); element.addAttribute("framelabel", goToLabel.getFrameLabel()); return element; } private static Element writeIf(Element parentElement, If ifAction) { Element element = parentElement.addElement("if"); element.addAttribute("branchlabel", ifAction.getBranchLabel()); return element; } private static Element writeJump(Element parentElement, Jump jump) { Element element = parentElement.addElement("jump"); element.addAttribute("branchlabel", jump.getBranchLabel()); return element; } private static Element writePush(Element parentElement, Push push) { Element element = parentElement.addElement("push"); List values = push.getValues(); for (Iterator it = values.iterator(); it.hasNext();) { StackValue value = (StackValue) it.next(); switch (value.getType()) { case StackValue.TYPE_BOOLEAN: element.addElement("boolean").addAttribute( "value", Boolean.toString(value.getBoolean())); break; case StackValue.TYPE_CONSTANT_16: element.addElement("constant16").addAttribute( "id", Integer.toString(value.getConstant16())); break; case StackValue.TYPE_CONSTANT_8: element.addElement("constant8").addAttribute( "id", Integer.toString(value.getConstant8())); break; case StackValue.TYPE_DOUBLE: element.addElement("double").addAttribute( "value", Double.toString(value.getDouble())); break; case StackValue.TYPE_FLOAT: element.addElement("float").addAttribute( "value", Float.toString(value.getFloat())); break; case StackValue.TYPE_INTEGER: element.addElement("integer").addAttribute( "value", Long.toString(value.getInteger())); break; case StackValue.TYPE_NULL: element.addElement("null"); break; case StackValue.TYPE_REGISTER: element.addElement("register").addAttribute( "number", Short.toString(value.getRegisterNumber())); break; case StackValue.TYPE_STRING: element.addElement("string").addAttribute("value", value.getString()); break; case StackValue.TYPE_UNDEFINED: element.addElement("undefined"); break; } } return element; } private static Element writeSetTarget( Element parentElement, SetTarget setTarget) { Element element = parentElement.addElement("settarget"); element.addAttribute("name", setTarget.getName()); return element; } private static Element writeStoreRegister( Element parentElement, StoreRegister storeRegister) { Element element = parentElement.addElement("storeregister"); element.addAttribute("number", Short.toString(storeRegister.getNumber())); return element; } private static Element writeTry(Element parentElement, Try tryAction) { Element element = parentElement.addElement("try"); if (tryAction.catchInRegister()) { element.addAttribute( "catchregister", Short.toString(tryAction.getCatchRegister())); } else { element.addAttribute("catchvariable", tryAction.getCatchVariable()); } RecordXMLWriter.writeActionBlock( element.addElement("try"), tryAction.getTryBlock()); if (tryAction.hasCatchBlock()) { RecordXMLWriter.writeActionBlock( element.addElement("catch"), tryAction.getCatchBlock()); } if (tryAction.hasFinallyBlock()) { RecordXMLWriter.writeActionBlock( element.addElement("finally"), tryAction.getFinallyBlock()); } return element; } private static Element writeUnknown( Element parentElement, UnknownAction action) { Element element = parentElement.addElement("unknownaction"); element.addAttribute("code", Integer.toString(action.getCode())); element.addText(Base64.encode(action.getData())); return element; } private static Element writeWaitForFrame( Element parentElement, WaitForFrame waitForFrame) { Element element = parentElement.addElement("waitforframe"); element.addAttribute("frame", Integer.toString(waitForFrame.getFrame())); element.addAttribute( "skipcount", Short.toString(waitForFrame.getSkipCount())); return element; } private static Element writeWaitForFrame2( Element parentElement, WaitForFrame2 waitForFrame2) { Element element = parentElement.addElement("waitforframe2"); element.addAttribute( "skipcount", Short.toString(waitForFrame2.getSkipCount())); return element; } private static Element writeWith(Element parentElement, With with) { Element element = parentElement.addElement("with"); RecordXMLWriter.writeActionBlock(element, with.getWithBlock()); return element; } }