/*
* 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.gui;
import com.jpexs.decompiler.flash.Configuration;
import com.jpexs.decompiler.flash.Main;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.abc.gui.ABCPanel;
import com.jpexs.decompiler.flash.abc.gui.ClassesListTreeModel;
import com.jpexs.decompiler.flash.abc.gui.DeobfuscationDialog;
import com.jpexs.decompiler.flash.abc.gui.LineMarkedEditorPane;
import com.jpexs.decompiler.flash.abc.gui.TreeElement;
import com.jpexs.decompiler.flash.abc.gui.TreeLeafScript;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
import com.jpexs.decompiler.flash.action.gui.ActionPanel;
import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel;
import com.jpexs.decompiler.flash.helpers.Helper;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG2Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsLossless2Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsLosslessTag;
import com.jpexs.decompiler.flash.tags.DefineBitsTag;
import com.jpexs.decompiler.flash.tags.DefineButton2Tag;
import com.jpexs.decompiler.flash.tags.DefineButtonTag;
import com.jpexs.decompiler.flash.tags.DefineEditTextTag;
import com.jpexs.decompiler.flash.tags.DefineFont2Tag;
import com.jpexs.decompiler.flash.tags.DefineFont3Tag;
import com.jpexs.decompiler.flash.tags.DefineFont4Tag;
import com.jpexs.decompiler.flash.tags.DefineFontTag;
import com.jpexs.decompiler.flash.tags.DefineMorphShape2Tag;
import com.jpexs.decompiler.flash.tags.DefineMorphShapeTag;
import com.jpexs.decompiler.flash.tags.DefineShape2Tag;
import com.jpexs.decompiler.flash.tags.DefineShape3Tag;
import com.jpexs.decompiler.flash.tags.DefineShape4Tag;
import com.jpexs.decompiler.flash.tags.DefineShapeTag;
import com.jpexs.decompiler.flash.tags.DefineSoundTag;
import com.jpexs.decompiler.flash.tags.DefineSpriteTag;
import com.jpexs.decompiler.flash.tags.DefineText2Tag;
import com.jpexs.decompiler.flash.tags.DefineTextTag;
import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag;
import com.jpexs.decompiler.flash.tags.EndTag;
import com.jpexs.decompiler.flash.tags.ExportAssetsTag;
import com.jpexs.decompiler.flash.tags.JPEGTablesTag;
import com.jpexs.decompiler.flash.tags.PlaceObject2Tag;
import com.jpexs.decompiler.flash.tags.PlaceObjectTypeTag;
import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag;
import com.jpexs.decompiler.flash.tags.SoundStreamHead2Tag;
import com.jpexs.decompiler.flash.tags.SoundStreamHeadTag;
import com.jpexs.decompiler.flash.tags.SoundStreamHeadTypeTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.AloneTag;
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.Container;
import com.jpexs.decompiler.flash.tags.base.FontTag;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
import com.jpexs.decompiler.flash.tags.base.TextTag;
import com.jpexs.decompiler.flash.tags.text.ParseException;
import com.jpexs.decompiler.flash.types.GLYPHENTRY;
import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.RGB;
import com.jpexs.decompiler.flash.types.TEXTRECORD;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.border.BevelBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
/**
*
* @author Jindra
*/
public class MainFrame extends JFrame implements ActionListener, TreeSelectionListener {
private SWF swf;
public ABCPanel abcPanel;
public ActionPanel actionPanel;
private JTabbedPane tabPane;
public LoadingPanel loadingPanel = new LoadingPanel(20, 20);
public JLabel statusLabel = new JLabel("");
public JPanel statusPanel = new JPanel();
public JProgressBar progressBar = new JProgressBar(0, 100);
private DeobfuscationDialog deobfuscationDialog;
public JTree tagTree;
public FlashPlayerPanel flashPanel;
public JPanel displayPanel;
public ImagePanel imagePanel;
final static String CARDFLASHPANEL = "Flash card";
final static String CARDIMAGEPANEL = "Image card";
final static String CARDEMPTYPANEL = "Empty card";
final static String CARDACTIONSCRIPTPANEL = "ActionScript card";
final static String DETAILCARDAS3NAVIGATOR = "Traits list";
final static String DETAILCARDEMPTYPANEL = "Empty card";
final static String CARDTEXTPANEL = "Text card";
private LineMarkedEditorPane textValue;
private JPEGTablesTag jtt;
private HashMap characters;
private List abcList;
JSplitPane splitPane1;
JSplitPane splitPane2;
private JPanel detailPanel;
private JTextField filterField = new JTextField("");
private JPanel searchPanel;
private JCheckBoxMenuItem autoDeobfuscateMenuItem;
private JPanel displayWithPreview;
private JButton textSaveButton;
private JButton textEditButton;
private JButton textCancelButton;
private JPanel parametersPanel;
private JSplitPane previewSplitPane;
private JButton imageReplaceButton;
private JPanel imageButtonsPanel;
public void setPercent(int percent) {
progressBar.setValue(percent);
progressBar.setVisible(true);
}
public void hidePercent() {
if (progressBar.isVisible()) {
progressBar.setVisible(false);
}
}
static {
try {
File.createTempFile("temp", ".swf").delete(); //First call to this is slow, so make it first
} catch (IOException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static void addTab(JTabbedPane tabbedPane, Component tab, String title, Icon icon) {
tabbedPane.add(tab);
JLabel lbl = new JLabel(title);
lbl.setIcon(icon);
lbl.setIconTextGap(5);
lbl.setHorizontalTextPosition(SwingConstants.RIGHT);
tabbedPane.setTabComponentAt(tabbedPane.getTabCount() - 1, lbl);
}
public void setStatus(String s) {
statusLabel.setText(s);
}
public void setWorkStatus(String s) {
if (s.equals("")) {
loadingPanel.setVisible(false);
} else {
loadingPanel.setVisible(true);
}
statusLabel.setText(s);
}
public MainFrame(SWF swf) {
setSize(1000, 700);
tabPane = new JTabbedPane();
View.setWindowIcon(this);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
if (Main.proxyFrame != null) {
if (Main.proxyFrame.isVisible()) {
return;
}
}
Main.exit();
}
});
setTitle(Main.applicationVerName + (Main.DISPLAY_FILENAME ? " - " + Main.getFileTitle() : ""));
JMenuBar menuBar = new JMenuBar();
JMenu menuFile = new JMenu("File");
JMenuItem miOpen = new JMenuItem("Open...");
miOpen.setIcon(View.getIcon("open16"));
miOpen.setActionCommand("OPEN");
miOpen.addActionListener(this);
JMenuItem miSave = new JMenuItem("Save");
miSave.setIcon(View.getIcon("save16"));
miSave.setActionCommand("SAVE");
miSave.addActionListener(this);
JMenuItem miSaveAs = new JMenuItem("Save as...");
miSaveAs.setIcon(View.getIcon("saveas16"));
miSaveAs.setActionCommand("SAVEAS");
miSaveAs.addActionListener(this);
JMenuItem menuExportAll = new JMenuItem("Export all");
menuExportAll.setActionCommand("EXPORT");
menuExportAll.addActionListener(this);
JMenuItem menuExportSel = new JMenuItem("Export selection");
menuExportSel.setActionCommand("EXPORTSEL");
menuExportSel.addActionListener(this);
menuExportAll.setIcon(View.getIcon("export16"));
menuExportSel.setIcon(View.getIcon("exportsel16"));
menuFile.add(miOpen);
menuFile.add(miSave);
menuFile.add(miSaveAs);
menuFile.add(menuExportAll);
menuFile.add(menuExportSel);
menuFile.addSeparator();
JMenuItem miClose = new JMenuItem("Exit");
miClose.setIcon(View.getIcon("exit16"));
miClose.setActionCommand("EXIT");
miClose.addActionListener(this);
menuFile.add(miClose);
menuBar.add(menuFile);
JMenu menuDeobfuscation = new JMenu("Deobfuscation");
menuDeobfuscation.setIcon(View.getIcon("deobfuscate16"));
JMenuItem miDeobfuscation = new JMenuItem("PCode deobfuscation...");
miDeobfuscation.setActionCommand("DEOBFUSCATE");
miDeobfuscation.addActionListener(this);
autoDeobfuscateMenuItem = new JCheckBoxMenuItem("Automatic deobfuscation");
autoDeobfuscateMenuItem.setState((Boolean) Configuration.getConfig("autoDeobfuscate", true));
autoDeobfuscateMenuItem.addActionListener(this);
autoDeobfuscateMenuItem.setActionCommand("AUTODEOBFUSCATE");
menuDeobfuscation.add(autoDeobfuscateMenuItem);
JCheckBoxMenuItem miSubLimiter = new JCheckBoxMenuItem("Enable sub limiter");
miSubLimiter.setActionCommand("SUBLIMITER");
miSubLimiter.addActionListener(this);
JMenuItem miRenameIdentifiers = new JMenuItem("Rename identifiers");
miRenameIdentifiers.setActionCommand("RENAMEIDENTIFIERS");
miRenameIdentifiers.addActionListener(this);
JMenuItem miRemoveDeadCode = new JMenuItem("Remove dead code");
miRemoveDeadCode.setActionCommand("REMOVEDEADCODE");
miRemoveDeadCode.addActionListener(this);
JMenuItem miRemoveDeadCodeAll = new JMenuItem("Remove all dead code");
miRemoveDeadCodeAll.setActionCommand("REMOVEDEADCODEALL");
miRemoveDeadCodeAll.addActionListener(this);
JMenuItem miTraps = new JMenuItem("Remove traps");
miTraps.setActionCommand("REMOVETRAPS");
miTraps.addActionListener(this);
JMenuItem miTrapsAll = new JMenuItem("Remove all traps");
miTrapsAll.setActionCommand("REMOVETRAPSALL");
miTrapsAll.addActionListener(this);
JMenuItem miControlFlow = new JMenuItem("Restore control flow");
miControlFlow.setActionCommand("RESTORECONTROLFLOW");
miControlFlow.addActionListener(this);
JMenuItem miControlFlowAll = new JMenuItem("Restore all control flow");
miControlFlowAll.setActionCommand("RESTORECONTROLFLOWALL");
miControlFlowAll.addActionListener(this);
menuDeobfuscation.add(miRenameIdentifiers);
//menuDeobfuscation.add(miSubLimiter);
menuDeobfuscation.add(miDeobfuscation);
/*menuDeobfuscation.add(miDeobfuscate);
menuDeobfuscation.addSeparator();*/
/*menuDeobfuscation.add(miRemoveDeadCode);
menuDeobfuscation.add(miRemoveDeadCodeAll);
menuDeobfuscation.add(miTraps);
menuDeobfuscation.add(miTrapsAll);
menuDeobfuscation.add(miControlFlow);
menuDeobfuscation.add(miControlFlowAll);
*/
JMenu menuTools = new JMenu("Tools");
JMenuItem miProxy = new JMenuItem("Proxy");
miProxy.setActionCommand("SHOWPROXY");
miProxy.setIcon(View.getIcon("proxy16"));
miProxy.addActionListener(this);
menuTools.add(miProxy);
//menuTools.add(menuDeobfuscation);
menuTools.add(menuDeobfuscation);
menuBar.add(menuTools);
JMenu menuHelp = new JMenu("Help");
JMenuItem miAbout = new JMenuItem("About...");
miAbout.setIcon(View.getIcon("about16"));
miAbout.setActionCommand("ABOUT");
miAbout.addActionListener(this);
JMenuItem miCheckUpdates = new JMenuItem("Check for updates...");
miCheckUpdates.setActionCommand("CHECKUPDATES");
miCheckUpdates.setIcon(View.getIcon("update16"));
miCheckUpdates.addActionListener(this);
JMenuItem miHelpUs = new JMenuItem("Help us!");
miHelpUs.setActionCommand("HELPUS");
miHelpUs.setIcon(View.getIcon("donate16"));
miHelpUs.addActionListener(this);
JMenuItem miHomepage = new JMenuItem("Visit homepage");
miHomepage.setActionCommand("HOMEPAGE");
miHomepage.setIcon(View.getIcon("homepage16"));
miHomepage.addActionListener(this);
menuHelp.add(miCheckUpdates);
menuHelp.add(miHelpUs);
menuHelp.add(miHomepage);
menuHelp.add(miAbout);
menuBar.add(menuHelp);
setJMenuBar(menuBar);
List