Skip to content

Commit

Permalink
- Fixes #20: Add a way to dump individual Flash elements
Browse files Browse the repository at this point in the history
  • Loading branch information
sporst committed Jun 11, 2011
1 parent 656f7c8 commit 26a00c8
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 1 deletion.
Expand Up @@ -3,9 +3,11 @@
import javax.swing.JTree;
import javax.swing.SwingUtilities;

import tv.porst.swfretools.dissector.gui.main.flashtree.menus.FlashAnyNodeMenu;
import tv.porst.swfretools.dissector.gui.main.flashtree.menus.FlashFileNodeMenu;
import tv.porst.swfretools.dissector.gui.main.flashtree.nodes.FlashFileNode;
import tv.porst.swfretools.dissector.gui.main.flashtree.nodes.FlashTreeNode;
import tv.porst.swfretools.dissector.gui.main.models.LoadedFile;

/**
* Contains methods for handling clicks on the tree that shows the SWF
Expand All @@ -27,8 +29,15 @@ public static void handleRightClick(final JTree tree, final FlashTreeNode<?> nod
throw new IllegalArgumentException("Node argument must not be null.");
}

final LoadedFile loadedFile = FlashTreeHelpers.getLoadedFile(node);

if (node instanceof FlashFileNode) {
final FlashFileNodeMenu menu = new FlashFileNodeMenu(SwingUtilities.getWindowAncestor(tree), ((FlashFileNode)node).getUserObject().getLoadedFile());
final FlashFileNodeMenu menu = new FlashFileNodeMenu(SwingUtilities.getWindowAncestor(tree), loadedFile);

menu.show(tree, x, y);
}
else {
final FlashAnyNodeMenu menu = new FlashAnyNodeMenu(SwingUtilities.getWindowAncestor(tree), loadedFile, node);

menu.show(tree, x, y);
}
Expand Down
@@ -0,0 +1,63 @@
package tv.porst.swfretools.dissector.gui.main.flashtree.actions;

import java.awt.Window;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;

import tv.porst.splib.binaryparser.IFileElement;
import tv.porst.swfretools.dissector.gui.main.flashtree.implementations.FlashTreeImplementations;
import tv.porst.swfretools.dissector.gui.main.models.LoadedFile;

/**
* Action that is used to dump SWF elements to a file.
*/
public final class DumpElementAction extends AbstractAction {

/**
* Parent window used for dialogs.
*/
private final Window parent;

/**
* The loaded file whose decompressed data is dumped to disk.
*/
private final LoadedFile loadedFile;

/**
* The element to dump to a file.
*/
private final IFileElement element;

/**
* Creates a new action object.
*
* @param parent Parent window used for dialogs.
* @param loadedFile The loaded file whose decompressed data is dumped to disk.
* @param element The element to dump to a file.
*/
public DumpElementAction(final Window parent, final LoadedFile loadedFile, final IFileElement element) {
super("Dump to file");

if (parent == null) {
throw new IllegalArgumentException("Parent argument must not be null.");
}

if (loadedFile == null) {
throw new IllegalArgumentException("Loaded file argument must not be null.");
}

if (element == null) {
throw new IllegalArgumentException("Element argument must not be null.");
}

this.parent = parent;
this.loadedFile = loadedFile;
this.element = element;
}

@Override
public void actionPerformed(final ActionEvent event) {
FlashTreeImplementations.dumpElement(parent, loadedFile, element);
}
}
Expand Up @@ -6,8 +6,11 @@

import javax.swing.JFileChooser;

import tv.porst.splib.arrays.ArrayHelpers;
import tv.porst.splib.binaryparser.IFileElement;
import tv.porst.splib.file.FileHelpers;
import tv.porst.swfretools.dissector.gui.main.MessageBox;
import tv.porst.swfretools.dissector.gui.main.implementations.FileActions.BinFileFilter;
import tv.porst.swfretools.dissector.gui.main.implementations.FileActions.SWFFileFilter;
import tv.porst.swfretools.dissector.gui.main.models.LoadedFile;

Expand Down Expand Up @@ -51,4 +54,39 @@ public static void dumpDecompressedFile(final Window parent, final LoadedFile lo
}
}
}

public static void dumpElement(final Window parent, final LoadedFile loadedFile, final IFileElement element) {

if (parent == null) {
throw new IllegalArgumentException("Parent argument must not be null.");
}

if (element == null) {
throw new IllegalArgumentException("Element argument must not be null.");
}

final JFileChooser fc = new JFileChooser();
fc.setFileFilter(new BinFileFilter());

final File parentFile = loadedFile.getFile().getParentFile();

if (parent != null) {
fc.setCurrentDirectory(parentFile);
}

if (JFileChooser.APPROVE_OPTION == fc.showSaveDialog(parent)) {
final File outputFile = fc.getSelectedFile();

try {

final byte[] data = loadedFile.getSWFFile().getDecompressedData();

final byte[] elementData = ArrayHelpers.getSubArray(data, element.getBitPosition() / 8, element.getBitLength() / 8);

FileHelpers.writeFile(outputFile, elementData);
} catch (final IOException e) {
MessageBox.showError(parent, "Element could not be saved");
}
}
}
}
@@ -0,0 +1,42 @@
package tv.porst.swfretools.dissector.gui.main.flashtree.menus;

import java.awt.Window;

import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

import tv.porst.swfretools.dissector.gui.main.flashtree.actions.DumpElementAction;
import tv.porst.swfretools.dissector.gui.main.flashtree.nodes.FlashTreeNode;
import tv.porst.swfretools.dissector.gui.main.models.LoadedFile;

/**
* Popup menu that is shown when the user right-clicks on a node that does not
* have a more specific menu.
*/
public final class FlashAnyNodeMenu extends JPopupMenu {

/**
* Creates a new menu object.
*
* @param parent Parent window used for dialogs.
* @param loadedFile The loaded file.
* @param node The clicked node.
*/
public FlashAnyNodeMenu(final Window parent, final LoadedFile loadedFile, final FlashTreeNode<?> node) {

if (parent == null) {
throw new IllegalArgumentException("Parent argument must not be null.");
}

if (loadedFile == null) {
throw new IllegalArgumentException("Loaded file argument must not be null.");
}

if (node == null) {
throw new IllegalArgumentException("Node argument must not be null.");
}

add(new JMenuItem(new DumpElementAction(parent, loadedFile, node.getUserObject())));
}

}
Expand Up @@ -87,6 +87,27 @@ public static void openFile(final FlashTree tree, final FileModel model, final F
}
}

/**
* File filter class to make sure only BIN files can be selected.
*/
public static class BinFileFilter extends FileFilter {

@Override
public boolean accept(final File f) {

if (f.isDirectory()) {
return true;
}

return f.getAbsolutePath().toLowerCase().endsWith("bin");
}

@Override
public String getDescription() {
return "Binary files";
}
}

/**
* File filter class to make sure only SWF files can be selected.
*/
Expand Down

0 comments on commit 26a00c8

Please sign in to comment.