some more ByteArraRange objects instead of reading them to new byte array, method to read netstings (length + characters) in SwfInputStream

This commit is contained in:
honfika@gmail.com
2015-07-27 11:21:26 +02:00
parent c9f1f45ed5
commit c5d960f10b
18 changed files with 124 additions and 85 deletions

View File

@@ -1028,7 +1028,7 @@ public final class SWF implements SWFContainerItem, Timelined {
SWFInputStream sis = new SWFInputStream(this, uncompressedData);
dumpInfo = new DumpInfoSwfNode(this, "rootswf", "", null, 0, 0);
sis.dumpInfo = dumpInfo;
sis.readBytesEx(3, "signature"); // skip siganture
sis.skipBytesEx(3, "signature"); // skip siganture
version = sis.readUI8("version");
fileSize = sis.readUI32("fileSize");
dumpInfo.lengthBytes = fileSize;

View File

@@ -277,6 +277,7 @@ import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -467,7 +468,7 @@ public class SWFInputStream implements AutoCloseable {
}
/**
* Reads one string value from the stream
* Reads one null terminated string value from the stream
*
* @param name
* @return String value
@@ -487,6 +488,37 @@ public class SWFInputStream implements AutoCloseable {
}
}
/**
* Reads one netstring (length + string) value from the stream
*
* @param name
* @return String value
* @throws IOException
*/
public String readNetString(String name) throws IOException {
newDumpLevel(name, "string");
int length = readEx();
String ret = new String(readBytesInternalEx(length));
endDumpLevel();
return ret;
}
/**
* Reads one netstring (length + string) value from the stream
*
* @param name
* @param charset
* @return String value
* @throws IOException
*/
public String readNetString(String name, Charset charset) throws IOException {
newDumpLevel(name, "string");
int length = readEx();
String ret = new String(readBytesInternalEx(length), charset);
endDumpLevel();
return ret;
}
/**
* Reads one UI32 (Unsigned 32bit integer) value from the stream
*
@@ -703,6 +735,7 @@ public class SWFInputStream implements AutoCloseable {
if (count <= 0) {
return BYTE_ARRAY_EMPTY;
}
newDumpLevel(name, "bytes");
byte[] ret = readBytesInternalEx(count);
endDumpLevel();
@@ -721,6 +754,7 @@ public class SWFInputStream implements AutoCloseable {
if (count <= 0) {
return ByteArrayRange.EMPTY;
}
newDumpLevel(name, "bytes");
int startPos = (int) getPos();
skipBytesEx(count);
@@ -770,6 +804,23 @@ public class SWFInputStream implements AutoCloseable {
informListeners();
}
/**
* Skip bytes from the stream
*
* @param count Number of bytes to skip
* @param name
* @throws IOException
*/
public void skipBytesEx(long count, String name) throws IOException {
if (count <= 0) {
return;
}
newDumpLevel(name, "bytes");
skipBytesEx(count);
endDumpLevel();
}
/**
* Skip bytes from the stream
*
@@ -1489,7 +1540,7 @@ public class SWFInputStream implements AutoCloseable {
}
if (sis.available() > 0) {
ret.remainingData = sis.readBytesEx(sis.available(), "remaining");
ret.remainingData = sis.readByteRangeEx(sis.available(), "remaining");
}
} catch (IOException ex) {
logger.log(Level.SEVERE, "Error during tag reading. SWF: " + swf.getShortFileName() + " ID: " + tag.getId() + " name: " + tag.getName() + " pos: " + data.getPos(), ex);
@@ -3344,6 +3395,7 @@ public class SWFInputStream implements AutoCloseable {
for (int i = 0; i < colorTableSize + 1; i++) {
ret.colorTableRGB[i] = readRGBInt("colorTableRGB");
}
int dataLen = 0;
for (int y = 0; y < bitmapHeight; y++) {
int x = 0;
@@ -3355,6 +3407,7 @@ public class SWFInputStream implements AutoCloseable {
x++;
}
}
ret.colorMapPixelData = readBytesEx(dataLen, "colorMapPixelData");
endDumpLevel();
return ret;
@@ -3444,6 +3497,7 @@ public class SWFInputStream implements AutoCloseable {
for (int i = 0; i < colorTableSize + 1; i++) {
ret.colorTableRGB[i] = readRGBAInt("colorTableRGB");
}
int dataLen = 0;
for (int y = 0; y < bitmapHeight; y++) {
int x = 0;
@@ -3455,7 +3509,8 @@ public class SWFInputStream implements AutoCloseable {
x++;
}
}
ret.colorMapPixelData = readBytesEx(dataLen, "");
ret.colorMapPixelData = readBytesEx(dataLen, "colorMapPixelData");
endDumpLevel();
return ret;
}

View File

@@ -80,6 +80,7 @@ import com.jpexs.helpers.utf8.Utf8Helper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -167,7 +168,7 @@ public class SWFOutputStream extends OutputStream {
}
/**
* Writes String value to the stream
* Writes null terminated string value to the stream
*
* @param value String value
* @throws IOException
@@ -184,6 +185,31 @@ public class SWFOutputStream extends OutputStream {
write(0);
}
/**
* Writes netstring (length + string) value to the stream
*
* @param value String value
* @throws IOException
*/
public void writeNetString(String value) throws IOException {
byte[] data = value.getBytes();
writeUI8(data.length);
write(data);
}
/**
* Writes netstring (length + string) value to the stream
*
* @param value String value
* @param charset
* @throws IOException
*/
public void writeNetString(String value, Charset charset) throws IOException {
byte[] data = value.getBytes(charset);
writeUI8(data.length);
write(data);
}
/**
* Writes UI32 (Unsigned 32bit integer) value to the stream
*

View File

@@ -110,10 +110,10 @@ public class DefineBitsTag extends ImageTag implements TagChangedListener {
public InputStream getOriginalImageData() {
if (swf.getJtt() != null) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
byte[] jttdata = swf.getJtt().jpegData;
if (jttdata.length != 0) {
ByteArrayRange jttdata = swf.getJtt().jpegData;
if (jttdata.getLength() != 0) {
int jttErrorLength = hasErrorHeader(jttdata) ? 4 : 0;
baos.write(jttdata, jttErrorLength, jttdata.length - jttErrorLength);
baos.write(jttdata.getArray(), jttdata.getPos() + jttErrorLength, jttdata.getLength() - jttErrorLength);
}
int errorLength = hasErrorHeader(jpegData) ? 4 : 0;

View File

@@ -135,11 +135,10 @@ public class DefineFont2Tag extends FontTag {
fontFlagsItalic = sis.readUB(1, "fontFlagsItalic") == 1;
fontFlagsBold = sis.readUB(1, "fontFlagsBold") == 1;
languageCode = sis.readLANGCODE("languageCode");
int fontNameLen = sis.readUI8("fontNameLen");
if (swf.version >= 6) {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"), Utf8Helper.charset);
fontName = sis.readNetString("fontName", Utf8Helper.charset);
} else {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"));
fontName = sis.readNetString("fontName");
}
int numGlyphs = sis.readUI16("numGlyphs");
long[] offsetTable = new long[numGlyphs];
@@ -212,9 +211,7 @@ public class DefineFont2Tag extends FontTag {
sos.writeUB(1, fontFlagsItalic ? 1 : 0);
sos.writeUB(1, fontFlagsBold ? 1 : 0);
sos.writeLANGCODE(languageCode);
byte[] fontNameBytes = Utf8Helper.getBytes(fontName);
sos.writeUI8(fontNameBytes.length);
sos.write(fontNameBytes);
sos.writeNetString(fontName, Utf8Helper.charset); // todo: check swf version and write non utf-8 for version < 6
int numGlyphs = glyphShapeTable.size();
sos.writeUI16(numGlyphs);

View File

@@ -128,11 +128,10 @@ public class DefineFont3Tag extends FontTag {
fontFlagsItalic = sis.readUB(1, "fontFlagsItalic") == 1;
fontFlagsBold = sis.readUB(1, "fontFlagsBold") == 1;
languageCode = sis.readLANGCODE("languageCode");
int fontNameLen = sis.readUI8("fontNameLen");
if (swf.version >= 6) {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"), Utf8Helper.charset);
fontName = sis.readNetString("fontName", Utf8Helper.charset);
} else {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"));
fontName = sis.readNetString("fontName");
}
int numGlyphs = sis.readUI16("numGlyphs");
long[] offsetTable = new long[numGlyphs];
@@ -220,9 +219,7 @@ public class DefineFont3Tag extends FontTag {
sos.writeUB(1, fontFlagsItalic ? 1 : 0);
sos.writeUB(1, fontFlagsBold ? 1 : 0);
sos.writeLANGCODE(languageCode);
byte[] fontNameBytes = Utf8Helper.getBytes(fontName);
sos.writeUI8(fontNameBytes.length);
sos.write(fontNameBytes);
sos.writeNetString(fontName, Utf8Helper.charset); // todo: check swf version and write non utf-8 for version < 6
sos.writeUI16(numGlyphs);
for (long offset : offsetTable) {

View File

@@ -93,11 +93,10 @@ public class DefineFontInfo2Tag extends Tag implements CharacterIdTag {
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
fontID = sis.readUI16("fontID");
int fontNameLen = sis.readUI8("fontNameLen");
if (swf.version >= 6) {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"), Utf8Helper.charset);
fontName = sis.readNetString("fontName", Utf8Helper.charset);
} else {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"));
fontName = sis.readNetString("fontName");
}
reserved = (int) sis.readUB(2, "reserved");
fontFlagsSmallText = sis.readUB(1, "fontFlagsSmallText") == 1;
@@ -123,9 +122,7 @@ public class DefineFontInfo2Tag extends Tag implements CharacterIdTag {
@Override
public void getData(SWFOutputStream sos) throws IOException {
sos.writeUI16(fontID);
byte[] fontNameBytes = Utf8Helper.getBytes(fontName);
sos.writeUI8(fontNameBytes.length);
sos.write(fontNameBytes);
sos.writeNetString(fontName, Utf8Helper.charset); // todo: check swf version and write non utf-8 for version < 6
sos.writeUB(2, reserved);
sos.writeUB(1, fontFlagsSmallText ? 1 : 0);
sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0);

View File

@@ -89,11 +89,10 @@ public class DefineFontInfoTag extends Tag implements CharacterIdTag {
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
fontId = sis.readUI16("fontId");
int fontNameLen = sis.readUI8("fontNameLen");
if (swf.version >= 6) {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"), Utf8Helper.charset);
fontName = sis.readNetString("fontName", Utf8Helper.charset);
} else {
fontName = new String(sis.readBytesEx(fontNameLen, "fontName"));
fontName = sis.readNetString("fontName");
}
reserved = (int) sis.readUB(2, "reserved");
fontFlagsSmallText = sis.readUB(1, "fontFlagsSmallText") == 1;
@@ -121,9 +120,7 @@ public class DefineFontInfoTag extends Tag implements CharacterIdTag {
@Override
public void getData(SWFOutputStream sos) throws IOException {
sos.writeUI16(fontId);
byte[] fontNameBytes = Utf8Helper.getBytes(fontName);
sos.writeUI8(fontNameBytes.length);
sos.write(fontNameBytes);
sos.writeNetString(fontName, Utf8Helper.charset); // todo: check swf version and write non utf-8 for version < 6
sos.writeUB(2, reserved);
sos.writeUB(1, fontFlagsSmallText ? 1 : 0);
sos.writeUB(1, fontFlagsShiftJIS ? 1 : 0);

View File

@@ -19,7 +19,6 @@ 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 com.jpexs.decompiler.flash.types.annotations.HideInRawEdit;
import com.jpexs.helpers.ByteArrayRange;
import java.io.IOException;
@@ -29,8 +28,7 @@ public class JPEGTablesTag extends Tag {
public static final String NAME = "JPEGTables";
@HideInRawEdit
public byte[] jpegData;
public ByteArrayRange jpegData;
/**
* Constructor
@@ -39,7 +37,7 @@ public class JPEGTablesTag extends Tag {
*/
public JPEGTablesTag(SWF swf) {
super(swf, ID, NAME, null);
jpegData = SWFInputStream.BYTE_ARRAY_EMPTY;
jpegData = ByteArrayRange.EMPTY;
}
public JPEGTablesTag(SWFInputStream sis, ByteArrayRange data) throws IOException {
@@ -49,7 +47,7 @@ public class JPEGTablesTag extends Tag {
@Override
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
jpegData = sis.readBytesEx(sis.available(), "jpegData");
jpegData = sis.readByteRangeEx(sis.available(), "jpegData");
}
/**

View File

@@ -318,6 +318,7 @@ public class PlaceObject4Tag extends PlaceObjectTypeTag implements ASMSourceCont
if (placeFlagHasClipActions) {
clipActions = sis.readCLIPACTIONS(swf, this, "clipActions");
}
amfData = sis.readBytesEx(sis.available(), "amfData");
}

View File

@@ -93,7 +93,7 @@ public abstract class Tag implements NeedsCharacters, Exportable, Serializable {
private final HashSet<TagChangedListener> listeners = new HashSet<>();
@Internal
public byte[] remainingData;
public ByteArrayRange remainingData;
/**
* Constructor

View File

@@ -58,9 +58,7 @@ public class DefineExternalGradient extends Tag {
sos.writeUI16(gradientId);
sos.writeUI16(bitmapsFormat);
sos.writeUI16(gradientSize);
byte[] fileNameBytes = fileName.getBytes();
sos.writeUI8(fileNameBytes.length);
sos.write(fileNameBytes);
sos.writeNetString(fileName);
}
/**
@@ -80,7 +78,6 @@ public class DefineExternalGradient extends Tag {
gradientId = sis.readUI16("gradientId");
bitmapsFormat = sis.readUI16("bitmapsFormat");
gradientSize = sis.readUI16("gradientSize");
int fileNameLen = sis.readUI8("fileNameLen");
fileName = new String(sis.readBytesEx(fileNameLen, "fileName"));
fileName = sis.readNetString("fileName");
}
}

View File

@@ -61,9 +61,7 @@ public class DefineExternalImage extends Tag {
sos.writeUI16(bitmapFormat);
sos.writeUI16(targetWidth);
sos.writeUI16(targetHeight);
byte[] fileNameBytes = fileName.getBytes();
sos.writeUI8(fileNameBytes.length);
sos.write(fileNameBytes);
sos.writeNetString(fileName);
}
/**
@@ -84,8 +82,6 @@ public class DefineExternalImage extends Tag {
bitmapFormat = sis.readUI16("bitmapFormat");
targetWidth = sis.readUI16("targetWidth");
targetHeight = sis.readUI16("targetHeight");
int fileNameLen = sis.readUI8("fileNameLen");
fileName = new String(sis.readBytesEx(fileNameLen, "fileName"));
fileName = sis.readNetString("fileName");
}
}

View File

@@ -65,12 +65,8 @@ public class DefineExternalImage2 extends Tag {
sos.writeUI16(bitmapFormat);
sos.writeUI16(targetWidth);
sos.writeUI16(targetHeight);
byte[] exportNameBytes = exportName.getBytes();
sos.writeUI8(exportNameBytes.length);
sos.write(exportNameBytes);
byte[] fileNameBytes = fileName.getBytes();
sos.writeUI8(fileNameBytes.length);
sos.write(fileNameBytes);
sos.writeNetString(exportName);
sos.writeNetString(fileName);
if (extraData != null) {
sos.write(extraData);
}
@@ -94,10 +90,8 @@ public class DefineExternalImage2 extends Tag {
bitmapFormat = sis.readUI16("bitmapFormat");
targetWidth = sis.readUI16("targetWidth");
targetHeight = sis.readUI16("targetHeight");
int exportNameLen = sis.readUI8("exportNameLen");
exportName = new String(sis.readBytesEx(exportNameLen, "exportName"));
int fileNameLen = sis.readUI8("fileNameLen");
fileName = new String(sis.readBytesEx(fileNameLen, "fileName"));
exportName = sis.readNetString("exportName");
fileName = sis.readNetString("fileName");
if (sis.available() > 0) { //there is usually one zero byte, bod knows why
extraData = sis.readBytesEx(sis.available(), "extraData");
}

View File

@@ -68,12 +68,8 @@ public class DefineExternalSound extends Tag {
sos.writeUI32(sampleRate);
sos.writeUI32(sampleCount);
sos.writeUI32(seekSample);
byte[] exportNameBytes = exportName.getBytes();
sos.writeUI8(exportNameBytes.length);
sos.write(exportNameBytes);
byte[] fileNameBytes = fileName.getBytes();
sos.writeUI8(fileNameBytes.length);
sos.write(fileNameBytes);
sos.writeNetString(exportName);
sos.writeNetString(fileName);
}
/**
@@ -97,10 +93,8 @@ public class DefineExternalSound extends Tag {
sampleRate = sis.readUI32("sampleRate");
sampleCount = sis.readUI32("sampleCount");
seekSample = sis.readUI32("seekSample");
int exportNameLen = sis.readUI8("exportNameLen");
exportName = new String(sis.readBytesEx(exportNameLen, "exportName"));
int fileNameLen = sis.readUI8("fileNameLen");
fileName = new String(sis.readBytesEx(fileNameLen, "fileName"));
exportName = sis.readNetString("exportName");
fileName = sis.readNetString("fileName");
}
}

View File

@@ -69,9 +69,7 @@ public class DefineExternalStreamSound extends Tag {
sos.writeUI32(seekSample);
sos.writeUI32(startFrame);
sos.writeUI32(lastFrame);
byte[] fileNameBytes = fileName.getBytes();
sos.writeUI8(fileNameBytes.length);
sos.write(fileNameBytes);
sos.writeNetString(fileName);
}
/**
@@ -96,8 +94,6 @@ public class DefineExternalStreamSound extends Tag {
seekSample = sis.readUI32("seekSample");
startFrame = sis.readUI32("startFrame");
lastFrame = sis.readUI32("lastFrame");
int fileNameLen = sis.readUI8("fileNameLen");
fileName = new String(sis.readBytesEx(fileNameLen, "fileName"));
fileName = sis.readNetString("fileName");
}
}

View File

@@ -74,9 +74,7 @@ public class ExporterInfo extends Tag {
sos.writeUI16(bitmapFormat);
sos.writeUI8(prefix.length);
sos.write(prefix);
byte[] swfNameBytes = swfName.getBytes();
sos.writeUI8(swfNameBytes.length);
sos.write(swfNameBytes);
sos.writeNetString(swfName);
if (codeOffsets != null) {
sos.writeUI16(codeOffsets.size());
for (long l : codeOffsets) {
@@ -106,8 +104,7 @@ public class ExporterInfo extends Tag {
bitmapFormat = sis.readUI16("bitmapFormat");
int prefixLen = sis.readUI8("prefixLen");
prefix = sis.readBytesEx(prefixLen, "prefix");
int swfNameLen = sis.readUI8("swfNameLen");
swfName = new String(sis.readBytesEx(swfNameLen, "swfName"));
swfName = sis.readNetString("swfName");
if (sis.available() > 0) // (version >= 0x401) //?
{
codeOffsets = new ArrayList<>();

View File

@@ -72,9 +72,7 @@ public class FontTextureInfo extends Tag {
public void getData(SWFOutputStream sos) throws IOException {
sos.writeUI32(textureID);
sos.writeUI16(textureFormat);
byte[] fileNameBytes = fileName.getBytes();
sos.writeUI8(fileNameBytes.length);
sos.write(fileNameBytes);
sos.writeNetString(fileName);
sos.writeUI16(textureWidth);
sos.writeUI16(textureHeight);
sos.writeUI8(padPixels);
@@ -105,8 +103,7 @@ public class FontTextureInfo extends Tag {
public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException {
textureID = sis.readUI32("textureID");
textureFormat = sis.readUI16("textureFormat");
int fileNameLen = sis.readUI8("fileNameLen");
fileName = new String(sis.readBytesEx(fileNameLen, "fileName"));
fileName = sis.readNetString("fileName");
textureWidth = sis.readUI16("textureWidth");
textureHeight = sis.readUI16("textureHeight");
padPixels = sis.readUI8("padPixels");