anti-abuse filter upgrade
authorzapata <zapata>
Sun, 20 Jul 2003 05:49:47 +0000 (05:49 +0000)
committerzapata <zapata>
Sun, 20 Jul 2003 05:49:47 +0000 (05:49 +0000)
24 files changed:
bundles/admin_en.properties
source/Mir.java
source/default.properties
source/mir/generator/FreemarkerGenerator.java
source/mir/session/HTTPAdapters.java
source/mir/util/GeneratorFormatAdapters.java
source/mir/util/StringRoutines.java
source/mircoders/global/Abuse.java
source/mircoders/global/MirGlobal.java
source/mircoders/localizer/MirAdminInterfaceLocalizer.java
source/mircoders/localizer/MirAntiAbuseFilterType.java [new file with mode: 0755]
source/mircoders/localizer/MirOpenPostingLocalizer.java
source/mircoders/localizer/basic/MirBasicAntiAbuseFilterTypes.java [new file with mode: 0755]
source/mircoders/localizer/basic/MirBasicOpenPostingLocalizer.java
source/mircoders/servlet/ServletHelper.java
source/mircoders/servlet/ServletModuleAbuse.java
source/mircoders/servlet/ServletModuleLocalizer.java
templates/admin/EDITFUNCTIONS.template [new file with mode: 0755]
templates/admin/FUNCTIONS.template
templates/admin/LISTFUNCTIONS.template [new file with mode: 0755]
templates/admin/SETTINGS.template [new file with mode: 0755]
templates/admin/abuse.filter.template [new file with mode: 0755]
templates/admin/abuse.filters.template
templates/admin/topic.template

index 52c7065..10ecc05 100755 (executable)
@@ -1,6 +1,6 @@
 ########## admin ##########
 # language: english
-# $Id: admin_en.properties,v 1.48.2.6 2003/07/03 22:47:01 zapata Exp $
+# $Id: admin_en.properties,v 1.48.2.7 2003/07/20 05:49:47 zapata Exp $
 
 languagename=English
 
@@ -439,10 +439,22 @@ abuse.log.browser=Browser
 
 abuse.filters = Filters
 abuse.filter.type = Type
+abuse.filter.expression = Expression
+abuse.filter.articleaction = Article 
+abuse.filter.commentaction = Comment 
+abuse.filter.comments = Comments (internal usage)
+abuse.filter.lasthit = Last hit
+abuse.filter.htmltitle = Edit filter
+
 abuse.filtertype.ip = IP Number
 abuse.filtertype.regexp = Regular expression
-abuse.filter.expression = Expression
 
+abuse.filtererror.title = Error:
+abuse.filtererror.invalidtype = Invalid filter type
+abuse.filtererror.invalidexpression = Invalid expression for this type
+
+abuse.filters.htmltitle = Anti-abuse filter rules
+abuse.log.htmltitle = Anti-abuse open posting log
 
 # head
 head.start=start
@@ -482,8 +494,8 @@ error.title=The system caused an error
 error.text=This can happen. Even if the following error message is not be comprehensible for you, <br>it might be helpful to <a href="mailto:{0}">{1}</a>:
 error.text2=So please send an e-mail with the <font color="Red">red text</font> and detailed information regarding the events that led to this error to <a href="mailto:{0}">{1}</a>. Thanks!
 
-usererror.htmltitle=validation error
-usererror.title=Validation error
+usererror.htmltitle=Input error
+usererror.title=Input error
 usererror.text=Your input caused the following error:
 usererror.what_to_do=Please press the back button and try it again
 
@@ -494,6 +506,8 @@ user.error.missingpassword=A password must be entered
 user.error.incorrectpassword= Incorrect password
 
 
+
+
 ########## infomessages ##########
 infomessage.htmltitle = Information
 infomessage.produceAllNewAddedToQueue = Your request has been added to the queue.
index c66f9c5..328864f 100755 (executable)
@@ -80,7 +80,7 @@ import mircoders.storage.DatabaseUsers;
  * Mir.java - main servlet, that dispatches to servletmodules\r
  *\r
  * @author $Author: zapata $\r
- * @version $Id: Mir.java,v 1.49.2.4 2003/07/03 22:47:02 zapata Exp $\r
+ * @version $Id: Mir.java,v 1.49.2.5 2003/07/20 05:49:47 zapata Exp $\r
  *\r
  */\r
 public class Mir extends AbstractServlet {\r
@@ -287,7 +287,8 @@ public class Mir extends AbstractServlet {
           // first we try to get ServletModule from stern.che3.servlet\r
           theServletModuleClass =\r
             Class.forName("mircoders.servlet.ServletModule" + moduleName);\r
-        } catch (ClassNotFoundException e) {\r
+        }\r
+        catch (ClassNotFoundException e) {\r
           // on failure, we try to get it from lib-layer\r
           theServletModuleClass =\r
             Class.forName("mir.servlet.ServletModule" + moduleName);\r
index def30db..15f60b5 100755 (executable)
@@ -521,6 +521,13 @@ ServletModule.CommentStatus.EditTemplate=commentstatus.template
 ServletModule.CommentStatus.ListTemplate=commentstatuslist.template
 
 #
+# config for abuse
+ServletModule.Abuse.EditFilter.Template = abuse.filter.template\r
+ServletModule.Abuse.ListFilters.Template = abuse.filters.template\r
+ServletModule.Abuse.ViewLog.Template = abuse.log.template\r
+ServletModule.Abuse.Main.Template = abuse.template\r
+
+#
 # producer-related configs below
 #
 
index edab67c..52efcb7 100755 (executable)
@@ -30,6 +30,7 @@
 package mir.generator;\r
 \r
 import java.io.PrintWriter;\r
+import java.util.Date;\r
 import java.util.HashMap;\r
 import java.util.Iterator;\r
 import java.util.List;\r
@@ -38,7 +39,6 @@ import java.util.Vector;
 \r
 import org.apache.commons.beanutils.MethodUtils;\r
 import org.apache.commons.beanutils.PropertyUtils;\r
-\r
 import freemarker.template.FileTemplateCache;\r
 import freemarker.template.SimpleScalar;\r
 import freemarker.template.Template;\r
@@ -49,7 +49,6 @@ import freemarker.template.TemplateModel;
 import freemarker.template.TemplateModelException;\r
 import freemarker.template.TemplateModelRoot;\r
 import freemarker.template.TemplateScalarModel;\r
-\r
 import mir.log.LoggerWrapper;\r
 import mir.util.GeneratorFormatAdapters;\r
 import mir.util.RewindableIterator;\r
@@ -123,6 +122,8 @@ public class FreemarkerGenerator implements Generator {
       return makeIteratorAdapter(((List) anObject).iterator());\r
     else if (anObject instanceof Number)\r
       return makeAdapter(new GeneratorFormatAdapters.NumberFormatAdapter((Number) anObject));\r
+    else if (anObject instanceof Date)\r
+      return makeAdapter(new GeneratorFormatAdapters.DateFormatAdapter((Date) anObject));\r
     else\r
       return makeBeanAdapter(anObject);\r
   }\r
index fec51f6..835ed2d 100755 (executable)
@@ -48,6 +48,9 @@ public class HTTPAdapters {
     }
 
     public String getHeader(String aHeaderName) {
+      if (aHeaderName.equals("ip"))
+        return request.getRemoteAddr();
+
       return request.getHeader(aHeaderName);
     };
 
@@ -76,6 +79,9 @@ public class HTTPAdapters {
     }
 
     public String getHeader(String aHeaderName) {
+      if (aHeaderName.equals("ip"))
+        return request.getRequest().getRemoteAddr();
+
       return request.getHeader(aHeaderName);
     };
 
index 1e5a55b..2da18e5 100755 (executable)
@@ -81,6 +81,10 @@ public class GeneratorFormatAdapters {
     private TimeZone defaultTimezone;
     private String defaultTimezoneName;
 
+    public DateFormatAdapter(Date aValue) {
+      this(aValue, "");
+    }
+
     public DateFormatAdapter(Date aValue, String aDefaultTimezone) {
       value = aValue;
       defaultTimezoneName = aDefaultTimezone;
index ce0a2da..a3ac35c 100755 (executable)
@@ -40,7 +40,7 @@ public class StringRoutines {
   private StringRoutines() {\r
   }\r
 \r
-  static int indexOfCharacters(String aString, char[] aCharacters, int aFrom) {\r
+  public static int indexOfCharacters(String aString, char[] aCharacters, int aFrom) {\r
     int i;\r
     int result=-1;\r
     int position;\r
@@ -56,7 +56,7 @@ public class StringRoutines {
     return result;\r
   }\r
 \r
-  static String replaceStringCharacters(String aText, char[] aCharactersToReplace, String[] aStringsToSubstitute) {\r
+  public static String replaceStringCharacters(String aText, char[] aCharactersToReplace, String[] aStringsToSubstitute) {\r
     if (aText==null)\r
       return null;\r
 \r
@@ -197,7 +197,6 @@ public class StringRoutines {
     List result= new Vector();\r
     int previousPosition = 0;\r
     int position;\r
-    int endOfNamePosition;\r
 \r
     if((position = aString.indexOf(aSeparator, previousPosition))>=0) {\r
       result.add(aString.substring(previousPosition, position));\r
@@ -209,6 +208,36 @@ public class StringRoutines {
     return result;\r
   }\r
 \r
+  public static List splitStringWithEscape(String aString, char aSeparator, char anEscape) {\r
+    List result= new Vector();\r
+    int previousPosition = 0;\r
+    int position;\r
+    int endOfNamePosition;\r
+    StringBuffer currentItem = new StringBuffer();\r
+\r
+    if (aString!=null) {\r
+      while ((position = indexOfCharacters(aString, new char[] {aSeparator, anEscape}, previousPosition))>=0) {\r
+        currentItem.append(aString.substring(previousPosition, position));\r
+\r
+        if (aString.charAt(position)==aSeparator) {\r
+          result.add(currentItem.toString());\r
+          currentItem.delete(0, currentItem.length());\r
+        }\r
+        else {\r
+          if (aString.length()>position+1) {\r
+            position=position+1;\r
+            currentItem.append(aString.charAt(position));\r
+          }\r
+        }\r
+        previousPosition = position + 1;\r
+      }\r
+      currentItem.append(aString.substring(previousPosition, aString.length()));\r
+      result.add(currentItem.toString());\r
+    }\r
+\r
+    return result;\r
+  }\r
+\r
   public static String replicateString(String aString, int aCount) {\r
     StringBuffer result = new StringBuffer();\r
 \r
index 9e98adc..f82ee0f 100755 (executable)
@@ -35,6 +35,7 @@ import java.io.FileNotFoundException;
 import java.io.FileOutputStream;\r
 import java.util.Arrays;\r
 import java.util.Date;\r
+import java.util.GregorianCalendar;\r
 import java.util.HashMap;\r
 import java.util.Iterator;\r
 import java.util.List;\r
@@ -42,29 +43,26 @@ import java.util.Map;
 import java.util.Random;\r
 import java.util.Vector;\r
 import javax.servlet.http.Cookie;\r
-import javax.servlet.http.HttpServletRequest;\r
 import javax.servlet.http.HttpServletResponse;\r
 \r
 import org.apache.commons.collections.ExtendedProperties;\r
-import gnu.regexp.RE;\r
-\r
 import mir.config.MirPropertiesConfiguration;\r
 import mir.entity.Entity;\r
 import mir.log.LoggerWrapper;\r
-import mir.session.HTTPAdapters;\r
 import mir.session.Request;\r
 import mir.util.GeneratorFormatAdapters;\r
-import mir.util.InternetFunctions;\r
 import mir.util.StringRoutines;\r
-import mir.config.*;\r
 import mircoders.entity.EntityComment;\r
 import mircoders.entity.EntityContent;\r
 import mircoders.entity.EntityUsers;\r
 import mircoders.localizer.MirAdminInterfaceLocalizer;\r
+import mircoders.localizer.MirAntiAbuseFilterType;\r
 \r
 \r
 public class Abuse {\r
-  private List filters;\r
+  private List filterRules;\r
+  private Map filterTypes;\r
+  private List filterTypeIds;\r
   private int maxIdentifier;\r
   private LoggerWrapper logger;\r
   private LoggerWrapper adminUsageLogger;\r
@@ -80,16 +78,13 @@ public class Abuse {
 \r
   private MirPropertiesConfiguration configuration;\r
 \r
-\r
-  private static final String IP_FILTER_TYPE="ip";\r
-  private static final String REGEXP_FILTER_TYPE="regexp";\r
   private static String cookieName=MirGlobal.config().getString("Abuse.CookieName");\r
   private static int cookieMaxAge = 60*60*MirGlobal.config().getInt("Abuse.CookieMaxAge");\r
 \r
   public Abuse() {\r
     logger = new LoggerWrapper("Global.Abuse");\r
     adminUsageLogger = new LoggerWrapper("AdminUsage");\r
-    filters = new Vector();\r
+    filterRules = new Vector();\r
     maxIdentifier = 0;\r
     log = new Vector();\r
 \r
@@ -108,61 +103,23 @@ public class Abuse {
     openPostingDisabled = false;\r
     cookieOnBlock = false;\r
 \r
-    load();\r
-  }\r
+    try {\r
+      filterTypes = new HashMap();\r
+      filterTypeIds = new Vector();\r
 \r
-  public boolean checkIpFilter(String anIpAddress) {\r
-    synchronized (filters) {\r
-      Iterator i = filters.iterator();\r
+      Iterator i = MirGlobal.localizer().openPostings().getAntiAbuseFilterTypes().iterator();\r
 \r
       while (i.hasNext()) {\r
-        Filter filter = (Filter) i.next();\r
-\r
-        try {\r
-          if ( (filter.getType().equals(IP_FILTER_TYPE)) &&\r
-              InternetFunctions.isIpAddressInNetwork(anIpAddress, filter.getExpression())) {\r
-            logger.debug("ip match on " + filter.getExpression());\r
-            return true;\r
-          }\r
-        }\r
-        catch (Throwable t) {\r
-          logger.warn("error while checking ip address " + anIpAddress + " over network " + filter.expression + ": " + t.getMessage());\r
-        }\r
+        MirAntiAbuseFilterType filterType = (MirAntiAbuseFilterType) i.next();\r
+        filterTypes.put(filterType.getName(), filterType);\r
+        filterTypeIds.add(filterType.getName());\r
       }\r
-\r
-      return false;\r
     }\r
-  }\r
-\r
-  private boolean checkRegExpFilter(Entity anEntity) {\r
-    synchronized (filters) {\r
-      Iterator i = filters.iterator();\r
-\r
-      while (i.hasNext()) {\r
-        Filter filter = (Filter) i.next();\r
-\r
-        if (filter.getType().equals(REGEXP_FILTER_TYPE)) {\r
-          try {\r
-            RE regularExpression = new RE(filter.getExpression(), RE.REG_ICASE);\r
-\r
-            Iterator j = anEntity.getFields().iterator();\r
-            while (j.hasNext()) {\r
-              String field = anEntity.getValue( (String) j.next());\r
-\r
-              if (field != null && regularExpression.isMatch(field.toLowerCase())) {\r
-                logger.debug("regexp match on " + filter.getExpression());\r
-                return true;\r
-              }\r
-            }\r
-          }\r
-          catch (Throwable t) {\r
-            logger.warn("error while checking entity with regexp " + filter.getExpression() + ": " + t.getMessage());\r
-          }\r
-        }\r
-      }\r
-\r
-      return false;\r
+    catch (Throwable t) {\r
+      throw new RuntimeException("Can't get filter types: " + t.getMessage());\r
     }\r
+\r
+    load();\r
   }\r
 \r
   private void setCookie(HttpServletResponse aResponse) {\r
@@ -192,50 +149,33 @@ public class Abuse {
 \r
     return false;\r
   }\r
+  FilterRule findMatchingFilter(Entity anEntity, Request aRequest) {\r
+    Iterator iterator = filterRules.iterator();\r
 \r
-  public boolean checkRequest(Request aRequest, HttpServletResponse aResponse, String anId, boolean anIsComment) {\r
-    String address = "0.0.0.0";\r
-    String browser = "unknown";\r
-    List cookies = null;\r
-\r
-    HttpServletRequest request = null;\r
+    while (iterator.hasNext()) {\r
+      FilterRule rule = (FilterRule) iterator.next();\r
 \r
-    if (aRequest instanceof HTTPAdapters.HTTPParsedRequestAdapter) {\r
-      request = ((HTTPAdapters.HTTPParsedRequestAdapter) aRequest).getRequest();\r
+      if (rule.test(anEntity, aRequest))\r
+        return rule;\r
     }\r
-    else if (aRequest instanceof HTTPAdapters.HTTPRequestAdapter) {\r
-      request = ((HTTPAdapters.HTTPRequestAdapter) aRequest).getRequest();\r
-    }\r
-    if (request!=null) {\r
-      browser = (String) request.getHeader("User-Agent");\r
-      address = request.getRemoteAddr();\r
-      if (request.getCookies()!=null)\r
-        cookies = Arrays.asList(request.getCookies());\r
-      else\r
-        cookies = new Vector();\r
-    }\r
-\r
-    if (anIsComment)\r
-      logComment(address, anId , new Date(), browser);\r
-    else\r
-      logArticle(address, anId , new Date(), browser);\r
 \r
-    return checkCookie(cookies) || checkIpFilter(address);\r
+    return null;\r
   }\r
 \r
   public void checkComment(EntityComment aComment, Request aRequest, HttpServletResponse aResponse) {\r
     try {\r
       long time = System.currentTimeMillis();\r
 \r
-      MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = MirGlobal.localizer().adminInterface().simpleCommentOperationForName(commentBlockAction);\r
+      FilterRule filterRule = findMatchingFilter(aComment, aRequest);\r
 \r
-      if (checkRequest(aRequest, aResponse, aComment.getId(), true) || checkRegExpFilter(aComment)) {\r
-        logger.debug("performing operation " + operation.getName());\r
-        operation.perform(null, MirGlobal.localizer().dataModel().adapterModel().makeEntityAdapter("comment", aComment));\r
+      if (filterRule!=null) {\r
+        logger.debug("Match for " + filterRule.getType()+" rule '"+ filterRule.getExpression()+"'");\r
+        filterRule.setLastHit(new GregorianCalendar().getTime());\r
+        MirGlobal.performCommentOperation(null, aComment, filterRule.getCommentAction());\r
         setCookie(aResponse);\r
       }\r
 \r
-      logger.info("checkComment: " + (System.currentTimeMillis()-time) + "ms");\r
+      logger.debug("checkComment: " + (System.currentTimeMillis()-time) + "ms");\r
     }\r
     catch (Throwable t) {\r
       t.printStackTrace(logger.asPrintWriter(logger.DEBUG_MESSAGE));\r
@@ -247,11 +187,12 @@ public class Abuse {
     try {\r
       long time = System.currentTimeMillis();\r
 \r
-      MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = MirGlobal.localizer().adminInterface().simpleArticleOperationForName(articleBlockAction);\r
+      FilterRule filterRule = findMatchingFilter(anArticle, aRequest);\r
 \r
-      if (checkRequest(aRequest, aResponse, anArticle.getId(), false) || checkRegExpFilter(anArticle)) {\r
-        logger.debug("performing operation " + operation.getName());\r
-        operation.perform(null, MirGlobal.localizer().dataModel().adapterModel().makeEntityAdapter("content", anArticle));\r
+      if (filterRule!=null) {\r
+        logger.debug("Match for " + filterRule.getType() + " rule '" + filterRule.getExpression()+"'");\r
+        filterRule.setLastHit(new GregorianCalendar().getTime());\r
+        MirGlobal.performArticleOperation(null, anArticle, filterRule.getArticleAction());\r
         setCookie(aResponse);\r
       }\r
 \r
@@ -322,7 +263,6 @@ public class Abuse {
     commentBlockAction = anAction;\r
   }\r
 \r
-\r
   public List getLog() {\r
     synchronized(log) {\r
       try {\r
@@ -371,7 +311,7 @@ public class Abuse {
       catch (FileNotFoundException e) {\r
       }\r
 \r
-      getFilterConfig(filters, "abuse.filter", configuration);\r
+      getFilterConfig(filterRules, "abuse.filter", configuration);\r
 \r
       setOpenPostingDisabled(configuration.getString("abuse.openPostingDisabled", "0").equals("1"));\r
       setOpenPostingPassword(configuration.getString("abuse.openPostingPassword", "0").equals("1"));\r
@@ -389,7 +329,7 @@ public class Abuse {
     try {\r
       ExtendedProperties configuration = new ExtendedProperties();\r
 \r
-      setFilterConfig(filters, "abuse.filter", configuration);\r
+      setFilterConfig(filterRules, "abuse.filter", configuration);\r
 \r
       configuration.addProperty("abuse.openPostingDisabled", getOpenPostingDisabled()?"1":"0");\r
       configuration.addProperty("abuse.openPostingPassword", getOpenPostingPassword()?"1":"0");\r
@@ -407,19 +347,25 @@ public class Abuse {
   }\r
 \r
   public List getFilterTypes() {\r
-    List result = new Vector();\r
+    try {\r
+      List result = new Vector();\r
+\r
+      Iterator i = filterTypeIds.iterator();\r
+      while (i.hasNext()) {\r
+        String id = (String) i.next();\r
 \r
-    Map entry = new HashMap();\r
-    entry.put("resource", "ip");\r
-    entry.put("id", IP_FILTER_TYPE);\r
-    result.add(entry);\r
+        Map action = new HashMap();\r
+        action.put("resource", id);\r
+        action.put("identifier", id);\r
 \r
-    entry = new HashMap();\r
-    entry.put("resource", "regexp");\r
-    entry.put("id", REGEXP_FILTER_TYPE);\r
-    result.add(entry);\r
+        result.add(action);\r
+      }\r
 \r
-    return result;\r
+      return result;\r
+    }\r
+    catch (Throwable t) {\r
+      throw new RuntimeException("can't get article actions");\r
+    }\r
   }\r
 \r
   public List getArticleActions() {\r
@@ -469,71 +415,96 @@ public class Abuse {
   }\r
 \r
   public List getFilters() {\r
-    return getFiltersAsMaps(filters);\r
-  }\r
+    List result = new Vector();\r
 \r
-  public void addFilter(String aType, String anExpression) {\r
-    addFilter(filters, aType, anExpression);\r
+    synchronized(filterRules) {\r
+      Iterator i = filterRules.iterator();\r
+      while (i.hasNext()) {\r
+        FilterRule filter = (FilterRule) i.next();\r
+        result.add(filter.clone());\r
+      }\r
+      return result;\r
+    }\r
   }\r
 \r
-  public void setFilter(String anIdentifier, String aType, String anExpression) {\r
-    setFilter(filters, anIdentifier, aType, anExpression);\r
+  public String addFilter(String aType, String anExpression, String aComments, String aCommentAction, String anArticleAction) {\r
+    return addFilter(filterRules, aType, anExpression, aComments, aCommentAction, anArticleAction);\r
   }\r
 \r
-  public void deleteFilter(String anIdentifier) {\r
-    deleteFilter(filters, anIdentifier);\r
+  public FilterRule getFilter(String anId) {\r
+    synchronized (filterRules) {\r
+      FilterRule result = (FilterRule) findFilter(filterRules, anId);\r
+      if (result==null)\r
+        return result;\r
+      else\r
+        return (FilterRule) result.clone();\r
+    }\r
   }\r
 \r
-  public void validateIpFilter(String anIdentifier, String anArticleAction, String aCommentAction) throws Exception {\r
+  public String setFilter(String anIdentifier, String aType, String anExpression, String aComments, String aCommentAction, String anArticleAction) {\r
+    return setFilter(filterRules, anIdentifier, aType, anExpression, aComments, aCommentAction, anArticleAction);\r
   }\r
 \r
-  private List getFiltersAsMaps(List aFilters) {\r
-    synchronized(aFilters) {\r
-      List result = new Vector();\r
+  public void deleteFilter(String anIdentifier) {\r
+    deleteFilter(filterRules, anIdentifier);\r
+  }\r
 \r
-      Iterator i = aFilters.iterator();\r
-      while (i.hasNext()) {\r
-        Filter filter = (Filter) i.next();\r
-        Map map = new HashMap();\r
+  private String addFilter(List aFilters, String aType, String anExpression, String aComments, String aCommentAction, String anArticleAction) {\r
+    MirAntiAbuseFilterType type = (MirAntiAbuseFilterType) filterTypes.get(aType);\r
 \r
-        map.put("id", filter.getId());\r
-        map.put("expression", filter.getExpression());\r
-        map.put("type", filter.getType());\r
+    if (type==null)\r
+      return "invalidtype";\r
 \r
-        result.add(map);\r
-      }\r
-      return result;\r
+    if (!type.validate(anExpression)) {\r
+      return "invalidexpression";\r
     }\r
-  }\r
 \r
-  private void addFilter(List aFilters, String aType, String anExpression) {\r
-    Filter filter = new Filter();\r
+    FilterRule filter = new FilterRule();\r
 \r
     filter.setId(generateId());\r
     filter.setExpression(anExpression);\r
     filter.setType(aType);\r
+    filter.setComments(aComments);\r
+    filter.setArticleAction(anArticleAction);\r
+    filter.setCommentAction(aCommentAction);\r
 \r
     synchronized (aFilters) {\r
       aFilters.add(filter);\r
     }\r
+\r
+    return null;\r
   }\r
 \r
-  private void setFilter(List aFilters, String anIdentifier, String aType, String anExpression) {\r
+  private String setFilter(List aFilters, String anIdentifier, String aType, String anExpression, String aComments, String aCommentAction, String anArticleAction) {\r
+    MirAntiAbuseFilterType type = (MirAntiAbuseFilterType) filterTypes.get(aType);\r
+\r
+    if (type==null)\r
+      return "invalidtype";\r
+\r
+    if (!type.validate(anExpression)) {\r
+      return "invalidexpression";\r
+    }\r
+\r
     synchronized (aFilters) {\r
-      Filter filter = findFilter(aFilters, anIdentifier);\r
+      FilterRule filter = findFilter(aFilters, anIdentifier);\r
 \r
       if (filter!=null) {\r
         filter.setExpression(anExpression);\r
         filter.setType(aType);\r
+        filter.setCommentAction(aCommentAction);\r
+        filter.setArticleAction(anArticleAction);\r
+        filter.setComments(aComments);\r
       }\r
+\r
+      return null;\r
     }\r
   }\r
 \r
-  private Filter findFilter(List aFilters, String anIdentifier) {\r
+  private FilterRule findFilter(List aFilters, String anIdentifier) {\r
     synchronized (aFilters) {\r
       Iterator i = aFilters.iterator();\r
       while (i.hasNext()) {\r
-        Filter filter = (Filter) i.next();\r
+        FilterRule filter = (FilterRule) i.next();\r
 \r
         if (filter.getId().equals(anIdentifier)) {\r
           return filter;\r
@@ -546,7 +517,7 @@ public class Abuse {
 \r
   private void deleteFilter(List aFilters, String anIdentifier) {\r
     synchronized (aFilters) {\r
-      Filter filter = findFilter(aFilters, anIdentifier);\r
+      FilterRule filter = findFilter(aFilters, anIdentifier);\r
 \r
       if (filter!=null) {\r
         aFilters.remove(filter);\r
@@ -562,15 +533,31 @@ public class Abuse {
     }\r
   }\r
 \r
-  private static class Filter {\r
+  public class FilterRule {\r
     private String identifier;\r
     private String expression;\r
     private String type;\r
+    private String comments;\r
+    private String articleAction;\r
+    private String commentAction;\r
+    private Date lastHit;\r
+\r
+    public FilterRule() {\r
+      expression = "";\r
+      type = "";\r
+      identifier = "";\r
+      comments = "";\r
+      articleAction = articleBlockAction;\r
+      commentAction = commentBlockAction;\r
+      lastHit = null;\r
+    }\r
 \r
-    public Filter() {\r
-      expression="";\r
-      type="";\r
-      identifier="";\r
+    public Date getLastHit() {\r
+      return lastHit;\r
+    }\r
+\r
+    public void setLastHit(Date aDate) {\r
+      lastHit = aDate;\r
     }\r
 \r
     public String getId() {\r
@@ -596,6 +583,56 @@ public class Abuse {
     public void setType(String aType) {\r
       type = aType;\r
     }\r
+\r
+    public void setComments(String aComments) {\r
+      comments = aComments;\r
+    }\r
+\r
+    public String getComments() {\r
+      return comments;\r
+    }\r
+\r
+    public String getArticleAction() {\r
+      return articleAction;\r
+    }\r
+\r
+    public void setArticleAction(String anArticleAction) {\r
+      articleAction = anArticleAction;\r
+    }\r
+\r
+    public String getCommentAction() {\r
+      return commentAction;\r
+    }\r
+\r
+    public void setCommentAction(String aCommentAction) {\r
+      commentAction = aCommentAction;\r
+    }\r
+\r
+    public boolean test(Entity anEntity, Request aRequest) {\r
+      MirAntiAbuseFilterType filterType = (MirAntiAbuseFilterType) filterTypes.get(type);\r
+      try {\r
+        if (filterType != null)\r
+          return filterType.test(expression, anEntity, aRequest);\r
+      }\r
+      catch (Throwable t) {\r
+        logger.error("error while testing "+type+"-filter '"+expression+"'");\r
+      }\r
+\r
+      return false;\r
+    };\r
+\r
+    public Object clone() {\r
+      FilterRule result = new FilterRule();\r
+      result.setComments(getComments());\r
+      result.setExpression(getExpression());\r
+      result.setId(getId());\r
+      result.setType(getType());\r
+      result.setArticleAction(getArticleAction());\r
+      result.setCommentAction(getCommentAction());\r
+      result.setLastHit(getLastHit());\r
+\r
+      return result;\r
+    }\r
   }\r
 \r
   private void setFilterConfig(List aFilters, String aConfigKey, ExtendedProperties aConfiguration) {\r
@@ -603,9 +640,12 @@ public class Abuse {
       Iterator i = aFilters.iterator();\r
 \r
       while (i.hasNext()) {\r
-        Filter filter = (Filter) i.next();\r
+        FilterRule filter = (FilterRule) i.next();\r
+\r
+        String comments = StringRoutines.replaceStringCharacters(filter.getComments(), new char[] { '\\', ':'}, new String[] { "\\\\", "\\:"} );\r
 \r
-        aConfiguration.addProperty(aConfigKey, filter.getType()+":"+filter.getExpression());\r
+        aConfiguration.addProperty(aConfigKey, filter.getType()+":"+filter.getExpression()+":"+filter.getArticleAction() + ":" + filter.getCommentAction() + ":" +\r
+           comments);\r
       }\r
     }\r
   }\r
@@ -621,10 +661,15 @@ public class Abuse {
 \r
         while (i.hasNext()) {\r
           String filter = (String) i.next();\r
-          List parts = StringRoutines.separateString(filter, ":");\r
-\r
+          List parts = StringRoutines.splitStringWithEscape(filter, ':', '\\');\r
           if (parts.size() == 2) {\r
-            addFilter( (String) parts.get(0), (String) parts.get(1));\r
+            parts.add(articleBlockAction);\r
+            parts.add(commentBlockAction);\r
+            parts.add("");\r
+          }\r
+\r
+          if (parts.size() == 5) {\r
+            addFilter( (String) parts.get(0), (String) parts.get(1), (String) parts.get(4), (String) parts.get(2), (String) parts.get(3));\r
           }\r
         }\r
       }\r
index aaff287..59c61e1 100755 (executable)
-/*
- * Copyright (C) 2001, 2002 The Mir-coders group
- *
- * This file is part of Mir.
- *
- * Mir is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Mir is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Mir; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * In addition, as a special exception, The Mir-coders gives permission to link
- * the code of this program with  any library licensed under the Apache Software License,
- * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
- * (or with modified versions of the above that use the same license as the above),
- * and distribute linked combinations including the two.  You must obey the
- * GNU General Public License in all respects for all of the code used other than
- * the above mentioned libraries.  If you modify this file, you may extend this
- * exception to your version of the file, but you are not obligated to do so.
- * If you do not wish to do so, delete this exception statement from your version.
- */
-
-package mircoders.global;
-
-import mir.config.MirPropertiesConfiguration;
-import mir.config.MirPropertiesConfiguration.PropertiesConfigExc;
-import mir.misc.ConfigException;
-import mircoders.localizer.MirCachingLocalizerDecorator;
-import mircoders.localizer.MirLocalizer;
-import mircoders.accesscontrol.*;
-
-public class MirGlobal {
-  static private MirPropertiesConfiguration configuration;
-  static private MirLocalizer localizer;
-  static private ProducerEngine producerEngine;
-  static private Abuse abuse;
-  static private MRUCache mruCache;
-  static private AccessControl accessControl;
-
-  public static MirLocalizer localizer() {
-    String localizerClassName;
-    Class localizerClass;
-
-    if (localizer == null ) {
-      synchronized(MirGlobal.class) {
-        if (localizer == null ) {
-          localizerClassName = config().getString("Mir.Localizer", "mirlocal.localizer.basic.MirBasicLocalizer");
-
-          try {
-            localizerClass = Class.forName(localizerClassName);
-          }
-          catch (Throwable t) {
-            throw new ConfigException("localizer class '" + localizerClassName + "' not found: " + t.toString());
-          }
-
-          if (!(MirLocalizer.class.isAssignableFrom(localizerClass)))
-            throw new ConfigException("localizer class '" + localizerClassName + "' is not assignable from MirLocalizer");
-
-          try {
-            localizer = new MirCachingLocalizerDecorator((MirLocalizer) localizerClass.newInstance());
-          }
-          catch (Throwable t) {
-            throw new ConfigException("localizer class '" + localizerClassName + "' cannot be instantiated: " + t.toString());
-          }
-        }
-      }
-    }
-
-    return localizer;
-  }
-
-  public static Abuse abuse() {
-    if (abuse==null) {
-      synchronized(MirGlobal.class) {
-        if (abuse==null)
-          abuse = new Abuse();
-      }
-    }
-
-    return abuse;
-  }
-
-  public static MirPropertiesConfiguration config() {
-    try {
-      return MirPropertiesConfiguration.instance();
-    }
-    catch (PropertiesConfigExc e) {
-      throw new RuntimeException(e.getMessage());
-    }
-  }
-
-  public static ProducerEngine producerEngine() {
-    if (producerEngine == null) {
-      producerEngine = new ProducerEngine();
-    }
-
-    return producerEngine;
-  }
-
-  public static MRUCache mruCache() {
-    synchronized(MirGlobal.class) {
-      if (mruCache == null) {
-        mruCache = new MRUCache();
-      }
-      return mruCache;
-    }
-  }
-
-  public static synchronized AccessControl accessControl() {
-    if (accessControl == null) {
-      accessControl=new AccessControl();
-    }
-
-    return accessControl;
-  }
-}
-
-
+/*\r
+ * Copyright (C) 2001, 2002 The Mir-coders group\r
+ *\r
+ * This file is part of Mir.\r
+ *\r
+ * Mir is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Mir is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with Mir; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ *\r
+ * In addition, as a special exception, The Mir-coders gives permission to link\r
+ * the code of this program with  any library licensed under the Apache Software License,\r
+ * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library\r
+ * (or with modified versions of the above that use the same license as the above),\r
+ * and distribute linked combinations including the two.  You must obey the\r
+ * GNU General Public License in all respects for all of the code used other than\r
+ * the above mentioned libraries.  If you modify this file, you may extend this\r
+ * exception to your version of the file, but you are not obligated to do so.\r
+ * If you do not wish to do so, delete this exception statement from your version.\r
+ */\r
+\r
+package mircoders.global;\r
+\r
+import java.util.*;\r
+\r
+import mir.config.MirPropertiesConfiguration;\r
+import mir.config.MirPropertiesConfiguration.PropertiesConfigExc;\r
+import mir.misc.ConfigException;\r
+import mircoders.localizer.MirCachingLocalizerDecorator;\r
+import mircoders.localizer.*;\r
+import mircoders.accesscontrol.*;\r
+import mircoders.entity.*;\r
+import mir.entity.adapter.*;\r
+\r
+public class MirGlobal {\r
+  static private MirPropertiesConfiguration configuration;\r
+  static private MirLocalizer localizer;\r
+  static private ProducerEngine producerEngine;\r
+  static private Abuse abuse;\r
+  static private MRUCache mruCache;\r
+  static private AccessControl accessControl;\r
+  static private Map articleOperations;\r
+  static private Map commentOperations;\r
+\r
+  public synchronized static MirLocalizer localizer() {\r
+    String localizerClassName;\r
+    Class localizerClass;\r
+\r
+    if (localizer == null ) {\r
+      localizerClassName = config().getString("Mir.Localizer", "mirlocal.localizer.basic.MirBasicLocalizer");\r
+\r
+      try {\r
+        localizerClass = Class.forName(localizerClassName);\r
+      }\r
+      catch (Throwable t) {\r
+        throw new ConfigException("localizer class '" + localizerClassName + "' not found: " + t.toString());\r
+      }\r
+\r
+      if (!(MirLocalizer.class.isAssignableFrom(localizerClass)))\r
+        throw new ConfigException("localizer class '" + localizerClassName + "' is not assignable from MirLocalizer");\r
+\r
+      try {\r
+        localizer = new MirCachingLocalizerDecorator((MirLocalizer) localizerClass.newInstance());\r
+      }\r
+      catch (Throwable t) {\r
+        throw new ConfigException("localizer class '" + localizerClassName + "' cannot be instantiated: " + t.toString());\r
+      }\r
+    }\r
+\r
+    return localizer;\r
+  }\r
+\r
+  public static Abuse abuse() {\r
+    if (abuse==null) {\r
+      synchronized(MirGlobal.class) {\r
+        if (abuse==null)\r
+          abuse = new Abuse();\r
+      }\r
+    }\r
+\r
+    return abuse;\r
+  }\r
+\r
+  public static MirPropertiesConfiguration config() {\r
+    try {\r
+      return MirPropertiesConfiguration.instance();\r
+    }\r
+    catch (PropertiesConfigExc e) {\r
+      throw new RuntimeException(e.getMessage());\r
+    }\r
+  }\r
+\r
+  public static ProducerEngine producerEngine() {\r
+    if (producerEngine == null) {\r
+      producerEngine = new ProducerEngine();\r
+    }\r
+\r
+    return producerEngine;\r
+  }\r
+\r
+  public static MRUCache mruCache() {\r
+    synchronized(MirGlobal.class) {\r
+      if (mruCache == null) {\r
+        mruCache = new MRUCache();\r
+      }\r
+      return mruCache;\r
+    }\r
+  }\r
+\r
+  public static synchronized AccessControl accessControl() {\r
+    if (accessControl == null) {\r
+      accessControl=new AccessControl();\r
+    }\r
+\r
+    return accessControl;\r
+  }\r
+\r
+  public static void performArticleOperation(EntityUsers aUser, EntityContent  anArticle, String anOperation) {\r
+    MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = getArticleOperationForName(anOperation);\r
+\r
+    try {\r
+      if (operation!=null)\r
+        operation.perform(\r
+            localizer().dataModel().adapterModel().makeEntityAdapter("user", aUser),\r
+            localizer().dataModel().adapterModel().makeEntityAdapter("content", anArticle));\r
+    }\r
+    catch (Throwable t) {\r
+      throw new RuntimeException(t.toString());\r
+    }\r
+  }\r
+\r
+  public static void performCommentOperation(EntityUsers aUser, EntityComment  aComment, String anOperation) {\r
+    MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = getCommentOperationForName(anOperation);\r
+\r
+    try {\r
+      if (operation!=null)\r
+        operation.perform(\r
+            localizer().dataModel().adapterModel().makeEntityAdapter("user", aUser),\r
+            localizer().dataModel().adapterModel().makeEntityAdapter("comment", aComment));\r
+    }\r
+    catch (Throwable t) {\r
+      throw new RuntimeException(t.toString());\r
+    }\r
+  }\r
+\r
+  private synchronized static MirAdminInterfaceLocalizer.MirSimpleEntityOperation getArticleOperationForName(String aName) {\r
+    try {\r
+      if (articleOperations == null) {\r
+        articleOperations = new HashMap();\r
+        Iterator i = localizer().adminInterface().simpleArticleOperations().iterator();\r
+        while (i.hasNext()) {\r
+          MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next();\r
+          articleOperations.put(operation.getName(), operation);\r
+        }\r
+      }\r
+\r
+      return (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) articleOperations.get(aName);\r
+    }\r
+    catch (Throwable t) {\r
+      throw new RuntimeException(t.toString());\r
+    }\r
+  }\r
+\r
+  private synchronized static MirAdminInterfaceLocalizer.MirSimpleEntityOperation getCommentOperationForName(String aName) {\r
+    try {\r
+      if (commentOperations == null) {\r
+        commentOperations = new HashMap();\r
+        Iterator i = localizer().adminInterface().simpleCommentOperations().iterator();\r
+        while (i.hasNext()) {\r
+          MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next();\r
+          commentOperations.put(operation.getName(), operation);\r
+        }\r
+      }\r
+\r
+      return (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) commentOperations.get(aName);\r
+    }\r
+    catch (Throwable t) {\r
+      throw new RuntimeException(t.toString());\r
+    }\r
+  }\r
+\r
+}\r
+\r
+\r
index 25fc488..5e66c4b 100755 (executable)
@@ -71,14 +71,9 @@ public interface MirAdminInterfaceLocalizer {
 
   /**
    *
-   * @param aName
    * @return
    */
-  public MirSimpleEntityOperation simpleCommentOperationForName(String aName);
-
-
   public List simpleArticleOperations();
-  public MirSimpleEntityOperation simpleArticleOperationForName(String aName);
 
   public interface MirSimpleEntityOperation {
     public String getName();
diff --git a/source/mircoders/localizer/MirAntiAbuseFilterType.java b/source/mircoders/localizer/MirAntiAbuseFilterType.java
new file mode 100755 (executable)
index 0000000..d14ea32
--- /dev/null
@@ -0,0 +1,68 @@
+/*\r
+ * Copyright (C) 2001, 2002 The Mir-coders group\r
+ *\r
+ * This file is part of Mir.\r
+ *\r
+ * Mir is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Mir is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with Mir; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ *\r
+ * In addition, as a special exception, The Mir-coders gives permission to link\r
+ * the code of this program with  any library licensed under the Apache Software License,\r
+ * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library\r
+ * (or with modified versions of the above that use the same license as the above),\r
+ * and distribute linked combinations including the two.  You must obey the\r
+ * GNU General Public License in all respects for all of the code used other than\r
+ * the above mentioned libraries.  If you modify this file, you may extend this\r
+ * exception to your version of the file, but you are not obligated to do so.\r
+ * If you do not wish to do so, delete this exception statement from your version.\r
+ */\r
+package mircoders.localizer;\r
+\r
+import mir.entity.Entity;\r
+import mir.session.Request;\r
+\r
+/**\r
+ *\r
+ *\r
+ * <p>Title: Anti-abuse filter type</p>\r
+ * <p>Description: Interface to define filter types for the anti-abuse system\r
+ *  </p>\r
+ * <p>Copyright: Copyright (c) 2003</p>\r
+ * <p>Company: Mir coders</p>\r
+ * @author Zapata\r
+ * @version 1.0\r
+ */\r
+\r
+public interface MirAntiAbuseFilterType {\r
+  /**\r
+   * The identifying name of the filter type. Must be unique.\r
+   *\r
+   * @return\r
+   */\r
+  public String getName();\r
+\r
+  /**\r
+   * Must return <code>true</code> if the expression is valid for this filter. <code>false</code> if not.\r
+   * @param anExpression\r
+   * @return\r
+   */\r
+  public boolean validate(String anExpression);\r
+\r
+  /**\r
+   * Must return <code>true</code> if the posting matches the filter.\r
+   * @param anExpression\r
+   * @return\r
+   */\r
+  public boolean test(String anExpression, Entity anEntity, Request aRequest);\r
+}
\ No newline at end of file
index 6670249..bec059e 100755 (executable)
@@ -1,76 +1,90 @@
-/*
- * Copyright (C) 2001, 2002 The Mir-coders group
- *
- * This file is part of Mir.
- *
- * Mir is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Mir is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Mir; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * In addition, as a special exception, The Mir-coders gives permission to link
- * the code of this program with  any library licensed under the Apache Software License, 
- * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library 
- * (or with modified versions of the above that use the same license as the above), 
- * and distribute linked combinations including the two.  You must obey the 
- * GNU General Public License in all respects for all of the code used other than 
- * the above mentioned libraries.  If you modify this file, you may extend this 
- * exception to your version of the file, but you are not obligated to do so.  
- * If you do not wish to do so, delete this exception statement from your version.
- */
-package mircoders.localizer;
-
-import mir.session.Request;
-import mir.session.Session;
-import mir.session.SessionHandler;
-import mircoders.entity.EntityComment;
-import mircoders.entity.EntityContent;
-
-public interface MirOpenPostingLocalizer {
-
-  /**
-   * Class to encapsulate a validation error
-   *
-   * <p>Title: </p>
-   * <p>Description: </p>
-   * <p>Copyright: Copyright (c) 2003</p>
-   * <p>Company: </p>
-   * @author not attributable
-   * @version 1.0
-   */
-
-  /**
-   *
-   * @param aRequest
-   * @param aSession
-   * @return
-   * @throws MirLocalizerExc
-   * @throws MirLocalizerFailure
-   */
-  public SessionHandler getOpenSessionHandler(Request aRequest, Session aSession) throws MirLocalizerExc, MirLocalizerFailure;
-
-  /**
-   *
-   * @param aComment
-   * @throws MirLocalizerExc
-   * @throws MirLocalizerFailure
-   */
-  public void afterCommentPosting(EntityComment aComment) throws MirLocalizerExc, MirLocalizerFailure;
-
-  /**
-   *
-   * @param aContent
-   * @throws MirLocalizerExc
-   * @throws MirLocalizerFailure
-   */
-  public void afterContentPosting(EntityContent aContent) throws MirLocalizerExc, MirLocalizerFailure;
-}
+/*\r
+ * Copyright (C) 2001, 2002 The Mir-coders group\r
+ *\r
+ * This file is part of Mir.\r
+ *\r
+ * Mir is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Mir is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with Mir; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ *\r
+ * In addition, as a special exception, The Mir-coders gives permission to link\r
+ * the code of this program with  any library licensed under the Apache Software License,\r
+ * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library\r
+ * (or with modified versions of the above that use the same license as the above),\r
+ * and distribute linked combinations including the two.  You must obey the\r
+ * GNU General Public License in all respects for all of the code used other than\r
+ * the above mentioned libraries.  If you modify this file, you may extend this\r
+ * exception to your version of the file, but you are not obligated to do so.\r
+ * If you do not wish to do so, delete this exception statement from your version.\r
+ */\r
+package mircoders.localizer;\r
+\r
+import java.util.List;\r
+\r
+import mir.session.Request;\r
+import mir.session.Session;\r
+import mir.session.SessionHandler;\r
+\r
+import mircoders.entity.EntityComment;\r
+import mircoders.entity.EntityContent;\r
+\r
+public interface MirOpenPostingLocalizer {\r
+\r
+  /**\r
+   * Class to encapsulate a validation error\r
+   *\r
+   * <p>Title: </p>\r
+   * <p>Description: </p>\r
+   * <p>Copyright: Copyright (c) 2003</p>\r
+   * <p>Company: </p>\r
+   * @author not attributable\r
+   * @version 1.0\r
+   */\r
+\r
+  /**\r
+   *\r
+   * @param aRequest\r
+   * @param aSession\r
+   * @return\r
+   * @throws MirLocalizerExc\r
+   * @throws MirLocalizerFailure\r
+   */\r
+  public SessionHandler getOpenSessionHandler(Request aRequest, Session aSession) throws MirLocalizerExc, MirLocalizerFailure;\r
+\r
+  /**\r
+   *\r
+   * @param aComment\r
+   * @throws MirLocalizerExc\r
+   * @throws MirLocalizerFailure\r
+   */\r
+  public void afterCommentPosting(EntityComment aComment) throws MirLocalizerExc, MirLocalizerFailure;\r
+\r
+  /**\r
+   * This method will be called after an article is posted via the open posting interface.\r
+   *\r
+   * @param aContent\r
+   * @throws MirLocalizerExc\r
+   * @throws MirLocalizerFailure\r
+   */\r
+  public void afterContentPosting(EntityContent aContent) throws MirLocalizerExc, MirLocalizerFailure;\r
+\r
+  /**\r
+   *\r
+   *\r
+   * @return\r
+   * @throws MirLocalizerExc\r
+   * @throws MirLocalizerFailure\r
+   */\r
+\r
+  public List getAntiAbuseFilterTypes() throws MirLocalizerExc, MirLocalizerFailure;\r
+}\r
diff --git a/source/mircoders/localizer/basic/MirBasicAntiAbuseFilterTypes.java b/source/mircoders/localizer/basic/MirBasicAntiAbuseFilterTypes.java
new file mode 100755 (executable)
index 0000000..e7ae73d
--- /dev/null
@@ -0,0 +1,180 @@
+/*\r
+ * Copyright (C) 2001, 2002 The Mir-coders group\r
+ *\r
+ * This file is part of Mir.\r
+ *\r
+ * Mir is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Mir is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with Mir; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ *\r
+ * In addition, as a special exception, The Mir-coders gives permission to link\r
+ * the code of this program with  any library licensed under the Apache Software License,\r
+ * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library\r
+ * (or with modified versions of the above that use the same license as the above),\r
+ * and distribute linked combinations including the two.  You must obey the\r
+ * GNU General Public License in all respects for all of the code used other than\r
+ * the above mentioned libraries.  If you modify this file, you may extend this\r
+ * exception to your version of the file, but you are not obligated to do so.\r
+ * If you do not wish to do so, delete this exception statement from your version.\r
+ */\r
+\r
+package mircoders.localizer.basic;\r
+\r
+import java.util.*;\r
+\r
+import gnu.regexp.*;\r
+\r
+import mir.entity.Entity;\r
+import mir.session.Request;\r
+import mir.util.InternetFunctions;\r
+import mircoders.localizer.MirAntiAbuseFilterType;\r
+\r
+\r
+/**\r
+ * <p>Title: </p>\r
+ * <p>Description: </p>\r
+ * <p>Copyright: Copyright (c) 2003</p>\r
+ * <p>Company: </p>\r
+ * @author not attributable\r
+ * @version 1.0\r
+ */\r
+\r
+public class MirBasicAntiAbuseFilterTypes {\r
+  private MirBasicAntiAbuseFilterTypes() {\r
+  }\r
+\r
+  public static abstract class BasicFilterType implements MirAntiAbuseFilterType {\r
+    private String name;\r
+\r
+    public BasicFilterType(String aName) {\r
+      name = aName;\r
+    }\r
+\r
+    public String getName() {\r
+      return name;\r
+    }\r
+  }\r
+\r
+  /**\r
+   * A basic ip filter. Supports x.x.x.x, x.x.x.x/x and x.x.x.x/x.x.x.x expressions.\r
+   *\r
+   * <p>Title: </p>\r
+   * <p>Description: </p>\r
+   * <p>Copyright: Copyright (c) 2003</p>\r
+   * <p>Company: </p>\r
+   * @author not attributable\r
+   * @version 1.0\r
+   */\r
+\r
+  public static class IPFilter extends BasicFilterType {\r
+    public IPFilter(String aName) {\r
+      super(aName);\r
+    }\r
+\r
+    public boolean validate(String anExpression) {\r
+      try {\r
+        InternetFunctions.isIpAddressInNetwork("1.1.1.1", anExpression);\r
+        return true;\r
+      }\r
+      catch (Throwable t) {\r
+        return false;\r
+      }\r
+    };\r
+\r
+    public boolean test(String anExpression, Entity anEntity, Request aRequest) {\r
+      try {\r
+        return InternetFunctions.isIpAddressInNetwork(aRequest.getHeader("ip"), anExpression);\r
+      }\r
+      catch (Throwable t) {\r
+        return false;\r
+      }\r
+    };\r
+  }\r
+\r
+  /**\r
+   * A regular expression filter.\r
+   *\r
+   * <p>Title: </p>\r
+   * <p>Description: </p>\r
+   * <p>Copyright: Copyright (c) 2003</p>\r
+   * <p>Company: </p>\r
+   * @author not attributable\r
+   * @version 1.0\r
+   */\r
+\r
+  public static class RegularExpressionFilter extends BasicFilterType {\r
+    private boolean exactMatch;\r
+    private boolean caseSensitive;\r
+    private List selectedFields;\r
+\r
+    public RegularExpressionFilter(String aName) {\r
+      this(aName, false, false, null);\r
+    }\r
+\r
+    public RegularExpressionFilter(String aName, boolean aCaseSensitive, boolean anExactMatch, String[] aSelectedFields) {\r
+      super(aName);\r
+\r
+      caseSensitive = aCaseSensitive;\r
+      exactMatch = anExactMatch;\r
+      if (aSelectedFields==null)\r
+        selectedFields = null;\r
+      else\r
+        selectedFields = Arrays.asList(aSelectedFields);\r
+    }\r
+\r
+    public boolean validate(String anExpression) {\r
+      try {\r
+        new RE(anExpression);\r
+        return true;\r
+      }\r
+      catch (Throwable t) {\r
+        return false;\r
+      }\r
+    };\r
+\r
+    public boolean test(String anExpression, Entity anEntity, Request aRequest) {\r
+      try {\r
+        Iterator j;\r
+        int flags = 0;\r
+\r
+        if (caseSensitive)\r
+          flags |= RE.REG_ICASE;\r
+\r
+        RE regularExpression = new RE(anExpression, RE.REG_ICASE);\r
+\r
+        if (selectedFields!=null)\r
+          j = selectedFields.iterator();\r
+        else\r
+          j = anEntity.getFields().iterator();\r
+\r
+        while (j.hasNext()) {\r
+          String field = anEntity.getValue( (String) j.next());\r
+\r
+          if (exactMatch) {\r
+            if (field != null && regularExpression.isMatch(field)) {\r
+              return true;\r
+            }\r
+          }\r
+          else {\r
+            if (field != null && regularExpression.getMatch(field) != null) {\r
+              return true;\r
+            }\r
+          }\r
+        }\r
+      }\r
+      catch (Throwable t) {\r
+      }\r
+      return false;\r
+    }\r
+  }\r
+}
\ No newline at end of file
index 637f4ac..14ba032 100755 (executable)
@@ -29,7 +29,7 @@
  */
 package mircoders.localizer.basic;
 
-import java.util.List;
+import java.util.*;
 import java.util.Random;
 
 import mir.config.MirPropertiesConfiguration;
@@ -41,13 +41,15 @@ import mircoders.entity.EntityComment;
 import mircoders.entity.EntityContent;
 import mircoders.global.MirGlobal;
 import mircoders.global.ProducerEngine;
-import mircoders.localizer.MirLocalizerExc;
+import mircoders.localizer.*;
 import mircoders.localizer.MirLocalizerFailure;
 import mircoders.localizer.MirOpenPostingLocalizer;
 
 public class MirBasicOpenPostingLocalizer implements MirOpenPostingLocalizer {
   private List afterContentProducerTasks;
   private List afterCommentProducerTasks;
+  private List filterTypes;
+  private Map filterTypesMap;
   protected LoggerWrapper logger;
   protected MirPropertiesConfiguration configuration;
 
@@ -73,6 +75,12 @@ public class MirBasicOpenPostingLocalizer implements MirOpenPostingLocalizer {
 
       throw new MirLocalizerFailure(t);
     }
+
+    filterTypes = new Vector();
+    filterTypesMap = new HashMap();
+
+    addSimpleAntiAbuseFilterType(new MirBasicAntiAbuseFilterTypes.RegularExpressionFilter("regexp"));
+    addSimpleAntiAbuseFilterType(new MirBasicAntiAbuseFilterTypes.IPFilter("ip"));
   }
 
   public SessionHandler getOpenSessionHandler(String aSessionType) {
@@ -122,4 +130,18 @@ public class MirBasicOpenPostingLocalizer implements MirOpenPostingLocalizer {
     return returnString.substring(5);
   }
 
+  public List getAntiAbuseFilterTypes() {
+    return filterTypes;
+  }
+
+  public void removeSimpleAntiAbuseFilterType(String aName) {
+    filterTypes.remove(filterTypesMap.get(aName));
+    filterTypesMap.remove(aName);
+  }
+
+  public void addSimpleAntiAbuseFilterType(MirAntiAbuseFilterType aFilterType) {
+    removeSimpleAntiAbuseFilterType(aFilterType.getName());
+    filterTypesMap.put(aFilterType.getName(), aFilterType);
+    filterTypes.add(aFilterType);
+  }
 }
index 0185cb4..11e2375 100755 (executable)
@@ -162,4 +162,12 @@ public class ServletHelper {
   public static EntityUsers getUser(HttpServletRequest aRequest) {
     return (EntityUsers) aRequest.getSession().getAttribute("login.uid");
   }
+  public static String getUserName(HttpServletRequest aRequest) {
+    EntityUsers user = getUser(aRequest);
+
+    if (user!=null)
+      return user.getValue("login");
+    else
+      return "nobody";
+  }
 }
index 8ab8aec..6c0fb93 100755 (executable)
-/*
- * Copyright (C) 2001, 2002 The Mir-coders group
- *
- * This file is part of Mir.
- *
- * Mir is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Mir is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Mir; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * In addition, as a special exception, The Mir-coders gives permission to link
- * the code of this program with  any library licensed under the Apache Software License,
- * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
- * (or with modified versions of the above that use the same license as the above),
- * and distribute linked combinations including the two.  You must obey the
- * GNU General Public License in all respects for all of the code used other than
- * the above mentioned libraries.  If you modify this file, you may extend this
- * exception to your version of the file, but you are not obligated to do so.
- * If you do not wish to do so, delete this exception statement from your version.
- */
-
-package mircoders.servlet;
-
-import java.util.Locale;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import mir.log.LoggerWrapper;
-import mir.servlet.ServletModule;
-import mir.servlet.ServletModuleFailure;
-import mir.util.HTTPRequestParser;
-import mir.util.URLBuilder;
-import mircoders.global.MirGlobal;
-
-public class ServletModuleAbuse extends ServletModule {
-  private static ServletModuleAbuse instance = new ServletModuleAbuse();
-  public static ServletModule getInstance() { return instance; }
-
-  private ServletModuleAbuse() {
-    logger = new LoggerWrapper("ServletModule.Abuse");
-    defaultAction = "showsettings";
-  }
-
-  public void editfilter(HttpServletRequest aRequest, HttpServletResponse aResponse) {
-    HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
-
-    String type=requestParser.getParameterWithDefault("type", "");
-    String id=requestParser.getParameterWithDefault("id", "");
-    String expression=requestParser.getParameterWithDefault("expression", "");
-
-    if (id.equals("")) {
-      MirGlobal.abuse().addFilter(type, expression);
-    }
-    else {
-      MirGlobal.abuse().setFilter(id, type, expression);
-    }
-
-    MirGlobal.abuse().save();
-
-    showfilters(aRequest, aResponse);
-  }
-
-  public void deletefilter(HttpServletRequest aRequest, HttpServletResponse aResponse) {
-    HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
-
-    String id=requestParser.getParameterWithDefault("id", "");
-    MirGlobal.abuse().deleteFilter(id);
-
-    MirGlobal.abuse().save();
-
-    showfilters(aRequest, aResponse);
-  }
-
-  public void showfilters(HttpServletRequest aRequest, HttpServletResponse aResponse) {
-    URLBuilder urlBuilder = new URLBuilder();
-
-    try {
-      Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)});
-
-      urlBuilder.setValue("module", "Abuse");
-      urlBuilder.setValue("do", "showfilters");
-      responseData.put("thisurl", urlBuilder.getQuery());
-
-      responseData.put("filters", MirGlobal.abuse().getFilters());
-      responseData.put("filtertypes", MirGlobal.abuse().getFilterTypes());
-
-      ServletHelper.generateResponse(aResponse.getWriter(), responseData, "abuse.filters.template");
-    }
-    catch (Throwable e) {
-      throw new ServletModuleFailure(e);
-    }
-  }
-
-
-  public void showsettings(HttpServletRequest aRequest, HttpServletResponse aResponse) {
-    URLBuilder urlBuilder = new URLBuilder();
-
-    try {
-      Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)});
-
-      urlBuilder.setValue("module", "Abuse");
-      urlBuilder.setValue("do", "showsettings");
-
-      responseData.put("thisurl", urlBuilder.getQuery());
-
-      responseData.put("articleactions", MirGlobal.abuse().getArticleActions());
-      responseData.put("commentactions", MirGlobal.abuse().getCommentActions());
-
-      responseData.put("disableop", new Boolean(MirGlobal.abuse().getOpenPostingDisabled()));
-      responseData.put("passwordop", new Boolean(MirGlobal.abuse().getOpenPostingPassword()));
-      responseData.put("logenabled", new Boolean(MirGlobal.abuse().getLogEnabled()));
-      responseData.put("logsize", Integer.toString(MirGlobal.abuse().getLogSize()));
-      responseData.put("usecookies", new Boolean(MirGlobal.abuse().getCookieOnBlock()));
-      responseData.put("articleaction", MirGlobal.abuse().getArticleBlockAction());
-      responseData.put("commentaction", MirGlobal.abuse().getCommentBlockAction());
-
-      ServletHelper.generateResponse(aResponse.getWriter(), responseData, "abuse.template");
-    }
-    catch (Throwable e) {
-      throw new ServletModuleFailure(e);
-    }
-  }
-
-  public void savesettings(HttpServletRequest aRequest, HttpServletResponse aResponse) {
-    try {
-      HTTPRequestParser parser = new HTTPRequestParser(aRequest);
-
-      MirGlobal.abuse().setOpenPostingDisabled(parser.getParameterWithDefault("disableop", "").equals("1"));
-      MirGlobal.abuse().setOpenPostingPassword(parser.getParameterWithDefault("passwordop", "").equals("1"));
-      MirGlobal.abuse().setLogEnabled(parser.getParameterWithDefault("logenabled", "").equals("1"));
-
-      try {
-        MirGlobal.abuse().setLogSize(parser.getIntegerWithDefault("logsize", MirGlobal.abuse().getLogSize()));
-      }
-      catch (Throwable t) {
-      }
-
-      MirGlobal.abuse().setCookieOnBlock(parser.getParameterWithDefault("usecookies", "").equals("1"));
-
-      MirGlobal.abuse().setArticleBlockAction(parser.getParameter("articleaction"));
-      MirGlobal.abuse().setCommentBlockAction(parser.getParameter("commentaction"));
-
-      MirGlobal.abuse().save();
-
-      showsettings(aRequest, aResponse);
-    }
-    catch (Throwable e) {
-      throw new ServletModuleFailure(e);
-    }
-  }
-
-  public void showlog(HttpServletRequest aRequest, HttpServletResponse aResponse) {
-    URLBuilder urlBuilder = new URLBuilder();
-    int count;
-
-    try {
-      Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)});
-      urlBuilder.setValue("module", "Abuse");
-      urlBuilder.setValue("do", "showlog");
-      responseData.put("thisurl", urlBuilder.getQuery());
-
-      responseData.put("log", MirGlobal.abuse().getLog());
-
-      ServletHelper.generateResponse(aResponse.getWriter(), responseData, "abuse.log.template");
-    }
-    catch (Throwable e) {
-      throw new ServletModuleFailure(e);
-    }
-  }
+/*\r
+ * Copyright (C) 2001, 2002 The Mir-coders group\r
+ *\r
+ * This file is part of Mir.\r
+ *\r
+ * Mir is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Mir is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with Mir; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ *\r
+ * In addition, as a special exception, The Mir-coders gives permission to link\r
+ * the code of this program with  any library licensed under the Apache Software License,\r
+ * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library\r
+ * (or with modified versions of the above that use the same license as the above),\r
+ * and distribute linked combinations including the two.  You must obey the\r
+ * GNU General Public License in all respects for all of the code used other than\r
+ * the above mentioned libraries.  If you modify this file, you may extend this\r
+ * exception to your version of the file, but you are not obligated to do so.\r
+ * If you do not wish to do so, delete this exception statement from your version.\r
+ */\r
+\r
+package mircoders.servlet;\r
+\r
+import java.util.Locale;\r
+import java.util.Map;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+import mir.log.LoggerWrapper;\r
+import mir.servlet.ServletModule;\r
+import mir.servlet.ServletModuleExc;\r
+import mir.servlet.ServletModuleFailure;\r
+import mir.util.HTTPRequestParser;\r
+import mir.util.URLBuilder;\r
+import mircoders.global.Abuse;\r
+import mircoders.global.MirGlobal;\r
+\r
+public class ServletModuleAbuse extends ServletModule {\r
+  private static ServletModuleAbuse instance = new ServletModuleAbuse();\r
+  private String editFilterTemplate;\r
+  private String listFiltersTemplate;\r
+  private String mainTemplate;\r
+  private String viewLogTemplate;\r
+\r
+  public static ServletModule getInstance() { return instance; }\r
+\r
+  private ServletModuleAbuse() {\r
+    logger = new LoggerWrapper("ServletModule.Abuse");\r
+    defaultAction = "showsettings";\r
+\r
+    editFilterTemplate = configuration.getString("ServletModule.Abuse.EditFilter.Template");\r
+    listFiltersTemplate = configuration.getString("ServletModule.Abuse.ListFilters.Template");\r
+    viewLogTemplate = configuration.getString("ServletModule.Abuse.ViewLog.Template");\r
+    mainTemplate = configuration.getString("ServletModule.Abuse.Main.Template");\r
+  }\r
+\r
+  public void edit(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {\r
+    HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);\r
+    String id=requestParser.getParameterWithDefault("id", "");\r
+\r
+    if (id.equals("")) {\r
+      editfilter(aRequest, aResponse, "", "", "", "", "", "", "");\r
+    }\r
+    else {\r
+      Abuse.FilterRule filter = MirGlobal.abuse().getFilter(id);\r
+      if (filter==null)\r
+        throw new ServletModuleExc("Filter not found");\r
+\r
+      editfilter(aRequest, aResponse, filter.getId(), filter.getType(), filter.getExpression(), filter.getComments(), filter.getCommentAction(), filter.getArticleAction(), "");\r
+    }\r
+  }\r
+\r
+  public void editfilter(HttpServletRequest aRequest, HttpServletResponse aResponse,\r
+        String anId, String aType, String anExpression, String aComments,\r
+        String aCommentAction, String anArticleAction, String anErrorMessage) throws ServletModuleExc {\r
+    try {\r
+      Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)});\r
+\r
+      responseData.put("id", anId);\r
+      responseData.put("type", aType);\r
+      responseData.put("expression", anExpression);\r
+      responseData.put("comments", aComments);\r
+      responseData.put("articleaction", anArticleAction);\r
+      responseData.put("commentaction", aCommentAction);\r
+      responseData.put("errormessage", anErrorMessage);\r
+\r
+      responseData.put("articleactions", MirGlobal.abuse().getArticleActions());\r
+      responseData.put("commentactions", MirGlobal.abuse().getCommentActions());\r
+      responseData.put("filtertypes", MirGlobal.abuse().getFilterTypes());\r
+\r
+      ServletHelper.generateResponse(aResponse.getWriter(), responseData, editFilterTemplate);\r
+    }\r
+    catch (Throwable e) {\r
+      throw new ServletModuleFailure(e);\r
+    }\r
+  }\r
+\r
+  public void updatefilter(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {\r
+    HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);\r
+\r
+    String type=requestParser.getParameterWithDefault("type", "");\r
+    String id=requestParser.getParameterWithDefault("id", "");\r
+    String expression=requestParser.getParameterWithDefault("expression", "");\r
+    String commentaction=requestParser.getParameterWithDefault("commentaction", "");\r
+    String articleaction=requestParser.getParameterWithDefault("articleaction", "");\r
+    String comments=requestParser.getParameterWithDefault("comments", "");\r
+\r
+    String errorMessage;\r
+\r
+    String userName = ServletHelper.getUserName(aRequest);\r
+\r
+    if (id.equals("")) {\r
+      errorMessage = MirGlobal.abuse().addFilter(type, expression,comments, commentaction, articleaction);\r
+    }\r
+    else {\r
+      errorMessage = MirGlobal.abuse().setFilter(id, type, expression, comments, commentaction, articleaction);\r
+    }\r
+\r
+    if (errorMessage!=null) {\r
+      editfilter(aRequest, aResponse, id, type, expression, comments, commentaction, articleaction, errorMessage);\r
+    }\r
+    else {\r
+      MirGlobal.abuse().save();\r
+      showfilters(aRequest, aResponse);\r
+    }\r
+  }\r
+\r
+  public void delete(HttpServletRequest aRequest, HttpServletResponse aResponse) {\r
+    HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);\r
+\r
+    String id=requestParser.getParameterWithDefault("id", "");\r
+    MirGlobal.abuse().deleteFilter(id);\r
+\r
+    MirGlobal.abuse().save();\r
+\r
+    showfilters(aRequest, aResponse);\r
+  }\r
+\r
+  public void add(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc {\r
+    editfilter(aRequest, aResponse, "", "", "", "", "", "", "");\r
+  }\r
+  public void showfilters(HttpServletRequest aRequest, HttpServletResponse aResponse) {\r
+    URLBuilder urlBuilder = new URLBuilder();\r
+\r
+    try {\r
+      Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)});\r
+\r
+      urlBuilder.setValue("module", "Abuse");\r
+      urlBuilder.setValue("do", "showfilters");\r
+      responseData.put("thisurl", urlBuilder.getQuery());\r
+\r
+      responseData.put("filters", MirGlobal.abuse().getFilters());\r
+\r
+      ServletHelper.generateResponse(aResponse.getWriter(), responseData, listFiltersTemplate);\r
+    }\r
+    catch (Throwable e) {\r
+      throw new ServletModuleFailure(e);\r
+    }\r
+  }\r
+\r
+  public void showsettings(HttpServletRequest aRequest, HttpServletResponse aResponse) {\r
+    URLBuilder urlBuilder = new URLBuilder();\r
+\r
+    try {\r
+      Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)});\r
+\r
+      urlBuilder.setValue("module", "Abuse");\r
+      urlBuilder.setValue("do", "showsettings");\r
+\r
+      responseData.put("thisurl", urlBuilder.getQuery());\r
+\r
+      responseData.put("articleactions", MirGlobal.abuse().getArticleActions());\r
+      responseData.put("commentactions", MirGlobal.abuse().getCommentActions());\r
+\r
+      responseData.put("disableop", new Boolean(MirGlobal.abuse().getOpenPostingDisabled()));\r
+      responseData.put("passwordop", new Boolean(MirGlobal.abuse().getOpenPostingPassword()));\r
+      responseData.put("logenabled", new Boolean(MirGlobal.abuse().getLogEnabled()));\r
+      responseData.put("logsize", Integer.toString(MirGlobal.abuse().getLogSize()));\r
+      responseData.put("usecookies", new Boolean(MirGlobal.abuse().getCookieOnBlock()));\r
+      responseData.put("articleaction", MirGlobal.abuse().getArticleBlockAction());\r
+      responseData.put("commentaction", MirGlobal.abuse().getCommentBlockAction());\r
+\r
+      ServletHelper.generateResponse(aResponse.getWriter(), responseData, mainTemplate);\r
+    }\r
+    catch (Throwable e) {\r
+      throw new ServletModuleFailure(e);\r
+    }\r
+  }\r
+\r
+  public void savesettings(HttpServletRequest aRequest, HttpServletResponse aResponse) {\r
+    try {\r
+      HTTPRequestParser parser = new HTTPRequestParser(aRequest);\r
+\r
+      MirGlobal.abuse().setOpenPostingDisabled(parser.getParameterWithDefault("disableop", "").equals("1"));\r
+      MirGlobal.abuse().setOpenPostingPassword(parser.getParameterWithDefault("passwordop", "").equals("1"));\r
+      MirGlobal.abuse().setLogEnabled(parser.getParameterWithDefault("logenabled", "").equals("1"));\r
+\r
+      try {\r
+        MirGlobal.abuse().setLogSize(parser.getIntegerWithDefault("logsize", MirGlobal.abuse().getLogSize()));\r
+      }\r
+      catch (Throwable t) {\r
+      }\r
+\r
+      MirGlobal.abuse().setCookieOnBlock(parser.getParameterWithDefault("usecookies", "").equals("1"));\r
+\r
+      MirGlobal.abuse().setArticleBlockAction(parser.getParameter("articleaction"));\r
+      MirGlobal.abuse().setCommentBlockAction(parser.getParameter("commentaction"));\r
+\r
+      MirGlobal.abuse().save();\r
+\r
+      showsettings(aRequest, aResponse);\r
+    }\r
+    catch (Throwable e) {\r
+      throw new ServletModuleFailure(e);\r
+    }\r
+  }\r
+\r
+  public void showlog(HttpServletRequest aRequest, HttpServletResponse aResponse) {\r
+    URLBuilder urlBuilder = new URLBuilder();\r
+    int count;\r
+\r
+    try {\r
+      Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)});\r
+      urlBuilder.setValue("module", "Abuse");\r
+      urlBuilder.setValue("do", "showlog");\r
+      responseData.put("thisurl", urlBuilder.getQuery());\r
+\r
+      responseData.put("log", MirGlobal.abuse().getLog());\r
+\r
+      ServletHelper.generateResponse(aResponse.getWriter(), responseData, viewLogTemplate);\r
+    }\r
+    catch (Throwable e) {\r
+      throw new ServletModuleFailure(e);\r
+    }\r
+  }\r
 }
\ No newline at end of file
index 0f9a895..26c3e4b 100755 (executable)
  */
 package mircoders.servlet;
 
-import java.util.*;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-import mir.entity.adapter.EntityAdapter;
-import mir.log.LoggerWrapper;
-import mir.servlet.ServletModule;
-import mir.servlet.ServletModuleExc;
-import mir.servlet.ServletModuleFailure;
-import mir.util.*;
-import mircoders.entity.EntityComment;
-import mircoders.entity.EntityContent;
-import mircoders.entity.EntityUsers;
-import mircoders.global.MirGlobal;
-import mircoders.localizer.MirAdminInterfaceLocalizer;
-import mircoders.module.ModuleComment;
-import mircoders.module.ModuleContent;
-import mircoders.storage.DatabaseComment;
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Vector;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+import mir.entity.adapter.EntityAdapter;\r
+import mir.log.LoggerWrapper;\r
+import mir.servlet.ServletModule;\r
+import mir.servlet.ServletModuleExc;\r
+import mir.util.StringRoutines;\r
+import mircoders.entity.EntityComment;\r
+import mircoders.entity.EntityContent;\r
+import mircoders.entity.EntityUsers;\r
+import mircoders.global.MirGlobal;\r
+import mircoders.localizer.MirAdminInterfaceLocalizer;\r
+import mircoders.module.ModuleComment;\r
+import mircoders.module.ModuleContent;\r
+import mircoders.storage.DatabaseComment;\r
 import mircoders.storage.DatabaseContent;
 
 public class ServletModuleLocalizer extends ServletModule {
@@ -96,18 +96,7 @@ public class ServletModuleLocalizer extends ServletModule {
 
   }
 
-  private EntityAdapter getActiveUser(HttpServletRequest aRequest) throws ServletModuleExc {
-    try {
-      HttpSession session = aRequest.getSession(false);
-      return MirGlobal.localizer().dataModel().adapterModel().makeEntityAdapter
-          ("user", ServletHelper.getUser(aRequest));
-    }
-    catch (Throwable e) {
-      throw new ServletModuleFailure("ServletModuleLocalizer.getActiveUser: " + e.getMessage(), e);
-    }
-  }
-
-  public void performCommentOperation(EntityAdapter aUser, String anId, String anOperation) {
+  public void performCommentOperation(EntityUsers aUser, String anId, String anOperation) {
     MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation;
     EntityAdapter comment;
     EntityComment entity;
@@ -116,9 +105,7 @@ public class ServletModuleLocalizer extends ServletModule {
       entity = (EntityComment) commentModule.getById(anId);
 
       if (entity != null) {
-        comment = MirGlobal.localizer().dataModel().adapterModel().makeEntityAdapter("comment", entity);
-        operation = MirGlobal.localizer().adminInterface().simpleCommentOperationForName(anOperation);
-        operation.perform(aUser, comment);
+        MirGlobal.performCommentOperation(aUser, entity, anOperation);
         logger.info("Operation " + anOperation + " successfully performed on comment " + anId);
       }
       else {
@@ -135,7 +122,7 @@ public class ServletModuleLocalizer extends ServletModule {
     String operationString = aRequest.getParameter("operation");
     String returnUrlString = aRequest.getParameter("returnurl");
 
-    performCommentOperation(getActiveUser(aRequest), commentIdString, operationString);
+    performCommentOperation(ServletHelper.getUser(aRequest), commentIdString, operationString);
 
     redirect(aResponse, returnUrlString);
   }
@@ -158,7 +145,7 @@ public class ServletModuleLocalizer extends ServletModule {
             String commentIdString = (String) parts.get(0);
             String operationString = (String) parts.get(1);
 
-            performCommentOperation(getActiveUser(aRequest), commentIdString, operationString);
+            performCommentOperation(ServletHelper.getUser(aRequest), commentIdString, operationString);
           }
         }
       }
@@ -167,7 +154,7 @@ public class ServletModuleLocalizer extends ServletModule {
     redirect(aResponse, returnUrlString);
   }
 
-  public void performArticleOperation(EntityAdapter aUser, String anId, String anOperation) {
+  public void performArticleOperation(EntityUsers aUser, String anId, String anOperation) {
     MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation;
     EntityAdapter article;
     EntityContent entity;
@@ -176,11 +163,7 @@ public class ServletModuleLocalizer extends ServletModule {
       entity = (EntityContent) contentModule.getById(anId);
 
       if (entity != null) {
-        article = MirGlobal.localizer().dataModel().adapterModel().
-            makeEntityAdapter("content", entity);
-        operation = MirGlobal.localizer().adminInterface().
-            simpleArticleOperationForName(anOperation);
-        operation.perform(aUser, article);
+        MirGlobal.performArticleOperation(aUser, entity, anOperation);
         logger.info("Operation " + anOperation + " successfully performed on article " + anId);
       }
       else {
@@ -197,7 +180,7 @@ public class ServletModuleLocalizer extends ServletModule {
     String operationString = aRequest.getParameter("operation");
     String returnUrlString = aRequest.getParameter("returnurl");
 
-    performArticleOperation(getActiveUser(aRequest), articleIdString, operationString);
+    performArticleOperation(ServletHelper.getUser(aRequest), articleIdString, operationString);
     redirect(aResponse, returnUrlString);
   }
 
@@ -219,7 +202,7 @@ public class ServletModuleLocalizer extends ServletModule {
             String articleIdString = (String) parts.get(0);
             String operationString = (String) parts.get(1);
 
-            performArticleOperation(getActiveUser(aRequest), articleIdString, operationString);
+            performArticleOperation(ServletHelper.getUser(aRequest), articleIdString, operationString);
           }
         }
       }
diff --git a/templates/admin/EDITFUNCTIONS.template b/templates/admin/EDITFUNCTIONS.template
new file mode 100755 (executable)
index 0000000..14a7a51
--- /dev/null
@@ -0,0 +1,111 @@
+<include "SETTINGS.template">\r
+\r
+<function EditStart(aHiddenFields, aHiddenValues)>\r
+    <form action="${config.actionRoot}" method="post">
+        <assign index="0">\r
+        <list aHiddenFields as i>\r
+          <input type="hidden" name="${i}" value="${utility.encodeHTML(aHiddenValues[index])}">\r
+          <assign index=utility.increment(index)>
+        </list>\r
+      <table border="0">
+</function>
+\r
+<function EditEnd()>\r
+      </table>\r
+    </form>\r
+</function>\r
+\r
+<function EditFieldStart(aLabel, aHint, aLabelClass, aValueClass)>\r
+  <tr>
+    <td align="right" class="${aLabelClass}">
+      <b>${aLabel}:</b>
+      <if aHint>
+        <br>
+        <span class="small">${aHint}</span>      
+      </if>
+    </td>
+    
+    <td class="${aValueClass}">
+</function>\r
+\r
+<function EditFieldEnd()>\r
+    </td>
+  </tr>\r
+</function>  \r
+\r
+
+<function EditText(label, size, maxlength, fieldname, fieldcontent, aLabelClass, aValueClass)>\r
+  <call EditFieldStart(label, "", aLabelClass, aValueClass)>
+      <input type="text" size="${size}" maxlength="${maxlength}" name="${fieldname}" value="${utility.encodeHTML(fieldcontent)}">
+  <call EditFieldEnd()>
+</function>
+<function EditTextNormal(label, size, maxlength, fieldname, fieldcontent)>\r
+  <call EditText(label, size, maxlength, fieldname, fieldcontent, "table-left", "listrow2")>\r
+</function>
+<function EditTextHighlighted(label, size, maxlength, fieldname, fieldcontent)>\r
+  <call EditText(label, size, maxlength, fieldname, fieldcontent, "table-left-light", "listrow1")>\r
+</function>
+\r
+\r
+<function EditPassword(label, size, maxlength, fieldname, fieldcontent, aLabelClass, aValueClass)>
+  <call EditFieldStart(label, "", aLabelClass, aValueClass)>
+      <input type="password" size="${size}" maxlength="${maxlength}" name="${fieldname}" value="${utility.encodeHTML(fieldcontent)}">
+  <call EditFieldEnd()>
+</function>\r
+\r
+<function EditPasswordNormal(label, size, maxlength, fieldname, fieldcontent)>\r
+  <call EditPassword(label, size, maxlength, fieldname, fieldcontent, "table-left", "listrow2")>\r
+</function>
+<function EditPasswordHighlighted(label, size, maxlength, fieldname, fieldcontent)>\r
+  <call EditPassword(label, size, maxlength, fieldname, fieldcontent, "table-left-light", "listrow1")>\r
+</function>
+\r
+
+<function EditCheckbox(label, fieldname, fieldcontent, aLabelClass, aValueClass)>
+  <call EditFieldStart(label, "", aLabelClass, aValueClass)>
+      <input type="checkbox" name="${fieldname}" value="1"<if fieldcontent=="1"> checked</if>>&nbsp;&nbsp;
+  <call EditFieldEnd()>
+</function> \r
+\r
+<function EditCheckboxNormal(label, fieldname, fieldcontent)>\r
+  <call EditCheckbox(label, fieldname, fieldcontent, "table-left", "listrow2")>\r
+</function>
+<function EditCheckboxHighlighted(label, fieldname, fieldcontent)>\r
+  <call EditCheckbox(label, fieldname, fieldcontent, "table-left-light", "listrow1")>\r
+</function>
+
+
+<function EditTextArea(label, aHint, cols, rows, fieldname, fieldcontent, aLabelClass, aValueClass)>
+  <call EditFieldStart(label, aHint, aLabelClass, aValueClass)>
+      <textarea cols="${cols}" rows="${rows}" name="${fieldname}" wrap="virtual">${utility.encodeHTML(fieldcontent)}</textarea>
+  <call EditFieldEnd()>
+</function>\r
+\r
+<function EditTextAreaNormal(label, aHint, cols, rows, fieldname, fieldcontent)>\r
+  <call EditTextArea(label, aHint, cols, rows, fieldname, fieldcontent, "table-left", "listrow2")>\r
+</function>
+<function EditTextAreaHighlighted(label, size, maxlength, fieldname, fieldcontent)>\r
+  <call EditTextArea(label, aHint, cols, rows, fieldname, fieldcontent, "table-left-light", "listrow1")>\r
+</function>
+\r
+
+\r
+\r
+<function EditPullDown (label, fieldname, entrieslist, keyfield, valuefield, value, langprefix, aLabelClass, aValueClass)>
+  <call EditFieldStart(label, "", aLabelClass, aValueClass)>
+       <select name="${fieldname}">
+         <list entrieslist as a>
+           <option value="${a[keyfield]}" <if (a[keyfield] == value)>selected</if>><if langprefix>${lang(langprefix+a[valuefield])}<else>${a[valuefield]}</if></option>
+         </list>
+       </select>
+  <call EditFieldEnd()>
+</function>   \r
+
+<function EditPullDownNormal(label, fieldname, entrieslist, keyfield, valuefield, value, langprefix)>\r
+  <call EditPullDown(label, fieldname, entrieslist, keyfield, valuefield, value, langprefix, "table-left", "listrow2")>\r
+</function>
+<function EditPullDownHighlighted(label, fieldname, entrieslist, keyfield, valuefield, value, langprefix)>\r
+  <call EditPullDown(label, fieldname, entrieslist, keyfield, valuefield, value, langprefix, "table-left-light", "listrow1")>\r
+</function>
+\r
+
index 62b4eb0..b9c68bc 100755 (executable)
@@ -1,3 +1,5 @@
+<include "EDITFUNCTIONS.template">
+
 <function showAbsoluteLinkButton(anUrl, aLabel)>
     <span class="link-box-div">
   <a class="link-box" href="${utility.encodeHTML(anUrl)}">${aLabel}</a>
 </function>   
 
 
-<comment>4 functions to create Table rows with input-fields</comment>
+
+
+
+
+
+
+
 <function TextInputTableRow (label, size, maxlength, fieldname, fieldcontent)>
   <tr>
     <td align="right" class="table-left">
 </function>
 
 <function CheckboxTableRow (label, fieldname, fieldcontent )>
+  <call EditCheckboxNormal(label, fieldname, fieldcontent)>
+<comment>
   <tr>
     <td align="right" valign="top" class="table-left">
       <b>${label}:</b>
       <input type="checkbox" name="${fieldname}" value="1"<if fieldcontent=="1"> checked</if>>&nbsp;&nbsp;
     </td>
   </tr>
+</comment>  
 </function> 
 
 <function TextAreaTableRow (label, hint, cols, rows, fieldname, fieldcontent )>
diff --git a/templates/admin/LISTFUNCTIONS.template b/templates/admin/LISTFUNCTIONS.template
new file mode 100755 (executable)
index 0000000..256e652
--- /dev/null
@@ -0,0 +1,66 @@
+<include "SETTINGS.template">\r
+<function ListStart()>\r
+  <table cellspacing="2" border="0">
+  <assign alt="0">
+</function>
+\r
+<function ListHead(aHeaders)>\r
+  <assign TABLE_NR_COLUMNS="1">
+  <list aHeaders as h>
+    <assign TABLE_NR_COLUMNS=utility.increment(TABLE_NR_COLUMNS)>
+  </list>
+\r
+  <tr class="${TABLE_HEAD_CLASS}">
+    <list aHeaders as i>
+      <td class="${TABLE_HEAD_CLASS}">
+        <b>${i}</b> 
+      </td>
+    </list>
+      <td class="${TABLE_HEAD_CLASS}">
+        &nbsp;
+      </td> 
+  </tr>
+</function>
+\r
+<function ListFoot(aNrRecords, aFrom, aTo)>\r
+  <tr>    
+    <td colspan="${TABLE_NR_COLUMNS}" class="table-foot">
+      ${aNrRecords} ${lang("records")} / ${lang("show_from_to", aFrom, aTo)}
+    </td>
+  </tr>
+</function>
+\r
+<function ListEnd()>\r
+</table>\r
+</function>\r
+
+<function ListEntry(aFields, aLinkPrefix, aLinks, aLinkTitles)>\r
+    <if alt=="1">
+      <assign alt="0">
+      <tr class="${LIST_ROW_CLASS_ALTERNATIVE}">
+    <else>
+      <assign alt="1"> 
+      <tr class="${LIST_ROW_CLASS}">
+    </if>
+      
+    <list aFields as i>   
+      <td>
+        ${i}
+      </td>
+    </list>
+      <td>\r
+        <assign index="0">\r
+        <assign first="1">\r
+        <list aLinks as i>\r
+          <if first=="1">\r
+            <assign first="0">\r
+          <else>  \r
+            |\r
+          </if>\r
+          <a class="listcommand" href="${config.actionRoot}?${utility.encodeHTML(aLinkPrefix)}${utility.encodeHTML(i)}">${aLinkTitles[index]}</a>        \r
+          <assign index=utility.increment(index)>
+        </list>\r
+      </td>
+    </tr>
+</function>\r
+\r
diff --git a/templates/admin/SETTINGS.template b/templates/admin/SETTINGS.template
new file mode 100755 (executable)
index 0000000..ccbdc43
--- /dev/null
@@ -0,0 +1,4 @@
+<assign TABLE_HEAD_CLASS          "table-head">
+<assign TABLE_FOOT_CLASS          "table-foot">
+<assign LIST_ROW_CLASS             "listrow1">
+<assign LIST_ROW_CLASS_ALTERNATIVE "listrow2">
diff --git a/templates/admin/abuse.filter.template b/templates/admin/abuse.filter.template
new file mode 100755 (executable)
index 0000000..0fc20dc
--- /dev/null
@@ -0,0 +1,46 @@
+<html>
+<head>
+  <title>${lang("abuse.filter.htmltitle")}</title>
+  <link rel="stylesheet" type="text/css" href="${config.docRoot}/style/admin.css"
+</head>
+
+<body marginwidth="0" marginheight="0" topmargin="0" leftmargin="0">
+
+<include "FUNCTIONS.template">
+<include "EDITFUNCTIONS.template">
+
+<include "head.template">
+
+<body marginwidth="0" marginheight="0" topmargin="0" leftmargin="0">
+
+  <if errormessage>
+     <p class="text-alert"> ${lang("abuse.filtererror."+errormessage)}
+     </p>
+  </if>
+
+
+  <call EditStart( 
+        ["module", "id", "do"], 
+        ["Abuse", id, "updatefilter"])>
+
+        <call EditPullDownNormal(lang("abuse.filter.type"), "type", filtertypes, "identifier", "resource", type, "abuse.filtertype.")>\r
+        <call EditTextNormal (lang("abuse.filter.expression"), 40, 255, "expression", expression)>
+        <call EditPullDownNormal(lang("abuse.filter.articleaction"), "articleaction", articleactions, "identifier", "resource", articleaction, "content.operation.")>\r
+        <call EditPullDownNormal(lang("abuse.filter.commentaction"), "commentaction", commentactions, "identifier", "resource", commentaction, "comment.operation.")>\r
+        <call EditTextAreaNormal (lang("abuse.filter.comments"), "", 40, 3, "comments", comments)>
+        
+        <tr>
+          <td class="table-foot" colspan="2" align="right"> 
+          <if id>
+            <input type="submit" name="save" value="${lang("save")}">
+          <else>
+            <input type="submit" name="save" value="${lang("insert")}">
+          </if> 
+          </td>
+        </tr>
+        
+  <call EditEnd()>
+  <p><a class="link-box" href="${config.actionRoot}?module=Abuse&do=showfilters">[&lt;] ${lang("back")} </a> &nbsp;</p>
+    <include "foot.template">
+  </body>
+</html>
index 1c02048..3455f8a 100755 (executable)
@@ -1,75 +1,66 @@
-<function showFilterEntry(aType, anExpression, anId)>
-      <form method="post" action="${config.actionRoot}">
-        <input type="hidden" name="module" value="Abuse">
-        <input type="hidden" name="do" value="editfilter">
-        <if anId>
-          <input type="hidden" name="id" value="${anId}">
-        </if>
-        <if grey=="1"><assign grey="0"><tr class="listrow1"><else><tr class="listrow2"><assign grey="1"> </if>
-          <td>
-            <select name="type">
-              <list filtertypes as t>
-                <option value="${t.id}" <if t.id==aType>selected</if>>${lang("abuse.filtertype."+t.resource)}</option>
-              </list>
-            </select>
-          </td>
-          <td><input type="text" name="expression" size="30" value="${utility.encodeHTML(anExpression)}"></td>
-          <if anId>
-            <td>
-              <input type="submit" name="save" value="${lang("save")}">
-            </td>
-            <td>
-                <a class="listcommand" href="${config.actionRoot}?module=Abuse&do=deletefilter&id=${anId}">[${lang("delete")}]</a>
-                &nbsp;
-            </td>
-          <else>
-            <td>
-              <input class="majorbutton" type="submit" name="save" value="${lang("add")}">
-            </td>
-          </if>
-        </tr>
-      </form>
-</function>
-
-
 <html>
 <head>
-  <title>${config["Mir.Name"]} | ${lang("userlist.htmltitle")}</title>
+  <title>${config["Mir.Name"]} | ${lang("abuse.filters.htmltitle")}</title>
   <link rel="stylesheet" type="text/css" href="${config.docRoot}/style/admin.css">
 </head>
-
 <body marginwidth="0" marginheight="0" topmargin="0" leftmargin="0">
+<include "LISTFUNCTIONS.template">
+<include "FUNCTIONS.template">
 <include "head.template">
-<p>
-  <a class="link-box" href="${config.actionRoot}?module=Abuse">[ &lt; ] ${lang("back")}</a>&nbsp;&nbsp;
-  <a class="link-box" href="${config.actionRoot}?module=Abuse&do=showlog">${lang("abuse.showlog")}</a>
-  <br><br>
-</p>
-<table border="0" cellpadding="2" cellspacing="1">
-  <tr>
-    <td class="table-head"><b>${lang("abuse.filter.type")}</b></td>
-    <td class="table-head"><b>${lang("abuse.filter.expression")}</b></td>
-    <td class="table-head"><b>&nbsp;</b></td>
-    <td class="table-head"><b>&nbsp;</b></td>
-  </tr>
 
-  <assign grey="0">      
-  <list filters as i>
-    <call showFilterEntry(i.type, i.expression, i.id)>
-  </list>
+    <p>
+      <a class="link-box" href="${config.actionRoot}?module=Abuse">[ &lt; ] ${lang("back")}</a>&nbsp;&nbsp;
+      <a class="link-box" href="${config.actionRoot}?module=Abuse&do=add">[+] ${lang("add")}</a> &nbsp;
+      <if config["Abuse.DisallowIPLogging"]!="1">
+        <a class="link-box" href="${config.actionRoot}?module=Abuse&do=showlog">${lang("abuse.showlog")}</a>
+      </if>
+      <br><br>
+    </p>
+    <call ListStart()>\r
+    <call ListHead([
+          lang("abuse.filter.type"), 
+          lang("abuse.filter.expression"),
+          lang("abuse.filter.articleaction"),
+          lang("abuse.filter.commentaction"),
+          lang("abuse.filter.comments"),
+          lang("abuse.filter.lasthit"), 
+           ])>
+    <list filters as f>    
+      <if f.lastHit>\r
+        <call ListEntry([
+          lang("abuse.filtertype."+f.type),
+          utility.encodeHTML(f.expression),
+          lang("content.operation."+f.articleAction),
+          lang("comment.operation."+f.commentAction),
+          f.comments,
+          f.lastHit.format(config["Mir.DefaultDateTimeFormat"], config["Mir.DefaultTimezone"])
+          ], 
+          "module=Abuse&id="+f.id, 
+          ["&do=edit", "&do=delete"], 
+          [lang("edit"), lang("delete")])
+        >
+      <else>
+        <call ListEntry([
+          lang("abuse.filtertype."+f.type),
+          utility.encodeHTML(f.expression),
+          lang("content.operation."+f.articleAction),
+          lang("comment.operation."+f.commentAction),
+          f.comments,
+          "-"
+          ], 
+          "module=Abuse&id="+f.id, 
+          ["&do=edit", "&do=delete"], 
+          [lang("edit"), lang("delete")])
+        >
+      </if>
+    </list>\r
+    <call ListEnd()>\r
+    
+  <call AddOrBack("Abuse", module_jumpback, do_jumpback)>
+  <include "foot.template">
+</body>
+</html>
 
-  <call showFilterEntry("", "", "")>
-  </table>
 
-  
-<p>
-  <a class="link-box" href="${config.actionRoot}?module=Abuse">[ &lt; ] ${lang("back")}</a>&nbsp;&nbsp;
-  <a class="link-box" href="${config.actionRoot}?module=Abuse&do=showlog">${lang("abuse.showlog")}</a>
-</p>
-    <include "foot.template">
-  </body>
-</html>
 
 
index 999547d..1c90b7d 100755 (executable)
@@ -6,25 +6,24 @@
 
   <body marginwidth="0" marginheight="0" topmargin="0" leftmargin="0">
     <include "FUNCTIONS.template">
+    <include "head.template">
   
-  <include "head.template">
-
-    <form action="${config.actionRoot}" method="post">
-      <input type=hidden name=module value=Topics>
-      <input type="hidden" name="id" value="${data.id}">
       <if data.new>
-        <input type="hidden" name="do" value="insert">
+        <assign method="insert">
       <else>
-        <input type="hidden" name="do" value="update">
+        <assign method="update">
       </if>
-
-      <table border="0">
-    <call TextInputTableRow (lang("topic.title"), 40, 255, "title", data.title)>
-    <call TextAreaTableRow (lang("topic.description"), "", 40, 3, "description", data.description)>
-    <call TextInputTableRow (lang("topic.filename"), 20, 255, "filename", data.filename)>
-    <call TextInputTableRow (lang("topic.main_url"), 40, 255, "main_url", data.main_url)>
-    <call TextInputTableRow (lang("topic.archive_url"), 40, 255, "archiv_url", data.archiv_url)>
-
+      <call EditStart(
+         ["module", "id", "do"],
+         ["Topics", data.id, method])>
+         
+        <call EditTextNormal(lang("topic.title"), 40, 255, "title", data.title)>
+        <call EditTextAreaNormal(lang("topic.description"), "", 40, 3, "description", data.description)>
+        <call EditTextNormal(lang("topic.filename"), 20, 255, "filename", data.filename)>
+        <call EditTextNormal(lang("topic.main_url"), 40, 255, "main_url", data.main_url)>
+        <call EditTextNormal(lang("topic.archive_url"), 40, 255, "archiv_url", data.archiv_url)>
+      
+        <tr>
           <td class="table-foot" colspan="2" align="right"> 
           <if data.new>
             <input type="submit" name="save" value="${lang("insert")}">
@@ -33,8 +32,7 @@
           </if> 
           </td>
         </tr>
-      </table>    
-    </form>
+      <call EditEnd()>
   <p><a class="link-box" href="${config.actionRoot}?module=Topics&do=list">[&lt;] ${lang("back")} </a> &nbsp;</p>
     <include "foot.template">
   </body>