Commit 461670da authored by conor's avatar conor

added new features to content filter, see changelog.html for details

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@3262 b35dd754-fafc-0310-a699-88a17e54d16e
parent 8e88fb87
...@@ -44,6 +44,19 @@ ...@@ -44,6 +44,19 @@
ContentFilter Plugin Changelog ContentFilter Plugin Changelog
</h1> </h1>
<p><b>1.2</b> -- Jan, 2006</p>
<ul>
<li>Added support to notify administrator by email on content match notification.</li>
<li>Added support to include original packet when sending violation notifications.</li>
<li>Added support to filter users presence status.</li>
<li>Increased size of patterns input area to allow more patterns.</li>
<li>Fixed masking function.</li>
<li>Added debug logging to help users identify problems.</li>
<li>Updated readme.html</li>
</ul>
<p><b>1.0.1</b> -- December 15, 2005</p> <p><b>1.0.1</b> -- December 15, 2005</p>
<ul> <ul>
<li>Now requires Wildfire 2.4.0</li> <li>Now requires Wildfire 2.4.0</li>
......
...@@ -53,7 +53,7 @@ alternative content. ...@@ -53,7 +53,7 @@ alternative content.
<h2>Installation</h2> <h2>Installation</h2>
<p> <p>
Copy the contentfilter.jar into the plugins directory of your Wildfire Copy the contentfilter.jar into the plugins directory of your Jive Messenger
installation. The plugin will then be automatically deployed. To upgrade to a installation. The plugin will then be automatically deployed. To upgrade to a
new version, copy the new contentfilter.jar file over the existing file. new version, copy the new contentfilter.jar file over the existing file.
</p> </p>
...@@ -62,7 +62,7 @@ new version, copy the new contentfilter.jar file over the existing file. ...@@ -62,7 +62,7 @@ new version, copy the new contentfilter.jar file over the existing file.
<p> <p>
By default, after the plugin has been deployed all of its features are disabled. By default, after the plugin has been deployed all of its features are disabled.
This plugin is configured via the "Content Filter" sidebar item located under the This plugin is configured via the "Content Filter" sidebar item located under the
"System" tab in the Wildfire Admin Console. "System" tab in the Jive Messenger Admin Console.
</p> </p>
<p> <p>
...@@ -73,16 +73,28 @@ can be enhanced with more complex regular expressions as required e.g.: ...@@ -73,16 +73,28 @@ can be enhanced with more complex regular expressions as required e.g.:
<ul> <ul>
<li>for a complete word match, add boundary checks with \b e.g. \bfox\b will match against the word "fox" and nothing else. <li>for a complete word match, add boundary checks with \b e.g. \bfox\b will match against the word "fox" and nothing else.
<li>for case insensitive matchs add (?i) e.g. (?i)\bfox\b will match against "fox", "Fox", "foX" etc. <li>for case insensitive matchs add (?i) e.g. (?i)\bfox\b will match against "fox", "Fox", "foX" etc.
<li>it is also possible to group related patterns patterns e.g. fox|dog, this can be used to reduce the number of individual patterns to test for.
</ul> </ul>
</p>
<p>
If you choose to filter your users presence status and there is a content match then:
<ul>
<li>if you are masking content, other users will see a masked status.
<li>if you are rejecting content, other users not see the status change, how it affects the user with the invalid status is client dependant.
</ul>
</p>
<p>
Want to know more about regular expressions in Java? This official <a href="http://java.sun.com/docs/books/tutorial/extra/regex/">tutorial</a> Want to know more about regular expressions in Java? This official <a href="http://java.sun.com/docs/books/tutorial/extra/regex/">tutorial</a>
is useful. is useful.
</p> </p>
<p>
The default mask is "***", you can change it to anything you like including smilies!
</p>
<h2>Using the Plugin</h2> <h2>Using the Plugin</h2>
<p> <p>
After the plugin has been configured, nothing else needs to be done to use it. After the plugin has been configured, nothing else needs to be done to use it.
TODO - update
</p> </p>
</body> </body>
......
/** /**
* $RCSfile$ * $RCSfile$
* $Revision: 1594 $ * $Revision: 1594 $
* $Date: 2005-07-04 14:08:42 -0300 (Mon, 04 Jul 2005) $ * $Date: 2005-07-04 18:08:42 +0100 (Mon, 04 Jul 2005) $
* *
* Copyright (C) 2004 Jive Software. All rights reserved. * Copyright (C) 2004 Jive Software. All rights reserved.
* *
* This software is published under the terms of the GNU Public License (GPL), * This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution. * a copy of which is included in this distribution.
*/ */
package org.jivesoftware.wildfire.plugin; package org.jivesoftware.wildfire.plugin;
import org.xmpp.packet.Message; import java.util.ArrayList;
import java.util.Collection;
import java.util.ArrayList; import java.util.Iterator;
import java.util.Collection; import java.util.regex.Matcher;
import java.util.regex.Matcher; import java.util.regex.Pattern;
import java.util.regex.Pattern;
import org.dom4j.Element;
/** import org.xmpp.packet.Message;
* Filters message content using regular expressions. If a content mask is import org.xmpp.packet.Packet;
* provided message content will be altered.
* /**
* @author Conor Hayes * Filters message content using regular expressions. If a content mask is
*/ * provided message content will be altered.
public class ContentFilter { *
* @author Conor Hayes
private String patterns; */
public class ContentFilter {
private Collection<Pattern> compiledPatterns = new ArrayList<Pattern>();
private String patterns;
private String mask;
private Collection<Pattern> compiledPatterns = new ArrayList<Pattern>();
/** private String mask;
* A default instance will allow all message content.
*
* @see #setPatterns(String) /**
* @see #setMask(String) * A default instance will allow all message content.
*/ *
public ContentFilter() { * @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 /**
*/ * Set the patterns to use for searching content.
public void setPatterns(String patterns) { *
if (patterns != null) { * @param regExps a comma separated String of regular expressions
this.patterns = patterns; */
String[] data = patterns.split(","); public void setPatterns(String patterns) {
if (patterns != null) {
compiledPatterns.clear(); this.patterns = patterns;
String[] data = patterns.split(",");
for (int i = 0; i < data.length; i++) {
compiledPatterns.add(Pattern.compile(data[i])); compiledPatterns.clear();
}
} for (int i = 0; i < data.length; i++) {
else { compiledPatterns.add(Pattern.compile(data[i]));
clearPatterns(); }
} }
else {
} clearPatterns();
}
public String getPatterns() {
return this.patterns; }
}
public String getPatterns() {
/** return this.patterns;
* Clears all patterns. Calling this method means that all message content }
* will be allowed.
*/ /**
public void clearPatterns() { * Clears all patterns. Calling this method means that all message content
patterns = null; * will be allowed.
compiledPatterns.clear(); */
} public void clearPatterns() {
patterns = null;
/** compiledPatterns.clear();
* Set the content replacement mask. }
*
* @param mask the mask to use when replacing content /**
*/ * Set the content replacement mask.
public void setMask(String mask) { *
this.mask = 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; * @return the current mask or null if none has been set
} */
public String getMask() {
/** return mask;
* Clears the content mask. }
*
* @see #filter(Message) /**
*/ * Clears the content mask.
public void clearMask() { *
mask = null; * @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; * @return true if the filter is currently masking content, false otherwise
} */
public boolean isMaskingContent() {
/** return mask != null;
* Filters message content. }
*
* @param msg the message to filter, its subject/body may be altered if there /**
* are content matches and a content mask is set * Filters packet content.
* @return true if the msg content matched up, false otherwise *
*/ * @param packet the packet to filter, its content may be altered if there
public boolean filter(Message msg) { * are content matches and a content mask is set
boolean hasMatch = false; * @return true if the msg content matched up, false otherwise
*/
if (msg.getSubject() != null) { public boolean filter(Packet p) {
if (hasMatch(msg.getSubject())) { return process(p.getElement());
hasMatch = true; }
if (isMaskingContent()) {
String newSubject = replaceContent(msg.getSubject()); private boolean process(Element element) {
msg.setSubject(newSubject);
} boolean matched = mask(element);
}
} if (!matched || isMaskingContent())
{
if (msg.getBody() != null) { //only check children if no match has yet been found
if (hasMatch(msg.getBody())) { //or all content must be masked
hasMatch = true; Iterator iter = element.elementIterator();
if (isMaskingContent()) { while (iter.hasNext()) {
String newBody = replaceContent(msg.getBody()); matched |= process((Element)iter.next());
msg.setBody(newBody); }
} }
}
} return matched;
}
return hasMatch;
} private boolean mask(Element element) {
private String replaceContent(String content) { boolean match = false;
for (Pattern pattern : compiledPatterns) {
Matcher m = pattern.matcher(content); String content = element.getText();
content = m.replaceAll(mask);
} if ((content != null) && (content.length() > 0)) {
return content; for (Pattern pattern : compiledPatterns) {
}
Matcher matcher = pattern.matcher(content);
/**
* Performs sequential search for any pattern match. if (matcher.find()) {
*
* @param content the content to search against match = true;
* @return true if a match is found, false otherwise
*/ if (isMaskingContent()) {
private boolean hasMatch(String content) { content = matcher.replaceAll(mask);
boolean hasMatch = false; element.setText(content);
}
for (Pattern pattern : compiledPatterns) { }
Matcher m = pattern.matcher(content); }
}
if (m.find()) {
hasMatch = true; return match;
break; }
}
} /**
* Applies mask to the given <code>content</code>
return hasMatch; *
} * @param content
* @return masked content
*/
private String mask(String content) {
for (Pattern pattern : compiledPatterns) {
Matcher m = pattern.matcher(content);
content = m.replaceAll(mask);
}
return content;
}
/**
* Applies patterns against the given <code>content</code>. Terminates on
* first match.
*
* @param content the content to search against
* @return true if a match is found, false otherwise
*/
private boolean hasMatch(String content) {
boolean hasMatch = false;
for (Pattern pattern : compiledPatterns) {
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
hasMatch = true;
break;
}
}
return hasMatch;
}
} }
\ No newline at end of file
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