small fixes here and there
authorzapata <zapata>
Wed, 9 Jul 2003 22:09:35 +0000 (22:09 +0000)
committerzapata <zapata>
Wed, 9 Jul 2003 22:09:35 +0000 (22:09 +0000)
doc/MAINTENANCE.postgresql
source/mir/producer/reader/ProducerConfigReader.java
source/mir/util/XMLReader.java
source/mircoders/global/Abuse.java

index 0cc7df0..434a87f 100755 (executable)
@@ -23,22 +23,6 @@ these can be used as a basis to write your own custom scripts.
 
 USER MANAGMENT IN POSTGRESQL
 
--- set owner of datbase
-select * from pg_database;
-select * from pg_user;
-update pg_database set datdba=ID_FROM_PG_USER where datname=DATABASENAME
-
--- find all tables to grant privs / select is just building sql
--- to be exectued
-
-select 'grant all on '||relname||' to "de_indy";'
-from pg_class
-where relname not like 'pg%'
-order by relname;
-
--- alter table owner / select is just building sql
--- to be exectued
-select 'alter table '||relname||' owner to "de_indy";'
-from pg_class
-where relname not like 'pg%'
-order by relname;
\ No newline at end of file
+If you want to change the db user of a mir db, there's a script for 
+that in mir/dbscripts/extra.
+
index 0831d17..dd91805 100755 (executable)
@@ -411,8 +411,7 @@ public class ProducerConfigReader {
           }
         }
         else
-          throw new XMLReader.XMLReaderExc("Unknown producer node tag: '" +
-                                           aTag + "'");
+          throw new XMLReader.XMLReaderExc("Unknown producer node tag: '" + aTag + "'");
       }
       catch (Throwable t) {
         throw new XMLReader.XMLReaderFailure(t);
index 19628c8..954b2e7 100755 (executable)
@@ -88,8 +88,6 @@ public class XMLReader {
       Throwable t = ExceptionFunctions.traceCauseException(e);
 
       if (t instanceof XMLReaderExc) {
-        if (locator!=null && filename!=null)
-          ((XMLReaderExc) t).setLocation(filename, locator.getLineNumber(), locator.getColumnNumber());
         throw (XMLReaderExc) t;
       }
 
@@ -125,11 +123,33 @@ public class XMLReader {
         inputSource = new InputSource(anInputStream);
         parser.parse(inputSource, this);
       }
-      catch (ParserConfigurationException e) {
-        throw new XMLReaderExc("Internal exception: "+e.getMessage());
-      }
       catch (Throwable e) {
-        throw new XMLReaderFailure(e);
+        Throwable t = ExceptionFunctions.traceCauseException(e);
+
+        if (t instanceof XMLReaderExc) {
+          if (locator!=null && filename!=null)
+            ((XMLReaderExc) t).setLocation(filename, locator.getLineNumber(), locator.getColumnNumber());
+          throw (XMLReaderExc) t;
+        }
+
+        if (t instanceof SAXParseException) {
+          XMLReaderExc r = new XMLReaderExc(t.getMessage());
+
+          if (locator!=null && filename!=null)
+            r.setLocation(filename, locator.getLineNumber(), locator.getColumnNumber());
+
+          throw r;
+        }
+
+        if (t instanceof XMLReaderFailure) {
+          throw (XMLReaderFailure) t;
+        }
+
+        if (t instanceof ParserConfigurationException) {
+          throw new XMLReaderFailure("Internal exception: "+t.toString(), t);
+        }
+
+        throw new XMLReaderFailure(t);
       }
     }
 
index e404783..9e98adc 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 java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.Vector;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.collections.ExtendedProperties;
-import gnu.regexp.RE;
-
-import mir.config.MirPropertiesConfiguration;
-import mir.entity.Entity;
-import mir.log.LoggerWrapper;
-import mir.session.HTTPAdapters;
-import mir.session.Request;
-import mir.util.GeneratorFormatAdapters;
-import mir.util.InternetFunctions;
-import mir.util.StringRoutines;
-import mir.config.*;
-import mircoders.entity.EntityComment;
-import mircoders.entity.EntityContent;
-import mircoders.entity.EntityUsers;
-import mircoders.localizer.MirAdminInterfaceLocalizer;
-
-
-public class Abuse {
-  private List filters;
-  private int maxIdentifier;
-  private LoggerWrapper logger;
-  private LoggerWrapper adminUsageLogger;
-  private int logSize;
-  private boolean logEnabled;
-  private boolean openPostingDisabled;
-  private boolean openPostingPassword;
-  private boolean cookieOnBlock;
-  private String articleBlockAction;
-  private String commentBlockAction;
-  private List log;
-  private String configFile = MirGlobal.config().getStringWithHome("Abuse.Config");
-
-  private MirPropertiesConfiguration configuration;
-
-
-  private static final String IP_FILTER_TYPE="ip";
-  private static final String REGEXP_FILTER_TYPE="regexp";
-  private static String cookieName=MirGlobal.config().getString("Abuse.CookieName");
-  private static int cookieMaxAge = 60*60*MirGlobal.config().getInt("Abuse.CookieMaxAge");
-
-  public Abuse() {
-    logger = new LoggerWrapper("Global.Abuse");
-    adminUsageLogger = new LoggerWrapper("AdminUsage");
-    filters = new Vector();
-    maxIdentifier = 0;
-    log = new Vector();
-
-    try {
-      configuration = MirPropertiesConfiguration.instance();
-    }
-    catch (Throwable e) {
-      throw new RuntimeException("Can't get configuration: " + e.getMessage());
-    }
-
-    logSize = 100;
-    logEnabled = false;
-    articleBlockAction = "";
-    commentBlockAction = "";
-    openPostingPassword = false;
-    openPostingDisabled = false;
-    cookieOnBlock = false;
-
-    load();
-  }
-
-  public boolean checkIpFilter(String anIpAddress) {
-    synchronized (filters) {
-      Iterator i = filters.iterator();
-
-      while (i.hasNext()) {
-        Filter filter = (Filter) i.next();
-
-        try {
-          if ( (filter.getType().equals(IP_FILTER_TYPE)) &&
-              InternetFunctions.isIpAddressInNetwork(anIpAddress, filter.getExpression())) {
-            logger.debug("ip match on " + filter.getExpression());
-            return true;
-          }
-        }
-        catch (Throwable t) {
-          logger.warn("error while checking ip address " + anIpAddress + " over network " + filter.expression + ": " + t.getMessage());
-        }
-      }
-
-      return false;
-    }
-  }
-
-  private boolean checkRegExpFilter(Entity anEntity) {
-    synchronized (filters) {
-      Iterator i = filters.iterator();
-
-      while (i.hasNext()) {
-        Filter filter = (Filter) i.next();
-
-        if (filter.getType().equals(REGEXP_FILTER_TYPE)) {
-          try {
-            RE regularExpression = new RE(filter.getExpression(), RE.REG_ICASE);
-
-            Iterator j = anEntity.getFields().iterator();
-            while (j.hasNext()) {
-              String field = anEntity.getValue( (String) j.next());
-
-              if (field != null && regularExpression.isMatch(field.toLowerCase())) {
-                logger.debug("regexp match on " + filter.getExpression());
-                return true;
-              }
-            }
-          }
-          catch (Throwable t) {
-            logger.warn("error while checking entity with regexp " + filter.getExpression() + ": " + t.getMessage());
-          }
-        }
-      }
-
-      return false;
-    }
-  }
-
-  private void setCookie(HttpServletResponse aResponse) {
-    Random random = new Random();
-
-    Cookie cookie = new Cookie(cookieName, Integer.toString(random.nextInt(1000000000)));
-    cookie.setMaxAge(cookieMaxAge);
-    cookie.setPath("/");
-
-    if (aResponse!=null)
-      aResponse.addCookie(cookie);
-  }
-
-  private boolean checkCookie(List aCookies) {
-    if (getCookieOnBlock()) {
-      Iterator i = aCookies.iterator();
-
-      while (i.hasNext()) {
-        Cookie cookie = (Cookie) i.next();
-
-        if (cookie.getName().equals(cookieName)) {
-          logger.debug("cookie match");
-          return true;
-        }
-      }
-    }
-
-    return false;
-  }
-
-  public boolean checkRequest(Request aRequest, HttpServletResponse aResponse, String anId, boolean anIsComment) {
-    String address = "0.0.0.0";
-    String browser = "unknown";
-    List cookies = null;
-
-    HttpServletRequest request = null;
-
-    if (aRequest instanceof HTTPAdapters.HTTPParsedRequestAdapter) {
-      request = ((HTTPAdapters.HTTPParsedRequestAdapter) aRequest).getRequest();
-    }
-    else if (aRequest instanceof HTTPAdapters.HTTPRequestAdapter) {
-      request = ((HTTPAdapters.HTTPRequestAdapter) aRequest).getRequest();
-    }
-    if (request!=null) {
-      browser = (String) request.getHeader("User-Agent");
-      address = request.getRemoteAddr();
-      cookies = Arrays.asList(request.getCookies());
-    }
-
-    if (anIsComment)
-      logComment(address, anId , new Date(), browser);
-    else
-      logArticle(address, anId , new Date(), browser);
-
-    return checkCookie(cookies) || checkIpFilter(address);
-  }
-
-  public void checkComment(EntityComment aComment, Request aRequest, HttpServletResponse aResponse) {
-    try {
-      long time = System.currentTimeMillis();
-
-      MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = MirGlobal.localizer().adminInterface().simpleCommentOperationForName(commentBlockAction);
-
-      if (checkRequest(aRequest, aResponse, aComment.getId(), true) || checkRegExpFilter(aComment)) {
-        logger.debug("performing operation " + operation.getName());
-        operation.perform(null, MirGlobal.localizer().dataModel().adapterModel().makeEntityAdapter("comment", aComment));
-        setCookie(aResponse);
-      }
-
-      logger.info("checkComment: " + (System.currentTimeMillis()-time) + "ms");
-    }
-    catch (Throwable t) {
-      t.printStackTrace(logger.asPrintWriter(logger.DEBUG_MESSAGE));
-      logger.error("Abuse.checkComment: " + t.toString());
-    }
-  }
-
-  public void checkArticle(EntityContent anArticle, Request aRequest, HttpServletResponse aResponse) {
-    try {
-      long time = System.currentTimeMillis();
-
-      MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = MirGlobal.localizer().adminInterface().simpleArticleOperationForName(articleBlockAction);
-
-      if (checkRequest(aRequest, aResponse, anArticle.getId(), false) || checkRegExpFilter(anArticle)) {
-        logger.debug("performing operation " + operation.getName());
-        operation.perform(null, MirGlobal.localizer().dataModel().adapterModel().makeEntityAdapter("content", anArticle));
-        setCookie(aResponse);
-      }
-
-      logger.info("checkArticle: " + (System.currentTimeMillis()-time) + "ms");
-    }
-    catch (Throwable t) {
-      t.printStackTrace(logger.asPrintWriter(logger.DEBUG_MESSAGE));
-      logger.error("Abuse.checkArticle: " + t.toString());
-    }
-  }
-
-  public boolean getLogEnabled() {
-    return logEnabled;
-  }
-
-  public void setLogEnabled(boolean anEnabled) {
-    if (!configuration.getString("Abuse.DisallowIPLogging", "0").equals("1"))
-      logEnabled = anEnabled;
-    truncateLog();
-  }
-
-  public int getLogSize() {
-    return logSize;
-  }
-
-  public void setLogSize(int aSize) {
-    logSize = aSize;
-    truncateLog();
-  }
-
-  public boolean getOpenPostingDisabled() {
-    return openPostingDisabled;
-  }
-
-  public void setOpenPostingDisabled(boolean anOpenPostingDisabled) {
-    openPostingDisabled = anOpenPostingDisabled;
-  }
-
-  public boolean getOpenPostingPassword() {
-    return openPostingPassword;
-  }
-
-  public void setOpenPostingPassword(boolean anOpenPostingPassword) {
-    openPostingPassword = anOpenPostingPassword;
-  }
-
-  public boolean getCookieOnBlock() {
-    return cookieOnBlock;
-  }
-
-  public void setCookieOnBlock(boolean aCookieOnBlock) {
-    cookieOnBlock = aCookieOnBlock;
-  }
-
-  public String getArticleBlockAction() {
-    return articleBlockAction;
-  }
-
-  public void setArticleBlockAction(String anAction) {
-    articleBlockAction = anAction;
-  }
-
-  public String getCommentBlockAction() {
-    return commentBlockAction;
-  }
-
-  public void setCommentBlockAction(String anAction) {
-    commentBlockAction = anAction;
-  }
-
-
-  public List getLog() {
-    synchronized(log) {
-      try {
-        List result = new Vector();
-
-        Iterator i = log.iterator();
-        while (i.hasNext()) {
-          LogEntry logEntry = (LogEntry) i.next();
-          Map entry = new HashMap();
-
-          entry.put("ip", logEntry.getIpNumber());
-          entry.put("id", logEntry.getId());
-          entry.put("timestamp", new GeneratorFormatAdapters.DateFormatAdapter(logEntry.getTimeStamp(), MirPropertiesConfiguration.instance().getString("Mir.DefaultTimezone")));
-          if (logEntry.getIsArticle())
-            entry.put("type", "content");
-          else
-            entry.put("type", "comment");
-          entry.put("browser", logEntry.getBrowserString());
-
-          result.add(entry);
-        }
-
-        return result;
-      }
-      catch (Throwable t) {
-        throw new RuntimeException(t.toString());
-      }
-    }
-  }
-
-  public void logComment(String anIp, String anId, Date aTimeStamp, String aBrowser) {
-    appendLog(new LogEntry(aTimeStamp, anIp, aBrowser, anId, false));
-  }
-
-  public void logArticle(String anIp, String anId, Date aTimeStamp, String aBrowser) {
-    appendLog(new LogEntry(aTimeStamp, anIp, aBrowser, anId, true));
-  }
-
-  public void load() {
-    try {
-      ExtendedProperties configuration = new ExtendedProperties();
-
-      try {
-        configuration = new ExtendedProperties(configFile);
-      }
-      catch (FileNotFoundException e) {
-      }
-
-      getFilterConfig(filters, "abuse.filter", configuration);
-
-      setOpenPostingDisabled(configuration.getString("abuse.openPostingDisabled", "0").equals("1"));
-      setOpenPostingPassword(configuration.getString("abuse.openPostingPassword", "0").equals("1"));
-      setCookieOnBlock(configuration.getString("abuse.cookieOnBlock", "0").equals("1"));
-      setLogEnabled(configuration.getString("abuse.logEnabled", "0").equals("1"));
-      setLogSize(configuration.getInt("abuse.logSize", 10));
-      setArticleBlockAction(configuration.getString("abuse.articleBlockAction", ""));
-      setCommentBlockAction(configuration.getString("abuse.commentBlockAction", ""));
-    }
-    catch (Throwable t) {
-      throw new RuntimeException(t.toString());
-    }
-  }
-  public void save() {
-    try {
-      ExtendedProperties configuration = new ExtendedProperties();
-
-      setFilterConfig(filters, "abuse.filter", configuration);
-
-      configuration.addProperty("abuse.openPostingDisabled", getOpenPostingDisabled()?"1":"0");
-      configuration.addProperty("abuse.openPostingPassword", getOpenPostingPassword()?"1":"0");
-      configuration.addProperty("abuse.cookieOnBlock", getCookieOnBlock()?"1":"0");
-      configuration.addProperty("abuse.logEnabled", getLogEnabled()?"1":"0");
-      configuration.addProperty("abuse.logSize", Integer.toString(getLogSize()));
-      configuration.addProperty("abuse.articleBlockAction", getArticleBlockAction());
-      configuration.addProperty("abuse.commentBlockAction", getCommentBlockAction());
-
-      configuration.save(new FileOutputStream(new File(configFile)), "Anti abuse configuration");
-    }
-    catch (Throwable t) {
-      throw new RuntimeException(t.toString());
-    }
-  }
-
-  public List getFilterTypes() {
-    List result = new Vector();
-
-    Map entry = new HashMap();
-    entry.put("resource", "ip");
-    entry.put("id", IP_FILTER_TYPE);
-    result.add(entry);
-
-    entry = new HashMap();
-    entry.put("resource", "regexp");
-    entry.put("id", REGEXP_FILTER_TYPE);
-    result.add(entry);
-
-    return result;
-  }
-
-  public List getArticleActions() {
-    try {
-      List result = new Vector();
-
-      Iterator i = MirGlobal.localizer().adminInterface().simpleArticleOperations().iterator();
-      while (i.hasNext()) {
-        MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation =
-            (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next();
-
-        Map action = new HashMap();
-        action.put("resource", operation.getName());
-        action.put("identifier", operation.getName());
-
-        result.add(action);
-      }
-
-      return result;
-    }
-    catch (Throwable t) {
-      throw new RuntimeException("can't get article actions");
-    }
-  }
-
-  public List getCommentActions() {
-    try {
-      List result = new Vector();
-
-      Iterator i = MirGlobal.localizer().adminInterface().simpleCommentOperations().iterator();
-      while (i.hasNext()) {
-        MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation =
-            (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next();
-
-        Map action = new HashMap();
-        action.put("resource", operation.getName());
-        action.put("identifier", operation.getName());
-
-        result.add(action);
-      }
-
-      return result;
-    }
-    catch (Throwable t) {
-      throw new RuntimeException("can't get comment actions");
-    }
-  }
-
-  public List getFilters() {
-    return getFiltersAsMaps(filters);
-  }
-
-  public void addFilter(String aType, String anExpression) {
-    addFilter(filters, aType, anExpression);
-  }
-
-  public void setFilter(String anIdentifier, String aType, String anExpression) {
-    setFilter(filters, anIdentifier, aType, anExpression);
-  }
-
-  public void deleteFilter(String anIdentifier) {
-    deleteFilter(filters, anIdentifier);
-  }
-
-  public void validateIpFilter(String anIdentifier, String anArticleAction, String aCommentAction) throws Exception {
-  }
-
-  private List getFiltersAsMaps(List aFilters) {
-    synchronized(aFilters) {
-      List result = new Vector();
-
-      Iterator i = aFilters.iterator();
-      while (i.hasNext()) {
-        Filter filter = (Filter) i.next();
-        Map map = new HashMap();
-
-        map.put("id", filter.getId());
-        map.put("expression", filter.getExpression());
-        map.put("type", filter.getType());
-
-        result.add(map);
-      }
-      return result;
-    }
-  }
-
-  private void addFilter(List aFilters, String aType, String anExpression) {
-    Filter filter = new Filter();
-
-    filter.setId(generateId());
-    filter.setExpression(anExpression);
-    filter.setType(aType);
-
-    synchronized (aFilters) {
-      aFilters.add(filter);
-    }
-  }
-
-  private void setFilter(List aFilters, String anIdentifier, String aType, String anExpression) {
-    synchronized (aFilters) {
-      Filter filter = findFilter(aFilters, anIdentifier);
-
-      if (filter!=null) {
-        filter.setExpression(anExpression);
-        filter.setType(aType);
-      }
-    }
-  }
-
-  private Filter findFilter(List aFilters, String anIdentifier) {
-    synchronized (aFilters) {
-      Iterator i = aFilters.iterator();
-      while (i.hasNext()) {
-        Filter filter = (Filter) i.next();
-
-        if (filter.getId().equals(anIdentifier)) {
-          return filter;
-        }
-      }
-    }
-
-    return null;
-  }
-
-  private void deleteFilter(List aFilters, String anIdentifier) {
-    synchronized (aFilters) {
-      Filter filter = findFilter(aFilters, anIdentifier);
-
-      if (filter!=null) {
-        aFilters.remove(filter);
-      }
-    }
-  }
-
-  private String generateId() {
-    synchronized(this) {
-      maxIdentifier = maxIdentifier+1;
-
-      return Integer.toString(maxIdentifier);
-    }
-  }
-
-  private static class Filter {
-    private String identifier;
-    private String expression;
-    private String type;
-
-    public Filter() {
-      expression="";
-      type="";
-      identifier="";
-    }
-
-    public String getId() {
-      return identifier;
-    }
-
-    public void setId(String anId) {
-      identifier = anId;
-    }
-
-    public String getExpression() {
-      return expression;
-    }
-
-    public void setExpression(String anExpression) {
-      expression = anExpression;
-    }
-
-    public String getType() {
-      return type;
-    }
-
-    public void setType(String aType) {
-      type = aType;
-    }
-  }
-
-  private void setFilterConfig(List aFilters, String aConfigKey, ExtendedProperties aConfiguration) {
-    synchronized(aFilters) {
-      Iterator i = aFilters.iterator();
-
-      while (i.hasNext()) {
-        Filter filter = (Filter) i.next();
-
-        aConfiguration.addProperty(aConfigKey, filter.getType()+":"+filter.getExpression());
-      }
-    }
-  }
-
-  private void getFilterConfig(List aFilters, String aConfigKey, ExtendedProperties aConfiguration) {
-    synchronized(aFilters) {
-      aFilters.clear();
-
-      Iterator i = Arrays.asList(aConfiguration.getStringArray(aConfigKey)).iterator();
-
-      while (i.hasNext()) {
-        String filter = (String) i.next();
-        List parts = StringRoutines.separateString(filter, ":");
-
-        if (parts.size()==2) {
-          addFilter( (String) parts.get(0), (String) parts.get(1));
-        }
-      }
-    }
-  }
-
-  private static class LogEntry {
-    private String ipNumber;
-    private String browserString;
-    private String id;
-    private Date timeStamp;
-    private boolean isArticle;
-
-    public LogEntry(Date aTimeStamp, String anIpNumber, String aBrowserString, String anId, boolean anIsArticle) {
-      ipNumber = anIpNumber;
-      browserString = aBrowserString;
-      id = anId;
-      isArticle = anIsArticle;
-      timeStamp=aTimeStamp;
-    }
-
-    public String getIpNumber() {
-      return ipNumber;
-    }
-
-    public String getBrowserString() {
-      return browserString;
-    }
-
-    public String getId() {
-      return id;
-    }
-
-    public Date getTimeStamp() {
-      return timeStamp;
-    }
-
-    public boolean getIsArticle() {
-      return isArticle;
-    }
-  }
-
-  private void truncateLog() {
-    synchronized(log) {
-      if (!logEnabled)
-        log.clear();
-      else {
-        while (log.size()>0 && log.size()>logSize) {
-          log.remove(0);
-        }
-      }
-    }
-  };
-
-  private void appendLog(LogEntry anEntry) {
-    synchronized (log) {
-      if (logEnabled) {
-        log.add(anEntry);
-        truncateLog();
-      }
-    }
-  }
-
-  public void logAdminUsage(EntityUsers aUser, String aDescription) {
-    try {
-      String user = "unknown (" + aUser.toString() +")";
-      if (user!=null)
-        user = aUser.getValue("login");
-      adminUsageLogger.info(user + ": " + aDescription);
-    }
-    catch (Throwable t) {
-      logger.error("Error while logging admin usage ("+aUser.toString()+", "+aDescription+"): " +t.toString());
-    }
-  }
+/*\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.io.File;\r
+import java.io.FileNotFoundException;\r
+import java.io.FileOutputStream;\r
+import java.util.Arrays;\r
+import java.util.Date;\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.util.Map;\r
+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
+\r
+\r
+public class Abuse {\r
+  private List filters;\r
+  private int maxIdentifier;\r
+  private LoggerWrapper logger;\r
+  private LoggerWrapper adminUsageLogger;\r
+  private int logSize;\r
+  private boolean logEnabled;\r
+  private boolean openPostingDisabled;\r
+  private boolean openPostingPassword;\r
+  private boolean cookieOnBlock;\r
+  private String articleBlockAction;\r
+  private String commentBlockAction;\r
+  private List log;\r
+  private String configFile = MirGlobal.config().getStringWithHome("Abuse.Config");\r
+\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
+    maxIdentifier = 0;\r
+    log = new Vector();\r
+\r
+    try {\r
+      configuration = MirPropertiesConfiguration.instance();\r
+    }\r
+    catch (Throwable e) {\r
+      throw new RuntimeException("Can't get configuration: " + e.getMessage());\r
+    }\r
+\r
+    logSize = 100;\r
+    logEnabled = false;\r
+    articleBlockAction = "";\r
+    commentBlockAction = "";\r
+    openPostingPassword = false;\r
+    openPostingDisabled = false;\r
+    cookieOnBlock = false;\r
+\r
+    load();\r
+  }\r
+\r
+  public boolean checkIpFilter(String anIpAddress) {\r
+    synchronized (filters) {\r
+      Iterator i = filters.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
+      }\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
+    }\r
+  }\r
+\r
+  private void setCookie(HttpServletResponse aResponse) {\r
+    Random random = new Random();\r
+\r
+    Cookie cookie = new Cookie(cookieName, Integer.toString(random.nextInt(1000000000)));\r
+    cookie.setMaxAge(cookieMaxAge);\r
+    cookie.setPath("/");\r
+\r
+    if (aResponse!=null)\r
+      aResponse.addCookie(cookie);\r
+  }\r
+\r
+  private boolean checkCookie(List aCookies) {\r
+    if (getCookieOnBlock()) {\r
+      Iterator i = aCookies.iterator();\r
+\r
+      while (i.hasNext()) {\r
+        Cookie cookie = (Cookie) i.next();\r
+\r
+        if (cookie.getName().equals(cookieName)) {\r
+          logger.debug("cookie match");\r
+          return true;\r
+        }\r
+      }\r
+    }\r
+\r
+    return false;\r
+  }\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
+\r
+    if (aRequest instanceof HTTPAdapters.HTTPParsedRequestAdapter) {\r
+      request = ((HTTPAdapters.HTTPParsedRequestAdapter) aRequest).getRequest();\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
+  }\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
+\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
+        setCookie(aResponse);\r
+      }\r
+\r
+      logger.info("checkComment: " + (System.currentTimeMillis()-time) + "ms");\r
+    }\r
+    catch (Throwable t) {\r
+      t.printStackTrace(logger.asPrintWriter(logger.DEBUG_MESSAGE));\r
+      logger.error("Abuse.checkComment: " + t.toString());\r
+    }\r
+  }\r
+\r
+  public void checkArticle(EntityContent anArticle, Request aRequest, HttpServletResponse aResponse) {\r
+    try {\r
+      long time = System.currentTimeMillis();\r
+\r
+      MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = MirGlobal.localizer().adminInterface().simpleArticleOperationForName(articleBlockAction);\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
+        setCookie(aResponse);\r
+      }\r
+\r
+      logger.info("checkArticle: " + (System.currentTimeMillis()-time) + "ms");\r
+    }\r
+    catch (Throwable t) {\r
+      t.printStackTrace(logger.asPrintWriter(logger.DEBUG_MESSAGE));\r
+      logger.error("Abuse.checkArticle: " + t.toString());\r
+    }\r
+  }\r
+\r
+  public boolean getLogEnabled() {\r
+    return logEnabled;\r
+  }\r
+\r
+  public void setLogEnabled(boolean anEnabled) {\r
+    if (!configuration.getString("Abuse.DisallowIPLogging", "0").equals("1"))\r
+      logEnabled = anEnabled;\r
+    truncateLog();\r
+  }\r
+\r
+  public int getLogSize() {\r
+    return logSize;\r
+  }\r
+\r
+  public void setLogSize(int aSize) {\r
+    logSize = aSize;\r
+    truncateLog();\r
+  }\r
+\r
+  public boolean getOpenPostingDisabled() {\r
+    return openPostingDisabled;\r
+  }\r
+\r
+  public void setOpenPostingDisabled(boolean anOpenPostingDisabled) {\r
+    openPostingDisabled = anOpenPostingDisabled;\r
+  }\r
+\r
+  public boolean getOpenPostingPassword() {\r
+    return openPostingPassword;\r
+  }\r
+\r
+  public void setOpenPostingPassword(boolean anOpenPostingPassword) {\r
+    openPostingPassword = anOpenPostingPassword;\r
+  }\r
+\r
+  public boolean getCookieOnBlock() {\r
+    return cookieOnBlock;\r
+  }\r
+\r
+  public void setCookieOnBlock(boolean aCookieOnBlock) {\r
+    cookieOnBlock = aCookieOnBlock;\r
+  }\r
+\r
+  public String getArticleBlockAction() {\r
+    return articleBlockAction;\r
+  }\r
+\r
+  public void setArticleBlockAction(String anAction) {\r
+    articleBlockAction = anAction;\r
+  }\r
+\r
+  public String getCommentBlockAction() {\r
+    return commentBlockAction;\r
+  }\r
+\r
+  public void setCommentBlockAction(String anAction) {\r
+    commentBlockAction = anAction;\r
+  }\r
+\r
+\r
+  public List getLog() {\r
+    synchronized(log) {\r
+      try {\r
+        List result = new Vector();\r
+\r
+        Iterator i = log.iterator();\r
+        while (i.hasNext()) {\r
+          LogEntry logEntry = (LogEntry) i.next();\r
+          Map entry = new HashMap();\r
+\r
+          entry.put("ip", logEntry.getIpNumber());\r
+          entry.put("id", logEntry.getId());\r
+          entry.put("timestamp", new GeneratorFormatAdapters.DateFormatAdapter(logEntry.getTimeStamp(), MirPropertiesConfiguration.instance().getString("Mir.DefaultTimezone")));\r
+          if (logEntry.getIsArticle())\r
+            entry.put("type", "content");\r
+          else\r
+            entry.put("type", "comment");\r
+          entry.put("browser", logEntry.getBrowserString());\r
+\r
+          result.add(entry);\r
+        }\r
+\r
+        return result;\r
+      }\r
+      catch (Throwable t) {\r
+        throw new RuntimeException(t.toString());\r
+      }\r
+    }\r
+  }\r
+\r
+  public void logComment(String anIp, String anId, Date aTimeStamp, String aBrowser) {\r
+    appendLog(new LogEntry(aTimeStamp, anIp, aBrowser, anId, false));\r
+  }\r
+\r
+  public void logArticle(String anIp, String anId, Date aTimeStamp, String aBrowser) {\r
+    appendLog(new LogEntry(aTimeStamp, anIp, aBrowser, anId, true));\r
+  }\r
+\r
+  public void load() {\r
+    try {\r
+      ExtendedProperties configuration = new ExtendedProperties();\r
+\r
+      try {\r
+        configuration = new ExtendedProperties(configFile);\r
+      }\r
+      catch (FileNotFoundException e) {\r
+      }\r
+\r
+      getFilterConfig(filters, "abuse.filter", configuration);\r
+\r
+      setOpenPostingDisabled(configuration.getString("abuse.openPostingDisabled", "0").equals("1"));\r
+      setOpenPostingPassword(configuration.getString("abuse.openPostingPassword", "0").equals("1"));\r
+      setCookieOnBlock(configuration.getString("abuse.cookieOnBlock", "0").equals("1"));\r
+      setLogEnabled(configuration.getString("abuse.logEnabled", "0").equals("1"));\r
+      setLogSize(configuration.getInt("abuse.logSize", 10));\r
+      setArticleBlockAction(configuration.getString("abuse.articleBlockAction", ""));\r
+      setCommentBlockAction(configuration.getString("abuse.commentBlockAction", ""));\r
+    }\r
+    catch (Throwable t) {\r
+      throw new RuntimeException(t.toString());\r
+    }\r
+  }\r
+  public void save() {\r
+    try {\r
+      ExtendedProperties configuration = new ExtendedProperties();\r
+\r
+      setFilterConfig(filters, "abuse.filter", configuration);\r
+\r
+      configuration.addProperty("abuse.openPostingDisabled", getOpenPostingDisabled()?"1":"0");\r
+      configuration.addProperty("abuse.openPostingPassword", getOpenPostingPassword()?"1":"0");\r
+      configuration.addProperty("abuse.cookieOnBlock", getCookieOnBlock()?"1":"0");\r
+      configuration.addProperty("abuse.logEnabled", getLogEnabled()?"1":"0");\r
+      configuration.addProperty("abuse.logSize", Integer.toString(getLogSize()));\r
+      configuration.addProperty("abuse.articleBlockAction", getArticleBlockAction());\r
+      configuration.addProperty("abuse.commentBlockAction", getCommentBlockAction());\r
+\r
+      configuration.save(new FileOutputStream(new File(configFile)), "Anti abuse configuration");\r
+    }\r
+    catch (Throwable t) {\r
+      throw new RuntimeException(t.toString());\r
+    }\r
+  }\r
+\r
+  public List getFilterTypes() {\r
+    List result = new Vector();\r
+\r
+    Map entry = new HashMap();\r
+    entry.put("resource", "ip");\r
+    entry.put("id", IP_FILTER_TYPE);\r
+    result.add(entry);\r
+\r
+    entry = new HashMap();\r
+    entry.put("resource", "regexp");\r
+    entry.put("id", REGEXP_FILTER_TYPE);\r
+    result.add(entry);\r
+\r
+    return result;\r
+  }\r
+\r
+  public List getArticleActions() {\r
+    try {\r
+      List result = new Vector();\r
+\r
+      Iterator i = MirGlobal.localizer().adminInterface().simpleArticleOperations().iterator();\r
+      while (i.hasNext()) {\r
+        MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation =\r
+            (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next();\r
+\r
+        Map action = new HashMap();\r
+        action.put("resource", operation.getName());\r
+        action.put("identifier", operation.getName());\r
+\r
+        result.add(action);\r
+      }\r
+\r
+      return result;\r
+    }\r
+    catch (Throwable t) {\r
+      throw new RuntimeException("can't get article actions");\r
+    }\r
+  }\r
+\r
+  public List getCommentActions() {\r
+    try {\r
+      List result = new Vector();\r
+\r
+      Iterator i = MirGlobal.localizer().adminInterface().simpleCommentOperations().iterator();\r
+      while (i.hasNext()) {\r
+        MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation =\r
+            (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next();\r
+\r
+        Map action = new HashMap();\r
+        action.put("resource", operation.getName());\r
+        action.put("identifier", operation.getName());\r
+\r
+        result.add(action);\r
+      }\r
+\r
+      return result;\r
+    }\r
+    catch (Throwable t) {\r
+      throw new RuntimeException("can't get comment actions");\r
+    }\r
+  }\r
+\r
+  public List getFilters() {\r
+    return getFiltersAsMaps(filters);\r
+  }\r
+\r
+  public void addFilter(String aType, String anExpression) {\r
+    addFilter(filters, aType, anExpression);\r
+  }\r
+\r
+  public void setFilter(String anIdentifier, String aType, String anExpression) {\r
+    setFilter(filters, anIdentifier, aType, anExpression);\r
+  }\r
+\r
+  public void deleteFilter(String anIdentifier) {\r
+    deleteFilter(filters, anIdentifier);\r
+  }\r
+\r
+  public void validateIpFilter(String anIdentifier, String anArticleAction, String aCommentAction) throws Exception {\r
+  }\r
+\r
+  private List getFiltersAsMaps(List aFilters) {\r
+    synchronized(aFilters) {\r
+      List result = new Vector();\r
+\r
+      Iterator i = aFilters.iterator();\r
+      while (i.hasNext()) {\r
+        Filter filter = (Filter) i.next();\r
+        Map map = new HashMap();\r
+\r
+        map.put("id", filter.getId());\r
+        map.put("expression", filter.getExpression());\r
+        map.put("type", filter.getType());\r
+\r
+        result.add(map);\r
+      }\r
+      return result;\r
+    }\r
+  }\r
+\r
+  private void addFilter(List aFilters, String aType, String anExpression) {\r
+    Filter filter = new Filter();\r
+\r
+    filter.setId(generateId());\r
+    filter.setExpression(anExpression);\r
+    filter.setType(aType);\r
+\r
+    synchronized (aFilters) {\r
+      aFilters.add(filter);\r
+    }\r
+  }\r
+\r
+  private void setFilter(List aFilters, String anIdentifier, String aType, String anExpression) {\r
+    synchronized (aFilters) {\r
+      Filter filter = findFilter(aFilters, anIdentifier);\r
+\r
+      if (filter!=null) {\r
+        filter.setExpression(anExpression);\r
+        filter.setType(aType);\r
+      }\r
+    }\r
+  }\r
+\r
+  private Filter findFilter(List aFilters, String anIdentifier) {\r
+    synchronized (aFilters) {\r
+      Iterator i = aFilters.iterator();\r
+      while (i.hasNext()) {\r
+        Filter filter = (Filter) i.next();\r
+\r
+        if (filter.getId().equals(anIdentifier)) {\r
+          return filter;\r
+        }\r
+      }\r
+    }\r
+\r
+    return null;\r
+  }\r
+\r
+  private void deleteFilter(List aFilters, String anIdentifier) {\r
+    synchronized (aFilters) {\r
+      Filter filter = findFilter(aFilters, anIdentifier);\r
+\r
+      if (filter!=null) {\r
+        aFilters.remove(filter);\r
+      }\r
+    }\r
+  }\r
+\r
+  private String generateId() {\r
+    synchronized(this) {\r
+      maxIdentifier = maxIdentifier+1;\r
+\r
+      return Integer.toString(maxIdentifier);\r
+    }\r
+  }\r
+\r
+  private static class Filter {\r
+    private String identifier;\r
+    private String expression;\r
+    private String type;\r
+\r
+    public Filter() {\r
+      expression="";\r
+      type="";\r
+      identifier="";\r
+    }\r
+\r
+    public String getId() {\r
+      return identifier;\r
+    }\r
+\r
+    public void setId(String anId) {\r
+      identifier = anId;\r
+    }\r
+\r
+    public String getExpression() {\r
+      return expression;\r
+    }\r
+\r
+    public void setExpression(String anExpression) {\r
+      expression = anExpression;\r
+    }\r
+\r
+    public String getType() {\r
+      return type;\r
+    }\r
+\r
+    public void setType(String aType) {\r
+      type = aType;\r
+    }\r
+  }\r
+\r
+  private void setFilterConfig(List aFilters, String aConfigKey, ExtendedProperties aConfiguration) {\r
+    synchronized(aFilters) {\r
+      Iterator i = aFilters.iterator();\r
+\r
+      while (i.hasNext()) {\r
+        Filter filter = (Filter) i.next();\r
+\r
+        aConfiguration.addProperty(aConfigKey, filter.getType()+":"+filter.getExpression());\r
+      }\r
+    }\r
+  }\r
+\r
+  private void getFilterConfig(List aFilters, String aConfigKey, ExtendedProperties aConfiguration) {\r
+    synchronized(aFilters) {\r
+      aFilters.clear();\r
+\r
+      if (aConfiguration.getStringArray(aConfigKey)!=null) {\r
+\r
+        Iterator i = Arrays.asList(aConfiguration.getStringArray(aConfigKey)).\r
+            iterator();\r
+\r
+        while (i.hasNext()) {\r
+          String filter = (String) i.next();\r
+          List parts = StringRoutines.separateString(filter, ":");\r
+\r
+          if (parts.size() == 2) {\r
+            addFilter( (String) parts.get(0), (String) parts.get(1));\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  private static class LogEntry {\r
+    private String ipNumber;\r
+    private String browserString;\r
+    private String id;\r
+    private Date timeStamp;\r
+    private boolean isArticle;\r
+\r
+    public LogEntry(Date aTimeStamp, String anIpNumber, String aBrowserString, String anId, boolean anIsArticle) {\r
+      ipNumber = anIpNumber;\r
+      browserString = aBrowserString;\r
+      id = anId;\r
+      isArticle = anIsArticle;\r
+      timeStamp=aTimeStamp;\r
+    }\r
+\r
+    public String getIpNumber() {\r
+      return ipNumber;\r
+    }\r
+\r
+    public String getBrowserString() {\r
+      return browserString;\r
+    }\r
+\r
+    public String getId() {\r
+      return id;\r
+    }\r
+\r
+    public Date getTimeStamp() {\r
+      return timeStamp;\r
+    }\r
+\r
+    public boolean getIsArticle() {\r
+      return isArticle;\r
+    }\r
+  }\r
+\r
+  private void truncateLog() {\r
+    synchronized(log) {\r
+      if (!logEnabled)\r
+        log.clear();\r
+      else {\r
+        while (log.size()>0 && log.size()>logSize) {\r
+          log.remove(0);\r
+        }\r
+      }\r
+    }\r
+  };\r
+\r
+  private void appendLog(LogEntry anEntry) {\r
+    synchronized (log) {\r
+      if (logEnabled) {\r
+        log.add(anEntry);\r
+        truncateLog();\r
+      }\r
+    }\r
+  }\r
+\r
+  public void logAdminUsage(EntityUsers aUser, String aDescription) {\r
+    try {\r
+      String user = "unknown (" + aUser.toString() +")";\r
+      if (user!=null)\r
+        user = aUser.getValue("login");\r
+      adminUsageLogger.info(user + ": " + aDescription);\r
+    }\r
+    catch (Throwable t) {\r
+      logger.error("Error while logging admin usage ("+aUser.toString()+", "+aDescription+"): " +t.toString());\r
+    }\r
+  }\r
 }
\ No newline at end of file