1 31 package org.blojsom.plugin.trackback; 32 33 import org.apache.commons.logging.Log; 34 import org.apache.commons.logging.LogFactory; 35 import org.apache.commons.mail.Email; 36 import org.apache.commons.mail.EmailException; 37 import org.apache.commons.mail.HtmlEmail; 38 import org.blojsom.blog.Blog; 39 import org.blojsom.blog.Entry; 40 import org.blojsom.blog.Trackback; 41 import org.blojsom.blog.User; 42 import org.blojsom.event.Event; 43 import org.blojsom.event.EventBroadcaster; 44 import org.blojsom.event.Listener; 45 import org.blojsom.fetcher.Fetcher; 46 import org.blojsom.fetcher.FetcherException; 47 import org.blojsom.plugin.PluginException; 48 import org.blojsom.plugin.common.ResponseConstants; 49 import org.blojsom.plugin.email.EmailConstants; 50 import org.blojsom.plugin.trackback.event.TrackbackAddedEvent; 51 import org.blojsom.plugin.trackback.event.TrackbackResponseSubmissionEvent; 52 import org.blojsom.plugin.velocity.StandaloneVelocityPlugin; 53 import org.blojsom.util.BlojsomConstants; 54 import org.blojsom.util.BlojsomMetaDataConstants; 55 import org.blojsom.util.BlojsomUtils; 56 57 import javax.mail.Session ; 58 import javax.naming.Context ; 59 import javax.naming.InitialContext ; 60 import javax.naming.NamingException ; 61 import javax.servlet.http.HttpServletRequest ; 62 import javax.servlet.http.HttpServletResponse ; 63 import java.util.*; 64 65 72 public class TrackbackPlugin extends StandaloneVelocityPlugin implements BlojsomMetaDataConstants, Listener, EmailConstants { 73 74 private Log _logger = LogFactory.getLog(TrackbackPlugin.class); 75 76 79 public static final String TRACKBACK_PLUGIN_EMAIL_TEMPLATE_TEXT = "org/blojsom/plugin/trackback/trackback-plugin-email-template-text.vm"; 80 public static final String TRACKBACK_PLUGIN_EMAIL_TEMPLATE_HTML = "org/blojsom/plugin/trackback/trackback-plugin-email-template-html.vm"; 81 82 85 public static final String DEFAULT_TRACKBACK_PREFIX = "[blojsom] Trackback on: "; 86 87 90 public static final String TRACKBACK_PREFIX_IP = "plugin-trackback-email-prefix"; 91 92 95 public static final String TRACKBACK_THROTTLE_MINUTES_IP = "plugin-trackback-throttle"; 96 97 100 public static final String TRACKBACK_DAYS_EXPIRATION_IP = "plugin-trackback-days-expiration"; 101 102 105 private static final int TRACKBACK_THROTTLE_DEFAULT_MINUTES = 5; 106 107 110 public static final String TRACKBACK_PARAM = "tb"; 111 112 115 public static final String TRACKBACK_TITLE_PARAM = "title"; 116 117 120 public static final String TRACKBACK_EXCERPT_PARAM = "excerpt"; 121 122 125 public static final String TRACKBACK_URL_PARAM = "url"; 126 127 130 public static final String TRACKBACK_BLOG_NAME_PARAM = "blog_name"; 131 132 136 public static final String BLOJSOM_TRACKBACK_PLUGIN_ENABLED = "BLOJSOM_TRACKBACK_PLUGIN_ENABLED"; 137 138 142 public static final String BLOJSOM_TRACKBACK_RETURN_CODE = "BLOJSOM_TRACKBACK_RETURN_CODE"; 143 144 148 public static final String BLOJSOM_TRACKBACK_MESSAGE = "BLOJSOM_TRACKBACK_MESSAGE"; 149 150 153 public static final String BLOJSOM_TRACKBACK_PLUGIN_METADATA_IP = "BLOJSOM_TRACKBACK_PLUGIN_METADATA_IP"; 154 155 158 private static final String TRACKBACK_SUCCESS_PAGE = "/trackback-success"; 159 160 163 private static final String TRACKBACK_FAILURE_PAGE = "/trackback-failure"; 164 165 168 public static final String BLOJSOM_TRACKBACK_PLUGIN_BLOG_ENTRY = "BLOJSOM_TRACKBACK_PLUGIN_BLOG_ENTRY"; 169 170 173 public static final String BLOJSOM_TRACKBACK_PLUGIN_TRACKBACK = "BLOJSOM_TRACKBACK_PLUGIN_TRACKBACK"; 174 175 public static final String BLOJSOM_PLUGIN_TRACKBACK_METADATA = "BLOJSOM_PLUGIN_TRACKBACK_METADATA"; 176 177 public static final String BLOJSOM_PLUGIN_TRACKBACK_METADATA_DESTROY = "BLOJSOM_PLUGIN_TRACKBACK_METADATA_DESTROY"; 178 179 private Map _ipAddressTrackbackTimes; 180 private String _mailServer; 181 private String _mailServerUsername; 182 private String _mailServerPassword; 183 private Session _session; 184 private Fetcher _fetcher; 185 private EventBroadcaster _eventBroadcaster; 186 187 190 public TrackbackPlugin() { 191 } 192 193 198 public void setEventBroadcaster(EventBroadcaster eventBroadcaster) { 199 _eventBroadcaster = eventBroadcaster; 200 } 201 202 207 public void setFetcher(Fetcher fetcher) { 208 _fetcher = fetcher; 209 } 210 211 216 public void init() throws PluginException { 217 super.init(); 218 219 _mailServer = _servletConfig.getInitParameter(SMTPSERVER_IP); 220 221 if (_mailServer != null) { 222 if (_mailServer.startsWith("java:comp/env")) { 223 try { 224 Context context = new InitialContext (); 225 _session = (Session ) context.lookup(_mailServer); 226 } catch (NamingException e) { 227 _logger.error(e); 228 throw new PluginException(e); 229 } 230 } else { 231 _mailServerUsername = _servletConfig.getInitParameter(SMTPSERVER_USERNAME_IP); 232 _mailServerPassword = _servletConfig.getInitParameter(SMTPSERVER_PASSWORD_IP); 233 } 234 } else { 235 throw new PluginException("Missing SMTP servername servlet initialization parameter: " + SMTPSERVER_IP); 236 } 237 238 _ipAddressTrackbackTimes = new WeakHashMap(); 239 _eventBroadcaster.addListener(this); 240 } 241 242 253 public Entry[] process(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Blog blog, Map context, Entry[] entries) throws PluginException { 254 context.put(BLOJSOM_TRACKBACK_PLUGIN_ENABLED, blog.getBlogTrackbacksEnabled()); 255 if (!blog.getBlogTrackbacksEnabled().booleanValue()) { 256 if (_logger.isDebugEnabled()) { 257 _logger.debug("Trackbacks not enabled for blog: " + blog.getBlogId()); 258 } 259 260 return entries; 261 } 262 263 Boolean _blogTrackbacksEnabled; 264 265 _blogTrackbacksEnabled = blog.getBlogTrackbacksEnabled(); 266 267 if (entries.length == 0) { 268 return entries; 269 } 270 271 if (!_blogTrackbacksEnabled.booleanValue()) { 272 return entries; 273 } 274 275 String url = httpServletRequest.getParameter(TRACKBACK_URL_PARAM); 276 String permalink = httpServletRequest.getParameter(BlojsomConstants.PERMALINK_PARAM); 277 String title = httpServletRequest.getParameter(TRACKBACK_TITLE_PARAM); 278 String excerpt = httpServletRequest.getParameter(TRACKBACK_EXCERPT_PARAM); 279 String blogName = httpServletRequest.getParameter(TRACKBACK_BLOG_NAME_PARAM); 280 String tb = httpServletRequest.getParameter(TRACKBACK_PARAM); 281 String remoteIPAddress = httpServletRequest.getRemoteAddr(); 282 283 if ((permalink != null) && (!"".equals(permalink)) && (tb != null) && ("y".equalsIgnoreCase(tb))) { 284 if ((url == null) || ("".equals(url.trim()))) { 285 context.put(BLOJSOM_TRACKBACK_RETURN_CODE, new Integer (1)); 286 context.put(BLOJSOM_TRACKBACK_MESSAGE, "No url parameter for trackback. url must be specified."); 287 httpServletRequest.setAttribute(BlojsomConstants.PAGE_PARAM, TRACKBACK_FAILURE_PAGE); 288 289 return entries; 290 } 291 292 String trackbackThrottleValue = blog.getProperty(TRACKBACK_THROTTLE_MINUTES_IP); 294 if (!BlojsomUtils.checkNullOrBlank(trackbackThrottleValue)) { 295 int trackbackThrottleMinutes; 296 297 try { 298 trackbackThrottleMinutes = Integer.parseInt(trackbackThrottleValue); 299 } catch (NumberFormatException e) { 300 trackbackThrottleMinutes = TRACKBACK_THROTTLE_DEFAULT_MINUTES; 301 } 302 if (_logger.isDebugEnabled()) { 303 _logger.debug("Trackback throttling enabled at: " + trackbackThrottleMinutes + " minutes"); 304 } 305 306 if (_ipAddressTrackbackTimes.containsKey(remoteIPAddress)) { 307 Calendar currentTime = Calendar.getInstance(); 308 Calendar timeOfLastTrackback = (Calendar) _ipAddressTrackbackTimes.get(remoteIPAddress); 309 long timeDifference = currentTime.getTimeInMillis() - timeOfLastTrackback.getTimeInMillis(); 310 311 long differenceInMinutes = timeDifference / (60 * 1000); 312 if (differenceInMinutes < trackbackThrottleMinutes) { 313 if (_logger.isDebugEnabled()) { 314 _logger.debug("Trackback throttle enabled. Comment from IP address: " + remoteIPAddress + " in less than " + trackbackThrottleMinutes + " minutes"); 315 } 316 317 context.put(BLOJSOM_TRACKBACK_RETURN_CODE, new Integer (1)); 318 context.put(BLOJSOM_TRACKBACK_MESSAGE, "Trackback throttling enabled."); 319 httpServletRequest.setAttribute(BlojsomConstants.PAGE_PARAM, TRACKBACK_FAILURE_PAGE); 320 321 return entries; 322 } else { 323 if (_logger.isDebugEnabled()) { 324 _logger.debug("Trackback throttle enabled. Resetting date of last comment to current time"); 325 } 326 _ipAddressTrackbackTimes.put(remoteIPAddress, currentTime); 327 } 328 } else { 329 Calendar calendar = Calendar.getInstance(); 330 _ipAddressTrackbackTimes.put(remoteIPAddress, calendar); 331 } 332 } 333 334 url = url.trim(); 335 if (!url.toLowerCase().startsWith("http://")) { 336 url = "http://" + url; 337 } 338 339 if (BlojsomUtils.checkNullOrBlank(title)) { 340 title = url; 341 } else { 342 title = title.trim(); 343 title = BlojsomUtils.escapeStringSimple(title); 344 title = BlojsomUtils.stripLineTerminators(title, " "); 345 } 346 347 if (excerpt == null) { 348 excerpt = ""; 349 } else { 350 if (excerpt.length() >= 255) { 351 excerpt = excerpt.substring(0, 252); 352 excerpt += "..."; 353 } 354 355 excerpt = BlojsomUtils.stripLineTerminators(excerpt, " "); 356 } 357 excerpt = BlojsomUtils.escapeStringSimple(excerpt); 358 359 if (blogName == null) { 360 blogName = ""; 361 } else { 362 blogName = blogName.trim(); 363 blogName = BlojsomUtils.escapeStringSimple(blogName); 364 blogName = BlojsomUtils.stripLineTerminators(blogName, " "); 365 } 366 367 Entry entryForTrackback = _fetcher.newEntry(); 368 try { 369 String blogEntryId = BlojsomUtils.getRequestValue("entry_id", httpServletRequest); 370 Integer entryId; 371 try { 372 entryId = Integer.valueOf(blogEntryId); 373 } catch (NumberFormatException e) { 374 if (_logger.isErrorEnabled()) { 375 _logger.error(e); 376 } 377 378 return entries; 379 } 380 381 entryForTrackback.setId(entryId); 382 383 _fetcher.loadEntry(blog, entryForTrackback); 384 if (_logger.isDebugEnabled()) { 385 _logger.debug("Loaded entry for trackback: " + entryId.toString()); 386 } 387 388 String trackbackDaysExpiration = blog.getProperty(TRACKBACK_DAYS_EXPIRATION_IP); 390 if (!BlojsomUtils.checkNullOrBlank(trackbackDaysExpiration)) { 391 try { 392 int daysExpiration = Integer.parseInt(trackbackDaysExpiration); 393 int daysBetweenDates = BlojsomUtils.daysBetweenDates(entryForTrackback.getDate(), new Date()); 394 if ((daysExpiration > 0) && (daysBetweenDates >= daysExpiration)) { 395 if (_logger.isDebugEnabled()) { 396 _logger.debug("Trackback period for this entry has expired. Expiration period set at " + daysExpiration + " days. Difference in days: " + daysBetweenDates); 397 } 398 399 return entries; 400 } 401 } catch (NumberFormatException e) { 402 } 403 } 404 } catch (FetcherException e) { 405 if (_logger.isErrorEnabled()) { 406 _logger.error(e); 407 } 408 } 409 410 Map trackbackMetaData = new HashMap(); 411 412 if (context.containsKey(BLOJSOM_PLUGIN_TRACKBACK_METADATA)) { 414 Map metaData = (Map) context.get(BLOJSOM_PLUGIN_TRACKBACK_METADATA); 415 416 Iterator metaDataKeys = metaData.keySet().iterator(); 417 Object key; 418 Object value; 419 while (metaDataKeys.hasNext()) { 420 key = metaDataKeys.next(); 421 value = metaData.get(key); 422 trackbackMetaData.put(key, value); 423 } 424 } 425 426 Trackback trackback = _fetcher.newTrackback(); 427 trackback.setBlogEntryId(entryForTrackback.getId()); 428 trackback.setEntry(entryForTrackback); 429 430 Integer code = new Integer (1); 431 432 _eventBroadcaster.processEvent(new TrackbackResponseSubmissionEvent(this, new Date(), blog, httpServletRequest, httpServletResponse, blogName, title, url, excerpt, entryForTrackback, trackbackMetaData)); 433 434 if (!trackbackMetaData.containsKey(BLOJSOM_PLUGIN_TRACKBACK_METADATA_DESTROY)) { 436 code = addTrackback(title, excerpt, url, blogName, trackbackMetaData, trackback, blog, context, httpServletRequest); 437 438 context.put(BlojsomConstants.BLOJSOM_LAST_MODIFIED, new Long (new Date().getTime())); 440 } else { 441 if (_logger.isInfoEnabled()) { 442 _logger.info("Trackback meta-data contained destroy key. Trackback was not saved"); 443 } 444 } 445 446 context.put(BLOJSOM_TRACKBACK_RETURN_CODE, code); 447 if (code.intValue() == 0) { 448 httpServletRequest.setAttribute(BlojsomConstants.PAGE_PARAM, TRACKBACK_SUCCESS_PAGE); 449 450 try { 451 _fetcher.loadEntry(blog, entries[0]); 452 _fetcher.loadEntry(blog, entryForTrackback); 453 _eventBroadcaster.broadcastEvent(new TrackbackAddedEvent(this, new Date(), trackback, blog)); 454 } catch (FetcherException e) { 455 if (_logger.isErrorEnabled()) { 456 _logger.error(e); 457 } 458 } 459 } else { 460 httpServletRequest.setAttribute(BlojsomConstants.PAGE_PARAM, TRACKBACK_FAILURE_PAGE); 461 } 462 } 463 464 return entries; 465 } 466 467 481 private Integer addTrackback(String title, String excerpt, String url, String blogName, Map trackbackMetaData, Trackback trackback, Blog blog, Map context, HttpServletRequest httpServletRequest) { 482 try { 483 excerpt = BlojsomUtils.escapeMetaAndLink(excerpt); 484 trackback.setTitle(title); 485 trackback.setExcerpt(excerpt); 486 trackback.setUrl(url); 487 trackback.setBlogName(blogName); 488 trackback.setTrackbackDate(new Date()); 489 trackback.setBlogId(blog.getId()); 490 trackback.setIp(httpServletRequest.getRemoteAddr()); 491 trackback.setMetaData(trackbackMetaData); 492 if (trackbackMetaData.containsKey(TrackbackModerationPlugin.BLOJSOM_TRACKBACK_MODERATION_PLUGIN_APPROVED) 493 && "true".equals(trackbackMetaData.get(TrackbackModerationPlugin.BLOJSOM_TRACKBACK_MODERATION_PLUGIN_APPROVED))) { 494 trackback.setStatus(ResponseConstants.APPROVED_STATUS); 495 } else { 496 if ("true".equals(blog.getProperty(TrackbackModerationPlugin.TRACKBACK_MODERATION_ENABLED))) { 497 trackback.setStatus(ResponseConstants.NEW_STATUS); 498 } else { 499 trackback.setStatus(ResponseConstants.APPROVED_STATUS); 500 } 501 } 502 503 _fetcher.saveTrackback(blog, trackback); 504 505 return new Integer (0); 506 } catch (FetcherException e) { 507 if (_logger.isErrorEnabled()) { 508 _logger.error(e); 509 } 510 511 context.put(BLOJSOM_TRACKBACK_MESSAGE, e.getMessage()); 512 513 return new Integer (1); 514 } 515 } 516 517 522 public void cleanup() throws PluginException { 523 } 524 525 530 public void destroy() throws PluginException { 531 } 532 533 540 protected void setupEmail(Blog blog, Entry entry, Email email) throws EmailException { 541 email.setCharset(BlojsomConstants.UTF8); 542 543 if (_session != null) { 545 email.setMailSession(_session); 546 } else { 547 if (!BlojsomUtils.checkNullOrBlank(_mailServerUsername) && !BlojsomUtils.checkNullOrBlank(_mailServerPassword)) { 549 email.setHostName(_mailServer); 550 email.setAuthentication(_mailServerUsername, _mailServerPassword); 551 } else { 552 email.setHostName(_mailServer); 553 } 554 } 555 556 email.setFrom(blog.getBlogOwnerEmail(), "Blojsom Trackback"); 557 558 String author = entry.getAuthor(); 559 if (BlojsomUtils.checkNullOrBlank(author)) { 560 author = blog.getBlogOwner(); 561 } 562 563 String authorEmail = blog.getBlogOwnerEmail(); 564 565 if (author != null) { 566 try { 567 User user = _fetcher.loadUser(blog, author); 568 569 if (user == null) { 570 authorEmail = blog.getBlogOwnerEmail(); 571 } else { 572 authorEmail = user.getUserEmail(); 573 if (BlojsomUtils.checkNullOrBlank(authorEmail)) { 574 authorEmail = blog.getBlogOwnerEmail(); 575 } 576 } 577 } catch (FetcherException e) { 578 } 579 } 580 581 email.addTo(authorEmail, author); 582 email.setSentDate(new Date()); 583 } 584 585 590 public void handleEvent(Event event) { 591 if (event instanceof TrackbackAddedEvent) { 592 HtmlEmail email = new HtmlEmail(); 593 594 TrackbackAddedEvent trackbackAddedEvent = (TrackbackAddedEvent) event; 595 596 if (trackbackAddedEvent.getBlog().getBlogEmailEnabled().booleanValue()) { 597 try { 598 setupEmail(trackbackAddedEvent.getBlog(), trackbackAddedEvent.getEntry(), email); 599 600 Map emailTemplateContext = new HashMap(); 601 emailTemplateContext.put(BlojsomConstants.BLOJSOM_BLOG, trackbackAddedEvent.getBlog()); 602 emailTemplateContext.put(BLOJSOM_TRACKBACK_PLUGIN_TRACKBACK, trackbackAddedEvent.getTrackback()); 603 emailTemplateContext.put(BLOJSOM_TRACKBACK_PLUGIN_BLOG_ENTRY, trackbackAddedEvent.getEntry()); 604 605 String htmlText = mergeTemplate(TRACKBACK_PLUGIN_EMAIL_TEMPLATE_HTML, trackbackAddedEvent.getBlog(), emailTemplateContext); 606 String plainText = mergeTemplate(TRACKBACK_PLUGIN_EMAIL_TEMPLATE_TEXT, trackbackAddedEvent.getBlog(), emailTemplateContext); 607 608 email = email.setHtmlMsg(htmlText); 609 email = email.setTextMsg(plainText); 610 611 String emailPrefix = (String ) trackbackAddedEvent.getBlog().getProperties().get(TRACKBACK_PREFIX_IP); 612 if (BlojsomUtils.checkNullOrBlank(emailPrefix)) { 613 emailPrefix = DEFAULT_TRACKBACK_PREFIX; 614 } 615 616 email = (HtmlEmail) email.setSubject(emailPrefix + trackbackAddedEvent.getEntry().getTitle()); 617 618 email.send(); 619 } catch (EmailException e) { 620 if (_logger.isErrorEnabled()) { 621 _logger.error(e); 622 } 623 } 624 } 625 } 626 } 627 628 633 public void processEvent(Event event) { 634 } 635 } 636 | Popular Tags |