-/*
- * 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