version info reader implemented

This commit is contained in:
Dmitry Jemerov
2013-02-20 20:14:10 +01:00
parent bc0e5ac18a
commit 8459153c5f
9 changed files with 307 additions and 132 deletions
@@ -18,6 +18,7 @@
package com.pme.exe;
import com.pme.util.BitsUtil;
import com.pme.util.OffsetTrackingInputStream;
import java.io.*;
import java.util.ArrayList;
@@ -356,6 +357,40 @@ public abstract class Bin {
}
}
public static class Padding extends Bin {
private int myBytes;
public Padding(int bytes) {
super("Padding");
myBytes = bytes;
}
@Override
public long sizeInBytes() {
throw new UnsupportedOperationException();
}
@Override
public void read(DataInput stream) throws IOException {
if (stream instanceof OffsetTrackingInputStream) {
long offset = ((OffsetTrackingInputStream) stream).getOffset();
int offsetMask = myBytes-1;
long offsetBits = offset & offsetMask;
if (offsetBits > 0) {
stream.skipBytes((int) (myBytes - offsetBits));
}
}
}
@Override
public void write(DataOutput stream) throws IOException {
}
@Override
public void report(OutputStreamWriter writer) throws IOException {
}
}
public static class Txt extends Bin {
private StringBuffer myBuffer = new StringBuffer();
private Bin.Value mySize;
@@ -367,6 +402,7 @@ public abstract class Bin {
mySize = new DWord("").setValue(bytes.length);
setValue();
}
public Txt(String name, String string) {
super(name);
myBytes = new byte[string.length() * 2];
@@ -423,6 +459,44 @@ public abstract class Bin {
}
}
public static class WChar extends Bin {
private String myValue;
public WChar(String name) {
super(name);
}
@Override
public long sizeInBytes() {
throw new UnsupportedOperationException();
}
@Override
public void read(DataInput stream) throws IOException {
StringBuilder valueBuilder = new StringBuilder();
while(true) {
char c = BitsUtil.readChar(stream);
if (c == 0) break;
valueBuilder.append(c);
}
myValue = valueBuilder.toString();
}
@Override
public void write(DataOutput stream) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void report(OutputStreamWriter writer) throws IOException {
_report(writer, myValue);
}
public String getValue() {
return myValue;
}
}
public static class Bytes extends Bin {
private byte[] myBytes;
private Value myStartOffset;
@@ -18,26 +18,32 @@
package com.pme.exe.res.vi;
import com.pme.exe.Bin;
import com.pme.util.OffsetTrackingInputStream;
import java.io.DataInput;
import java.io.IOException;
/**
* Date: May 10, 2006
* Time: 8:01:15 PM
*/
public class StringFileInfo extends Bin.Structure {
public StringFileInfo() {
super("StringFileInfo");
addMember( new Word( "wLength" ) );
addMember( new Word( "wValueLength" ) );
addMember( new Word( "wType" ) );
addMember( new Bytes( "Bytes", 30 ) );
addMember(new Word("wLength"));
addMember(new Word("wValueLength"));
addMember(new Word("wType"));
addMember(new WChar("szKey"));
addMember(new Padding(4));
}
public void readWithPadding( DataInput stream, long offset ) throws IOException {
read( stream );
StringTableReader stringTableReader = new StringTableReader();
stringTableReader.readWithPadding( stream, offset + sizeInBytes() );
addMember( stringTableReader );
@Override
public void read(DataInput stream) throws IOException {
OffsetTrackingInputStream inputStream = (OffsetTrackingInputStream) stream;
long startOffset = inputStream.getOffset();
super.read(stream);
long length = getValue("wLength");
int i = 0;
while(inputStream.getOffset() < startOffset + length) {
StringTable stringTableReader = new StringTable("StringTable" + (i++));
stringTableReader.read(inputStream);
addMember(stringTableReader);
}
}
}
@@ -0,0 +1,49 @@
/*
* Copyright 2006 ProductiveMe Inc.
* Copyright 2013 JetBrains s.r.o.
*
* Licensed 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 com.pme.exe.res.vi;
import com.pme.exe.Bin;
import com.pme.util.OffsetTrackingInputStream;
import java.io.DataInput;
import java.io.IOException;
public class StringTable extends Bin.Structure {
public StringTable(String name) {
super(name);
addMember(new Word("wLength"));
addMember(new Word("wValueLength"));
addMember(new Word("wType"));
addMember(new WChar("szKey"));
addMember(new Padding(4));
}
public void read(DataInput stream) throws IOException {
OffsetTrackingInputStream inputStream = (OffsetTrackingInputStream) stream;
long startOffset = inputStream.getOffset();
super.read(stream);
long length = getValue("wLength");
int i = 0;
while(inputStream.getOffset() < startOffset + length) {
StringTableEntry stringTableEntry = new StringTableEntry();
stringTableEntry.read(inputStream);
addMember(stringTableEntry);
}
}
}
@@ -18,58 +18,34 @@
package com.pme.exe.res.vi;
import com.pme.exe.Bin;
import com.pme.util.OffsetTrackingInputStream;
import java.io.*;
import java.util.ArrayList;
/**
* Date: May 10, 2006
* Time: 8:26:03 PM
*/
public class StringTableEntry extends Bin.Structure {
public StringTableEntry(String key) {
super(key);
public StringTableEntry() {
super("<unnamed>");
addMember(new Word("wLength"));
addMember(new Word("wValueLength"));
addMember(new Word("wType"));
addMember(new Bytes("key", key.length() * 2));
addMember(new WChar("szKey"));
addMember(new Padding(4));
addMember(new WChar("Value"));
addMember(new Padding(4));
}
public void readWithPadding(DataInput stream, long offset) throws IOException {
read(stream);
long off = offset + sizeInBytes();
Bytes padding = new Bytes("Padding", off % 8);
padding.read(stream);
addMember(padding);
ArrayList list = new ArrayList();
for(int i = 0;;++i){
Word word = new Word( "" + i );
word.read( stream );
list.add( word );
if ( word.getValue() == 0 ) break;
}
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(list.size() * 2);
DataOutputStream bytesStream = new DataOutputStream( byteArrayOutputStream );
for (int i = 0; i < list.size(); ++i) {
Word word = (Word)list.get(i);
word.write( bytesStream );
}
bytesStream.close();
@Override
public void read(DataInput stream) throws IOException {
super.read(stream);
WChar key = (WChar) getMember("szKey");
setName(key.getValue());
}
Txt txt = new Txt("Value", byteArrayOutputStream.toByteArray());
System.out.println( txt.getText() );
addMember( txt );
offset += sizeInBytes();
System.out.println( "" + offset % 8 );
System.out.println( "" + offset % 4 );
System.out.println( "" + offset % 16 );
long r = offset % 8;
if ( r > 0 ){
Bytes padding2 = new Bytes( "Padding2", r );
padding2.read( stream );
addMember( padding2 );
}
@Override
public String toString() {
WChar key = (WChar) getMember("szKey");
WChar value = (WChar) getMember("Value");
return key.getValue() + " = " + value.getValue();
}
}
@@ -1,57 +0,0 @@
/*
* Copyright 2006 ProductiveMe Inc.
* Copyright 2013 JetBrains s.r.o.
*
* Licensed 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 com.pme.exe.res.vi;
import com.pme.exe.Bin;
import java.io.DataInput;
import java.io.IOException;
/**
* Date: May 10, 2006
* Time: 8:09:42 PM
*/
public class StringTableReader extends Bin.Structure{
public StringTableReader() {
super("StringTable");
addMember( new Word( "wLength" ) );
addMember( new Word( "wValueLength" ) );
addMember( new Word( "wType" ) );
addMember( new Bytes( "Bytes", 18 ) );
}
public void readWithPadding( DataInput stream, long offset ) throws IOException {
read(stream);
StringTableEntry stringTableEntry = new StringTableEntry("CompanyName");
stringTableEntry.readWithPadding( stream, offset + sizeInBytes() );
addMember( stringTableEntry );
StringTableEntry desc = new StringTableEntry("FileDescription");
desc.readWithPadding( stream, offset + sizeInBytes() + stringTableEntry.sizeInBytes() );
addMember( desc );
StringTableEntry fileVersion = new StringTableEntry("FileVersion");
fileVersion.readWithPadding( stream, offset + sizeInBytes() + stringTableEntry.sizeInBytes() + desc.sizeInBytes() );
addMember( fileVersion );
StringTableEntry internalName = new StringTableEntry("InternalName");
internalName.readWithPadding( stream, offset + sizeInBytes() + stringTableEntry.sizeInBytes() + desc.sizeInBytes() + fileVersion.sizeInBytes() );
addMember( internalName );
}
}
@@ -22,22 +22,12 @@ import com.pme.exe.Bin;
import java.io.DataInput;
import java.io.IOException;
/**
* Date: May 10, 2006
* Time: 1:33:34 PM
*/
public class VersionInfoReader extends Bin.Structure {
public VersionInfoReader() {
public class VersionInfo extends Bin.Structure {
public VersionInfo() {
super("VersionInfo");
addMember( new Word("wLength") );
addMember( new Bytes( "Bytes", 38 ) );
addMember( new FixedFileInfo() );
}
public void read(DataInput stream) throws IOException {
super.read(stream);
StringFileInfo stringFileInfo = new StringFileInfo();
stringFileInfo.readWithPadding( stream, sizeInBytes() );
addMember( stringFileInfo );
addMember(new Word("wLength"));
addMember(new Bytes("Bytes", 38));
addMember(new FixedFileInfo());
addMember(new StringFileInfo());
}
}
@@ -26,7 +26,8 @@ import com.pme.exe.res.RawResource;
import com.pme.exe.res.StringTable;
import com.pme.exe.res.bmp.PictureResourceInjector;
import com.pme.exe.res.icon.IconResourceInjector;
import com.pme.exe.res.vi.VersionInfoReader;
import com.pme.exe.res.vi.VersionInfo;
import com.pme.util.OffsetTrackingInputStream;
import java.io.*;
@@ -148,8 +149,8 @@ public class LauncherGenerator {
Bin.Bytes viBytes = viDir.getRawResource( 0 ).getBytes();
ByteArrayInputStream bytesStream = new ByteArrayInputStream(viBytes.getBytes());
VersionInfoReader viReader = new VersionInfoReader();
viReader.read(new DataInputStream(bytesStream));
VersionInfo viReader = new VersionInfo();
viReader.read(new OffsetTrackingInputStream(new DataInputStream(bytesStream)));
reader.resetOffsets(0);
@@ -17,6 +17,9 @@
package com.pme.util;
import java.io.DataInput;
import java.io.IOException;
/**
* Date: Mar 30, 2006
* Time: 7:10:10 PM
@@ -59,5 +62,11 @@ public class BitsUtil {
public static String byteToHexString( int value ){
return toHexString( value, 2 );
}
public static char readChar(DataInput stream) throws IOException {
int b1 = stream.readByte();
int b2 = stream.readByte();
return (char) (b1 + (b2 << 8));
}
}
@@ -0,0 +1,127 @@
/*
* Copyright 2006 ProductiveMe Inc.
* Copyright 2013 JetBrains s.r.o.
*
* Licensed 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 com.pme.util;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.IOException;
/**
* @author yole
*/
public class OffsetTrackingInputStream implements DataInput {
private final DataInputStream myBaseStream;
private long myOffset = 0;
public OffsetTrackingInputStream(DataInputStream baseStream) {
myBaseStream = baseStream;
}
public long getOffset() {
return myOffset;
}
@Override
public void readFully(byte[] b) throws IOException {
myBaseStream.readFully(b);
myOffset += b.length;
}
@Override
public void readFully(byte[] b, int off, int len) throws IOException {
myBaseStream.readFully(b, off, len);
myOffset += len;
}
@Override
public int skipBytes(int n) throws IOException {
int skipped = myBaseStream.skipBytes(n);
myOffset += skipped;
return skipped;
}
@Override
public boolean readBoolean() throws IOException {
myOffset++;
return myBaseStream.readBoolean();
}
@Override
public byte readByte() throws IOException {
myOffset++;
return myBaseStream.readByte();
}
@Override
public int readUnsignedByte() throws IOException {
myOffset++;
return myBaseStream.readUnsignedByte();
}
@Override
public short readShort() throws IOException {
myOffset += 2;
return myBaseStream.readShort();
}
@Override
public int readUnsignedShort() throws IOException {
myOffset += 2;
return myBaseStream.readUnsignedShort();
}
@Override
public char readChar() throws IOException {
myOffset += 2;
return myBaseStream.readChar();
}
@Override
public int readInt() throws IOException {
myOffset += 4;
return myBaseStream.readInt();
}
@Override
public long readLong() throws IOException {
myOffset += 8;
return myBaseStream.readLong();
}
@Override
public float readFloat() throws IOException {
myOffset += 4;
return myBaseStream.readFloat();
}
@Override
public double readDouble() throws IOException {
myOffset += 8;
return myBaseStream.readDouble();
}
@Override
public String readLine() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public String readUTF() throws IOException {
throw new UnsupportedOperationException();
}
}