Issue #367 Search in memory: save(export) SWFs

few refactorings
This commit is contained in:
Jindra Petk
2013-09-10 07:46:16 +02:00
parent 9696b91d4d
commit 17a5e75f1a
17 changed files with 133 additions and 48 deletions

View File

@@ -1,5 +1,6 @@
package com.jpexs.browsers.cache;
import com.jpexs.helpers.LimitedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

View File

@@ -352,7 +352,7 @@ public class SWF {
frameRate = sis.readUI8();
frameCount = sis.readUI16();
if (checkOnly) {
return;
//return;
}
tags = sis.readTagList(this, 0, parallelRead, true, !checkOnly);
if (!checkOnly) {

View File

@@ -179,7 +179,7 @@ public class SWFInputStream extends InputStream {
public int read(byte[] b, int off, int len) throws IOException {
int bytesRead = super.read(b, off, len);
bitPos = 0;
pos += bytesRead;
//pos += bytesRead;
return bytesRead;
}
@@ -528,7 +528,7 @@ public class SWFInputStream extends InputStream {
}
public List<Action> readActionList(List<DisassemblyListener> listeners, long containerSWFOffset, ReReadableInputStream rri, int maxlen, String path) throws IOException {
return ActionListReader.readActionList(listeners, containerSWFOffset, rri, version, rri.getPos(), rri.getPos() + maxlen, path);
return ActionListReader.readActionList(listeners, containerSWFOffset, rri, version, (int)rri.getPos(), (int)rri.getPos() + maxlen, path);
}
private static void dumpTag(PrintStream out, int version, Tag tag, int level) {

View File

@@ -635,14 +635,14 @@ public class ActionListReader {
if (deobfuscate) {
top = stack.pop();
}
int nip = rri.getPos() + aif.getJumpOffset();
int nip = (int)rri.getPos() + aif.getJumpOffset();
if (decideBranch) {
System.out.print("newip " + nip + ", ");
System.out.print("Action: jump(j),ignore(i),compute(c)?");
String next = sc.next();
if (next.equals("j")) {
newip = rri.getPos() + aif.getJumpOffset();
newip = (int)rri.getPos() + aif.getJumpOffset();
rri.setPos(newip);
} else if (next.equals("i")) {
@@ -655,7 +655,7 @@ public class ActionListReader {
System.err.print("is compiletime -> ");
}
if (EcmaScript.toBoolean(top.getResult())) {
newip = rri.getPos() + aif.getJumpOffset();
newip = (int)rri.getPos() + aif.getJumpOffset();
aif.jumpUsed = true;
if (aif.ignoreUsed) {
aif.compileTime = false;
@@ -679,7 +679,7 @@ public class ActionListReader {
goaif = true;
}
} else if (a instanceof ActionJump) {
newip = rri.getPos() + ((ActionJump) a).getJumpOffset();
newip = (int)rri.getPos() + ((ActionJump) a).getJumpOffset();
} else if (!(a instanceof GraphSourceItemContainer)) {
if (deobfuscate) {
//return in for..in, TODO:Handle this better way
@@ -793,8 +793,8 @@ public class ActionListReader {
if ((!stateChanged) && curVisited > 1) {
List<Integer> branches = new ArrayList<>();
branches.add(rri.getPos() + aif.getJumpOffset());
branches.add(rri.getPos());
branches.add((int)rri.getPos() + aif.getJumpOffset());
branches.add((int)rri.getPos());
for (int br : branches) {
int visc = 0;
if (visited.containsKey(br)) {
@@ -811,10 +811,10 @@ public class ActionListReader {
break loopip;
}
int oldPos = rri.getPos();
int oldPos = (int)rri.getPos();
@SuppressWarnings("unchecked")
Stack<GraphTargetItem> substack = (Stack<GraphTargetItem>) stack.clone();
deobfustaceActionListAtPosRecursive(listeners, output, containers, containerSWFOffset, prepareLocalBranch(localData), substack, cpool, sis, rri, rri.getPos() + aif.getJumpOffset(), ret, startIp, endip, path, visited, indeterminate, decisionStates, version);
deobfustaceActionListAtPosRecursive(listeners, output, containers, containerSWFOffset, prepareLocalBranch(localData), substack, cpool, sis, rri, (int)rri.getPos() + aif.getJumpOffset(), ret, startIp, endip, path, visited, indeterminate, decisionStates, version);
rri.setPos(oldPos);
}
prevIp = ip;

View File

@@ -69,7 +69,7 @@ public class ActionDefineFunction extends Action implements GraphSourceItemConta
long endPos = sis.getPos();
//code = new ArrayList<Action>();
hdrSize = endPos - startPos;
int posBef2 = rri.getPos();
int posBef2 = (int)rri.getPos();
//code = sis.readActionList(rri.getPos(), getFileAddress() + hdrSize, rri, codeSize);
//rri.setPos(posBef2 + codeSize);
}

View File

@@ -101,7 +101,7 @@ public class ActionDefineFunction2 extends Action implements GraphSourceItemCont
long posAfter = sis.getPos();
hdrSize = posAfter - posBef;
//code = new ArrayList<Action>();
int posBef2 = rri.getPos();
int posBef2 = (int)rri.getPos();
//code = sis.readActionList(rri.getPos(), getFileAddress() + hdrSize, rri, codeSize);
//rri.setPos(posBef2 + codeSize);
}

View File

@@ -21,6 +21,7 @@ import com.jpexs.browsers.cache.CacheImplementation;
import com.jpexs.browsers.cache.CacheReader;
import com.jpexs.decompiler.flash.Configuration;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.ReReadableInputStream;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
@@ -61,7 +62,7 @@ public class LoadFromCacheFrame extends AppFrame implements ActionListener {
private List<CacheEntry> entries;
public LoadFromCacheFrame() {
setSize(800, 600);
setSize(900, 600);
View.setWindowIcon(this);
View.centerScreen(this);
setTitle(translate("dialog.title"));
@@ -184,8 +185,7 @@ public class LoadFromCacheFrame extends AppFrame implements ActionListener {
private void openSWF() {
CacheEntry en = list.getSelectedValue();
if (en != null) {
BufferedInputStream str = new BufferedInputStream(en.getResponseDataStream());
str.mark(Integer.MAX_VALUE);
ReReadableInputStream str = new ReReadableInputStream(en.getResponseDataStream());
Main.openFile(entryToFileName(en), str);
}
}
@@ -231,7 +231,7 @@ public class LoadFromCacheFrame extends AppFrame implements ActionListener {
Helper.saveStream(selected.get(0).getResponseDataStream(), file);
} else {
for (CacheEntry sel : selected) {
Helper.saveStream(selected.get(0).getResponseDataStream(), new File(file, entryToFileName(sel)));
Helper.saveStream(sel.getResponseDataStream(), new File(file, entryToFileName(sel)));
}
}
Configuration.setConfig("lastSaveDir", file.getParentFile().getAbsolutePath());

View File

@@ -1,7 +1,13 @@
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.Configuration;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.LimitedInputStream;
import com.jpexs.helpers.PosMarkedInputStream;
import com.jpexs.helpers.ProgressListener;
import com.jpexs.helpers.ReReadableInputStream;
import com.jpexs.process.ProcessTools;
import java.awt.BorderLayout;
import java.awt.Color;
@@ -19,6 +25,7 @@ import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
@@ -33,6 +40,8 @@ import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
@@ -41,6 +50,7 @@ import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.SwingWorker;
import javax.swing.SwingWorker.StateValue;
import javax.swing.filechooser.FileFilter;
/**
*
@@ -49,9 +59,9 @@ import javax.swing.SwingWorker.StateValue;
public class LoadFromMemoryFrame extends AppFrame implements ActionListener {
private List<com.jpexs.process.Process> processlist;
private List<BufferedInputStream> foundIs;
private List<ReReadableInputStream> foundIs;
private com.jpexs.process.Process selProcess;
private JList list;
private JList<com.jpexs.process.Process> list;
private DefaultListModel<com.jpexs.process.Process> model;
private DefaultListModel<String> resModel;
private final JList listRes;
@@ -59,7 +69,7 @@ public class LoadFromMemoryFrame extends AppFrame implements ActionListener {
private boolean processing = false;
private JProgressBar progress;
private class SelectProcessWorker extends SwingWorker<List<BufferedInputStream>, Object> {
private class SelectProcessWorker extends SwingWorker<List<ReReadableInputStream>, Object> {
private com.jpexs.process.Process proc;
@@ -77,7 +87,7 @@ public class LoadFromMemoryFrame extends AppFrame implements ActionListener {
}
@Override
protected List<BufferedInputStream> doInBackground() throws Exception {
protected List<ReReadableInputStream> doInBackground() throws Exception {
Map<Long, InputStream> ret = new HashMap<>();
ret = proc.search(new ProgressListener() {
@Override
@@ -85,19 +95,23 @@ public class LoadFromMemoryFrame extends AppFrame implements ActionListener {
setProgress(p);
}
}, "CWS".getBytes(), "FWS".getBytes(), "ZWS".getBytes());
List<BufferedInputStream> swfStreams = new ArrayList<>();
List<ReReadableInputStream> swfStreams = new ArrayList<>();
int pos = 0;
for (Long addr : ret.keySet()) {
setProgress(pos * 100 / ret.size());
pos++;
try {
BufferedInputStream is = new BufferedInputStream(ret.get(addr));
is.mark(Integer.MAX_VALUE);
PosMarkedInputStream pmi=new PosMarkedInputStream(ret.get(addr));
ReReadableInputStream is = new ReReadableInputStream(pmi);
SWF swf = new SWF(is, null, false, true);
if (swf.fileSize > 0 && swf.version > 0 && swf.version < 25/*Needs to be fixed when SWF versions reaches this value*/) {
publish(translate("swfitem").replace("%version%", "" + swf.version).replace("%size%", "" + swf.fileSize));
long limit = pmi.getPos();
is.setPos(0);
is = new ReReadableInputStream(new LimitedInputStream(is, limit));
if (swf.fileSize > 0 && swf.version > 0 && !swf.tags.isEmpty() && swf.version < 25/*Needs to be fixed when SWF versions reaches this value*/) {
String p=translate("swfitem").replace("%version%", "" + swf.version).replace("%size%", "" + swf.fileSize);
publish(p);
swfStreams.add(is);
}
}
} catch (OutOfMemoryError ome) {
System.gc();
@@ -128,9 +142,9 @@ public class LoadFromMemoryFrame extends AppFrame implements ActionListener {
}
int index = listRes.getSelectedIndex();
if (index > -1) {
BufferedInputStream str = foundIs.get(index);
ReReadableInputStream str = foundIs.get(index);
try {
str.reset();
str.setPos(0);
} catch (IOException ex) {
Logger.getLogger(LoadFromMemoryFrame.class.getName()).log(Level.SEVERE, null, ex);
return;
@@ -189,7 +203,7 @@ public class LoadFromMemoryFrame extends AppFrame implements ActionListener {
@SuppressWarnings("unchecked")
public LoadFromMemoryFrame() {
setSize(800, 600);
setAlwaysOnTop(true);
//setAlwaysOnTop(true);
setTitle(translate("dialog.title"));
addWindowListener(new WindowAdapter() {
@@ -278,7 +292,13 @@ public class LoadFromMemoryFrame extends AppFrame implements ActionListener {
JButton openButton = new JButton(translate("button.open"));
openButton.setActionCommand("OPENSWF");
openButton.addActionListener(this);
JButton saveButton = new JButton(translate("button.save"));
saveButton.setActionCommand("SAVE");
saveButton.addActionListener(this);
rightButtonsPanel.add(openButton);
rightButtonsPanel.add(saveButton);
rightPanel.add(rightButtonsPanel, BorderLayout.SOUTH);
JPanel statePanel = new JPanel();
@@ -310,6 +330,55 @@ public class LoadFromMemoryFrame extends AppFrame implements ActionListener {
case "REFRESHPROCESSLIST":
refreshList();
break;
case "SAVE":
if (foundIs == null) {
return;
}
int[] selected = listRes.getSelectedIndices();
if (selected.length>0) {
JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory(new File(Configuration.getConfig("lastSaveDir", ".")));
if (selected.length > 1) {
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
} else {
fc.setSelectedFile(new File(Configuration.getConfig("lastSaveDir", "."), "movie.swf"));
fc.setFileFilter(new FileFilter() {
@Override
public boolean accept(File f) {
return (f.getName().endsWith(".swf")) || (f.isDirectory());
}
@Override
public String getDescription() {
return AppStrings.translate("filter.swf");
}
});
}
fc.setAcceptAllFileFilterUsed(false);
JFrame f = new JFrame();
View.setWindowIcon(f);
int returnVal = fc.showSaveDialog(f);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = Helper.fixDialogFile(fc.getSelectedFile());
try {
if (selected.length == 1) {
ReReadableInputStream bis=foundIs.get(selected[0]);
bis.setPos(0);
Helper.saveStream(bis, file);
} else {
for (int sel : selected) {
ReReadableInputStream bis=foundIs.get(sel);
bis.setPos(0);
Helper.saveStream(bis, new File(file, "movie"+sel+".swf"));
}
}
Configuration.setConfig("lastSaveDir", file.getParentFile().getAbsolutePath());
} catch (IOException ex) {
View.showMessageDialog(null, translate("error.file.write"));
}
}
}
break;
}
}
}

View File

@@ -29,6 +29,7 @@ import com.jpexs.decompiler.flash.gui.proxy.ProxyFrame;
import com.jpexs.helpers.Cache;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.ProgressListener;
import com.jpexs.helpers.ReReadableInputStream;
import com.sun.jna.Platform;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.Advapi32Util;
@@ -324,6 +325,13 @@ public class Main {
} else {
if (inputStream instanceof FileInputStream) {
openFile(file);
} else if(inputStream instanceof ReReadableInputStream){
try {
((ReReadableInputStream) inputStream).setPos(0);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
return openFile(fileTitle, inputStream);
} else if (inputStream instanceof BufferedInputStream) {
try {
((BufferedInputStream) inputStream).reset();

View File

@@ -15,7 +15,7 @@
button.open = Open
button.save = Save
button.refresh = Refresh
button.refresh = Refresh list
dialog.title = Search browsers cache
supported.browsers = Supported browsers:
info.closed = *This browser saves data to disk cache after application exit so close browser first.

View File

@@ -15,7 +15,7 @@
button.open = Otev\u0159\u00edt
button.save = Ulo\u017eit
button.refresh = Obnovit
button.refresh = Obnovit seznam
dialog.title = Prohledat cache prohl\u00ed\u017ee\u010d\u016f
supported.browsers = Podporovan\u00e9 prohl\u00ed\u017ee\u010de:
info.closed = *Tento prohl\u00ed\u017ee\u010d ukl\u00e1d\u00e1 data do diskov\u00e9 cache a\u017e po ukon\u010den\u00ed aplikace tak\u017ee ho nejd\u0159\u00edve ukon\u010dete.

View File

@@ -20,4 +20,7 @@ button.refresh = Refresh list
noprocess = No process selected
searching = Searching...
swfitem = [SWF version %version% size %size%]
notfound = No SWF found
notfound = No SWF found
#after version 1.7.1:
button.save = Save

View File

@@ -20,4 +20,7 @@ button.refresh = Obnovit seznam
noprocess = Nebyl vybr\u00e1n proces
searching = Prohled\u00e1v\u00e1n\u00ed...
swfitem = [SWF verze %version% velikost %size%]
notfound = \u017d\u00e1dn\u00e9 SWF nebylo nalezeno
notfound = \u017d\u00e1dn\u00e9 SWF nebylo nalezeno
#after version 1.7.1:
button.save = Ulo\u017eit

View File

@@ -568,7 +568,8 @@ public class Helper {
try (FileOutputStream fos = new FileOutputStream(output)) {
while((cnt=is.read(buf))>0){
fos.write(buf,0,cnt);
}
fos.flush();
}
}
}
}

View File

@@ -1,4 +1,4 @@
package com.jpexs.browsers.cache;
package com.jpexs.helpers;
import java.io.IOException;
import java.io.InputStream;
@@ -10,10 +10,10 @@ import java.io.InputStream;
public class LimitedInputStream extends InputStream {
private InputStream is;
private int pos = 0;
private int limit;
private long pos = 0;
private long limit;
public LimitedInputStream(InputStream is, int limit) {
public LimitedInputStream(InputStream is, long limit) {
this.is = is;
this.limit = limit;
}
@@ -31,7 +31,7 @@ public class LimitedInputStream extends InputStream {
public int available() throws IOException {
int avail = is.available();
if (pos + avail > limit) {
avail = limit - pos;
avail = (int)(limit - pos);
}
return avail;
}

View File

@@ -25,7 +25,7 @@ import java.io.InputStream;
*/
public class PosMarkedInputStream extends InputStream {
private int pos = 0;
private long pos = 0;
private InputStream is;
public PosMarkedInputStream(InputStream is) {
@@ -38,11 +38,11 @@ public class PosMarkedInputStream extends InputStream {
return is.read();
}
public int getPos() {
public long getPos() {
return pos;
}
public void setPos(int pos) throws IOException {
public void setPos(long pos) throws IOException {
this.pos = pos;
}

View File

@@ -29,7 +29,7 @@ public class ReReadableInputStream extends InputStream {
InputStream is;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] converted;
int pos = 0;
long pos = 0;
int count = 0;
public int getCount() {
@@ -40,7 +40,7 @@ public class ReReadableInputStream extends InputStream {
return baos.toByteArray();
}
public int getPos() {
public long getPos() {
return pos;
}
@@ -48,7 +48,7 @@ public class ReReadableInputStream extends InputStream {
this.is = is;
}
public void setPos(int pos) throws IOException {
public void setPos(long pos) throws IOException {
if (pos > count) {
this.pos = count;
skip(pos - count);
@@ -62,7 +62,7 @@ public class ReReadableInputStream extends InputStream {
if (converted == null) {
converted = baos.toByteArray();
}
int ret = converted[pos] & 0xff;
int ret = converted[(int)pos] & 0xff;
pos++;
return ret;
}
@@ -79,7 +79,7 @@ public class ReReadableInputStream extends InputStream {
@Override
public int available() throws IOException {
return (count + is.available()) - pos;
return (count + is.available()) - (int)pos;
}
public long length() throws IOException {