diff --git a/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java b/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java index 12459889c..06f0b3345 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java @@ -1281,7 +1281,7 @@ public class SWFInputStream extends InputStream { case 2: ret = new DefineShapeTag(swf, data, version, pos); break; - //case 3 + //case 3: FreeCharacter case 4: ret = new PlaceObjectTag(swf, data, version, pos); break; @@ -1318,7 +1318,7 @@ public class SWFInputStream extends InputStream { case 15: ret = new StartSoundTag(swf, data, version, pos); break; - //case 16 + //case 16: case 17: ret = new DefineButtonSoundTag(swf, data, version, pos); break; @@ -1343,7 +1343,7 @@ public class SWFInputStream extends InputStream { case 24: ret = new ProtectTag(swf, data, version, pos); break; - //case 25: + //case 25: PathsArePostscript case 26: ret = new PlaceObject2Tag(swf, data, version, pos); break; @@ -1351,9 +1351,9 @@ public class SWFInputStream extends InputStream { case 28: ret = new RemoveObject2Tag(swf, data, version, pos); break; - //case 29: + //case 29: SyncFrame //case 30: - //case 31: + //case 31: FreeAll case 32: ret = new DefineShape3Tag(swf, data, version, pos); break; @@ -1372,15 +1372,15 @@ public class SWFInputStream extends InputStream { case 37: ret = new DefineEditTextTag(swf, data, version, pos); break; - //case 38: + //case 38: DefineVideo case 39: ret = new DefineSpriteTag(swf, data, version, level, pos, paralel, skipUnusualTags); break; - //case 40: + //case 40: NameCharacter case 41: ret = new ProductInfoTag(swf, data, version, pos); break; - //case 42: + //case 42: DefineTextFormat case 43: ret = new FrameLabelTag(swf, data, version, pos); break; @@ -1391,11 +1391,15 @@ public class SWFInputStream extends InputStream { case 46: ret = new DefineMorphShapeTag(swf, data, version, pos); break; - //case 47: + //case 47: GenerateFrame case 48: ret = new DefineFont2Tag(swf, data, version, pos); break; - //case 49-55: + //case 49: GeneratorCommand + //case 50: DefineCommandObject + //case 51: CharacterSet + //case 52: ExternalFont + //case 53-55 case 56: ret = new ExportAssetsTag(swf, data, version, pos); break; @@ -1489,6 +1493,13 @@ public class SWFInputStream extends InputStream { case 91: ret = new DefineFont4Tag(swf, data, version, pos); break; + //case 92: certificate + case 93: + ret = new EnableTelemetryTag(swf, data, version, pos); + break; + case 94: + ret = new PlaceObject4Tag(swf, data, version, pos); + break; default: ret = new Tag(swf, tag.getId(), "Unknown", data, pos); } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/EnableTelemetryTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/EnableTelemetryTag.java new file mode 100644 index 000000000..6dd8e16e3 --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/tags/EnableTelemetryTag.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010-2013 JPEXS + * + * 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 3 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, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Enable flash profiling information + * + * @author JPEXS + */ +public class EnableTelemetryTag extends Tag { + + public static final int ID = 93; + public int reserved; + public byte passwordHash[]; + + /** + * Gets data bytes + * + * @param version SWF version + * @return Bytes of data + */ + @Override + public byte[] getData(int version) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + SWFOutputStream sos = new SWFOutputStream(os, version); + try { + sos.writeUB(16, reserved); + sos.write(passwordHash); + } catch (IOException e) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param data Data bytes + * @param version SWF version + * @param pos + * @throws IOException + */ + public EnableTelemetryTag(SWF swf, byte data[], int version, long pos) throws IOException { + super(swf, ID, "", data, pos); + SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), version); + reserved = (int) sis.readUB(16); + passwordHash = sis.readBytes(32); + } +} diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject3Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject3Tag.java index 97a4e8443..8d28d0900 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject3Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject3Tag.java @@ -274,6 +274,7 @@ public class PlaceObject3Tag extends CharacterIdTag implements Container, PlaceO /** * Constructor * + * @param swf * @param data Data bytes * @param version SWF version * @param pos diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject4Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject4Tag.java new file mode 100644 index 000000000..8e9358650 --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject4Tag.java @@ -0,0 +1,512 @@ +/* + * Copyright (C) 2010-2013 JPEXS + * + * 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 3 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, see . + */ +package com.jpexs.decompiler.flash.tags; + +import com.jpexs.decompiler.flash.Configuration; +import com.jpexs.decompiler.flash.EndOfStreamException; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.abc.CopyOutputStream; +import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; +import com.jpexs.decompiler.flash.tags.base.Container; +import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; +import com.jpexs.decompiler.flash.types.CLIPACTIONS; +import com.jpexs.decompiler.flash.types.CXFORM; +import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA; +import com.jpexs.decompiler.flash.types.MATRIX; +import com.jpexs.decompiler.flash.types.RGBA; +import com.jpexs.decompiler.flash.types.filters.FILTER; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Same as PlaceObject3Tag except additional AMF data + * + * @author JPEXS + */ +public class PlaceObject4Tag extends CharacterIdTag implements Container, PlaceObjectTypeTag { + + /** + * @since SWF 5 has clip actions (sprite characters only) + */ + public boolean placeFlagHasClipActions; + /** + * Has clip depth + */ + public boolean placeFlagHasClipDepth; + /** + * Has name + */ + public boolean placeFlagHasName; + /** + * Has ratio + */ + public boolean placeFlagHasRatio; + /** + * Has color transform + */ + public boolean placeFlagHasColorTransform; + /** + * Has matrix + */ + public boolean placeFlagHasMatrix; + /** + * Places a character + */ + public boolean placeFlagHasCharacter; + /** + * Defines a character to be moved + */ + public boolean placeFlagMove; + /** + * Has class name or character ID of bitmap to place. If + * PlaceFlagHasClassName, use ClassName. If PlaceFlagHasCharacter, use + * CharacterId + */ + public boolean placeFlagHasImage; + /** + * Has class name of object to place + */ + public boolean placeFlagHasClassName; + /** + * Enables bitmap caching + */ + public boolean placeFlagHasCacheAsBitmap; + /** + * Has blend mode + */ + public boolean placeFlagHasBlendMode; + /** + * Has filter list + */ + public boolean placeFlagHasFilterList; + /** + * Has opaque background. SWF 11 and higher. + */ + public boolean placeFlagOpaqueBackground; + /** + * Has visibility flag. SWF 11 and higher. + */ + public boolean placeFlagHasVisible; + /** + * Depth of character + */ + public int depth; + /** + * If PlaceFlagHasClassName or (PlaceFlagHasImage and + * PlaceFlagHasCharacter), Name of the class to place + */ + public String className; + /** + * If PlaceFlagHasCharacter, ID of character to place + */ + public int characterId; + /** + * If PlaceFlagHasMatrix, Transform matrix data + */ + public MATRIX matrix; + /** + * If PlaceFlagHasColorTransform, Color transform data + */ + public CXFORMWITHALPHA colorTransform; + /** + * If PlaceFlagHasRatio, Ratio + */ + public int ratio; + /** + * If PlaceFlagHasName, Name of character + */ + public String name; + /** + * If PlaceFlagHasClipDepth, Clip depth + */ + public int clipDepth; + /** + * If PlaceFlagHasFilterList, List of filters on this object + */ + public List surfaceFilterList; + /** + * If PlaceFlagHasBlendMode, Blend mode + */ + public int blendMode; + /** + * If PlaceFlagHasCacheAsBitmap, 0 = Bitmap cache disabled, 1-255 = Bitmap + * cache enabled + */ + public int bitmapCache; + /** + * @since SWF 5 If PlaceFlagHasClipActions, Clip Actions Data + */ + public CLIPACTIONS clipActions; + /** + * If PlaceFlagHasVisible, 0 = Place invisible, 1 = Place visible + */ + public int visible; + /** + * If PlaceFlagHasVisible, Background color + */ + public RGBA backgroundColor; + // FIXME bug found in ecoDrive.swf, + private boolean bitmapCacheBug; + private int reserved; + public static final int ID = 94; + public byte amfData[]; //TODO: Parse AMF data? + + @Override + public List getFilters() { + if (placeFlagHasFilterList) { + return surfaceFilterList; + } else { + return null; + } + } + + @Override + public int getClipDepth() { + if (placeFlagHasClipDepth) { + return clipDepth; + } + return -1; + } + + /** + * Gets data bytes + * + * @param version SWF version + * @return Bytes of data + */ + @Override + public byte[] getData(int version) { + if (Configuration.DISABLE_DANGEROUS) { + return super.getData(version); + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStream os = baos; + if (Configuration.DEBUG_COPY) { + os = new CopyOutputStream(os, new ByteArrayInputStream(super.data)); + } + SWFOutputStream sos = new SWFOutputStream(os, version); + try { + sos.writeUB(1, placeFlagHasClipActions ? 1 : 0); + sos.writeUB(1, placeFlagHasClipDepth ? 1 : 0); + sos.writeUB(1, placeFlagHasName ? 1 : 0); + sos.writeUB(1, placeFlagHasRatio ? 1 : 0); + sos.writeUB(1, placeFlagHasColorTransform ? 1 : 0); + sos.writeUB(1, placeFlagHasMatrix ? 1 : 0); + sos.writeUB(1, placeFlagHasCharacter ? 1 : 0); + sos.writeUB(1, placeFlagMove ? 1 : 0); + sos.writeUB(1, reserved); + sos.writeUB(1, placeFlagOpaqueBackground ? 1 : 0); //SWF11 + sos.writeUB(1, placeFlagHasVisible ? 1 : 0); //SWF11 + sos.writeUB(1, placeFlagHasImage ? 1 : 0); + sos.writeUB(1, placeFlagHasClassName ? 1 : 0); + sos.writeUB(1, placeFlagHasCacheAsBitmap ? 1 : 0); + sos.writeUB(1, placeFlagHasBlendMode ? 1 : 0); + sos.writeUB(1, placeFlagHasFilterList ? 1 : 0); + sos.writeUI16(depth); + if (placeFlagHasClassName) { + sos.writeString(className); + } + if (placeFlagHasCharacter) { + sos.writeUI16(characterId); + } + if (placeFlagHasMatrix) { + sos.writeMatrix(matrix); + } + if (placeFlagHasColorTransform) { + sos.writeCXFORMWITHALPHA(colorTransform); + } + if (placeFlagHasRatio) { + sos.writeUI16(ratio); + } + if (placeFlagHasName) { + sos.writeString(name); + } + if (placeFlagHasClipDepth) { + sos.writeUI16(clipDepth); + } + if (placeFlagHasFilterList) { + sos.writeFILTERLIST(surfaceFilterList); + } + if (placeFlagHasBlendMode) { + sos.writeUI8(blendMode); + } + if (placeFlagHasCacheAsBitmap) { + if (!bitmapCacheBug) { + sos.writeUI8(bitmapCache); + } + } + if (placeFlagHasVisible) { + sos.writeUI8(visible); + } + if (placeFlagOpaqueBackground) { + sos.writeRGBA(backgroundColor); + } + if (placeFlagHasClipActions) { + sos.writeCLIPACTIONS(clipActions); + } + sos.close(); + } catch (IOException ex) { + } + return baos.toByteArray(); + } + + /** + * Constructor + * + * @param swf + * @param data Data bytes + * @param version SWF version + * @param pos + * @throws IOException + */ + public PlaceObject4Tag(SWF swf, byte data[], int version, long pos) throws IOException { + super(swf, ID, "PlaceObject4", data, pos); + SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), version); + placeFlagHasClipActions = sis.readUB(1) == 1; + placeFlagHasClipDepth = sis.readUB(1) == 1; + placeFlagHasName = sis.readUB(1) == 1; + placeFlagHasRatio = sis.readUB(1) == 1; + placeFlagHasColorTransform = sis.readUB(1) == 1; + placeFlagHasMatrix = sis.readUB(1) == 1; + placeFlagHasCharacter = sis.readUB(1) == 1; + placeFlagMove = sis.readUB(1) == 1; + reserved = (int) sis.readUB(1); + placeFlagOpaqueBackground = sis.readUB(1) == 1; //SWF11 + placeFlagHasVisible = sis.readUB(1) == 1; //SWF11 + placeFlagHasImage = sis.readUB(1) == 1; + placeFlagHasClassName = sis.readUB(1) == 1; + placeFlagHasCacheAsBitmap = sis.readUB(1) == 1; + placeFlagHasBlendMode = sis.readUB(1) == 1; + placeFlagHasFilterList = sis.readUB(1) == 1; + + depth = sis.readUI16(); + if (placeFlagHasClassName) { + className = sis.readString(); + } + if (placeFlagHasCharacter) { + characterId = sis.readUI16(); + } + if (placeFlagHasMatrix) { + matrix = sis.readMatrix(); + } + if (placeFlagHasColorTransform) { + colorTransform = sis.readCXFORMWITHALPHA(); + } + if (placeFlagHasRatio) { + ratio = sis.readUI16(); + } + if (placeFlagHasName) { + name = sis.readString(); + } + if (placeFlagHasClipDepth) { + clipDepth = sis.readUI16(); + } + if (placeFlagHasFilterList) { + surfaceFilterList = sis.readFILTERLIST(); + } + if (placeFlagHasBlendMode) { + blendMode = sis.readUI8(); + } + bitmapCacheBug = false; + if (placeFlagHasCacheAsBitmap) { + try { + bitmapCache = sis.readUI8(); + } catch (EndOfStreamException eex) { + bitmapCacheBug = true; + bitmapCache = 1; + } + } + + if (placeFlagHasVisible) { + visible = sis.readUI8(); + } + if (placeFlagOpaqueBackground) { + backgroundColor = sis.readRGBA(); + } + + if (placeFlagHasClipActions) { + clipActions = sis.readCLIPACTIONS(); + } + amfData = sis.readBytes(sis.available()); + } + + /** + * Returns all sub-items + * + * @return List of sub-items + */ + @Override + public List getSubItems() { + List ret = new ArrayList<>(); + if (placeFlagHasClipActions) { + ret.addAll(clipActions.clipActionRecords); + } + return ret; + } + + /** + * Returns number of sub-items + * + * @return Number of sub-items + */ + @Override + public int getItemCount() { + if (!placeFlagHasClipActions) { + return 0; + } + return clipActions.clipActionRecords.size(); + } + + @Override + public Set getNeededCharacters() { + Set ret = new HashSet<>(); + if (placeFlagHasCharacter) { + ret.add(characterId); + } + return ret; + } + + @Override + public int getCharacterId() { + if (placeFlagHasCharacter) { + return characterId; + } else { + return -1; + } + } + + @Override + public int getDepth() { + return depth; + } + + @Override + public MATRIX getMatrix() { + if (placeFlagHasMatrix) { + return matrix; + } else { + return null; + } + } + + @Override + public String getInstanceName() { + if (placeFlagHasName) { + return name; + } + return null; + } + + @Override + public CXFORM getColorTransform() { + return null; + } + + @Override + public CXFORMWITHALPHA getColorTransformWithAlpha() { + if (placeFlagHasColorTransform) { + return colorTransform; + } else { + return null; + } + } + + @Override + public int getBlendMode() { + return blendMode; + } + + @Override + public String getClassName() { + if (placeFlagHasClassName) { + return className; + } + return null; + } + + @Override + public boolean cacheAsBitmap() { + return placeFlagHasCacheAsBitmap; + } + + @Override + public boolean isVisible() { + if (placeFlagHasVisible) { + return visible == 1; + } + return true; + } + + @Override + public RGBA getBackgroundColor() { + if (placeFlagOpaqueBackground) { + return backgroundColor; + } + return null; + } + + @Override + public boolean flagMove() { + return placeFlagMove; + } + + @Override + public int getRatio() { + if (!placeFlagHasRatio) { + return -1; + } + return ratio; + } + + @Override + public void setInstanceName(String name) { + placeFlagHasName = true; + this.name = name; + } + + @Override + public void setClassName(String className) { + placeFlagHasClassName = true; + this.className = className; + } + + @Override + public String toString() { + if (name != null) { + return super.toString() + " (" + name + ")"; + } else { + return super.toString(); + } + } + + @Override + public CLIPACTIONS getClipActions() { + if (placeFlagHasClipActions) { + return clipActions; + } else { + return null; + } + } +}