1 18 19 package org.apache.roller.ui.rendering.servlets; 20 21 import java.io.IOException ; 22 import java.sql.Timestamp ; 23 import java.util.ArrayList ; 24 import java.util.Iterator ; 25 import java.util.List ; 26 import java.util.ResourceBundle ; 27 import java.util.Set ; 28 import java.util.TreeSet ; 29 import javax.mail.MessagingException ; 30 import javax.mail.Session ; 31 import javax.naming.Context ; 32 import javax.naming.InitialContext ; 33 import javax.naming.NamingException ; 34 import javax.servlet.RequestDispatcher ; 35 import javax.servlet.ServletConfig ; 36 import javax.servlet.ServletException ; 37 import javax.servlet.http.HttpServlet ; 38 import javax.servlet.http.HttpServletRequest ; 39 import javax.servlet.http.HttpServletResponse ; 40 import org.apache.commons.lang.StringUtils; 41 import org.apache.commons.logging.Log; 42 import org.apache.commons.logging.LogFactory; 43 import org.apache.roller.RollerException; 44 import org.apache.roller.config.RollerConfig; 45 import org.apache.roller.config.RollerRuntimeConfig; 46 import org.apache.roller.model.IndexManager; 47 import org.apache.roller.model.RollerFactory; 48 import org.apache.roller.model.UserManager; 49 import org.apache.roller.model.WeblogManager; 50 import org.apache.roller.pojos.CommentData; 51 import org.apache.roller.pojos.UserData; 52 import org.apache.roller.pojos.WeblogEntryData; 53 import org.apache.roller.pojos.WebsiteData; 54 import org.apache.roller.ui.rendering.model.UtilitiesModel; 55 import org.apache.roller.ui.rendering.util.CommentAuthenticator; 56 import org.apache.roller.ui.rendering.util.DefaultCommentAuthenticator; 57 import org.apache.roller.ui.rendering.util.WeblogCommentRequest; 58 import org.apache.roller.ui.rendering.util.WeblogEntryCommentForm; 59 import org.apache.roller.util.GenericThrottle; 60 import org.apache.roller.util.IPBanList; 61 import org.apache.roller.util.MailUtil; 62 import org.apache.roller.util.SpamChecker; 63 import org.apache.roller.util.URLUtilities; 64 import org.apache.roller.util.Utilities; 65 import org.apache.roller.util.cache.CacheManager; 66 import org.apache.struts.util.RequestUtils; 67 68 69 84 public class CommentServlet extends HttpServlet { 85 86 private static Log log = LogFactory.getLog(CommentServlet.class); 87 88 private static final String EMAIL_ADDR_REGEXP = "^.*@.*[.].{2,}$"; 89 90 private ResourceBundle bundle = ResourceBundle.getBundle("ApplicationResources"); 91 92 private CommentAuthenticator authenticator = null; 93 private GenericThrottle commentThrottle = null; 94 95 96 99 public void init(ServletConfig servletConfig) throws ServletException { 100 101 super.init(servletConfig); 102 103 log.info("Initializing CommentServlet"); 104 105 try { 107 String name = RollerConfig.getProperty("comment.authenticator.classname"); 108 109 Class clazz = Class.forName(name); 110 this.authenticator = (CommentAuthenticator) clazz.newInstance(); 111 112 } catch(Exception e) { 113 log.error(e); 114 this.authenticator = new DefaultCommentAuthenticator(); 115 } 116 117 if(RollerConfig.getBooleanProperty("comment.throttle.enabled")) { 119 120 int threshold = 25; 121 try { 122 threshold = Integer.parseInt(RollerConfig.getProperty("comment.throttle.threshold")); 123 } catch(Exception e) { 124 log.warn("bad input for config property comment.throttle.threshold", e); 125 } 126 127 int interval = 60000; 128 try { 129 interval = Integer.parseInt(RollerConfig.getProperty("comment.throttle.interval")); 130 interval = interval * 1000; 132 } catch(Exception e) { 133 log.warn("bad input for config property comment.throttle.interval", e); 134 } 135 136 int maxEntries = 250; 137 try { 138 maxEntries = Integer.parseInt(RollerConfig.getProperty("comment.throttle.maxentries")); 139 } catch(Exception e) { 140 log.warn("bad input for config property comment.throttle.maxentries", e); 141 } 142 143 commentThrottle = new GenericThrottle(threshold, interval, maxEntries); 144 145 log.info("Comment Throttling ENABLED"); 146 } else { 147 log.info("Comment Throttling DISABLED"); 148 } 149 } 150 151 152 157 public void doGet(HttpServletRequest request, HttpServletResponse response) 158 throws IOException , ServletException { 159 160 response.sendError(HttpServletResponse.SC_NOT_FOUND); 161 } 162 163 164 169 public void doPost(HttpServletRequest request, HttpServletResponse response) 170 throws IOException , ServletException { 171 172 String error = null; 173 String message = null; 174 String dispatch_url = null; 175 176 WebsiteData weblog = null; 177 WeblogEntryData entry = null; 178 179 String method = request.getParameter("method"); 181 boolean preview = (method != null && method.equals("preview")) ? true : false; 182 183 if(commentThrottle != null && 185 commentThrottle.processHit(request.getRemoteAddr())) { 186 187 log.debug("ABUSIVE "+request.getRemoteAddr()); 188 IPBanList.getInstance().addBannedIp(request.getRemoteAddr()); 189 response.sendError(HttpServletResponse.SC_NOT_FOUND); 190 return; 191 } 192 193 WeblogCommentRequest commentRequest = null; 194 try { 195 commentRequest = new WeblogCommentRequest(request); 196 197 UserManager uMgr = RollerFactory.getRoller().getUserManager(); 199 weblog = uMgr.getWebsiteByHandle(commentRequest.getWeblogHandle()); 200 201 if(weblog == null) { 202 throw new RollerException("unable to lookup weblog: "+ 203 commentRequest.getWeblogHandle()); 204 } 205 206 WeblogManager weblogMgr = RollerFactory.getRoller().getWeblogManager(); 208 entry = weblogMgr.getWeblogEntryByAnchor(weblog, commentRequest.getWeblogAnchor()); 209 210 if(entry == null) { 211 throw new RollerException("unable to lookup entry: "+ 212 commentRequest.getWeblogAnchor()); 213 } 214 215 dispatch_url = "/roller-ui/rendering/page/"+weblog.getHandle(); 217 if(commentRequest.getLocale() != null) { 218 dispatch_url += "/"+commentRequest.getLocale(); 219 } 220 dispatch_url += "/entry/"+URLUtilities.encode(commentRequest.getWeblogAnchor()); 221 222 } catch (Exception e) { 223 log.debug("error creating page request", e); 225 response.sendError(HttpServletResponse.SC_NOT_FOUND); 226 return; 227 } 228 229 230 log.debug("Doing comment posting for entry = "+entry.getPermaLink()); 231 232 CommentData comment = new CommentData(); 236 comment.setName(commentRequest.getName()); 237 comment.setEmail(commentRequest.getEmail()); 238 comment.setUrl(commentRequest.getUrl()); 239 comment.setContent(commentRequest.getContent()); 240 comment.setNotify(new Boolean (commentRequest.isNotify())); 241 comment.setWeblogEntry(entry); 242 comment.setRemoteHost(request.getRemoteHost()); 243 comment.setPostTime(new Timestamp (System.currentTimeMillis())); 244 245 WeblogEntryCommentForm cf = new WeblogEntryCommentForm(); 246 cf.setData(comment); 247 248 if(!RollerRuntimeConfig.getBooleanProperty("users.comments.enabled")) { 250 error = "Comments are disabled for this site."; 252 253 } else if(!weblog.getAllowComments().booleanValue() || 255 !entry.getCommentsStillAllowed()) { 256 error = "Comments not allowed on this entry"; 258 259 } else if(!this.authenticator.authenticate(request)) { 261 error = bundle.getString("error.commentAuthFailed"); 262 log.debug("Comment failed authentication"); 263 } 264 265 if(error != null) { 267 cf.setError(error); 268 request.setAttribute("commentForm", cf); 269 RequestDispatcher dispatcher = request.getRequestDispatcher(dispatch_url); 270 dispatcher.forward(request, response); 271 return; 272 } 273 274 275 if (preview) { 276 message = "This is a comment preview only"; 278 cf.setPreview(comment); 279 280 SpamChecker checker = new SpamChecker(); 282 if (checker.checkComment(comment)) { 283 error = bundle.getString("commentServlet.previewMarkedAsSpam"); 284 log.debug("Comment marked as spam"); 285 } 286 log.debug("Comment is a preview"); 287 288 } else { 289 SpamChecker checker = new SpamChecker(); 291 if (checker.checkComment(comment)) { 292 comment.setSpam(Boolean.TRUE); 293 error = bundle.getString("commentServlet.commentMarkedAsSpam"); 294 log.debug("Comment marked as spam"); 295 } 296 297 if (weblog.getCommentModerationRequired()) { 299 comment.setPending(Boolean.TRUE); 300 comment.setApproved(Boolean.FALSE); 301 message = bundle.getString("commentServlet.submittedToModerator"); 302 } else { 303 comment.setPending(Boolean.FALSE); 304 comment.setApproved(Boolean.TRUE); 305 } 306 307 try { 308 WeblogManager mgr = RollerFactory.getRoller().getWeblogManager(); 309 mgr.saveComment(comment); 310 RollerFactory.getRoller().flush(); 311 312 reindexEntry(entry); 313 314 CacheManager.invalidate(comment); 316 317 String rootURL = RollerRuntimeConfig.getAbsoluteContextURL(); 319 if (rootURL == null || rootURL.trim().length()==0) { 320 rootURL = RequestUtils.serverURL(request) + request.getContextPath(); 321 } 322 sendEmailNotification(comment, rootURL); 323 324 cf = new WeblogEntryCommentForm(); 326 327 } catch (RollerException re) { 328 log.error("Error saving comment", re); 329 error = re.getMessage(); 330 } 331 } 332 333 334 if (error != null) 336 cf.setError(error); 337 if (message != null) 338 cf.setMessage(message); 339 request.setAttribute("commentForm", cf); 340 341 log.debug("comment processed, forwarding to "+dispatch_url); 342 RequestDispatcher dispatcher = 343 request.getRequestDispatcher(dispatch_url); 344 dispatcher.forward(request, response); 345 } 346 347 348 351 private void reindexEntry(WeblogEntryData entry) 352 throws RollerException { 353 354 IndexManager manager = RollerFactory.getRoller().getIndexManager(); 355 356 manager.removeEntryIndexOperation(entry); 358 359 if (entry.isPublished()) { 361 manager.addEntryIndexOperation(entry); 362 } 363 } 364 365 366 371 public static void sendEmailNotification(CommentData cd, String rootURL) { 372 373 ResourceBundle resources = ResourceBundle.getBundle("ApplicationResources"); 375 376 WeblogEntryData entry = cd.getWeblogEntry(); 377 WebsiteData site = entry.getWebsite(); 378 UserData user = entry.getCreator(); 379 380 boolean notify = RollerRuntimeConfig.getBooleanProperty("users.comments.emailnotify"); 382 if (notify && site.getEmailComments().booleanValue()) { 383 log.debug("Comment notification enabled ... preparing email"); 384 385 boolean separateMessages = 387 RollerConfig.getBooleanProperty("comment.notification.separateOwnerMessage"); 388 boolean hideCommenterAddrs = 389 RollerConfig.getBooleanProperty("comment.notification.hideCommenterAddresses"); 390 391 395 String from = 396 (StringUtils.isEmpty(site.getEmailFromAddress())) 397 ? user.getEmailAddress() 398 : site.getEmailFromAddress(); 399 400 403 List comments = null; 404 try { 405 WeblogManager wMgr = RollerFactory.getRoller().getWeblogManager(); 406 comments = entry.getComments(true, true); 408 } catch(RollerException re) { 409 comments = new ArrayList (); 411 } 412 413 Set subscribers = new TreeSet (); 415 for (Iterator it = comments.iterator(); it.hasNext();) { 416 CommentData comment = (CommentData) it.next(); 417 if (!StringUtils.isEmpty(comment.getEmail())) { 418 if (comment.getNotify().booleanValue()) { 421 if (comment.getEmail().matches(EMAIL_ADDR_REGEXP)) { 423 subscribers.add(comment.getEmail()); 424 } 425 } else { 426 subscribers.remove(comment.getEmail()); 428 } 429 } 430 } 431 432 String [] commenterAddrs = (String [])subscribers.toArray(new String [0]); 434 435 439 StringBuffer msg = new StringBuffer (); 441 StringBuffer ownermsg = new StringBuffer (); 442 boolean escapeHtml = RollerRuntimeConfig.getBooleanProperty("users.comments.escapehtml"); 443 444 if (!escapeHtml) { 445 msg.append("<html><body style=\"background: white; "); 446 msg.append(" color: black; font-size: 12px\">"); 447 } 448 449 if (!StringUtils.isEmpty(cd.getName())) { 450 msg.append(cd.getName() + " " 451 + resources.getString("email.comment.wrote")+": "); 452 } else { 453 msg.append(resources.getString("email.comment.anonymous")+": "); 454 } 455 456 msg.append((escapeHtml) ? "\n\n" : "<br /><br />"); 457 458 msg.append((escapeHtml) ? Utilities.escapeHTML(cd.getContent()) 459 : UtilitiesModel.transformToHTMLSubset(Utilities.escapeHTML(cd.getContent()))); 460 461 msg.append((escapeHtml) ? "\n\n----\n" 462 : "<br /><br /><hr /><span style=\"font-size: 11px\">"); 463 msg.append(resources.getString("email.comment.respond") + ": "); 464 msg.append((escapeHtml) ? "\n" : "<br />"); 465 466 StringBuffer commentURL = new StringBuffer (rootURL); 468 commentURL.append(entry.getPermaLink()); 469 commentURL.append("#comments"); 470 471 if (escapeHtml) { 472 msg.append(commentURL.toString()); 473 } else { 474 msg.append("<a HREF=\""+commentURL+"\">"+commentURL+"</a></span>"); 475 } 476 477 ownermsg.append(msg); 478 479 ownermsg.append((escapeHtml) ? "\n\n----\n" : 481 "<br /><br /><hr /><span style=\"font-size: 11px\">"); 482 ownermsg.append("Link to comment management page:"); 483 ownermsg.append((escapeHtml) ? "\n" : "<br />"); 484 485 StringBuffer deleteURL = new StringBuffer (rootURL); 486 deleteURL.append("/roller-ui/authoring/commentManagement.do?method=query&entryId=" + entry.getId()); 487 488 if (escapeHtml) { 489 ownermsg.append(deleteURL.toString()); 490 } else { 491 ownermsg.append( 492 "<a HREF=\"" + deleteURL + "\">" + deleteURL + "</a></span>"); 493 msg.append("</Body></html>"); 494 ownermsg.append("</Body></html>"); 495 } 496 497 String subject = null; 498 if ((subscribers.size() > 1) || 499 (StringUtils.equals(cd.getEmail(), user.getEmailAddress()))) { 500 subject= "RE: "+resources.getString("email.comment.title")+": "; 501 } else { 502 subject = resources.getString("email.comment.title") + ": "; 503 } 504 subject += entry.getTitle(); 505 506 try { 509 Context ctx = (Context ) 510 new InitialContext ().lookup("java:comp/env"); 511 Session session = (Session )ctx.lookup("mail/Session"); 512 boolean isHtml = !escapeHtml; 513 if (separateMessages) { 514 sendMessage(session, from, 516 new String []{user.getEmailAddress()}, null, null, subject, ownermsg.toString(), isHtml); 517 if (commenterAddrs.length > 0) { 518 String [] to = hideCommenterAddrs ? null : commenterAddrs; 520 String [] bcc = hideCommenterAddrs ? commenterAddrs : null; 521 sendMessage(session, from, to, null, bcc, subject, msg.toString(), isHtml); 522 523 } 524 } else { 525 String [] cc = hideCommenterAddrs ? null : commenterAddrs; 527 String [] bcc = hideCommenterAddrs ? commenterAddrs : null; 528 sendMessage(session, from, new String []{user.getEmailAddress()}, cc, bcc, subject, 529 ownermsg.toString(), isHtml); 530 } 531 } catch (NamingException ne) { 532 log.error("Unable to lookup mail session. Check configuration. NamingException: " + ne.getMessage()); 533 } catch (Exception e) { 534 log.warn("Exception sending comment mail: " + e.getMessage()); 535 if (log.isDebugEnabled()) { 537 log.debug(e); 538 } 539 } 540 541 log.debug("Done sending email message"); 542 543 } } 545 546 547 552 public static void sendEmailApprovalNotification(CommentData cd, String rootURL) { 553 554 ResourceBundle resources = ResourceBundle.getBundle("ApplicationResources"); 556 557 WeblogEntryData entry = cd.getWeblogEntry(); 558 WebsiteData site = entry.getWebsite(); 559 UserData user = entry.getCreator(); 560 561 boolean notify = RollerRuntimeConfig.getBooleanProperty("users.comments.emailnotify"); 563 if (notify && site.getEmailComments().booleanValue()) { 564 log.debug("Comment notification enabled ... preparing email"); 565 566 567 568 572 String from = 573 (StringUtils.isEmpty(site.getEmailFromAddress())) 574 ? user.getEmailAddress() 575 : site.getEmailFromAddress(); 576 577 580 String subject = resources.getString("email.comment.commentApproved"); 581 582 StringBuffer msg = new StringBuffer (); 583 msg.append(resources.getString("email.comment.commentApproved")); 584 585 StringBuffer commentURL = new StringBuffer (rootURL); 587 commentURL.append(entry.getPermaLink()); 588 commentURL.append("#comments"); 589 msg.append(commentURL.toString()); 590 591 try { 594 Context ctx = (Context ) 595 new InitialContext ().lookup("java:comp/env"); 596 Session session = (Session )ctx.lookup("mail/Session"); 597 String [] cc = null; 598 String [] bcc = null; 599 sendMessage(session, from, 600 new String [] {cd.getEmail()}, 601 null, null, subject, msg.toString(), false); 604 } catch (NamingException ne) { 605 log.error("Unable to lookup mail session. Check configuration. NamingException: " + ne.getMessage()); 606 } catch (Exception e) { 607 log.warn("Exception sending comment mail: " + e.getMessage()); 608 if (log.isDebugEnabled()) { 610 log.debug(e); 611 } 612 } 613 614 log.debug("Done sending email message"); 615 616 } } 618 619 620 624 static void sendMessage(Session session, String from, String [] to, String [] cc, String [] bcc, String subject, 625 String msg, boolean isHtml) throws MessagingException { 626 if (isHtml) 627 MailUtil.sendHTMLMessage(session, from, to, cc, bcc, subject, msg); 628 else 629 MailUtil.sendTextMessage(session, from, to, cc, bcc, subject, msg); 630 } 631 632 } 633 634 | Popular Tags |