package org.jivesoftware.openfire.plugin; import org.jivesoftware.openfire.group.Group; 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.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; 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; } }