/* * Open Source Physics software is free software as described near the bottom of this code file. * * For additional information and documentation on Open Source Physics please see: * <https://www.compadre.org/osp/> */ package org.opensourcephysics.tools; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Frame; import java.awt.Point; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.File; import java.rmi.RemoteException; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JCheckBox; 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.JTextField; import javax.swing.JToolBar; import javax.swing.KeyStroke; import javax.swing.WindowConstants; import org.opensourcephysics.controls.Cryptic; import org.opensourcephysics.controls.OSPLog; import org.opensourcephysics.controls.XML; import org.opensourcephysics.controls.XMLControl; import org.opensourcephysics.controls.XMLControlElement; import org.opensourcephysics.controls.XMLTreePanel; import org.opensourcephysics.display.OSPRuntime; /** * This provides a GUI for encrypting and decrypting XMLControls. * * @author Douglas Brown * @version 1.0 */ @SuppressWarnings("serial") public class EncryptionTool extends JFrame implements Tool { // static fields private static Dimension dim = new Dimension(720, 500); // instance fields private XMLTreePanel treePanel; private JPanel contentPane = new JPanel(new BorderLayout()); private JobManager jobManager = new JobManager(this); private JTextField passwordField; private JCheckBox encryptedCheckBox; private JCheckBox previewCheckBox; private String fileName; private JMenuItem openItem; private JMenuItem saveItem; private JMenuItem saveAsItem; private JLabel passwordLabel; private JMenu fileMenu; private JMenu helpMenu; private JMenuItem exitItem; private JMenuItem logItem; private JMenuItem aboutItem; private Icon openIcon; private JButton openButton; private Icon saveIcon; private JButton saveButton; /** * A shared encryption tool. */ private static final EncryptionTool ENCRYPTION_TOOL = new EncryptionTool(); /** * Gets the shared EncryptionTool. * * @return the shared EncryptionTool */ public static EncryptionTool getTool() { return ENCRYPTION_TOOL; } /** * Constructs a blank EncryptionTool. */ public EncryptionTool() { String name = "EncryptionTool"; //$NON-NLS-1$ setName(name); createGUI(); refreshGUI(); Toolbox.addTool(name, this); // Toolbox.addRMITool(name, this); } /** * Constructs a EncryptionTool and opens the specified xml file. * * @param fileName the name of the xml file */ public EncryptionTool(String fileName) { this(); open(fileName); } /** * Opens an xml file specified by name. * * @param fileName the file name * @return the file name, if successfully opened */ public String open(String fileName) { OSPLog.fine("opening "+fileName); //$NON-NLS-1$ // read the file into an XML control XMLControlElement control = new XMLControlElement(); control.setDecryptPolicy(XMLControlElement.NEVER_DECRYPT); control.read(fileName); if(control.failedToRead()) { return null; } String pass = control.getPassword(); if(pass==null) { passwordField.setText(null); displayXML(control); encryptedCheckBox.setEnabled(true); } else if(passwordField.getText().equals(pass)) { displayXML(decrypt(control)); encryptedCheckBox.setEnabled(true); } else { displayXML(control); encryptedCheckBox.setEnabled(false); } this.fileName = fileName; refreshGUI(); return fileName; } /** * Sends a job to this tool and specifies a tool to reply to. * * @param job the Job * @param replyTo the tool to notify when the job is complete (may be null) * @throws RemoteException */ public void send(Job job, Tool replyTo) throws RemoteException { // read xml into XMLControl and display the control XMLControlElement control = new XMLControlElement(); control.setDecryptPolicy(XMLControlElement.NEVER_DECRYPT); control.readXML(job.getXML()); if(control.failedToRead()) { return; } String pass = control.getPassword(); if(pass==null) { passwordField.setText(null); displayXML(control); } else if(passwordField.getText().equals(pass)) { displayXML(decrypt(control)); } else { displayXML(control); } fileName = null; refreshGUI(); // log the job with the job manager jobManager.log(job, replyTo); } /** * Refreshes the GUI. */ public void refreshGUI() { String title = ToolsRes.getString("EncryptionTool.Title"); //$NON-NLS-1$ if(fileName!=null) { title += ": "+fileName; //$NON-NLS-1$ } setTitle(title); openButton.setToolTipText(ToolsRes.getString("EncryptionTool.Button.Open.ToolTip")); //$NON-NLS-1$ saveButton.setToolTipText(ToolsRes.getString("EncryptionTool.Button.Save.ToolTip")); //$NON-NLS-1$ passwordLabel.setText(ToolsRes.getString("EncryptionTool.Label.Password")); //$NON-NLS-1$ passwordField.setToolTipText(ToolsRes.getString("EncryptionTool.PasswordField.ToolTip")); //$NON-NLS-1$ encryptedCheckBox.setText(ToolsRes.getString("EncryptionTool.CheckBox.Encrypted")); //$NON-NLS-1$ encryptedCheckBox.setToolTipText(ToolsRes.getString("EncryptionTool.CheckBox.Encrypted.ToolTip")); //$NON-NLS-1$ previewCheckBox.setText(ToolsRes.getString("EncryptionTool.CheckBox.Preview")); //$NON-NLS-1$ previewCheckBox.setToolTipText(ToolsRes.getString("EncryptionTool.CheckBox.Preview.ToolTip")); //$NON-NLS-1$ fileMenu.setText(ToolsRes.getString("EncryptionTool.Menu.File")); //$NON-NLS-1$ openItem.setText(ToolsRes.getString("EncryptionTool.MenuItem.Open")); //$NON-NLS-1$ saveItem.setText(ToolsRes.getString("EncryptionTool.MenuItem.Save")); //$NON-NLS-1$ saveAsItem.setText(ToolsRes.getString("EncryptionTool.MenuItem.SaveAs")); //$NON-NLS-1$ exitItem.setText(ToolsRes.getString("EncryptionTool.MenuItem.Exit")); //$NON-NLS-1$ helpMenu.setText(ToolsRes.getString("EncryptionTool.Menu.Help")); //$NON-NLS-1$ logItem.setText(ToolsRes.getString("EncryptionTool.MenuItem.Log")); //$NON-NLS-1$ aboutItem.setText(ToolsRes.getString("EncryptionTool.MenuItem.About")); //$NON-NLS-1$ saveButton.setEnabled(encryptedCheckBox.isEnabled()); saveItem.setEnabled(encryptedCheckBox.isEnabled()); saveAsItem.setEnabled(encryptedCheckBox.isEnabled()); XMLControlElement control = getCurrentControl(); encryptedCheckBox.setSelected((control!=null)&&(control.getPassword()!=null)); passwordLabel.setEnabled(encryptedCheckBox.isSelected()); passwordField.setEnabled(encryptedCheckBox.isSelected()); previewCheckBox.setEnabled(encryptedCheckBox.isEnabled()&&encryptedCheckBox.isSelected()); previewCheckBox.setSelected((control!=null)&&(control.getObjectClass()==Cryptic.class)); } /** * Main entry point when used as application. * * @param args ignored */ public static void main(String[] args) { EncryptionTool tool = getTool(); tool.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); tool.open("Untitled.xset"); //$NON-NLS-1$ tool.setVisible(true); } // ______________________________ private methods _____________________________ /** * Gets the currently displayed XMLControlElement. * * @return the XMLControlElement */ private XMLControlElement getCurrentControl() { if(treePanel==null) { return null; } XMLControl control = treePanel.getControl(); if(control instanceof XMLControlElement) { return(XMLControlElement) control; } return null; } /** * Displays an XMLControlElement. * * @param control the XMLControlElement */ private void displayXML(XMLControlElement control) { if(treePanel!=null) { contentPane.remove(treePanel); } treePanel = new XMLTreePanel(control, false); contentPane.add(treePanel, BorderLayout.CENTER); validate(); // treePanel.setSelectedNode("xml_password"); //$NON-NLS-1$ refreshGUI(); } /** * Sets the password of the currently displayed control. * * @param password the password */ private void setPassword(String password) { XMLControlElement control = getCurrentControl(); if(control==null) { return; } String pass = control.getPassword(); if(!encryptedCheckBox.isEnabled()) { boolean verified = password.equals(pass); if(verified) { displayXML(decrypt(control)); encryptedCheckBox.setEnabled(true); } else { Toolkit.getDefaultToolkit().beep(); OSPLog.fine("Bad password: "+password); //$NON-NLS-1$ } } else if(control.getObjectClass()==Cryptic.class) { // decrypt control, change password, and re-encrypt XMLControlElement temp = decrypt(control); temp.setPassword(password); temp = encrypt(temp); control.setValue("cryptic", temp.getString("cryptic")); //$NON-NLS-1$ //$NON-NLS-2$ treePanel.refresh(); } else { // change password if(password.equals("")&&!encryptedCheckBox.isSelected()) { //$NON-NLS-1$ password = null; } control.setPassword(password); treePanel.refresh(); // treePanel.setSelectedNode("xml_password"); //$NON-NLS-1$ } refreshGUI(); } /** * Encrypts the specified XMLcontrol using a Cryptic object. * * @param control the XMLControl * @return the encrypted control */ private XMLControlElement encrypt(XMLControlElement control) { // return controls that are already encrypted if(control.getObjectClass()==Cryptic.class) { return control; } // encrypt control and set its password String xml = control.toXML(); Cryptic cryptic = new Cryptic(xml); XMLControlElement encrypted = new XMLControlElement(cryptic); encrypted.setPassword(control.getPassword()); return encrypted; } /** * Decrypts the specified XMLcontrol. * * @param control the XMLControl * @return the decrypted control */ private XMLControlElement decrypt(XMLControlElement control) { if(control.getObjectClass()!=Cryptic.class) { return control; } Cryptic cryptic = (Cryptic) control.loadObject(null); // get the decrypted xml, make new control and set password String xml = cryptic.decrypt(); XMLControlElement decrypted = new XMLControlElement(xml); return decrypted; } /** * Opens an xml file selected with a chooser. * * @return the name of the opened file, or null if none opened */ private String open() { @SuppressWarnings("deprecation") int result = OSPRuntime.getChooser().showOpenDialog(this); if(result==JFileChooser.APPROVE_OPTION) { OSPRuntime.chooserDir = OSPRuntime.getChooser().getCurrentDirectory().toString(); String fileName = OSPRuntime.getChooser().getSelectedFile().getAbsolutePath(); fileName = XML.getRelativePath(fileName); return open(fileName); } return null; } /** * Saves the current xml control to the specified file. * * @param fileName the file name * @return the name of the saved file, or null if not saved */ private String save(String fileName) { if((fileName==null)||fileName.equals("")) { //$NON-NLS-1$ return null; } if(passwordField.getBackground()==Color.yellow) { passwordField.setBackground(Color.white); setPassword(passwordField.getText()); } XMLControlElement control = getCurrentControl(); if(control==null) { return null; } if(control.getObjectClass()==Cryptic.class) { control = decrypt(control); } if(control.write(fileName)==null) { return null; } this.fileName = fileName; refreshGUI(); return fileName; } /** * Saves the currently displayed xml control to a file selected with a chooser. * * @return the name of the saved file, or null if not saved */ private String saveAs() { int result = OSPRuntime.getChooser().showSaveDialog(this); if(result==JFileChooser.APPROVE_OPTION) { OSPRuntime.chooserDir = OSPRuntime.getChooser().getCurrentDirectory().toString(); File file = OSPRuntime.getChooser().getSelectedFile(); // check to see if file already exists if(file.exists()) { int selected = JOptionPane.showConfirmDialog(this, ToolsRes.getString("EncryptionTool.Dialog.ReplaceFile.Message")+" "+file.getName()+"?", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ ToolsRes.getString("EncryptionTool.Dialog.ReplaceFile.Title"), //$NON-NLS-1$ JOptionPane.YES_NO_CANCEL_OPTION); if(selected!=JOptionPane.YES_OPTION) { return null; } } String fileName = file.getAbsolutePath(); if((fileName==null)||fileName.trim().equals("")) { //$NON-NLS-1$ return null; } return save(XML.getRelativePath(fileName)); } return null; } /** * Creates the GUI. */ private void createGUI() { // configure the frame contentPane.setPreferredSize(dim); setContentPane(contentPane); setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); JToolBar toolbar = new JToolBar(); toolbar.setFloatable(false); contentPane.add(toolbar, BorderLayout.NORTH); String imageFile = "/org/opensourcephysics/resources/tools/images/open.gif"; //$NON-NLS-1$ openIcon = ResourceLoader.getIcon(imageFile); openButton = new JButton(openIcon); openButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { open(); } }); toolbar.add(openButton); imageFile = "/org/opensourcephysics/resources/tools/images/save.gif"; //$NON-NLS-1$ saveIcon = ResourceLoader.getIcon(imageFile); saveButton = new JButton(saveIcon); saveButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { save(fileName); } }); toolbar.add(saveButton); toolbar.addSeparator(); passwordLabel = new JLabel(); passwordLabel.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 3)); passwordField = new JTextField(20); passwordField.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { if(e.getKeyCode()==KeyEvent.VK_ENTER) { passwordField.setBackground(Color.white); setPassword(passwordField.getText()); } else if(e.getKeyChar()!=KeyEvent.CHAR_UNDEFINED) { passwordField.setBackground(Color.yellow); } } }); passwordField.addFocusListener(new FocusAdapter() { public void focusLost(FocusEvent e) { if(passwordField.getBackground()==Color.yellow) { passwordField.setBackground(Color.white); setPassword(passwordField.getText()); } } }); toolbar.add(passwordLabel); toolbar.add(passwordField); encryptedCheckBox = new JCheckBox(""); //$NON-NLS-1$ encryptedCheckBox.setEnabled(false); encryptedCheckBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // if selected, set password to current passwordField text if(encryptedCheckBox.isSelected()) { setPassword(passwordField.getText()); } // else decrypt and set password to "" else { XMLControlElement control = getCurrentControl(); if(control.getObjectClass()==Cryptic.class) { control = decrypt(control); control.setPassword(null); displayXML(control); } setPassword(""); //$NON-NLS-1$ } } }); encryptedCheckBox.setContentAreaFilled(false); toolbar.add(encryptedCheckBox); previewCheckBox = new JCheckBox(""); //$NON-NLS-1$ previewCheckBox.setOpaque(false); previewCheckBox.setEnabled(false); previewCheckBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { XMLControlElement control = getCurrentControl(); if(previewCheckBox.isSelected()) { displayXML(encrypt(control)); } else { displayXML(decrypt(control)); } } }); toolbar.add(previewCheckBox); // create the menu bar int keyMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); JMenuBar menubar = new JMenuBar(); // file menu fileMenu = new JMenu(); menubar.add(fileMenu); // open item openItem = new JMenuItem(); openItem.setAccelerator(KeyStroke.getKeyStroke('O', keyMask)); openItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { open(); } }); fileMenu.add(openItem); fileMenu.addSeparator(); // save item saveItem = new JMenuItem(); saveItem.setAccelerator(KeyStroke.getKeyStroke('S', keyMask)); saveItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { save(fileName); } }); saveItem.setEnabled(false); fileMenu.add(saveItem); // save as item saveAsItem = new JMenuItem(); saveAsItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { saveAs(); } }); saveAsItem.setEnabled(false); fileMenu.add(saveAsItem); exitItem = new JMenuItem(ToolsRes.getString("MenuItem.Exit")); //$NON-NLS-1$ exitItem.setAccelerator(KeyStroke.getKeyStroke('Q', keyMask)); exitItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } }); fileMenu.addSeparator(); fileMenu.add(exitItem); // help menu helpMenu = new JMenu(); menubar.add(helpMenu); // log item logItem = new JMenuItem(); logItem.setAccelerator(KeyStroke.getKeyStroke('L', keyMask)); logItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Point p0 = new Frame().getLocation(); JFrame frame = OSPLog.showLog(); if((frame.getLocation().x==p0.x)&&(frame.getLocation().y==p0.y)) { Point p = getLocation(); frame.setLocation(p.x+28, p.y+28); } } }); helpMenu.add(logItem); helpMenu.addSeparator(); // about item aboutItem = new JMenuItem(); aboutItem.setAccelerator(KeyStroke.getKeyStroke('A', keyMask)); aboutItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String toolname = ToolsRes.getString("EncryptionTool.About.ToolName"); //$NON-NLS-1$ String aboutString = toolname+OSPRuntime.VERSION+XML.NEW_LINE+ToolsRes.getString("EncryptionTool.About.OSPName")+XML.NEW_LINE //$NON-NLS-1$ +"www.compadre.org/osp"; //$NON-NLS-1$ JOptionPane.showMessageDialog(EncryptionTool.this, aboutString, ToolsRes.getString("EncryptionTool.About.Title"), //$NON-NLS-1$ JOptionPane.INFORMATION_MESSAGE); } }); helpMenu.add(aboutItem); setJMenuBar(menubar); pack(); // center this on the screen Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); int x = (dim.width-getBounds().width)/2; int y = (dim.height-getBounds().height)/2; setLocation(x, y); } } /* * Open Source Physics software is free software; you can redistribute * it and/or modify it under the terms of the GNU General Public License (GPL) as * published by the Free Software Foundation; either version 2 of the License, * or(at your option) any later version. * Code that uses any portion of the code in the org.opensourcephysics package * or any subpackage (subdirectory) of this package must must also be be released * under the GNU GPL license. * * This software 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; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA * or view the license online at http://www.gnu.org/copyleft/gpl.html * * Copyright (c) 2019 The Open Source Physics project * https://www.compadre.org/osp */