2 * Copyright (C) 2001, 2002 The Mir-coders group
\r
4 * This file is part of Mir.
\r
6 * Mir is free software; you can redistribute it and/or modify
\r
7 * it under the terms of the GNU General Public License as published by
\r
8 * the Free Software Foundation; either version 2 of the License, or
\r
9 * (at your option) any later version.
\r
11 * Mir is distributed in the hope that it will be useful,
\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 * GNU General Public License for more details.
\r
16 * You should have received a copy of the GNU General Public License
\r
17 * along with Mir; if not, write to the Free Software
\r
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
20 * In addition, as a special exception, The Mir-coders gives permission to link
\r
21 * the code of this program with any library licensed under the Apache Software License,
\r
22 * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
\r
23 * (or with modified versions of the above that use the same license as the above),
\r
24 * and distribute linked combinations including the two. You must obey the
\r
25 * GNU General Public License in all respects for all of the code used other than
\r
26 * the above mentioned libraries. If you modify this file, you may extend this
\r
27 * exception to your version of the file, but you are not obligated to do so.
\r
28 * If you do not wish to do so, delete this exception statement from your version.
\r
31 package mircoders.global;
\r
33 import java.io.File;
\r
34 import java.io.FileNotFoundException;
\r
35 import java.io.FileOutputStream;
\r
36 import java.util.Arrays;
\r
37 import java.util.Date;
\r
38 import java.util.GregorianCalendar;
\r
39 import java.util.HashMap;
\r
40 import java.util.Iterator;
\r
41 import java.util.List;
\r
42 import java.util.Map;
\r
43 import java.util.Random;
\r
44 import java.util.Vector;
\r
45 import javax.servlet.http.Cookie;
\r
46 import javax.servlet.http.HttpServletResponse;
\r
48 import org.apache.commons.collections.ExtendedProperties;
\r
49 import mir.config.MirPropertiesConfiguration;
\r
50 import mir.entity.Entity;
\r
51 import mir.log.LoggerWrapper;
\r
52 import mir.session.Request;
\r
53 import mir.util.DateTimeFunctions;
\r
54 import mir.util.GeneratorFormatAdapters;
\r
55 import mir.util.StringRoutines;
\r
56 import mircoders.entity.EntityComment;
\r
57 import mircoders.entity.EntityContent;
\r
58 import mircoders.localizer.MirAdminInterfaceLocalizer;
\r
59 import mircoders.localizer.MirAntiAbuseFilterType;
\r
62 public class Abuse {
\r
63 private List filterRules;
\r
64 private Map filterTypes;
\r
65 private List filterTypeIds;
\r
66 private int maxIdentifier;
\r
67 private LoggerWrapper logger;
\r
68 private int logSize;
\r
69 private boolean logEnabled;
\r
70 private boolean openPostingDisabled;
\r
71 private boolean openPostingPassword;
\r
72 private boolean cookieOnBlock;
\r
73 private String articleBlockAction;
\r
74 private String commentBlockAction;
\r
76 private String configFile = MirGlobal.config().getStringWithHome("Abuse.Config");
\r
78 private MirPropertiesConfiguration configuration;
\r
80 private static String cookieName = MirGlobal.config().getString("Abuse.CookieName");
\r
81 private static int cookieMaxAge = 60 * 60 * MirGlobal.config().getInt("Abuse.CookieMaxAge");
\r
84 logger = new LoggerWrapper("Global.Abuse");
\r
85 filterRules = new Vector();
\r
90 configuration = MirPropertiesConfiguration.instance();
\r
92 catch (Throwable e) {
\r
93 throw new RuntimeException("Can't get configuration: " + e.getMessage());
\r
98 articleBlockAction = "";
\r
99 commentBlockAction = "";
\r
100 openPostingPassword = false;
\r
101 openPostingDisabled = false;
\r
102 cookieOnBlock = false;
\r
105 filterTypes = new HashMap();
\r
106 filterTypeIds = new Vector();
\r
108 Iterator i = MirGlobal.localizer().openPostings().getAntiAbuseFilterTypes().iterator();
\r
110 while (i.hasNext()) {
\r
111 MirAntiAbuseFilterType filterType = (MirAntiAbuseFilterType) i.next();
\r
112 filterTypes.put(filterType.getName(), filterType);
\r
113 filterTypeIds.add(filterType.getName());
\r
116 catch (Throwable t) {
\r
117 throw new RuntimeException("Can't get filter types: " + t.getMessage());
\r
123 private void setCookie(HttpServletResponse aResponse) {
\r
124 Random random = new Random();
\r
126 Cookie cookie = new Cookie(cookieName, Integer.toString(random.nextInt(1000000000)));
\r
127 cookie.setMaxAge(cookieMaxAge);
\r
128 cookie.setPath("/");
\r
130 if (aResponse != null)
\r
131 aResponse.addCookie(cookie);
\r
134 private boolean checkCookie(List aCookies) {
\r
135 if (getCookieOnBlock()) {
\r
136 Iterator i = aCookies.iterator();
\r
138 while (i.hasNext()) {
\r
139 Cookie cookie = (Cookie) i.next();
\r
141 if (cookie.getName().equals(cookieName)) {
\r
142 logger.debug("cookie match");
\r
151 FilterRule findMatchingFilter(Entity anEntity, Request aRequest) {
\r
152 Iterator iterator = filterRules.iterator();
\r
154 while (iterator.hasNext()) {
\r
155 FilterRule rule = (FilterRule) iterator.next();
\r
157 if (rule.test(anEntity, aRequest))
\r
164 public void checkComment(EntityComment aComment, Request aRequest, HttpServletResponse aResponse) {
\r
166 long time = System.currentTimeMillis();
\r
168 FilterRule filterRule = findMatchingFilter(aComment, aRequest);
\r
170 if (filterRule != null) {
\r
171 logger.debug("Match for " + filterRule.getType() + " rule '" + filterRule.getExpression() + "'");
\r
172 filterRule.setLastHit(new GregorianCalendar().getTime());
\r
173 MirGlobal.performCommentOperation(null, aComment, filterRule.getCommentAction());
\r
174 setCookie(aResponse);
\r
176 logComment(aComment, aRequest, filterRule.getType(), filterRule.getExpression());
\r
179 logComment(aComment, aRequest);
\r
182 logger.info("checkComment: " + (System.currentTimeMillis() - time) + "ms");
\r
184 catch (Throwable t) {
\r
185 t.printStackTrace(logger.asPrintWriter(logger.DEBUG_MESSAGE));
\r
186 logger.error("Abuse.checkComment: " + t.toString());
\r
190 public void checkArticle(EntityContent anArticle, Request aRequest, HttpServletResponse aResponse) {
\r
192 long time = System.currentTimeMillis();
\r
194 FilterRule filterRule = findMatchingFilter(anArticle, aRequest);
\r
196 if (filterRule != null) {
\r
197 logger.debug("Match for " + filterRule.getType() + " rule '" + filterRule.getExpression() + "'");
\r
198 filterRule.setLastHit(new GregorianCalendar().getTime());
\r
200 StringBuffer line = new StringBuffer();
\r
202 line.append(DateTimeFunctions.advancedDateFormat(
\r
203 configuration.getString("Mir.DefaultDateTimeFormat"),
\r
204 (new GregorianCalendar()).getTime(), configuration.getString("Mir.DefaultTimezone")));
\r
207 line.append("filter");
\r
210 line.append(filterRule.getType() +" ("+ filterRule.getExpression()+")");
\r
211 anArticle.appendToComments(line.toString());
\r
213 MirGlobal.performArticleOperation(null, anArticle, filterRule.getArticleAction());
\r
214 setCookie(aResponse);
\r
216 logArticle(anArticle, aRequest, filterRule.getType(), filterRule.getExpression());
\r
219 logArticle(anArticle, aRequest);
\r
221 logger.info("checkArticle: " + (System.currentTimeMillis() - time) + "ms");
\r
223 catch (Throwable t) {
\r
224 t.printStackTrace(logger.asPrintWriter(logger.DEBUG_MESSAGE));
\r
225 logger.error("Abuse.checkArticle: " + t.toString());
\r
229 public boolean getLogEnabled() {
\r
233 public void setLogEnabled(boolean anEnabled) {
\r
234 if (!configuration.getString("Abuse.DisallowIPLogging", "0").equals("1"))
\r
235 logEnabled = anEnabled;
\r
239 public int getLogSize() {
\r
243 public void setLogSize(int aSize) {
\r
248 public boolean getOpenPostingDisabled() {
\r
249 return openPostingDisabled;
\r
252 public void setOpenPostingDisabled(boolean anOpenPostingDisabled) {
\r
253 openPostingDisabled = anOpenPostingDisabled;
\r
256 public boolean getOpenPostingPassword() {
\r
257 return openPostingPassword;
\r
260 public void setOpenPostingPassword(boolean anOpenPostingPassword) {
\r
261 openPostingPassword = anOpenPostingPassword;
\r
264 public boolean getCookieOnBlock() {
\r
265 return cookieOnBlock;
\r
268 public void setCookieOnBlock(boolean aCookieOnBlock) {
\r
269 cookieOnBlock = aCookieOnBlock;
\r
272 public String getArticleBlockAction() {
\r
273 return articleBlockAction;
\r
276 public void setArticleBlockAction(String anAction) {
\r
277 articleBlockAction = anAction;
\r
280 public String getCommentBlockAction() {
\r
281 return commentBlockAction;
\r
284 public void setCommentBlockAction(String anAction) {
\r
285 commentBlockAction = anAction;
\r
288 public List getLog() {
\r
289 synchronized (log) {
\r
291 List result = new Vector();
\r
293 Iterator i = log.iterator();
\r
294 while (i.hasNext()) {
\r
295 LogEntry logEntry = (LogEntry) i.next();
\r
296 Map entry = new HashMap();
\r
298 entry.put("ip", logEntry.getIpNumber());
\r
299 entry.put("id", logEntry.getId());
\r
300 entry.put("timestamp", new GeneratorFormatAdapters.DateFormatAdapter(logEntry.getTimeStamp(), MirPropertiesConfiguration.instance().getString("Mir.DefaultTimezone")));
\r
301 if (logEntry.getIsArticle())
\r
302 entry.put("type", "content");
\r
304 entry.put("type", "comment");
\r
305 entry.put("browser", logEntry.getBrowserString());
\r
306 entry.put("hitfiltertype", logEntry.getHitFilterType());
\r
307 entry.put("hitfilterexpression", logEntry.getHitFilterExpression());
\r
314 catch (Throwable t) {
\r
315 throw new RuntimeException(t.toString());
\r
320 public void logComment(Entity aComment, Request aRequest) {
\r
321 logComment(aComment, aRequest, null, null);
\r
324 public void logComment(Entity aComment, Request aRequest, String aHitFilterType, String aHitFilterExpression) {
\r
325 String ipAddress = aRequest.getHeader("ip");
\r
326 String id = aComment.getId();
\r
327 String browser = aRequest.getHeader("User-Agent");
\r
329 logComment(ipAddress, id, new Date(), browser, aHitFilterType, aHitFilterExpression);
\r
332 public void logArticle(Entity anArticle, Request aRequest) {
\r
333 logArticle(anArticle, aRequest, null, null);
\r
336 public void logArticle(Entity anArticle, Request aRequest, String aHitFilterType, String aHitFilterExpression) {
\r
337 String ipAddress = aRequest.getHeader("ip");
\r
338 String id = anArticle.getId();
\r
339 String browser = aRequest.getHeader("User-Agent");
\r
341 logArticle(ipAddress, id, new Date(), browser, aHitFilterType, aHitFilterExpression);
\r
344 public void logComment(String anIp, String anId, Date aTimeStamp, String aBrowser, String aHitFilterType, String aHitFilterExpression) {
\r
345 appendLog(new LogEntry(aTimeStamp, anIp, aBrowser, anId, false, aHitFilterType, aHitFilterExpression));
\r
348 public void logArticle(String anIp, String anId, Date aTimeStamp, String aBrowser, String aHitFilterType, String aHitFilterExpression) {
\r
349 appendLog(new LogEntry(aTimeStamp, anIp, aBrowser, anId, true, aHitFilterType, aHitFilterExpression));
\r
352 public void load() {
\r
353 synchronized (filterRules) {
\r
355 ExtendedProperties configuration = new ExtendedProperties();
\r
358 configuration = new ExtendedProperties(configFile);
\r
360 catch (FileNotFoundException e) {
\r
363 getFilterConfig(filterRules, "abuse.filter", configuration);
\r
365 setOpenPostingDisabled(configuration.getString("abuse.openPostingDisabled", "0").equals("1"));
\r
366 setOpenPostingPassword(configuration.getString("abuse.openPostingPassword", "0").equals("1"));
\r
367 setCookieOnBlock(configuration.getString("abuse.cookieOnBlock", "0").equals("1"));
\r
368 setLogEnabled(configuration.getString("abuse.logEnabled", "0").equals("1"));
\r
369 setLogSize(configuration.getInt("abuse.logSize", 10));
\r
370 setArticleBlockAction(configuration.getString("abuse.articleBlockAction", ""));
\r
371 setCommentBlockAction(configuration.getString("abuse.commentBlockAction", ""));
\r
373 catch (Throwable t) {
\r
374 throw new RuntimeException(t.toString());
\r
379 public void save() {
\r
380 synchronized (filterRules) {
\r
382 ExtendedProperties configuration = new ExtendedProperties();
\r
384 setFilterConfig(filterRules, "abuse.filter", configuration);
\r
386 configuration.addProperty("abuse.openPostingDisabled", getOpenPostingDisabled() ? "1" : "0");
\r
387 configuration.addProperty("abuse.openPostingPassword", getOpenPostingPassword() ? "1" : "0");
\r
388 configuration.addProperty("abuse.cookieOnBlock", getCookieOnBlock() ? "1" : "0");
\r
389 configuration.addProperty("abuse.logEnabled", getLogEnabled() ? "1" : "0");
\r
390 configuration.addProperty("abuse.logSize", Integer.toString(getLogSize()));
\r
391 configuration.addProperty("abuse.articleBlockAction", getArticleBlockAction());
\r
392 configuration.addProperty("abuse.commentBlockAction", getCommentBlockAction());
\r
394 configuration.save(new FileOutputStream(new File(configFile)), "Anti abuse configuration");
\r
396 catch (Throwable t) {
\r
397 throw new RuntimeException(t.toString());
\r
402 public List getFilterTypes() {
\r
404 List result = new Vector();
\r
406 Iterator i = filterTypeIds.iterator();
\r
407 while (i.hasNext()) {
\r
408 String id = (String) i.next();
\r
410 Map action = new HashMap();
\r
411 action.put("resource", id);
\r
412 action.put("identifier", id);
\r
414 result.add(action);
\r
419 catch (Throwable t) {
\r
420 throw new RuntimeException("can't get article actions");
\r
424 public List getArticleActions() {
\r
426 List result = new Vector();
\r
428 Iterator i = MirGlobal.localizer().adminInterface().simpleArticleOperations().iterator();
\r
429 while (i.hasNext()) {
\r
430 MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation =
\r
431 (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next();
\r
433 Map action = new HashMap();
\r
434 action.put("resource", operation.getName());
\r
435 action.put("identifier", operation.getName());
\r
437 result.add(action);
\r
442 catch (Throwable t) {
\r
443 throw new RuntimeException("can't get article actions");
\r
447 public List getCommentActions() {
\r
449 List result = new Vector();
\r
451 Iterator i = MirGlobal.localizer().adminInterface().simpleCommentOperations().iterator();
\r
452 while (i.hasNext()) {
\r
453 MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation =
\r
454 (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next();
\r
456 Map action = new HashMap();
\r
457 action.put("resource", operation.getName());
\r
458 action.put("identifier", operation.getName());
\r
460 result.add(action);
\r
465 catch (Throwable t) {
\r
466 throw new RuntimeException("can't get comment actions");
\r
470 public List getFilters() {
\r
471 List result = new Vector();
\r
473 synchronized (filterRules) {
\r
474 Iterator i = filterRules.iterator();
\r
475 while (i.hasNext()) {
\r
476 FilterRule filter = (FilterRule) i.next();
\r
477 result.add(filter.clone());
\r
483 public String addFilter(String aType, String anExpression, String aComments, String aCommentAction, String anArticleAction) {
\r
484 return addFilter(aType, anExpression, aComments, aCommentAction, anArticleAction, null);
\r
487 public String addFilter(String aType, String anExpression, String aComments, String aCommentAction, String anArticleAction, Date aListHit) {
\r
488 return addFilter(filterRules, aType, anExpression, aComments, aCommentAction, anArticleAction, aListHit);
\r
491 public FilterRule getFilter(String anId) {
\r
492 synchronized (filterRules) {
\r
493 FilterRule result = (FilterRule) findFilter(filterRules, anId);
\r
494 if (result == null)
\r
497 return (FilterRule) result.clone();
\r
501 public String setFilter(String anIdentifier, String aType, String anExpression, String aComments, String aCommentAction, String anArticleAction) {
\r
502 return setFilter(filterRules, anIdentifier, aType, anExpression, aComments, aCommentAction, anArticleAction);
\r
505 public void deleteFilter(String anIdentifier) {
\r
506 deleteFilter(filterRules, anIdentifier);
\r
509 public void moveFilterUp(String anIdentifier) {
\r
510 moveFilter(filterRules, anIdentifier, -1);
\r
513 public void moveFilterDown(String anIdentifier) {
\r
514 moveFilter(filterRules, anIdentifier, 1);
\r
517 private String addFilter(List aFilters, String aType, String anExpression, String aComments, String aCommentAction, String anArticleAction, Date aLastHit) {
\r
518 MirAntiAbuseFilterType type = (MirAntiAbuseFilterType) filterTypes.get(aType);
\r
521 return "invalidtype";
\r
523 if (!type.validate(anExpression)) {
\r
524 return "invalidexpression";
\r
527 FilterRule filter = new FilterRule();
\r
529 filter.setId(generateId());
\r
530 filter.setExpression(anExpression);
\r
531 filter.setType(aType);
\r
532 filter.setComments(aComments);
\r
533 filter.setArticleAction(anArticleAction);
\r
534 filter.setCommentAction(aCommentAction);
\r
535 filter.setLastHit(aLastHit);
\r
537 synchronized (aFilters) {
\r
538 aFilters.add(filter);
\r
544 private String setFilter(List aFilters, String anIdentifier, String aType, String anExpression, String aComments, String aCommentAction, String anArticleAction) {
\r
545 MirAntiAbuseFilterType type = (MirAntiAbuseFilterType) filterTypes.get(aType);
\r
548 return "invalidtype";
\r
550 if (!type.validate(anExpression)) {
\r
551 return "invalidexpression";
\r
554 synchronized (aFilters) {
\r
555 FilterRule filter = findFilter(aFilters, anIdentifier);
\r
557 if (filter != null) {
\r
558 filter.setExpression(anExpression);
\r
559 filter.setType(aType);
\r
560 filter.setCommentAction(aCommentAction);
\r
561 filter.setArticleAction(anArticleAction);
\r
562 filter.setComments(aComments);
\r
569 private FilterRule findFilter(List aFilters, String anIdentifier) {
\r
570 synchronized (aFilters) {
\r
571 Iterator i = aFilters.iterator();
\r
572 while (i.hasNext()) {
\r
573 FilterRule filter = (FilterRule) i.next();
\r
575 if (filter.getId().equals(anIdentifier)) {
\r
584 private void moveFilter(List aFilters, String anIdentifier, int aDirection) {
\r
585 synchronized (aFilters) {
\r
586 for (int i = 0; i < aFilters.size(); i++) {
\r
587 FilterRule rule = (FilterRule) aFilters.get(i);
\r
589 if (rule.getId().equals(anIdentifier) && (i + aDirection >= 0) && (i + aDirection < aFilters.size())) {
\r
590 aFilters.remove(rule);
\r
591 aFilters.add(i + aDirection, rule);
\r
598 private void deleteFilter(List aFilters, String anIdentifier) {
\r
599 synchronized (aFilters) {
\r
600 FilterRule filter = findFilter(aFilters, anIdentifier);
\r
602 if (filter != null) {
\r
603 aFilters.remove(filter);
\r
608 private String generateId() {
\r
609 synchronized (this) {
\r
610 maxIdentifier = maxIdentifier + 1;
\r
612 return Integer.toString(maxIdentifier);
\r
616 public class FilterRule {
\r
617 private String identifier;
\r
618 private String expression;
\r
619 private String type;
\r
620 private String comments;
\r
621 private String articleAction;
\r
622 private String commentAction;
\r
623 private Date lastHit;
\r
625 public FilterRule() {
\r
630 articleAction = articleBlockAction;
\r
631 commentAction = commentBlockAction;
\r
635 public Date getLastHit() {
\r
639 public void setLastHit(Date aDate) {
\r
643 public String getId() {
\r
647 public void setId(String anId) {
\r
651 public String getExpression() {
\r
655 public void setExpression(String anExpression) {
\r
656 expression = anExpression;
\r
659 public String getType() {
\r
663 public void setType(String aType) {
\r
667 public void setComments(String aComments) {
\r
668 comments = aComments;
\r
671 public String getComments() {
\r
675 public String getArticleAction() {
\r
676 return articleAction;
\r
679 public void setArticleAction(String anArticleAction) {
\r
680 articleAction = anArticleAction;
\r
683 public String getCommentAction() {
\r
684 return commentAction;
\r
687 public void setCommentAction(String aCommentAction) {
\r
688 commentAction = aCommentAction;
\r
691 public boolean test(Entity anEntity, Request aRequest) {
\r
692 MirAntiAbuseFilterType filterType = (MirAntiAbuseFilterType) filterTypes.get(type);
\r
694 if (filterType != null)
\r
695 return filterType.test(expression, anEntity, aRequest);
\r
697 catch (Throwable t) {
\r
698 logger.error("error while testing " + type + "-filter '" + expression + "'");
\r
704 public Object clone() {
\r
705 FilterRule result = new FilterRule();
\r
706 result.setComments(getComments());
\r
707 result.setExpression(getExpression());
\r
708 result.setId(getId());
\r
709 result.setType(getType());
\r
710 result.setArticleAction(getArticleAction());
\r
711 result.setCommentAction(getCommentAction());
\r
712 result.setLastHit(getLastHit());
\r
718 private String escapeFilterPart(String aFilterPart) {
\r
719 return StringRoutines.replaceStringCharacters(aFilterPart,
\r
720 new char[] {'\\', ':', '\n', '\r', '\t', ' '},
\r
721 new String[] {"\\\\", "\\:", "\\n", "\\r", "\\t", "\\ "});
\r
724 private String deescapeFilterPart(String aFilterPart) {
\r
725 return StringRoutines.replaceEscapedStringCharacters(aFilterPart,
\r
727 new char[] {'\\', ':', 'n', 'r', 't', ' '},
\r
728 new String[] {"\\", ":", "\n", "\r", "\t", " "});
\r
731 private void setFilterConfig(List aFilters, String aConfigKey, ExtendedProperties aConfiguration) {
\r
732 synchronized (aFilters) {
\r
733 Iterator i = aFilters.iterator();
\r
735 while (i.hasNext()) {
\r
736 FilterRule filter = (FilterRule) i.next();
\r
738 String filterconfig =
\r
739 escapeFilterPart(filter.getType()) + ":" +
\r
740 escapeFilterPart(filter.getExpression()) + ":" +
\r
741 escapeFilterPart(filter.getArticleAction()) + ":" +
\r
742 escapeFilterPart(filter.getCommentAction()) + ":" +
\r
743 escapeFilterPart(filter.getComments()) + ":";
\r
745 if (filter.getLastHit() != null)
\r
746 filterconfig = filterconfig + filter.getLastHit().getTime();
\r
748 aConfiguration.addProperty(aConfigKey, filterconfig);
\r
753 private void getFilterConfig(List aFilters, String aConfigKey, ExtendedProperties aConfiguration) {
\r
754 synchronized (aFilters) {
\r
757 if (aConfiguration.getStringArray(aConfigKey) != null) {
\r
759 Iterator i = Arrays.asList(aConfiguration.getStringArray(aConfigKey)).
\r
762 while (i.hasNext()) {
\r
763 String filter = (String) i.next();
\r
764 List parts = StringRoutines.splitStringWithEscape(filter, ':', '\\');
\r
765 if (parts.size() == 2) {
\r
766 parts.add(articleBlockAction);
\r
767 parts.add(commentBlockAction);
\r
772 if (parts.size() >= 5) {
\r
773 Date lastHit = null;
\r
775 if (parts.size() >= 6) {
\r
776 String lastHitString = (String) parts.get(5);
\r
779 lastHit = new Date(Long.parseLong(lastHitString));
\r
781 catch (Throwable t) {
\r
785 addFilter(deescapeFilterPart( (String) parts.get(0)),
\r
786 deescapeFilterPart( (String) parts.get(1)),
\r
787 deescapeFilterPart( (String) parts.get(4)),
\r
788 deescapeFilterPart( (String) parts.get(3)),
\r
789 deescapeFilterPart( (String) parts.get(2)), lastHit);
\r
796 private static class LogEntry {
\r
797 private String ipNumber;
\r
798 private String browserString;
\r
800 private Date timeStamp;
\r
801 private boolean isArticle;
\r
802 private String hitFilterType;
\r
803 private String hitFilterExpression;
\r
805 public LogEntry(Date aTimeStamp, String anIpNumber, String aBrowserString, String anId, boolean anIsArticle, String aHitFilterType, String aHitFilterExpression) {
\r
806 ipNumber = anIpNumber;
\r
807 browserString = aBrowserString;
\r
809 isArticle = anIsArticle;
\r
810 timeStamp = aTimeStamp;
\r
811 hitFilterType = aHitFilterType;
\r
812 hitFilterExpression = aHitFilterExpression;
\r
815 public LogEntry(Date aTimeStamp, String anIpNumber, String aBrowserString, String anId, boolean anIsArticle) {
\r
816 this(aTimeStamp, anIpNumber, aBrowserString, anId, anIsArticle, null, null);
\r
819 public String getIpNumber() {
\r
823 public String getBrowserString() {
\r
824 return browserString;
\r
827 public String getId() {
\r
831 public String getHitFilterType() {
\r
832 return hitFilterType;
\r
835 public String getHitFilterExpression() {
\r
836 return hitFilterExpression;
\r
839 public Date getTimeStamp() {
\r
843 public boolean getIsArticle() {
\r
848 private void truncateLog() {
\r
849 synchronized (log) {
\r
853 while (log.size() > 0 && log.size() > logSize) {
\r
860 private void appendLog(LogEntry anEntry) {
\r
861 synchronized (log) {
\r