changeset 953:9de6713da051

Added possibility to group permissions in PolicyEditor gui
author Jiri Vanek <jvanek@redhat.com>
date Wed, 26 Mar 2014 18:46:13 +0100
parents ca18850addad
children 01a37b9ad8cb
files ChangeLog netx/net/sourceforge/jnlp/resources/Messages.properties netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditor.java netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditorPermissions.java
diffstat 4 files changed, 265 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Mar 26 12:07:23 2014 -0400
+++ b/ChangeLog	Wed Mar 26 18:46:13 2014 +0100
@@ -1,3 +1,14 @@
+2014-03-24  Jiri Vanek  <jvanek@redhat.com>
+
+	Added possibility to group permissions in PolicyEditor
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: added groups names
+	* netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditor.java	: (setLayout)
+	added grouping panels and checkboxes. (JcheckBoxWithGroup) New inner class to work
+	with groups.
+	netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditorPermissions.java:
+	Added inner class (Groups) and deffinied (ReadFileSystem) (WriteFileSystem)
+	(AccesUnowenedCode) (MediaAccess)
+
 2014-03-26  Andrew Azores  <aazores@redhat.com>
 
 	* netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditor.java:
--- 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:46:13 2014 +0100
@@ -549,6 +549,12 @@
 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
+PEGReadFileSystem = Read to system
+PEGWriteFileSystem = Write to system
+
 
 # Policy Editor CustomPolicyViewer
 PECPTitle=Custom Policy Viewer
--- 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:46:13 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<String, Map<PolicyEditorPermissions, Boolean>> codebasePermissionsMap = new HashMap<String, Map<PolicyEditorPermissions, Boolean>>();
     private final Map<String, Set<CustomPermission>> customPermissionsMap = new HashMap<String, Set<CustomPermission>>();
     private final Map<PolicyEditorPermissions, JCheckBox> checkboxMap = new TreeMap<PolicyEditorPermissions, JCheckBox>();
+    private final List<JCheckBoxWithGroup> groupBoxList = new ArrayList<JCheckBoxWithGroup>(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<PolicyEditorPermissions, Boolean> map) {
+            List<ActionListener> backup = new LinkedList<ActionListener>();
+            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,89 @@
                 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<ActionListener> backup = new LinkedList<ActionListener>();
+                    for (final ActionListener l : groupCh.getActionListeners()) {
+                        backup.add(l);
+                        groupCh.removeActionListener(l);
+                    }
+                    final Map<PolicyEditorPermissions, Boolean> 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 +1039,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 +1202,7 @@
                     }
                 }
                 list.setSelectedIndex(0);
+                updateCheckboxes("");
                 try {
                     fileLock.release();
                 } catch (final IOException e) {
--- 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:46:13 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,97 @@
     PRINT(R("PEPrint"), R("PEPrintDetail"),
             PermissionType.RUNTIME_PERMISSION, PermissionTarget.PRINT, PermissionActions.NONE);
 
+    
+    public static enum Group {
+
+       
+        ReadFileSystem(R("PEGReadFileSystem"),  READ_LOCAL_FILES, READ_PROPERTIES, READ_SYSTEM_FILES, READ_TMP_FILES, GET_ENV),
+        WriteFileSystem(R("PEGWriteFileSystem"), WRITE_LOCAL_FILES, WRITE_PROPERTIES, WRITE_SYSTEM_FILES, WRITE_TMP_FILES, EXEC_COMMANDS),
+        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<PolicyEditorPermissions, JCheckBox> checkboxMap) {
+            for (Map.Entry<PolicyEditorPermissions, JCheckBox> 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<PolicyEditorPermissions, Boolean> 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;