--- /dev/null
+/*
+ * 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.abuse;
+
+import mir.entity.Entity;
+import mir.entity.adapter.EntityAdapter;
+import mir.entity.adapter.EntityAdapterModel;
+import mir.entity.adapter.EntityIteratorAdapter;
+import mir.log.LoggerWrapper;
+import mir.session.Request;
+import mir.storage.DatabaseExc;
+import mir.storage.DatabaseHelper;
+import mircoders.global.MirGlobal;
+import mircoders.storage.DatabaseFilter;
+import mircoders.storage.DatabaseFilterGroup;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+/** The FilterEngine manages a list of all filters and filter groups.
+ * Use the testPosting() method to apply all filters on an
+ * Entity (for ex. an article or a comment)
+ */
+public class FilterEngine {
+ private final Map filterTypes = new HashMap();
+ private final List filterTypeIds = new ArrayList();
+
+ private final List filterGroups = new ArrayList();
+ private final Map idToFilterGroup = new HashMap();
+ private final LoggerWrapper logger = new LoggerWrapper("Global.Abuse.FilterEngine");
+ private EntityAdapterModel model;
+
+ public FilterEngine(EntityAdapterModel aModel) {
+ try {
+ Iterator i = MirGlobal.localizer().openPostings().getAntiAbuseFilterTypes().iterator();
+ while (i.hasNext()) {
+ FilterType filterType = (FilterType) i.next();
+
+ filterTypes.put(filterType.getName(), filterType);
+ filterTypeIds.add(filterType.getName());
+ }
+ }
+ catch (Throwable t) {
+ throw new RuntimeException(t.getMessage());
+ }
+
+ model = aModel;
+
+ reload();
+ }
+
+ /** applies all filters from all filter groups to an Entity.
+ * The entity may be, for example, an article, or a comment.
+ * It returns a filter that matches if it finds one, null otherwise
+ */
+ public synchronized Filter testPosting(Entity anEntity, Request aRequest) {
+ Iterator i = filterGroups.iterator();
+ while (i.hasNext()) {
+ FilterGroup group = (FilterGroup) i.next();
+
+ Iterator j = group.getFilters().iterator();
+ while (j.hasNext()) {
+ Filter filter = (Filter) j.next();
+ try {
+ if (filter.test(anEntity, aRequest)) {
+ return filter;
+ }
+ }
+ catch (Throwable t) {
+ logger.warn("Exception thrown while testing filter " + filter.getType() + " ( " + filter.getExpression() + ") " + t.toString());
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public List getFilterTypes() {
+ try {
+ List result = new ArrayList();
+
+ Iterator i = filterTypeIds.iterator();
+ while (i.hasNext()) {
+ String id = (String) i.next();
+
+ Map action = new HashMap();
+ action.put("resource", id);
+ action.put("identifier", id);
+
+ result.add(action);
+ }
+
+ return result;
+ }
+ catch (Throwable t) {
+ throw new RuntimeException("can't get article actions: " + t.getMessage());
+ }
+ }
+ /** This class reflects a row of the filter_group
+ * database table. Filters groups allow you to organize
+ * your filters. For example: group1=spammer ,
+ * group2=nazis etc.
+ */
+ public class FilterGroup {
+ private List filters;
+ private Entity entity;
+ private Map idToFilter;
+
+ public FilterGroup(Entity anEntity) {
+ this (anEntity, Collections.EMPTY_LIST);
+ }
+
+ public FilterGroup(Entity anEntity, List aFilters) {
+ entity = anEntity;
+ filters = new ArrayList();
+ idToFilter = new HashMap();
+ Iterator i = aFilters.iterator();
+
+ while (i.hasNext()) {
+ Entity entity = (Entity) i.next();
+ try {
+ Filter filter = new Filter(entity);
+ introduceFilter(filter);
+ }
+ catch (AbuseExc e) {
+ }
+ }
+ }
+
+ public Entity getEntity() {
+ return entity;
+ }
+
+ public EntityAdapter getEntityAdapter() {
+ return model.makeEntityAdapter("filterGroup", entity);
+ }
+
+ public List getFilterEntityAdapterList() {
+ List result = new ArrayList();
+
+ Iterator i = filters.iterator();
+ while (i.hasNext()) {
+ Filter filter = (Filter) i.next();
+ result.add(filter.getEntityAdapter());
+ }
+
+ return result;
+ }
+
+ public List getFilters() {
+ return filters;
+ }
+
+ public Filter getFilterForId(String anId) {
+ Filter result = (Filter) idToFilter.get(anId);
+ if (result==null) {
+ throw new NullPointerException("No such filter");
+ }
+
+ return result;
+ }
+
+ private void introduceFilter(Filter aFilter) {
+ filters.add(aFilter);
+ idToFilter.put(aFilter.getEntity().getId(), aFilter);
+ }
+
+ private void removeFilter(Filter aFilter) {
+ filters.remove(aFilter);
+ idToFilter.remove(aFilter.getEntity().getId());
+ }
+
+ private void deleteFilter(String anId) {
+ Filter filter = getFilterForId(anId);
+ removeFilter(filter);
+ DatabaseFilter.getInstance().delete(anId);
+ }
+
+ public void populateFilterEntity(Entity anEntity, String aType, String anExpression,
+ String aComments, String aTag, String anArticleAction,
+ String aCommentAction) {
+
+ anEntity.setFieldValue("type", aType);
+ anEntity.setFieldValue("expression", anExpression);
+ anEntity.setFieldValue("comment", aComments);
+ anEntity.setFieldValue("tag", aTag);
+ anEntity.setFieldValue("articleaction", anArticleAction);
+ anEntity.setFieldValue("commentaction", aCommentAction);
+ }
+
+ public String updateFilter(String anId, String aType, String anExpression,
+ String aComments, String aTag, String anArticleAction,
+ String aCommentAction) {
+
+ try {
+ getFilterTypeForId(aType).constructFilterInstance(anExpression);
+ }
+ catch (AbuseExc e) {
+ return e.getMessage();
+ }
+
+ Entity entity = getFilterForId(anId).getEntity();
+ populateFilterEntity(entity, aType, anExpression, aComments, aTag,
+ anArticleAction, aCommentAction);
+ entity.update();
+
+ return "";
+ }
+
+ public String createFilter(String aType, String anExpression,
+ String aComments, String aTag, String anArticleAction,
+ String aCommentAction) throws DatabaseExc {
+ FilterInstance instance;
+
+ try {
+ instance = getFilterTypeForId(aType).constructFilterInstance(anExpression);
+ }
+ catch (AbuseExc e) {
+ return e.getMessage();
+ }
+
+ Entity entity = DatabaseFilter.getInstance().createNewEntity();
+ populateFilterEntity(entity, aType, anExpression, aComments, aTag,
+ anArticleAction, aCommentAction);
+
+
+ String priority = "1";
+
+ if (filters.size() > 0) {
+ try {
+ String lastPriorityString = ((Filter) filters.get(filters.size()-1)).getEntity().getFieldValue("priority");
+ int lastPriority = Integer.parseInt(lastPriorityString);
+ priority = Integer.toString(lastPriority + 1);
+ }
+ catch (Exception e) {
+ }
+ }
+
+ entity.setFieldValue("priority", priority);
+ entity.setFieldValue("filter_group_id", getEntity().getId());
+ entity.insert();
+
+ Filter filter = new Filter(entity, instance);
+ introduceFilter(filter);
+
+ return "";
+ }
+
+ public String moveFilterUp(String anId) {
+ Filter filter = getFilterForId(anId);
+ String priority = filter.getEntity().getFieldValue("priority");
+ int index = filters.indexOf(filter);
+ if (index>=1) {
+ Filter filterBefore= (Filter) filters.remove(index-1);
+ filters.add(index, filterBefore);
+ filter.getEntity().setFieldValue("priority", filterBefore.getEntity().getFieldValue("priority"));
+ filterBefore.getEntity().setFieldValue("priority", priority);
+ filter.getEntity().update();
+ filterBefore.getEntity().update();
+ }
+
+ return "";
+ }
+
+ public String moveFilterToTop(String anId) {
+ Filter filter = getFilterForId(anId);
+ String priority = filter.getEntity().getFieldValue("priority");
+ int index = filters.indexOf(filter);
+ if (index>0) {
+ filters.remove(index);
+ Filter filterBefore= (Filter) filters.get(0);
+ filters.add(0, filter);
+ filter.getEntity().setFieldValue("priority", filterBefore.getEntity().getFieldValue("priority"));
+ filterBefore.getEntity().setFieldValue("priority", priority);
+ filter.getEntity().update();
+ filterBefore.getEntity().update();
+ }
+
+ return "";
+ }
+
+ public String moveFilterDown(String anId) {
+ Filter filter = getFilterForId(anId);
+ String priority = filter.getEntity().getFieldValue("priority");
+ int index = filters.indexOf(filter);
+ if (index<filters.size()-1) {
+ Filter filterAfter = (Filter) filters.remove(index+1);
+ filters.add(index, filterAfter);
+ filter.getEntity().setFieldValue("priority", filterAfter.getEntity().getFieldValue("priority"));
+ filterAfter.getEntity().setFieldValue("priority", priority);
+ filter.getEntity().update();
+ filterAfter.getEntity().update();
+ }
+
+ return "";
+ }
+
+ public String moveFilterToBottom(String anId) {
+ Filter filter = getFilterForId(anId);
+ String priority = filter.getEntity().getFieldValue("priority");
+ int index = filters.indexOf(filter);
+ if (index>=0 && index<filters.size()-1) {
+ filters.remove(index);
+ Filter filterBefore= (Filter) filters.get(filters.size()-1);
+ filters.add(filters.size(), filter);
+ filter.getEntity().setFieldValue("priority", filterBefore.getEntity().getFieldValue("priority"));
+ filterBefore.getEntity().setFieldValue("priority", priority);
+ filter.getEntity().update();
+ filterBefore.getEntity().update();
+ }
+
+ return "";
+ }
+
+
+ public String getName() {
+ return entity.getFieldValue("name");
+ }
+ }
+
+ /** This class reflects a row of the filter database table.
+ * To actually run a filter on data, use the test() method.
+ * This class will automatically retreive and use the correct
+ * filter type.
+ */
+ public class Filter {
+ private Entity entity;
+ private FilterInstance instance;
+
+ public Filter(Entity anEntity) throws AbuseExc {
+ this(anEntity, getFilterTypeForId(anEntity.getFieldValue("type")).constructFilterInstance(anEntity.getFieldValue("expression")));
+ }
+
+ public Filter(Entity anEntity, FilterInstance anInstance) {
+ entity = anEntity;
+ instance = anInstance;
+ }
+
+ public Entity getEntity() {
+ return entity;
+ }
+
+ public EntityAdapter getEntityAdapter() {
+ return model.makeEntityAdapter("filter", entity);
+ }
+
+ public void update(String aType, String anExpression, String aComments, String aTag,
+ String anArticleAction, String aCommentAction) throws AbuseExc {
+
+ instance = getFilterTypeForId(aType).constructFilterInstance(anExpression);
+
+ entity.setFieldValue("type", aType);
+ entity.setFieldValue("expression", anExpression);
+ entity.setFieldValue("tag", aType);
+ entity.setFieldValue("comment", aComments);
+ entity.setFieldValue("articleaction", anArticleAction);
+ entity.setFieldValue("commentaction", aCommentAction);
+ entity.setFieldValue("last_hit", null);
+ entity.update();
+ }
+
+ public void updateLastHit(Date aDate) {
+ entity.setFieldValue("last_hit",
+ DatabaseHelper.convertDateToInternalRepresenation(
+ new Date(System.currentTimeMillis())));
+ entity.update();
+ }
+
+ public String getType() {
+ return entity.getFieldValue("type");
+ }
+
+ public String getExpression() {
+ return entity.getFieldValue("expression");
+ }
+
+ public String getTag() {
+ return entity.getFieldValue("tag");
+ }
+
+ public String getComment() {
+ return entity.getFieldValue("comment");
+ }
+
+ public String getArticleAction() {
+ return entity.getFieldValue("articleaction");
+ }
+
+ public String getCommentAction() {
+ return entity.getFieldValue("commentaction");
+ }
+
+ public FilterInstance getInstance() {
+ return instance;
+ }
+
+ public boolean test(Entity anEntity, Request aRequest) {
+ return instance.test(anEntity, aRequest);
+ }
+ }
+
+ public synchronized void reload() {
+ filterGroups.clear();
+ idToFilterGroup.clear();
+
+ try {
+ Iterator i = new EntityIteratorAdapter("", "priority asc", 100, model, "filterGroup");
+ while (i.hasNext()) {
+ EntityAdapter entityAdapter = (EntityAdapter) i.next();
+ List filters = new ArrayList();
+ Iterator j = (Iterator) entityAdapter.getIterator("to_filters");
+ while (j.hasNext()) {
+ filters.add(((EntityAdapter) j.next()).getEntity());
+ }
+
+ FilterGroup filterGroup = new FilterGroup(entityAdapter.getEntity(), filters);
+ introduceFilterGroup(filterGroup);
+ }
+ }
+ catch (Throwable e) {
+ logger.error("Can't load filters: " + e.getMessage(), e);
+ }
+ }
+
+ public synchronized List getFilterGroups() {
+ List result = new ArrayList();
+ Iterator i = filterGroups.iterator();
+ while (i.hasNext()) {
+ result.add(((FilterGroup) i.next()).getEntityAdapter());
+ }
+
+ return result;
+ }
+
+ public synchronized void updateFilterGroup(String anId, String aName) {
+ FilterGroup filterGroup = getFilterGroupForId(anId);
+ filterGroup.getEntity().setFieldValue("name", aName);
+ filterGroup.getEntity().update();
+ }
+
+ public synchronized void addFilterGroup(String aName) throws DatabaseExc {
+ Entity entity = DatabaseFilterGroup.getInstance().createNewEntity();
+ entity.setFieldValue("name", aName);
+
+ String priority = "1";
+
+ if (filterGroups.size() > 0) {
+ try {
+ String lastPriorityString = ((FilterGroup) filterGroups.get(filterGroups.size()-1)).getEntity().getFieldValue("priority");
+ int lastPriority = Integer.parseInt(lastPriorityString);
+ priority = Integer.toString(lastPriority + 1);
+ }
+ catch (Exception e) {
+ }
+ }
+ entity.setFieldValue("priority", priority);
+ entity.insert();
+
+ FilterGroup filterGroup = new FilterGroup(entity);
+ introduceFilterGroup(filterGroup);
+ }
+
+ public synchronized void moveFilterGroupUp(String anId) {
+ FilterGroup group = (FilterGroup) idToFilterGroup.get(anId);
+ String priority = group.getEntity().getFieldValue("priority");
+ int index = filterGroups.indexOf(group);
+ if (index>=1) {
+ FilterGroup groupBefore = (FilterGroup) filterGroups.remove(index-1);
+ filterGroups.add(index, groupBefore);
+ group.getEntity().setFieldValue("priority", groupBefore.getEntity().getFieldValue("priority"));
+ groupBefore.getEntity().setFieldValue("priority", priority);
+ group.getEntity().update();
+ groupBefore.getEntity().update();
+ }
+ }
+
+ public synchronized void moveFilterGroupDown(String anId) {
+ FilterGroup group = (FilterGroup) idToFilterGroup.get(anId);
+ String priority = group.getEntity().getFieldValue("priority");
+ int index = filterGroups.indexOf(group);
+ if (index<filterGroups.size()-1) {
+ FilterGroup groupAfter = (FilterGroup) filterGroups.remove(index+1);
+ filterGroups.add(index, groupAfter);
+ group.getEntity().setFieldValue("priority", groupAfter.getEntity().getFieldValue("priority"));
+ groupAfter.getEntity().setFieldValue("priority", priority);
+ group.getEntity().update();
+ groupAfter.getEntity().update();
+ }
+ }
+
+ public synchronized void deleteFilterGroup(String anId) {
+
+ FilterGroup filterGroup = getFilterGroupForId(anId);
+ removeFilterGroup(filterGroup);
+ DatabaseFilter.getInstance().deleteByWhereClause("filter_group_id = " + anId);
+ DatabaseFilterGroup.getInstance().delete(anId);
+ }
+
+ public synchronized void deleteFilter(String aGroupId, String anId) {
+ getFilterGroupForId(aGroupId).deleteFilter(anId);
+ }
+
+
+ public synchronized String updateFilter(String aGroupId, String anId,
+ String aType, String anExpression,
+ String aComments,
+ String aTag,
+ String anArticleAction,
+ String aCommentAction) {
+ return getFilterGroupForId(aGroupId).updateFilter(anId, aType,
+ anExpression, aComments, aTag, anArticleAction, aCommentAction);
+ }
+
+ public synchronized String addFilter(String aGroupId,
+ String aType, String anExpression,
+ String aComments,
+ String aTag,
+ String anArticleAction,
+ String aCommentAction) throws DatabaseExc {
+ return getFilterGroupForId(aGroupId).createFilter(aType, anExpression,
+ aComments, aTag, anArticleAction, aCommentAction);
+ }
+
+ public synchronized String moveFilterUp(String aGroupId, String anId) {
+ return getFilterGroupForId(aGroupId).moveFilterUp(anId);
+ }
+
+ public synchronized String moveFilterDown(String aGroupId, String anId) {
+ return getFilterGroupForId(aGroupId).moveFilterDown(anId);
+ }
+
+ public synchronized String moveFilterToTop(String aGroupId, String anId) {
+ return getFilterGroupForId(aGroupId).moveFilterToTop(anId);
+ }
+
+ public synchronized String moveFilterToBottom(String aGroupId, String anId) {
+ return getFilterGroupForId(aGroupId).moveFilterToBottom(anId);
+ }
+
+
+
+ public FilterGroup getFilterGroupForId(String anId) {
+ FilterGroup result = (FilterGroup) idToFilterGroup.get(anId);
+ if (result == null) {
+ throw new NullPointerException("No such filter group");
+ }
+
+ return result;
+ }
+
+ public Filter getFilterForId(String aGroupId, String anId) {
+ return getFilterGroupForId(aGroupId).getFilterForId(anId);
+ }
+
+
+ public List getFilters(String aFilterGroupId) {
+ return getFilterGroupForId(aFilterGroupId).getFilterEntityAdapterList();
+ }
+
+ private synchronized void introduceFilterGroup(FilterGroup aFilterGroup) {
+ filterGroups.add(aFilterGroup);
+ idToFilterGroup.put(aFilterGroup.getEntity().getId(), aFilterGroup);
+ }
+
+ private synchronized void removeFilterGroup(FilterGroup aFilterGroup) {
+ filterGroups.remove(aFilterGroup);
+ idToFilterGroup.remove(aFilterGroup.getEntity().getId());
+ }
+
+ private FilterType getFilterTypeForId(String anId) {
+ return (FilterType) filterTypes.get(anId);
+ }
+}