1 package org.jivesoftware.openfire.pubsub;
2 
3 import org.jivesoftware.openfire.XMPPServer;
4 import org.jivesoftware.openfire.group.Group;
5 import org.jivesoftware.openfire.group.GroupManager;
6 import org.jivesoftware.openfire.group.GroupNotFoundException;
7 import org.jivesoftware.openfire.user.UserManager;
8 import org.jivesoftware.util.LocaleUtils;
9 import org.jivesoftware.util.ParamUtils;
10 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory;
12 import org.xmpp.forms.DataForm;
13 import org.xmpp.forms.FormField;
14 import org.xmpp.packet.JID;
15 
16 import java.util.*;
17 
18 import javax.servlet.http.HttpServletRequest;
19 
20 public class PubSubServiceInfo {
21 
22     private static final Logger Log = LoggerFactory.getLogger(PubSubServiceInfo.class);
23 
24     private PubSubService pubSubService;
25 
26     private PubSubModule pubSubModule;
27     private XMPPServer xmppServer;
28     private UserManager userManager;
29     private GroupManager groupManager;
30 
31     private String labelPreFix = "pubsub.service.form.";
32     private String variablePreFix = "pubsub#";
33 
PubSubServiceInfo(PubSubService pubSubService)34     public PubSubServiceInfo(PubSubService pubSubService) {
35         if (pubSubService == null) {
36             throw new IllegalArgumentException("Argument 'pubSubService' cannot be null.");
37         }
38         this.pubSubService = pubSubService;
39 
40         xmppServer = XMPPServer.getInstance();
41         pubSubModule = xmppServer.getPubSubModule();
42         groupManager = GroupManager.getInstance();
43         userManager = xmppServer.getUserManager();
44     }
45 
getNodes()46     public Collection<Node> getNodes() {
47         return pubSubService.getNodes();
48     }
49 
getNode(String nodeID)50     public Node getNode(String nodeID) {
51         return pubSubService.getNode(nodeID);
52     }
53 
getLeafNodes()54     public List<Node> getLeafNodes() {
55         List<Node> leafNodes = new ArrayList<Node>();
56         for (Node node : pubSubService.getNodes()) {
57             if (!node.isCollectionNode()) {
58                 leafNodes.add(node);
59             }
60         }
61         return leafNodes;
62     }
63 
getRootCollectionNode()64     public CollectionNode getRootCollectionNode() {
65         return pubSubService.getRootCollectionNode();
66     }
67 
getServiceID()68     public String getServiceID() {
69         return pubSubService.getServiceID();
70     }
71 
72     /*
73      * Returns a DataForm for configuring the pubsub service. Configurable fields
74      * 'serviceEnabled', 'nodeCreationRestricted', 'allowedToCreate', 'sysadmins'
75      * Some fields which appear to be configurable on the PubSubService interface
76      * are not configurable due to the PubSubModule implementation these include:
77      * 'MultipleSubscriptionsEnabled', 'InstantNodeSupported',
78      * 'CollectionNodesSupported' they are therefore not included on the form.
79      */
getServiceConfigurationForm()80     public DataForm getServiceConfigurationForm() {
81 
82         DataForm form = new DataForm(DataForm.Type.result);
83 
84         FormField formField = form.addField();
85         formField.setVariable(variablePreFix + "serviceEnabled");
86         formField.setType(FormField.Type.boolean_type);
87         formField.setLabel(LocaleUtils.getLocalizedString(labelPreFix + "serviceEnabled"));
88         formField.addValue(pubSubModule.isServiceEnabled());
89 
90         formField = form.addField();
91         formField.setVariable(variablePreFix + "nodeCreationRestricted");
92         formField.setType(FormField.Type.boolean_type);
93         formField.setLabel(LocaleUtils.getLocalizedString(labelPreFix + "nodeCreationRestricted"));
94         formField.addValue(pubSubModule.isNodeCreationRestricted());
95 
96         formField = form.addField();
97         formField.setVariable(variablePreFix + "allowedToCreate");
98         formField.setType(FormField.Type.jid_multi);
99         formField.setLabel(LocaleUtils.getLocalizedString(labelPreFix + "allowedToCreate"));
100         for (JID jid : pubSubModule.getUsersAllowedToCreate()) {
101             formField.addValue(jid);
102         }
103 
104         formField = form.addField();
105         formField.setVariable(variablePreFix + "sysadmins");
106         formField.setType(FormField.Type.jid_multi);
107         formField.setLabel(LocaleUtils.getLocalizedString(labelPreFix + "sysadmins"));
108         for (JID jid : pubSubModule.getSysadmins()) {
109             formField.addValue(jid);
110         }
111 
112         return form;
113     }
114 
getValidJID(String username)115     public JID getValidJID(String username) {
116         if (username != null && !username.isEmpty()) {
117             try {
118                 if (username.contains("@")) {
119                     JID jid = new JID(username);
120                     if (userManager.isRegisteredUser(jid, true)) {
121                         return jid;
122                     }
123                 } else {
124                     // Assume that the value refers to a user on the local server.
125                     final JID jid = xmppServer.createJID(username, null);
126                     if (userManager.isRegisteredUser(jid, false)) {
127                         return jid;
128                     }
129                 }
130             } catch (IllegalArgumentException e) {
131                 Log.debug("Unable to parse value '{}' as a JID.", username);
132             }
133         }
134         // Return null if JID is invalid or user not registered
135         return null;
136     }
137 
isValidGroup(String groupName)138     public boolean isValidGroup(String groupName) {
139         if (groupName != null && !groupName.isEmpty()) {
140             try {
141                 Group group = groupManager.getGroup(groupName);
142                 if (group != null) {
143                     return true;
144                 }
145             } catch (GroupNotFoundException e) {
146                 Log.debug("Group with name '{}' not found", groupName);
147             }
148         }
149         return false;
150     }
151 
processForm(DataForm form, HttpServletRequest request, Collection<String> excludedFields)152     public DataForm processForm(DataForm form, HttpServletRequest request, Collection<String> excludedFields) {
153 
154         DataForm completedForm = new DataForm(DataForm.Type.submit);
155 
156         for (FormField field : form.getFields()) {
157 
158             if (excludedFields == null || !excludedFields.contains(field.getVariable())) {
159 
160                 FormField completedField = completedForm.addField(field.getVariable(), field.getLabel(), field.getType());
161 
162                 switch (field.getType()) {
163                 case boolean_type:
164                     completedField.addValue(ParamUtils.getBooleanParameter(request, field.getVariable()));
165                     break;
166                 case jid_multi:
167                     for (String param : ParamUtils.getParameters(request, field.getVariable())) {
168                         completedField.addValue(param);
169                     }
170                     break;
171                 case list_multi:
172                     for (String param : ParamUtils.getParameters(request, field.getVariable())) {
173                         completedField.addValue(param);
174                     }
175                     break;
176                 case list_single:
177                     completedField.addValue(ParamUtils.getParameter(request, field.getVariable()));
178                     break;
179                 case text_single:
180                     completedField.addValue(ParamUtils.getParameter(request, field.getVariable()));
181                     break;
182                 default:
183                     break;
184                 }
185 
186                 for(FormField.Option option: field.getOptions()) {
187                     completedField.addOption(option.getLabel(), option.getValue());
188                 }
189 
190             }
191         }
192         return completedForm;
193     }
194 
configureService(DataForm form)195     public void configureService(DataForm form) {
196 
197         for (FormField field : form.getFields()) {
198             switch (field.getVariable().substring(field.getVariable().indexOf("#") + 1)) {
199             case "serviceEnabled":
200                 if (field.getFirstValue() != null) {
201                     pubSubModule.setServiceEnabled("1".equals(field.getFirstValue()));
202                 }
203                 break;
204             case "nodeCreationRestricted":
205                 if (field.getFirstValue() != null) {
206                     pubSubModule.setNodeCreationRestricted("1".equals(field.getFirstValue()));
207                 }
208                 break;
209             case "allowedToCreate":
210                 final Set<JID> allAllowed = new HashSet<>();
211                 for ( final String value : field.getValues() ) {
212                     try {
213                         allAllowed.add( new JID(value.trim()) );
214                     } catch ( IllegalArgumentException e ) {
215                         Log.warn( "Unable to add to 'allowedToCreate'. Value is not a valid JID: {}", value, e);
216                     }
217                 }
218                 pubSubModule.setUserAllowedToCreate(allAllowed);
219                 break;
220             case "sysadmins":
221                 final Set<JID> sysadmins = new HashSet<>();
222                 for ( final String value : field.getValues() ) {
223                     try {
224                         sysadmins.add( new JID(value.trim()) );
225                     } catch ( IllegalArgumentException e ) {
226                         Log.warn( "Unable to add to 'sysadmins'. Value is not a valid JID: {}", value, e);
227                     }
228                 }
229                 pubSubModule.setSysadmins(sysadmins);
230                 break;
231             default:
232                 // Shouldn't end up here
233                 break;
234             }
235         }
236     }
237 
validateAdditions(DataForm form, HttpServletRequest request, Map<String, listType> listTypes, Map<String, String> errors)238     public void validateAdditions(DataForm form, HttpServletRequest request, Map<String, listType> listTypes,
239             Map<String, String> errors) {
240 
241         for (FormField field : form.getFields()) {
242             if (listTypes.containsKey(field.getVariable())) {
243                 switch (listTypes.get(field.getVariable())) {
244                 case group:
245                     if (ParamUtils.getParameter(request, field.getVariable() + "-Add") != null) {
246                         String groupName = ParamUtils.getParameter(request, field.getVariable() + "-Additional");
247                         if (isValidGroup(groupName)) {
248 
249                             if (!field.getValues().contains(groupName)) {
250                                 field.addValue(groupName);
251                             } else {
252                                 // Group already in list
253                                 errors.put(field.getVariable(), LocaleUtils.getLocalizedString(
254                                         "pubsub.form.already_in_list",
255                                         Arrays.asList(LocaleUtils.getLocalizedString("pubsub.form.group"), groupName)));
256                             }
257                         } else {
258                             // Not a valid group
259                             errors.put(field.getVariable(), LocaleUtils.getLocalizedString("pubsub.form.not_valid",
260                                     Arrays.asList(groupName, LocaleUtils.getLocalizedString("pubsub.form.group"))));
261                         }
262                     }
263 
264                     break;
265                 case user:
266                     if (ParamUtils.getParameter(request, field.getVariable() + "-Add") != null) {
267                         String username = ParamUtils.getParameter(request, field.getVariable() + "-Additional");
268                         JID newUser = getValidJID(username);
269                         if (newUser != null) {
270 
271                             if (!field.getValues().contains(newUser.toBareJID())) {
272                                 field.addValue(newUser.toBareJID());
273                             } else {
274                                 // User already in list
275                                 errors.put(field.getVariable(), LocaleUtils.getLocalizedString(
276                                         "pubsub.form.already_in_list",
277                                         Arrays.asList(LocaleUtils.getLocalizedString("pubsub.form.user"), username)));
278                             }
279                         } else {
280                             // Not a valid username
281                             errors.put(field.getVariable(), LocaleUtils.getLocalizedString("pubsub.form.not_valid",
282                                     Arrays.asList(username, LocaleUtils.getLocalizedString("pubsub.form.user"))));
283                         }
284                     }
285                     break;
286                 default:
287                     break;
288                 }
289             }
290         }
291     }
292 
293     public enum listType {
294         user, group;
295     }
296 
297 }
298