/* * Copyright (C) 2004-2008 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jivesoftware.openfire.plugin; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.dom4j.Element; import org.xmpp.packet.Message; import org.xmpp.packet.Packet; /** * Filters message content using regular expressions. If a content mask is * provided message content will be altered. * * @author Conor Hayes */ public class ContentFilter { private String patterns; private Collection<Pattern> compiledPatterns = new ArrayList<Pattern>(); private String mask; /** * A default instance will allow all message content. * * @see #setPatterns(String) * @see #setMask(String) */ public ContentFilter() { } /** * Set the patterns to use for searching content. * * @param regExps a comma separated String of regular expressions */ public void setPatterns(String patterns) { if (patterns != null) { this.patterns = patterns; String[] data = patterns.split(","); compiledPatterns.clear(); for (int i = 0; i < data.length; i++) { compiledPatterns.add(Pattern.compile(data[i])); } } else { clearPatterns(); } } public String getPatterns() { return this.patterns; } /** * Clears all patterns. Calling this method means that all message content * will be allowed. */ public void clearPatterns() { patterns = null; compiledPatterns.clear(); } /** * Set the content replacement mask. * * @param mask the mask to use when replacing content */ public void setMask(String mask) { this.mask = mask; } /** * @return the current mask or null if none has been set */ public String getMask() { return mask; } /** * Clears the content mask. * * @see #filter(Message) */ public void clearMask() { mask = null; } /** * @return true if the filter is currently masking content, false otherwise */ public boolean isMaskingContent() { return mask != null; } /** * Filters packet content. * * @param packet the packet to filter, its content may be altered if there * are content matches and a content mask is set * @return true if the msg content matched up, false otherwise */ public boolean filter(Packet p) { return process(p.getElement()); } private boolean process(Element element) { boolean matched = mask(element); if (!matched || isMaskingContent()) { //only check children if no match has yet been found //or all content must be masked Iterator<Element> iter = element.elementIterator(); while (iter.hasNext()) { matched |= process(iter.next()); } } return matched; } private boolean mask(Element element) { boolean match = false; String content = element.getText(); if ((content != null) && (content.length() > 0)) { for (Pattern pattern : compiledPatterns) { Matcher matcher = pattern.matcher(content); if (matcher.find()) { match = true; if (isMaskingContent()) { content = matcher.replaceAll(mask); element.setText(content); } } } } return match; } }