Commit cb47d55c authored by conor's avatar conor

Added spy mode function, factory function. See change log for details

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@3854 b35dd754-fafc-0310-a699-88a17e54d16e
parent 25c69637
...@@ -44,6 +44,13 @@ ...@@ -44,6 +44,13 @@
ContentFilter Plugin Changelog ContentFilter Plugin Changelog
</h1> </h1>
<p><b>1.3</b> -- May 8, 2006</p>
<ul>
<li>Added ability to allow messages even when content has matched (thanks to Eduardo for the <a href="http://www.jivesoftware.org/community/message.jspa?messageID=118198">feature request</a>)</li>
<li>Added ability to restore plugin to its factory defaults.
</ul>
<p><b>1.2.2</b> -- January 26, 2006</p> <p><b>1.2.2</b> -- January 26, 2006</p>
<ul> <ul>
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
<name>Content Filter</name> <name>Content Filter</name>
<description>Scans message packets for defined patterns</description> <description>Scans message packets for defined patterns</description>
<author>Conor Hayes</author> <author>Conor Hayes</author>
<version>1.2.2</version> <version>1.3</version>
<date>01/26/2006</date> <date>05/08/2006</date>
<minServerVersion>2.4.0</minServerVersion> <minServerVersion>2.4.0</minServerVersion>
<!-- UI extension --> <!-- UI extension -->
......
...@@ -117,6 +117,14 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor { ...@@ -117,6 +117,14 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor {
* ignored. The default value is "**". * ignored. The default value is "**".
*/ */
public static final String MASK_PROPERTY = "plugin.contentFilter.mask"; public static final String MASK_PROPERTY = "plugin.contentFilter.mask";
/**
* The expected value is a boolean, if false packets whose contents matches one
* of the supplied regular expressions will be rejected, otherwise the packet will
* be accepted and may be optionally masked. The default value is false.
* @see #MASK_ENABLED_PROPERTY
*/
public static final String ALLOW_ON_MATCH_PROPERTY = "plugin.contentFilter.allow.on.match";
/** /**
* the hook into the inteceptor chain * the hook into the inteceptor chain
...@@ -193,7 +201,12 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor { ...@@ -193,7 +201,12 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor {
* the mask to use * the mask to use
*/ */
private String mask; private String mask;
/**
* flag if matching content should be accepted or rejected.
*/
private boolean allowOnMatch;
/** /**
* violation notification messages will be from this JID * violation notification messages will be from this JID
*/ */
...@@ -207,6 +220,37 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor { ...@@ -207,6 +220,37 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor {
messageRouter = XMPPServer.getInstance().getMessageRouter(); messageRouter = XMPPServer.getInstance().getMessageRouter();
} }
/**
* Restores the plugin defaults.
*/
public void reset() {
setViolationNotificationEnabled(false);
setViolationContact("admin");
setViolationNotificationByIMEnabled(true);
setViolationNotificationByEmailEnabled(false);
setViolationIncludeOriginalPacketEnabled(false);
setRejectionNotificationEnabled(false);
setRejectionMessage("Message rejected. This is an automated server response");
setPatternsEnabled(false);
setPatterns("fox,dog");
setFilterStatusEnabled(false);
setMaskEnabled(false);
setMask("***");
setAllowOnMatch(false);
}
public boolean isAllowOnMatch() {
return allowOnMatch;
}
public void setAllowOnMatch(boolean allow) {
allowOnMatch = allow;
JiveGlobals.setProperty(ALLOW_ON_MATCH_PROPERTY, allow ? "true"
: "false");
changeContentFilterMask();
}
public boolean isMaskEnabled() { public boolean isMaskEnabled() {
return maskEnabled; return maskEnabled;
} }
...@@ -227,7 +271,7 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor { ...@@ -227,7 +271,7 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor {
} }
private void changeContentFilterMask() { private void changeContentFilterMask() {
if (maskEnabled) { if (allowOnMatch && maskEnabled) {
contentFilter.setMask(mask); contentFilter.setMask(mask);
} else { } else {
contentFilter.clearMask(); contentFilter.clearMask();
...@@ -398,7 +442,7 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor { ...@@ -398,7 +442,7 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor {
changeContentFilterPatterns(); changeContentFilterPatterns();
} }
catch (PatternSyntaxException e) { catch (PatternSyntaxException e) {
Log.warn("Reseting to default patterns of ContentFilterPlugin", e); Log.warn("Resetting to default patterns of ContentFilterPlugin", e);
// Existing patterns are invalid so reset to default ones // Existing patterns are invalid so reset to default ones
setPatterns("fox,dog"); setPatterns("fox,dog");
} }
...@@ -409,11 +453,20 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor { ...@@ -409,11 +453,20 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor {
// default to false // default to false
maskEnabled = JiveGlobals.getBooleanProperty(MASK_ENABLED_PROPERTY, maskEnabled = JiveGlobals.getBooleanProperty(MASK_ENABLED_PROPERTY,
false); false);
// default to "***" // default to "***"
mask = JiveGlobals.getProperty(MASK_PROPERTY, "***"); mask = JiveGlobals.getProperty(MASK_PROPERTY, "***");
// default to false
allowOnMatch = JiveGlobals.getBooleanProperty(
ALLOW_ON_MATCH_PROPERTY, false);
//v1.2.2 backwards compatibility
if (maskEnabled) {
allowOnMatch = true;
}
changeContentFilterMask(); changeContentFilterMask();
} }
...@@ -460,24 +513,27 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor { ...@@ -460,24 +513,27 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor {
+ this.violationIncludeOriginalPacketEnabled); + this.violationIncludeOriginalPacketEnabled);
} }
// TODO consider spining off a separate thread here,
// in high volume situations, it will result in
// in faster response and notification is not required
// to be real time.
sendViolationNotification(original); sendViolationNotification(original);
} }
// msg will either be rejected silently, rejected with // msg will either be rejected silently, rejected with
// some notification to sender, or masked. // some notification to sender, or allowed and optionally masked.
// allowing a message without masking can be useful if the admin
// simply wants to get notified of matches without interrupting
// the conversation in the (spy mode!)
if (contentMatched) { if (contentMatched) {
if (maskEnabled) {
// masking enabled, no further action required if (allowOnMatch) {
if (Log.isDebugEnabled()) { if (Log.isDebugEnabled()) {
Log.debug("Content filter: masked content:" Log.debug("Content filter: allowed content:"
+ packet.toString()); + packet.toString());
} }
// no further action required
} else { } else {
// no masking, msg must be rejected // msg must be rejected
if (Log.isDebugEnabled()) { if (Log.isDebugEnabled()) {
Log.debug("Content filter: rejecting packet"); Log.debug("Content filter: rejecting packet");
} }
...@@ -517,8 +573,7 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor { ...@@ -517,8 +573,7 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor {
+ " to:" + " to:"
+ originalMsg.getTo() + originalMsg.getTo()
+ ", message was " + ", message was "
+ (contentFilter.isMaskingContent() ? "altered." + (allowOnMatch ? "allowed" + (contentFilter.isMaskingContent() ? " and masked." : " but not masked.") : "rejected.")
: "rejected.")
+ (violationIncludeOriginalPacketEnabled ? "\nOriginal subject:" + (violationIncludeOriginalPacketEnabled ? "\nOriginal subject:"
+ (originalMsg.getSubject() != null ? originalMsg + (originalMsg.getSubject() != null ? originalMsg
.getSubject() : "") .getSubject() : "")
...@@ -533,8 +588,7 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor { ...@@ -533,8 +588,7 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor {
body = "Disallowed status detected in presence from:" body = "Disallowed status detected in presence from:"
+ originalPresence.getFrom() + originalPresence.getFrom()
+ ", status was " + ", status was "
+ (contentFilter.isMaskingContent() ? "altered." + (allowOnMatch ? "allowed" + (contentFilter.isMaskingContent() ? " and masked." : " but not masked.") : "rejected.")
: "rejected.")
+ (violationIncludeOriginalPacketEnabled ? "\nOriginal status:" + (violationIncludeOriginalPacketEnabled ? "\nOriginal status:"
+ originalPresence.getStatus() + originalPresence.getStatus()
: ""); : "");
...@@ -559,6 +613,10 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor { ...@@ -559,6 +613,10 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor {
private void sendViolationNotificationIM(String subject, String body) { private void sendViolationNotificationIM(String subject, String body) {
Message message = createServerMessage(subject, body); Message message = createServerMessage(subject, body);
// TODO consider spining off a separate thread here,
// in high volume situations, it will result in
// in faster response and notification is not required
// to be real time.
messageRouter.route(message); messageRouter.route(message);
} }
...@@ -575,6 +633,8 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor { ...@@ -575,6 +633,8 @@ public class ContentFilterPlugin implements Plugin, PacketInterceptor {
private void sendViolationNotificationEmail(String subject, String body) { private void sendViolationNotificationEmail(String subject, String body) {
try { try {
User user = UserManager.getInstance().getUser(violationContact); User user = UserManager.getInstance().getUser(violationContact);
//this is automatically put on a another thread for execution.
EmailService.getInstance().sendMessage(user.getName(), user.getEmail(), "Wildfire", EmailService.getInstance().sendMessage(user.getName(), user.getEmail(), "Wildfire",
"no_reply@" + violationNotificationFrom.getDomain(), subject, body, null); "no_reply@" + violationNotificationFrom.getDomain(), subject, body, null);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
<% <%
boolean save = request.getParameter("save") != null; boolean save = request.getParameter("save") != null;
boolean reset = request.getParameter("reset") !=null;
boolean success = request.getParameter("success") != null; boolean success = request.getParameter("success") != null;
//filter options //filter options
...@@ -19,8 +20,10 @@ ...@@ -19,8 +20,10 @@
String [] filterStatusChecked = ParamUtils.getParameters(request, "filterstatus"); String [] filterStatusChecked = ParamUtils.getParameters(request, "filterstatus");
boolean filterStatusEnabled = filterStatusChecked.length > 0; boolean filterStatusEnabled = filterStatusChecked.length > 0;
//mask options //match options
boolean maskEnabled = ParamUtils.getBooleanParameter(request, "maskenabled"); boolean allowOnMatch = ParamUtils.getBooleanParameter(request, "allowonmatch");
String [] maskChecked = ParamUtils.getParameters(request, "maskenabled");
boolean maskEnabled = maskChecked.length > 0;
String mask = ParamUtils.getParameter(request, "mask"); String mask = ParamUtils.getParameter(request, "mask");
//rejection options //rejection options
...@@ -92,6 +95,7 @@ ...@@ -92,6 +95,7 @@
plugin.setPatternsEnabled(patternsEnabled); plugin.setPatternsEnabled(patternsEnabled);
plugin.setPatterns(patterns); plugin.setPatterns(patterns);
plugin.setFilterStatusEnabled(filterStatusEnabled); plugin.setFilterStatusEnabled(filterStatusEnabled);
plugin.setAllowOnMatch(allowOnMatch);
plugin.setMaskEnabled(maskEnabled); plugin.setMaskEnabled(maskEnabled);
plugin.setMask(mask); plugin.setMask(mask);
plugin.setViolationNotificationEnabled(notificationEnabled); plugin.setViolationNotificationEnabled(notificationEnabled);
...@@ -104,6 +108,9 @@ ...@@ -104,6 +108,9 @@
response.sendRedirect("contentfilter-props-edit-form.jsp?success=true"); response.sendRedirect("contentfilter-props-edit-form.jsp?success=true");
return; return;
} }
} else if (reset) {
plugin.reset();
response.sendRedirect("contentfilter-props-edit-form.jsp?success=true");
} else { } else {
patterns = plugin.getPatterns(); patterns = plugin.getPatterns();
mask = plugin.getMask(); mask = plugin.getMask();
...@@ -123,6 +130,7 @@ ...@@ -123,6 +130,7 @@
patternsEnabled = plugin.isPatternsEnabled(); patternsEnabled = plugin.isPatternsEnabled();
filterStatusEnabled = plugin.isFilterStatusEnabled(); filterStatusEnabled = plugin.isFilterStatusEnabled();
allowOnMatch = plugin.isAllowOnMatch();
maskEnabled = plugin.isMaskEnabled(); maskEnabled = plugin.isMaskEnabled();
notificationEnabled = plugin.isViolationNotificationEnabled(); notificationEnabled = plugin.isViolationNotificationEnabled();
rejectionNotificationEnabled = plugin.isRejectionNotificationEnabled(); rejectionNotificationEnabled = plugin.isRejectionNotificationEnabled();
...@@ -168,7 +176,7 @@ Use the form below to edit content filter settings.<br> ...@@ -168,7 +176,7 @@ Use the form below to edit content filter settings.<br>
<% } %> <% } %>
<form action="contentfilter-props-edit-form.jsp?save" method="post"> <form action="contentfilter-props-edit-form.jsp" method="post">
<fieldset> <fieldset>
<legend>Filter</legend> <legend>Filter</legend>
...@@ -229,31 +237,31 @@ Use the form below to edit content filter settings.<br> ...@@ -229,31 +237,31 @@ Use the form below to edit content filter settings.<br>
<br><br> <br><br>
<fieldset> <fieldset>
<legend>Content Mask</legend> <legend>On Content Match</legend>
<div> <div>
<p> <p>
Enable this feature to alter packet content when there is a pattern match. Configure this feature to reject or allow (and optionally mask) packet content when there is a match.
</p> </p>
<table cellpadding="3" cellspacing="0" border="0" width="100%"> <table cellpadding="3" cellspacing="0" border="0" width="100%">
<tbody> <tbody>
<tr> <tr>
<td width="1%"> <td width="1%">
<input type="radio" name="maskenabled" value="false" id="not03" <input type="radio" name="allowonmatch" value="false" id="not03"
<%= ((maskEnabled) ? "" : "checked") %>> <%= ((allowOnMatch) ? "" : "checked") %>>
</td> </td>
<td width="99%"> <td width="99%">
<label for="not01"><b>Disabled</b></label> - Packets will be rejected. <label for="not01"><b>Reject</b></label> - Packets will be rejected.
</td> </td>
</tr> </tr>
<tr> <tr>
<td width="1%"> <td width="1%">
<input type="radio" name="maskenabled" value="true" id="not04" <input type="radio" name="allowonmatch" value="true" id="not04"
<%= ((maskEnabled) ? "checked" : "") %>> <%= ((allowOnMatch) ? "checked" : "") %>>
</td> </td>
<td width="99%"> <td width="99%">
<label for="not02"><b>Enabled</b></label> - Packets will be masked. <label for="not02"><b>Allow</b></label> - Packets will be allowed.
</td> </td>
</tr> </tr>
<tr> <tr>
...@@ -268,6 +276,10 @@ Use the form below to edit content filter settings.<br> ...@@ -268,6 +276,10 @@ Use the form below to edit content filter settings.<br>
<% } %> <% } %>
</td> </td>
</tr> </tr>
<tr>
<td>&nbsp;</td>
<td><input type="checkbox" name="maskenabled" value="maskenabled" <%= maskEnabled ? "checked" : "" %>>Enable mask.</input></td>
</tr>
</tbody> </tbody>
</table> </table>
</div> </div>
...@@ -281,7 +293,7 @@ Use the form below to edit content filter settings.<br> ...@@ -281,7 +293,7 @@ Use the form below to edit content filter settings.<br>
<p> <p>
Enable this feature to have the sender notified whenever a packet is rejected. Enable this feature to have the sender notified whenever a packet is rejected.
NB: This feature is only operational if "Content Mask" feature is disabled. NB: This feature is only operational if "On Content Match" is set to reject packets.
</p> </p>
<table cellpadding="3" cellspacing="0" border="0" width="100%"> <table cellpadding="3" cellspacing="0" border="0" width="100%">
...@@ -394,8 +406,12 @@ Use the form below to edit content filter settings.<br> ...@@ -394,8 +406,12 @@ Use the form below to edit content filter settings.<br>
<br><br> <br><br>
<input type="submit" value="Save Properties"> <input type="submit" name="save" value="Save settings">
<input type="submit" name="reset" value="Restore factory settings*">
</form> </form>
<br><br>
<em>*Restores the plugin to its factory state, you will lose all changes ever made to this plugin!</em>
</body> </body>
</html> </html>
\ 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