diff -r ca18850addad netx/net/sourceforge/jnlp/resources/Messages.properties --- a/netx/net/sourceforge/jnlp/resources/Messages.properties Wed Mar 26 12:07:23 2014 -0400 +++ b/netx/net/sourceforge/jnlp/resources/Messages.properties Wed Mar 26 18:10:17 2014 +0100 @@ -549,6 +549,10 @@ PECustomPermissionsItem=Custom Permissions... PEFileModified=File Modification Warning PEFileModifiedDetail=The policy file at {0} has been modified since it was opened. Reload and re-edit before saving? +PEGAccesUnowenedCode = Execute unowned code +PEGMediaAccess = Media access +PEGrightClick = right click to fold/unfold + # Policy Editor CustomPolicyViewer PECPTitle=Custom Policy Viewer diff -r ca18850addad netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditor.java --- a/netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditor.java Wed Mar 26 12:07:23 2014 -0400 +++ b/netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditor.java Wed Mar 26 18:10:17 2014 +0100 @@ -36,6 +36,8 @@ package net.sourceforge.jnlp.security.policyeditor; +import java.awt.Color; +import java.awt.Container; import java.awt.Dialog.ModalityType; import static net.sourceforge.jnlp.runtime.Translator.R; @@ -45,6 +47,8 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; 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.File; @@ -55,12 +59,14 @@ import java.net.URL; import java.nio.channels.FileLock; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -92,8 +98,10 @@ import javax.swing.UIManager; import javax.swing.WindowConstants; import javax.swing.border.EmptyBorder; +import javax.swing.border.LineBorder; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; +import net.sourceforge.jnlp.security.policyeditor.PolicyEditorPermissions.Group; import net.sourceforge.jnlp.util.FileUtils; import net.sourceforge.jnlp.util.FileUtils.OpenFileResult; @@ -159,6 +167,7 @@ private final Map> codebasePermissionsMap = new HashMap>(); private final Map> customPermissionsMap = new HashMap>(); private final Map checkboxMap = new TreeMap(); + private final List groupBoxList = new ArrayList(Group.values().length); private final JScrollPane scrollPane = new JScrollPane(); private final DefaultListModel listModel = new DefaultListModel(); private final JList list = new JList(listModel); @@ -172,6 +181,43 @@ private final ActionListener okButtonAction, closeButtonAction, addCodebaseButtonAction, removeCodebaseButtonAction, openButtonAction, saveAsButtonAction, viewCustomButtonAction; + private static class JCheckBoxWithGroup extends JCheckBox{ + private final PolicyEditorPermissions.Group group; + + private JCheckBoxWithGroup(Group g) { + super(g.getTitle()); + group = g; + } + + public Group getGroup() { + return group; + } + + private void setState(Map map) { + List backup = new LinkedList(); + for (final ActionListener l : this.getActionListeners()) { + backup.add(l); + this.removeActionListener(l); + } + int i = group.getState(map); + this.setBackground(getParent().getBackground()); + if (i>0){ + this.setSelected(true); + } + if (i<0){ + this.setSelected(false); + } + if (i==0){ + this.setBackground(Color.yellow); + this.setSelected(false); + } + + for (ActionListener al : backup) { + this.addActionListener(al); + } + } + + } public PolicyEditor(final String filepath) { super(); setLayout(new GridBagLayout()); @@ -277,13 +323,10 @@ SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - String codebase = (String) list.getSelectedValue(); - if (codebase == null || codebase.isEmpty()) { + String codebase = getSelectedCodebase(); + if (codebase == null){ return; } - if (codebase.equals(R("PEGlobalSettings"))) { - codebase = ""; - } if (cpViewer == null) { cpViewer = new CustomPolicyViewer(weakThis.get(), codebase, customPermissionsMap.get(codebase)); cpViewer.setVisible(true); @@ -302,6 +345,17 @@ list.setSelectedIndex(0); updateCheckboxes(""); } + + private String getSelectedCodebase() { + String codebase = (String) list.getSelectedValue(); + if (codebase == null || codebase.isEmpty()) { + return null; + } + if (codebase.equals(R("PEGlobalSettings"))) { + return ""; + } + return codebase; + } private static void preparePolicyEditorWindow(final PolicyEditorWindow w, PolicyEditor e) { w.setModalityType(ModalityType.MODELESS); //at least some default @@ -767,12 +821,18 @@ } else { state = false; } + for (JCheckBoxWithGroup jg : groupBoxList) { + jg.setState(map); + } box.setSelected(state); box.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { changesMade = true; map.put(perm, box.isSelected()); + for (JCheckBoxWithGroup jg : groupBoxList) { + jg.setState(map); + } } }); } @@ -869,6 +929,10 @@ checkboxConstraints.gridy = 1; for (final JCheckBox box : checkboxMap.values()) { + if (PolicyEditorPermissions.Group.anyContains(box, checkboxMap)){ + //do not show boxes in any group + continue; + } add(box, checkboxConstraints); checkboxConstraints.gridx++; // Two columns of checkboxes @@ -877,6 +941,91 @@ checkboxConstraints.gridy++; } } + //add groups + for (PolicyEditorPermissions.Group g : PolicyEditorPermissions.Group.values()) { + //no metter what, put group title on new line + checkboxConstraints.gridy++; + //all groups are in second column + checkboxConstraints.gridx = 2; + final JCheckBoxWithGroup groupCh = new JCheckBoxWithGroup(g); + groupBoxList.add(groupCh); + final JPanel groupPanel = new JPanel(new GridBagLayout()); + groupPanel.setBorder(new LineBorder(Color.black)); + groupCh.setToolTipText(R("PEGrightClick")); + groupCh.addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON3){ + groupPanel.setVisible(!groupPanel.isVisible()); + PolicyEditor.this.validate(); + Container c = PolicyEditor.this.getParent(); + //find the window and repack it + while (!(c instanceof Window)){ + if (c == null){ + return; + } + c = c.getParent(); + } + Window w = (Window) c; + w.pack(); + + } + } + }); + groupCh.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String codebase = getSelectedCodebase(); + if (codebase == null) { + return; + } + List backup = new LinkedList(); + for (final ActionListener l : groupCh.getActionListeners()) { + backup.add(l); + groupCh.removeActionListener(l); + } + final Map map = codebasePermissionsMap.get(codebase); + for (PolicyEditorPermissions p : groupCh.getGroup().getPermissions()) { + map.put(p, groupCh.isSelected()); + } + changesMade = true; + updateCheckboxes(codebase); + for (ActionListener al : backup) { + groupCh.addActionListener(al); + } + + } + }); + add(groupCh, checkboxConstraints); + //place panel with mebers below the title + checkboxConstraints.gridy++; + checkboxConstraints.gridx = 2; + //spread group's panel over two columns + checkboxConstraints.gridwidth = 2; + checkboxConstraints.fill=checkboxConstraints.BOTH; + add(groupPanel, checkboxConstraints); + final GridBagConstraints groupCheckboxLabelConstraints = new GridBagConstraints(); + groupCheckboxLabelConstraints.anchor = GridBagConstraints.LINE_START; + groupCheckboxLabelConstraints.weightx = 0; + groupCheckboxLabelConstraints.weighty = 0; + groupCheckboxLabelConstraints.gridx = 1; + groupCheckboxLabelConstraints.gridy = 1; + for (PolicyEditorPermissions p : g.getPermissions()) { + groupPanel.add(checkboxMap.get(p), groupCheckboxLabelConstraints); + // Two columns of checkboxes + groupCheckboxLabelConstraints.gridx++; + if (groupCheckboxLabelConstraints.gridx > 2) { + groupCheckboxLabelConstraints.gridx = 1; + groupCheckboxLabelConstraints.gridy++; + } + } + groupPanel.setVisible(false); + //reset + checkboxConstraints.gridwidth = 1; + } + final JLabel codebaseListLabel = new JLabel(R("PECodebaseLabel")); codebaseListLabel.setBorder(new EmptyBorder(2, 2, 2, 2)); @@ -892,16 +1041,10 @@ if (e.getValueIsAdjusting()) { return; // ignore first click, act on release } - final String selectedCodebase = (String) list.getSelectedValue(); - if (selectedCodebase == null) { + final String codebase = getSelectedCodebase(); + if (codebase == null) { return; } - final String codebase; - if (selectedCodebase.equals(R("PEGlobalSettings"))) { - codebase = ""; - } else { - codebase = selectedCodebase; - } updateCheckboxes(codebase); } }); @@ -1061,6 +1204,7 @@ } } list.setSelectedIndex(0); + updateCheckboxes(""); try { fileLock.release(); } catch (final IOException e) { diff -r ca18850addad netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditorPermissions.java --- a/netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditorPermissions.java Wed Mar 26 12:07:23 2014 -0400 +++ b/netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditorPermissions.java Wed Mar 26 18:10:17 2014 +0100 @@ -36,10 +36,10 @@ package net.sourceforge.jnlp.security.policyeditor; +import java.util.Map; +import javax.swing.JCheckBox; import static net.sourceforge.jnlp.runtime.Translator.R; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * Defines the set of default permissions for PolicyEditor, ie the ones which are assigned @@ -107,6 +107,94 @@ PRINT(R("PEPrint"), R("PEPrintDetail"), PermissionType.RUNTIME_PERMISSION, PermissionTarget.PRINT, PermissionActions.NONE); + + public static enum Group { + + + AccesUnowenedCode(R("PEGAccesUnowenedCode"), JAVA_REFLECTION, GET_CLASSLOADER, ACCESS_CLASS_IN_PACKAGE, ACCESS_DECLARED_MEMBERS), + MediaAccess(R("PEGMediaAccess"), PLAY_AUDIO, RECORD_AUDIO, PRINT, CLIPBOARD); + + private final PolicyEditorPermissions[] permissions; + private final String title; + private Group(String title, PolicyEditorPermissions... permissions) { + this.title = title; + this.permissions = permissions; + + } + + public static boolean anyContains(PolicyEditorPermissions permission) { + for (Group g : Group.values()) { + if (g.contains(permission)) { + return true; + } + } + return false; + } + + public static boolean anyContains(JCheckBox view, Map checkboxMap) { + for (Map.Entry pairs : checkboxMap.entrySet()){ + if (pairs.getValue() == view) { + for (Group g : Group.values()) { + if (g.contains(pairs.getKey())) { + return true; + } + } + } + } + return false; + } + + /* + * + all is selected + * 0 invalid + * - none is selected + */ + public int getState (final Map map) { + boolean allTrue=true; + boolean allFalse=true; + for (PolicyEditorPermissions pp: getPermissions()){ + Boolean b = map.get(pp); + if (b == null){ + return 0; + } + if (b.booleanValue()){ + allFalse = false; + } else { + allTrue = false; + } + } + if (allFalse){ + return -1; + } + if (allTrue){ + return 1; + } + return 0; + } + + public boolean contains(PolicyEditorPermissions permission) { + for (PolicyEditorPermissions policyEditorPermissions : permissions) { + if (policyEditorPermissions == permission) { + return true; + } + } + return false; + + } + + public String getTitle() { + return title + " ˇ"; + } + + public PolicyEditorPermissions[] getPermissions() { + return permissions; + } + + + + } + + private final String name, description; private final PermissionType type; private final PermissionTarget target;