Commit a702d7ef authored by Leon Roy's avatar Leon Roy Committed by leonroy

RESOLVED - issue OF-679: Packet Filter - Add option for "All Groups" and auto...

RESOLVED - issue OF-679: Packet Filter - Add option for "All Groups" and auto creation of rules based on Openfire Group Settings 
http://issues.igniterealtime.org/browse/OF-679

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@13675 b35dd754-fafc-0310-a699-88a17e54d16e
parent bb4ccad1
......@@ -44,6 +44,11 @@
Packet Filter Plugin Changelog
</h1>
<p><b>3.1.0</b> -- June 10, 2013</p>
<ul>
<li>OF-679 - Packet Filter - Add option for "All Groups" and auto creation of rules based on Openfire Group Settings.</li>
</ul>
<p><b>3.0.2</b> -- June 6, 2013</p>
<ul>
<li>OF-680 - Packet Filter Plugin does not allow creation of wildcard rules.</li>
......
......@@ -7,8 +7,8 @@
<name>Packet Filter</name>
<description>Rules to enforce ethical communication</description>
<author>Nate Putnam</author>
<version>3.0.2</version>
<date>6/6/2013</date>
<version>3.1.0</version>
<date>2013/06/10</date>
<minServerVersion>3.7.0</minServerVersion>
<databaseKey>packetfilter</databaseKey>
<databaseVersion>2</databaseVersion>
......
......@@ -64,6 +64,16 @@ of the 1.0 version so I fixed it. The old format of the rules was unworkable wit
a good way to convert from the old format, sorry.
</p>
<h2>Group Rule Auto Creation</h2>
<p>
By default the packet filter plugin will auto-create rules on Shared Group changes ensuring groups can always communicate with each other.
<br/>
To disable this behaviour set the following Openfire System Property to false:
</p>
<ul>
<li>packetfilter.autocreate.grouprules - true/false</li>
</ul>
<h2>Installation</h2>
<p>Copy packetFilter.jar into the plugins directory of your Openfire installation. The
......@@ -150,7 +160,7 @@ packetFilter.jar file over the existing file.</p>
</li>
<li>
Group - All groups defined on your server. The source will match if the sender is a member of the specified
group.
group or if Any Group is selected will match members in any group.
</li>
<li>
Other - This will let you specify a free form JID. (test@example.com). One wild card can be specified to do
......
......@@ -13,4 +13,5 @@ pf.click.down=Move Rule Down
pf.error.sourceOther=Please specify a valid source JID or Domain
pf.error.destOther=Please specify a valid destination JID or Domain
pf.anygroup=Any Group
pf.anyuser=Any User
......@@ -5,123 +5,132 @@ import org.jivesoftware.openfire.group.GroupManager;
import org.jivesoftware.openfire.group.GroupNotFoundException;
import org.jivesoftware.openfire.plugin.rules.Rule;
import org.jivesoftware.openfire.plugin.rules.RuleManager;
import org.xmpp.packet.*;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import org.xmpp.packet.Packet;
import org.xmpp.packet.Presence;
public class PacketFilter {
private static PacketFilter packetFilter = new PacketFilter();
RuleManager ruleManager;
private PacketFilter() {
}
public static PacketFilter getInstance() {
return packetFilter;
}
public void setRuleManager(RuleManager ruleManager) {
this.ruleManager = ruleManager;
}
public Rule findMatch(Packet packet) {
if (packet.getTo() == null || packet.getFrom() == null) return null;
//TODO Would it be better to keep a local copy of the rules?
for (Rule rule : ruleManager.getRules()) {
if (!rule.isDisabled() &&
typeMatch(rule.getPackeType(), packet) &&
sourceDestMatch(rule.getDestType(), rule.getDestination(), packet.getTo()) &&
sourceDestMatch(rule.getSourceType(), rule.getSource(), packet.getFrom())) {
return rule;
}
}
return null;
}
private boolean typeMatch(Rule.PacketType rulePacketType, Packet packet) {
//Simple case. Any.
if (rulePacketType == Rule.PacketType.Any) return true;
else if (packet instanceof Message) {
Message message = (Message) packet;
if (rulePacketType == Rule.PacketType.Message) {
return true;
}
//Try some types.
else if (rulePacketType == Rule.PacketType.MessageChat
&& message.getType() == Message.Type.chat) {
return true;
} else if (rulePacketType == Rule.PacketType.MessageGroupChat
&& message.getType() == Message.Type.groupchat) {
return true;
}
return false;
} else if (packet instanceof Presence) {
if (rulePacketType == Rule.PacketType.Presence) {
return true;
} else return false;
} else if (packet instanceof IQ) {
if (rulePacketType == Rule.PacketType.Iq) {
return true;
} else return false;
}
return false;
}
private boolean sourceDestMatch(Rule.SourceDestType type, String ruleToFrom, JID packetToFrom) {
if (type == Rule.SourceDestType.Any) return true;
if (type == Rule.SourceDestType.User) {
if (ruleToFrom.equals(packetToFrom.toBareJID())) {
return true;
}
} else if (type == Rule.SourceDestType.Group) {
return packetToFromGroup(ruleToFrom, packetToFrom);
} else if (type == Rule.SourceDestType.Component) {
if (ruleToFrom.toLowerCase().equals(packetToFrom.getDomain().toLowerCase())) {
return true;
}
} else if (type == Rule.SourceDestType.Other) {
if (matchUser(ruleToFrom, packetToFrom)) {
return true;
}
}
return false;
}
private boolean matchUser(String ruleToFrom, JID packetToFrom) {
boolean match = false;
//Escape the text so I get a rule to packet match.
// String escapedPacketToFrom = JID.unescapeNode(packetToFrom.toBareJID().toString());
if (ruleToFrom.indexOf("*") == 0 && ruleToFrom.indexOf("@") == 1) {
if (PacketFilterUtil.getDomain(ruleToFrom).equals(packetToFrom.getDomain().toString())) {
match = true;
}
} else {
if (ruleToFrom.equals(packetToFrom.toBareJID())) {
match = true;
}
}
return match;
}
private boolean packetToFromGroup(String rulegroup, JID packetToFrom) {
Group group = null;
try {
group = GroupManager.getInstance().getGroup(rulegroup);
} catch (GroupNotFoundException e) {
e.printStackTrace();
}
if (group == null) {
return false;
} else {
if (group.isUser(packetToFrom)) {
return true;
}
}
return false;
}
private static PacketFilter packetFilter = new PacketFilter();
RuleManager ruleManager;
private PacketFilter() {
}
public static PacketFilter getInstance() {
return packetFilter;
}
public void setRuleManager(RuleManager ruleManager) {
this.ruleManager = ruleManager;
}
public Rule findMatch(Packet packet) {
if (packet.getTo() == null || packet.getFrom() == null)
return null;
// TODO Would it be better to keep a local copy of the rules?
for (Rule rule : ruleManager.getRules()) {
if (!rule.isDisabled() && typeMatch(rule.getPackeType(), packet)
&& sourceDestMatch(rule.getDestType(), rule.getDestination(), packet.getTo())
&& sourceDestMatch(rule.getSourceType(), rule.getSource(), packet.getFrom())) {
return rule;
}
}
return null;
}
private boolean typeMatch(Rule.PacketType rulePacketType, Packet packet) {
// Simple case. Any.
if (rulePacketType == Rule.PacketType.Any)
return true;
else if (packet instanceof Message) {
Message message = (Message) packet;
if (rulePacketType == Rule.PacketType.Message) {
return true;
}
// Try some types.
else if (rulePacketType == Rule.PacketType.MessageChat && message.getType() == Message.Type.chat) {
return true;
} else if (rulePacketType == Rule.PacketType.MessageGroupChat && message.getType() == Message.Type.groupchat) {
return true;
}
return false;
} else if (packet instanceof Presence) {
if (rulePacketType == Rule.PacketType.Presence) {
return true;
} else
return false;
} else if (packet instanceof IQ) {
if (rulePacketType == Rule.PacketType.Iq) {
return true;
} else
return false;
}
return false;
}
private boolean sourceDestMatch(Rule.SourceDestType type, String ruleToFrom, JID packetToFrom) {
if (type == Rule.SourceDestType.Any)
return true;
if (type == Rule.SourceDestType.User) {
if (ruleToFrom.equals(packetToFrom.toBareJID())) {
return true;
}
} else if (type == Rule.SourceDestType.Group) {
return packetToFromGroup(ruleToFrom, packetToFrom);
} else if (type == Rule.SourceDestType.Component) {
if (ruleToFrom.toLowerCase().equals(packetToFrom.getDomain().toLowerCase())) {
return true;
}
} else if (type == Rule.SourceDestType.Other) {
if (matchUser(ruleToFrom, packetToFrom)) {
return true;
}
}
return false;
}
private boolean matchUser(String ruleToFrom, JID packetToFrom) {
boolean match = false;
// Escape the text so I get a rule to packet match.
// String escapedPacketToFrom = JID.unescapeNode(packetToFrom.toBareJID().toString());
if (ruleToFrom.indexOf("*") == 0 && ruleToFrom.indexOf("@") == 1) {
if (PacketFilterUtil.getDomain(ruleToFrom).equals(packetToFrom.getDomain().toString())) {
match = true;
}
} else {
if (ruleToFrom.equals(packetToFrom.toBareJID())) {
match = true;
}
}
return match;
}
private boolean packetToFromGroup(String rulegroup, JID packetToFrom) {
Group group = null;
boolean result = false;
try {
group = GroupManager.getInstance().getGroup(rulegroup);
} catch (GroupNotFoundException e) {
if (PacketFilterConstants.ANY_GROUP.equals(rulegroup)) {
if (!GroupManager.getInstance().getGroups(packetToFrom).isEmpty()) {
result = true;
}
} else {
e.printStackTrace();
}
}
if (group != null) {
if (group.isUser(packetToFrom)) {
result = true;
}
}
return result;
}
}
package org.jivesoftware.openfire.plugin;
public final class PacketFilterConstants {
public static final String ANY_GROUP = "i7o33osvi5tecn42ndicol72dd9ca20f1o6";
public static final String ANY_USER = "4342pd8cpvub2eq4gs46e8f39lejrco7ot9";
private PacketFilterConstants() {
};
public static class Properties {
public static final String AUTOCREATE_GROUP_RULES = "packetfilter.autocreate.grouprules";
}
}
package org.jivesoftware.openfire.plugin;
import java.io.File;
import java.util.Map;
import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.openfire.event.GroupEventDispatcher;
import org.jivesoftware.openfire.interceptor.InterceptorManager;
import org.jivesoftware.openfire.interceptor.PacketInterceptor;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.jivesoftware.openfire.plugin.rules.Rule;
import org.jivesoftware.openfire.plugin.rules.RuleGroupEventListener;
import org.jivesoftware.openfire.plugin.rules.RuleManager;
import org.jivesoftware.openfire.plugin.rules.RuleManagerProxy;
import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.PropertyEventListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.packet.Packet;
public class PacketFilterPlugin implements Plugin, PacketInterceptor {
public class PacketFilterPlugin implements Plugin, PacketInterceptor, PropertyEventListener {
private static final Logger Log = LoggerFactory.getLogger(PacketFilterPlugin.class);
private static PluginManager pluginManager;
public PacketFilterPlugin() {
interceptorManager = InterceptorManager.getInstance();
}
//Packet Filter
private PacketFilter pf;
//Hook for intercpetorn
private InterceptorManager interceptorManager;
public void initializePlugin(PluginManager manager, File pluginDirectory) {
// register with interceptor manager
Log.info("Packet Filter loaded...");
interceptorManager.addInterceptor(this);
pluginManager = manager;
pf = PacketFilter.getInstance();
RuleManager ruleManager = new RuleManagerProxy();
pf.setRuleManager(ruleManager);
}
public void destroyPlugin() {
// unregister with interceptor manager
interceptorManager.removeInterceptor(this);
}
public String getName() {
return "packetFilter";
}
public static PluginManager getPluginManager() {
return pluginManager;
}
public void interceptPacket(Packet packet, Session session, boolean incoming, boolean processed) throws PacketRejectedException {
if (processed) {
return;
}
Rule rule = pf.findMatch(packet);
if (rule != null) {
rule.doAction(packet);
}
}
}
private static PluginManager pluginManager;
public PacketFilterPlugin() {
interceptorManager = InterceptorManager.getInstance();
}
// Packet Filter
private PacketFilter pf;
// Hook for intercpetorn
private InterceptorManager interceptorManager;
private RuleGroupEventListener groupEvListener;
public void initializePlugin(PluginManager manager, File pluginDirectory) {
// register with interceptor manager
Log.info("Packet Filter loaded...");
interceptorManager.addInterceptor(this);
pluginManager = manager;
pf = PacketFilter.getInstance();
RuleManager ruleManager = new RuleManagerProxy();
pf.setRuleManager(ruleManager);
if (JiveGlobals.getBooleanProperty(PacketFilterConstants.Properties.AUTOCREATE_GROUP_RULES, true)) {
groupEvListener = new RuleGroupEventListener();
GroupEventDispatcher.addListener(groupEvListener);
}
}
public void destroyPlugin() {
// unregister with interceptor manager
interceptorManager.removeInterceptor(this);
GroupEventDispatcher.removeListener(groupEvListener);
}
public String getName() {
return "packetFilter";
}
public static PluginManager getPluginManager() {
return pluginManager;
}
public void interceptPacket(Packet packet, Session session, boolean incoming, boolean processed) throws PacketRejectedException {
if (processed) {
return;
}
Rule rule = pf.findMatch(packet);
if (rule != null) {
rule.doAction(packet);
}
}
@Override
public void propertySet(String property, Map<String, Object> params) {
if (property.equals(PacketFilterConstants.Properties.AUTOCREATE_GROUP_RULES)) {
if (Boolean.parseBoolean((String) params.get("value"))) {
GroupEventDispatcher.removeListener(groupEvListener);
groupEvListener = new RuleGroupEventListener();
GroupEventDispatcher.addListener(groupEvListener);
} else {
GroupEventDispatcher.removeListener(groupEvListener);
groupEvListener = null;
}
}
}
@Override
public void propertyDeleted(String property, Map<String, Object> params) {
GroupEventDispatcher.removeListener(groupEvListener);
groupEvListener = new RuleGroupEventListener();
GroupEventDispatcher.addListener(groupEvListener);
}
@Override
public void xmlPropertySet(String property, Map<String, Object> params) {
// TODO Auto-generated method stub
}
@Override
public void xmlPropertyDeleted(String property, Map<String, Object> params) {
// TODO Auto-generated method stub
}
}
package org.jivesoftware.openfire.plugin;
import org.jivesoftware.util.LocaleUtils;
/*
Static util methods.
*/
public class PacketFilterUtil {
/*
Method to get the component part from a jid. The packet could
be from the component itself so just return.
*/
public static String getDomain(String jid) {
if (jid.contains("@")) {
int atIndex = jid.indexOf("@");
return (jid.substring(atIndex+1,jid.length()));
}
else {
return jid;
}
}
Static util methods.
*/
public class PacketFilterUtil {
/*
* Method to get the component part from a jid. The packet could be from the component itself so just return.
*/
public static String getDomain(String jid) {
if (jid.contains("@")) {
int atIndex = jid.indexOf("@");
return (jid.substring(atIndex + 1, jid.length()));
} else {
return jid;
}
}
public static String formatRuleSourceDest(String sourceDest) {
String result = sourceDest;
if (sourceDest != null && PacketFilterConstants.ANY_GROUP.equals(sourceDest)) {
try {
result = LocaleUtils.getPluginResourceBundle("packetFilter").getString("pf.anygroup");
} catch (Exception e) {
result = "Any Group";
}
}
return result;
}
}
package org.jivesoftware.openfire.plugin.rules;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.StringTokenizer;
import org.jivesoftware.openfire.event.GroupEventListener;
import org.jivesoftware.openfire.group.Group;
import org.jivesoftware.openfire.group.GroupManager;
import org.jivesoftware.openfire.group.GroupNotFoundException;
import org.jivesoftware.openfire.plugin.PacketFilterConstants;
import org.jivesoftware.openfire.plugin.rules.Rule.SourceDestType;
import org.jivesoftware.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RuleGroupEventListener implements GroupEventListener {
private static final Logger Log = LoggerFactory.getLogger(RuleGroupEventListener.class);
private RuleManager rm = new RuleManagerProxy();
@Override
public void groupDeleting(Group group, Map params) {
deleteAllAutoCreatedRules(group);
}
public void createPassRule(String source, String destination, String groupName) {
Pass pass = new Pass();
pass.setPacketType(Rule.PacketType.Any);
pass.setDestType(SourceDestType.Group);
pass.setDestination(destination);
pass.setSourceType(SourceDestType.Group);
pass.setSource(source);
pass.isDisabled(false);
pass.doLog(false);
pass.setDescription("Auto created rule for group: " + groupName);
rm.addRule(pass, 1);
Log.debug("Created rule for group: " + groupName + " rule: " + pass);
}
@Override
public void groupModified(Group group, Map params) {
String keyChanged = (String) params.get("propertyKey");
String originalValue = (String) params.get("originalValue");
Log.debug("Group: " + group.getName() + " params: " + params + " originalValue:" + originalValue);
if ("sharedRoster.groupList".equals(keyChanged)) {
String currentValue = group.getProperties().get("sharedRoster.groupList");
if (currentValue != null && !"".equals(currentValue)) {
deleteAllAutoCreatedRules(group);
Collection<Group> groupList = parseGroups(currentValue);
createPassRule(group.getName(), group.getName(), group.getName());
for (Group tmpGroup : groupList) {
createPassRule(tmpGroup.getName(), group.getName(), group.getName());
createPassRule(group.getName(), tmpGroup.getName(), group.getName());
}
}
}
else if ("sharedRoster.showInRoster".equals(keyChanged)) {
String currentValue = group.getProperties().get("sharedRoster.showInRoster");
if ("onlyGroup".equals(currentValue)) {
deleteAllAutoCreatedRules(group);
createPassRule(group.getName(), group.getName(), group.getName());
} else if ("everybody".equals(currentValue)) {
deleteAllAutoCreatedRules(group);
createPassRule(PacketFilterConstants.ANY_GROUP, group.getName(), group.getName());
createPassRule(group.getName(), PacketFilterConstants.ANY_GROUP, group.getName());
} else if ("nobody".equals(currentValue)) {
deleteAllAutoCreatedRules(group);
}
}
}
public void deleteAllAutoCreatedRules(Group group) {
for (Rule rule : rm.getRules()) {
if (Rule.SourceDestType.Group == rule.getSourceType()
&& (group.getName().equals(rule.getSource()) || group.getName().equals(rule.getDestination()))) {
if (rule.getDescription().startsWith("Auto created rule for group: " + group.getName())) {
rm.deleteRule(Integer.valueOf(rule.getRuleId()));
Log.debug("Deleted rule for group: " + group.getName() + " rule: " + rule);
}
}
}
}
@Override
public void groupCreated(Group group, Map params) {
// TODO Auto-generated method stub
}
@Override
public void memberAdded(Group group, Map params) {
// TODO Auto-generated method stub
}
@Override
public void memberRemoved(Group group, Map params) {
// TODO Auto-generated method stub
}
@Override
public void adminAdded(Group group, Map params) {
// TODO Auto-generated method stub
}
@Override
public void adminRemoved(Group group, Map params) {
// TODO Auto-generated method stub
}
/**
* Returns a collection of Groups obtained by parsing a comma delimited String with the name of groups.
*
* @param groupNames
* a comma delimited string with group names.
* @return a collection of Groups obtained by parsing a comma delimited String with the name of groups.
*/
private Collection<Group> parseGroups(String groupNames) {
Collection<Group> answer = new HashSet<Group>();
for (String groupName : parseGroupNames(groupNames)) {
try {
answer.add(GroupManager.getInstance().getGroup(groupName));
} catch (GroupNotFoundException e) {
// Do nothing. Silently ignore the invalid reference to the group
}
}
return answer;
}
/**
* Returns a collection of Groups obtained by parsing a comma delimited String with the name of groups.
*
* @param groupNames
* a comma delimited string with group names.
* @return a collection of Groups obtained by parsing a comma delimited String with the name of groups.
*/
private static Collection<String> parseGroupNames(String groupNames) {
Collection<String> answer = new HashSet<String>();
if (groupNames != null) {
StringTokenizer tokenizer = new StringTokenizer(groupNames, ",");
while (tokenizer.hasMoreTokens()) {
answer.add(tokenizer.nextToken());
}
}
return answer;
}
}
......@@ -20,7 +20,7 @@ public class RuleManagerProxy implements RuleManager {
}
public void addRule(Rule rule, Integer order) {
dbRuleManager.addRule(rule, order);
}
public void addRule(Rule rule) {
......
<%@page import="org.jivesoftware.openfire.plugin.PacketFilterUtil"%>
<%@ page import="org.jivesoftware.util.*"%>
<%@ page import="org.jivesoftware.openfire.plugin.rules.RuleManagerProxy" %>
<%@ page import="org.jivesoftware.openfire.plugin.rules.Rule" %>
......@@ -36,7 +37,7 @@
</head>
<body>
You have choosen to delete the rule form <%=rule.getSource()%> to <%=rule.getDestination()%>. Are you sure?
You have choosen to delete the rule form <%=PacketFilterUtil.formatRuleSourceDest(rule.getSource())%> to <%=rule.getDestination()%>. Are you sure?
<br>
<br>
......
<%@page import="org.jivesoftware.openfire.plugin.PacketFilterUtil"%>
<%@ page import="org.jivesoftware.openfire.component.InternalComponentManager,
org.jivesoftware.openfire.plugin.component.ComponentList,
org.jivesoftware.openfire.plugin.rules.Rule,
......@@ -82,8 +83,7 @@
&& componentManager.getComponentName(new JID(rule.getSource()))!= null) { %>
<td><%=componentManager.getComponentName(new JID(rule.getSource()))%></td>
<% } else {%>
<td><%=rule.getSource()%></td>
<td><%=PacketFilterUtil.formatRuleSourceDest(rule.getSource())%></td>
<%}%>
<% if (rule.isDisabled()) { %>
<td><strike><%=rule.getDestination()%></strike></td>
......@@ -91,7 +91,7 @@
&& componentManager.getComponentName(new JID(rule.getDestination()))!= null) {%>
<td><%=componentManager.getComponentName(new JID(rule.getDestination()))%></td>
<% }else {%>
<td><%=rule.getDestination()%></td>
<td><%=PacketFilterUtil.formatRuleSourceDest(rule.getDestination())%></td>
<%}%>
<% if (rule.isDisabled()) { %>
<td><strike><%=rule.getPackeType()%></strike></td>
......
<%@page import="org.jivesoftware.openfire.plugin.PacketFilterConstants"%>
<%@ page import="org.jivesoftware.openfire.XMPPServer,
org.jivesoftware.openfire.component.InternalComponentManager,
org.jivesoftware.openfire.group.Group,
......@@ -343,6 +344,10 @@
><%=group.getName()%>
</option>
<%}%>
<option value="<%=PacketFilterConstants.ANY_GROUP%>" <%if (isSourceGroup && source.equals(PacketFilterConstants.ANY_GROUP)) {%>
selected<%}%>
><fmt:message key="pf.anygroup" />
</option>
</select>
</td>
</tr>
......@@ -425,6 +430,10 @@
><%=group.getName()%>
</option>
<%}%>
<option value="<%=PacketFilterConstants.ANY_GROUP%>" <%if (isDestGroup && destination.equals(PacketFilterConstants.ANY_GROUP)) {%>
selected<%}%>
><fmt:message key="pf.anygroup" />
</option>
</select>
</td>
</tr>
......
<%@page import="org.jivesoftware.openfire.plugin.PacketFilterConstants"%>
<%@ page import="org.jivesoftware.openfire.XMPPServer,
org.jivesoftware.openfire.group.Group"
%>
......@@ -18,7 +19,6 @@
webManager.init(request, response, session, application, out);
Collection<Group> groups = webManager.getGroupManager().getGroups();
ComponentList cList = ComponentList.getInstance();
RuleManager rm = new RuleManagerProxy();
Rule rule = null;
......@@ -278,6 +278,10 @@
><%=group.getName()%>
</option>
<%}%>
<option value="<%=PacketFilterConstants.ANY_GROUP%>" <%if (sourceJID != null && sourceJID.equals(PacketFilterConstants.ANY_GROUP)) {%>
selected<%}%>
><fmt:message key="pf.anygroup" />
</option>
</select>
</td>
</tr>
......@@ -411,6 +415,10 @@
><%=group.getName()%>
</option>
<%}%>
<option value="<%=PacketFilterConstants.ANY_GROUP%>" <%if (sourceJID != null && sourceJID.equals(PacketFilterConstants.ANY_GROUP)) {%>
selected<%}%>
><fmt:message key="pf.anygroup" />
</option>
</select>
</td>
</tr>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment