You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by gh...@apache.org on 2013/07/30 13:38:12 UTC

svn commit: r1508393 - in /roller/trunk/app/src/main: java/org/apache/roller/weblogger/ui/rendering/servlets/ java/org/apache/roller/weblogger/util/ resources/ webapp/WEB-INF/jsps/admin/ webapp/WEB-INF/jsps/editor/ webapp/roller-ui/styles/

Author: ghuber
Date: Tue Jul 30 11:38:12 2013
New Revision: 1508393

URL: http://svn.apache.org/r1508393
Log:
UI testing

Modified:
    roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentServlet.java
    roller/trunk/app/src/main/java/org/apache/roller/weblogger/util/Utilities.java
    roller/trunk/app/src/main/resources/ApplicationResources.properties
    roller/trunk/app/src/main/webapp/WEB-INF/jsps/admin/GlobalCommentManagement.jsp
    roller/trunk/app/src/main/webapp/WEB-INF/jsps/editor/Comments.jsp
    roller/trunk/app/src/main/webapp/roller-ui/styles/roller.css

Modified: roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentServlet.java
URL: http://svn.apache.org/viewvc/roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentServlet.java?rev=1508393&r1=1508392&r2=1508393&view=diff
==============================================================================
--- roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentServlet.java (original)
+++ roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/CommentServlet.java Tue Jul 30 11:38:12 2013
@@ -16,7 +16,7 @@
  * directory of this distribution.
  */
 
-package org.apache.roller.weblogger.ui.rendering.servlets;  
+package org.apache.roller.weblogger.ui.rendering.servlets;
 
 import java.io.IOException;
 import java.sql.Timestamp;
@@ -53,93 +53,102 @@ import org.apache.roller.weblogger.util.
 import org.apache.roller.weblogger.util.Utilities;
 import org.apache.roller.weblogger.util.cache.CacheManager;
 
-
 /**
  * The CommentServlet handles all incoming weblog entry comment posts.
- *
- * We validate each incoming comment based on various comment settings and
- * if all checks are passed then the comment is saved.
- *
- * Incoming comments are tested against the MT Blacklist. If they are found
- * to be spam, then they are marked as spam and hidden from view.
- *
- * If email notification is turned on, each new comment will result in an
- * email sent to the blog owner and all who have commented on the same post.
+ * 
+ * We validate each incoming comment based on various comment settings and if
+ * all checks are passed then the comment is saved.
+ * 
+ * Incoming comments are tested against the MT Blacklist. If they are found to
+ * be spam, then they are marked as spam and hidden from view.
+ * 
+ * If email notification is turned on, each new comment will result in an email
+ * sent to the blog owner and all who have commented on the same post.
  */
 public class CommentServlet extends HttpServlet {
-    
+
     private static Log log = LogFactory.getLog(CommentServlet.class);
-    
-    private CommentAuthenticator     authenticator = null;
+
+    private CommentAuthenticator authenticator = null;
     private CommentValidationManager commentValidationManager = null;
-    private GenericThrottle          commentThrottle = null;
-    
-    
+    private GenericThrottle commentThrottle = null;
+
     /**
      * Initialization.
      */
     @Override
     public void init(ServletConfig servletConfig) throws ServletException {
-        
+
         super.init(servletConfig);
-        
+
         log.info("Initializing CommentServlet");
-        
+
         // lookup the authenticator we are going to use and instantiate it
         try {
-            String name = WebloggerConfig.getProperty("comment.authenticator.classname");
+            String name = WebloggerConfig
+                    .getProperty("comment.authenticator.classname");
             Class clazz = Class.forName(name);
             this.authenticator = (CommentAuthenticator) clazz.newInstance();
-        } catch(Exception e) {
+        } catch (Exception e) {
             log.error(e);
             this.authenticator = new DefaultCommentAuthenticator();
         }
-        
+
         // instantiate a comment validation manager for comment spam checking
         commentValidationManager = new CommentValidationManager();
-        
+
         // instantiate a comment format manager for comment formatting
-        String fmtrs = WebloggerConfig.getProperty("comment.formatter.classnames");
+        String fmtrs = WebloggerConfig
+                .getProperty("comment.formatter.classnames");
         String[] formatters = Utilities.stringToStringArray(fmtrs, ",");
-        
+
         // are we doing throttling?
-        if(WebloggerConfig.getBooleanProperty("comment.throttle.enabled")) {
-            
+        if (WebloggerConfig.getBooleanProperty("comment.throttle.enabled")) {
+
             int threshold = 25;
             try {
-                threshold = Integer.parseInt(WebloggerConfig.getProperty("comment.throttle.threshold"));
-            } catch(Exception e) {
-                log.warn("bad input for config property comment.throttle.threshold", e);
+                threshold = Integer.parseInt(WebloggerConfig
+                        .getProperty("comment.throttle.threshold"));
+            } catch (Exception e) {
+                log.warn(
+                        "bad input for config property comment.throttle.threshold",
+                        e);
             }
-            
+
             int interval = 60000;
             try {
-                interval = Integer.parseInt(WebloggerConfig.getProperty("comment.throttle.interval"));
+                interval = Integer.parseInt(WebloggerConfig
+                        .getProperty("comment.throttle.interval"));
                 // convert from seconds to milliseconds
                 interval = interval * 1000;
-            } catch(Exception e) {
-                log.warn("bad input for config property comment.throttle.interval", e);
+            } catch (Exception e) {
+                log.warn(
+                        "bad input for config property comment.throttle.interval",
+                        e);
             }
-            
+
             int maxEntries = 250;
             try {
-                maxEntries = Integer.parseInt(WebloggerConfig.getProperty("comment.throttle.maxentries"));
-            } catch(Exception e) {
-                log.warn("bad input for config property comment.throttle.maxentries", e);
+                maxEntries = Integer.parseInt(WebloggerConfig
+                        .getProperty("comment.throttle.maxentries"));
+            } catch (Exception e) {
+                log.warn(
+                        "bad input for config property comment.throttle.maxentries",
+                        e);
             }
-            
-            commentThrottle = new GenericThrottle(threshold, interval, maxEntries);
-            
+
+            commentThrottle = new GenericThrottle(threshold, interval,
+                    maxEntries);
+
             log.info("Comment Throttling ENABLED");
         } else {
             log.info("Comment Throttling DISABLED");
         }
     }
-    
-    
+
     /**
      * Handle incoming http GET requests.
-     *
+     * 
      * The CommentServlet does not support GET requests, it's a 404.
      */
     @Override
@@ -147,27 +156,26 @@ public class CommentServlet extends Http
             throws IOException, ServletException {
         response.sendError(HttpServletResponse.SC_NOT_FOUND);
     }
-    
-    
+
     /**
      * Service incoming POST requests.
-     *
+     * 
      * Here we handle incoming comment postings.
      */
     @Override
     public void doPost(HttpServletRequest request, HttpServletResponse response)
             throws IOException, ServletException {
-        
+
         String error = null;
         String dispatch_url = null;
-        
+
         Weblog weblog = null;
         WeblogEntry entry = null;
-        
+
         String message = null;
         RollerMessages messages = new RollerMessages();
-        
-        // are we doing a preview?  or a post?
+
+        // are we doing a preview? or a post?
         String method = request.getParameter("method");
         final boolean preview;
         if (method != null && method.equals("preview")) {
@@ -178,54 +186,54 @@ public class CommentServlet extends Http
             preview = false;
             log.debug("Handling regular comment post");
         }
-        
+
         // throttling protection against spammers
-        if(commentThrottle != null &&
-                commentThrottle.processHit(request.getRemoteAddr())) {
-            
-            log.debug("ABUSIVE "+request.getRemoteAddr());
+        if (commentThrottle != null
+                && commentThrottle.processHit(request.getRemoteAddr())) {
+
+            log.debug("ABUSIVE " + request.getRemoteAddr());
             IPBanList.getInstance().addBannedIp(request.getRemoteAddr());
             response.sendError(HttpServletResponse.SC_NOT_FOUND);
             return;
         }
-        
+
         WeblogCommentRequest commentRequest = null;
         try {
             commentRequest = new WeblogCommentRequest(request);
-            
+
             // lookup weblog specified by comment request
             weblog = WebloggerFactory.getWeblogger().getWeblogManager()
                     .getWeblogByHandle(commentRequest.getWeblogHandle());
-            
-            if(weblog == null) {
-                throw new WebloggerException("unable to lookup weblog: "+
-                        commentRequest.getWeblogHandle());
+
+            if (weblog == null) {
+                throw new WebloggerException("unable to lookup weblog: "
+                        + commentRequest.getWeblogHandle());
             }
-            
+
             // lookup entry specified by comment request
             entry = commentRequest.getWeblogEntry();
-            if(entry == null) {
-                throw new WebloggerException("unable to lookup entry: "+
-                        commentRequest.getWeblogAnchor());
+            if (entry == null) {
+                throw new WebloggerException("unable to lookup entry: "
+                        + commentRequest.getWeblogAnchor());
             }
-            
+
             // we know what the weblog entry is, so setup our urls
-            dispatch_url = "/roller-ui/rendering/page/"+weblog.getHandle();
-            if(commentRequest.getLocale() != null) {
-                dispatch_url += "/"+commentRequest.getLocale();
+            dispatch_url = "/roller-ui/rendering/page/" + weblog.getHandle();
+            if (commentRequest.getLocale() != null) {
+                dispatch_url += "/" + commentRequest.getLocale();
             }
-            dispatch_url += "/entry/"+URLUtilities.encode(commentRequest.getWeblogAnchor());
-            
+            dispatch_url += "/entry/"
+                    + URLUtilities.encode(commentRequest.getWeblogAnchor());
+
         } catch (Exception e) {
             // some kind of error parsing the request or looking up weblog
             log.debug("error creating page request", e);
             response.sendError(HttpServletResponse.SC_NOT_FOUND);
             return;
         }
-        
-        
-        log.debug("Doing comment posting for entry = "+entry.getPermalink());
-        
+
+        log.debug("Doing comment posting for entry = " + entry.getPermalink());
+
         // collect input from request params and construct new comment object
         // fields: name, email, url, content, notify
         // TODO: data validation on collected comment data
@@ -238,128 +246,152 @@ public class CommentServlet extends Http
         comment.setWeblogEntry(entry);
         comment.setRemoteHost(request.getRemoteHost());
         comment.setPostTime(new Timestamp(System.currentTimeMillis()));
-        
+
         // set comment content-type depending on if html is allowed
-        if(WebloggerRuntimeConfig.getBooleanProperty("users.comments.htmlenabled")) {
+        if (WebloggerRuntimeConfig
+                .getBooleanProperty("users.comments.htmlenabled")) {
             comment.setContentType("text/html");
         } else {
             comment.setContentType("text/plain");
         }
-        
+
         // set whatever comment plugins are configured
-        comment.setPlugins(WebloggerRuntimeConfig.getProperty("users.comments.plugins"));
-        
+        comment.setPlugins(WebloggerRuntimeConfig
+                .getProperty("users.comments.plugins"));
+
         WeblogEntryCommentForm cf = new WeblogEntryCommentForm();
         cf.setData(comment);
         if (preview) {
             cf.setPreview(comment);
         }
-        
-        I18nMessages messageUtils = I18nMessages.getMessages(commentRequest.getLocaleInstance());
-        
+
+        I18nMessages messageUtils = I18nMessages.getMessages(commentRequest
+                .getLocaleInstance());
+
         // check if comments are allowed for this entry
         // this checks site-wide settings, weblog settings, and entry settings
-        if(!entry.getCommentsStillAllowed() || !entry.isPublished()) {
+        if (!entry.getCommentsStillAllowed() || !entry.isPublished()) {
             error = messageUtils.getString("comments.disabled");
-            
-        // if this is a real comment post then authenticate request
-        } else if(!preview && !this.authenticator.authenticate(request)) {
-            error = messageUtils.getString("error.commentAuthFailed");
+
+            // if there is an email it must be valid
+        } else if (commentRequest.getEmail() != null
+                && !Utilities.isValidEmailAddress(commentRequest.getEmail())) {
+            error = messageUtils
+                    .getString("error.commentPostFailedEmailAddress");
+            log.debug("Email Adddress is invalid : "
+                    + commentRequest.getEmail());
+            // if this is a real comment post then authenticate request
+        } else if (!preview && !this.authenticator.authenticate(request)) {
+            String[] msg = { request.getParameter("answer") };
+            error = messageUtils.getString(
+                    "error.commentAuthFailed", msg);
             log.debug("Comment failed authentication");
         }
-        
+
         // bail now if we have already found an error
-        if(error != null) {
+        if (error != null) {
             cf.setError(error);
             request.setAttribute("commentForm", cf);
-            RequestDispatcher dispatcher = request.getRequestDispatcher(dispatch_url);
+            RequestDispatcher dispatcher = request
+                    .getRequestDispatcher(dispatch_url);
             dispatcher.forward(request, response);
             return;
         }
-        
-        int validationScore = commentValidationManager.validateComment(comment, messages);
+
+        int validationScore = commentValidationManager.validateComment(comment,
+                messages);
         log.debug("Comment Validation score: " + validationScore);
-        
+
         if (!preview) {
-            
+
             if (validationScore == 100 && weblog.getCommentModerationRequired()) {
                 // Valid comments go into moderation if required
                 comment.setStatus(WeblogEntryComment.PENDING);
-                message = messageUtils.getString("commentServlet.submittedToModerator");
+                message = messageUtils
+                        .getString("commentServlet.submittedToModerator");
             } else if (validationScore == 100) {
                 // else they're approved
                 comment.setStatus(WeblogEntryComment.APPROVED);
-                message = messageUtils.getString("commentServlet.commentAccepted");
+                message = messageUtils
+                        .getString("commentServlet.commentAccepted");
             } else {
                 // Invalid comments are marked as spam
                 log.debug("Comment marked as spam");
                 comment.setStatus(WeblogEntryComment.SPAM);
-                error = messageUtils.getString("commentServlet.commentMarkedAsSpam");
-                
+                error = messageUtils
+                        .getString("commentServlet.commentMarkedAsSpam");
+
                 // add specific error messages if they exist
-                if(messages.getErrorCount() > 0) {
+                if (messages.getErrorCount() > 0) {
                     Iterator errors = messages.getErrors();
                     RollerMessage errorKey = null;
-                    
+
                     StringBuilder buf = new StringBuilder();
                     buf.append("<ul>");
-                    while(errors.hasNext()) {
-                        errorKey = (RollerMessage)errors.next();
-                        
+                    while (errors.hasNext()) {
+                        errorKey = (RollerMessage) errors.next();
+
                         buf.append("<li>");
-                        if(errorKey.getArgs() != null) {
-                            buf.append(messageUtils.getString(errorKey.getKey(), errorKey.getArgs()));
+                        if (errorKey.getArgs() != null) {
+                            buf.append(messageUtils.getString(
+                                    errorKey.getKey(), errorKey.getArgs()));
                         } else {
                             buf.append(messageUtils.getString(errorKey.getKey()));
                         }
                         buf.append("</li>");
                     }
                     buf.append("</ul>");
-                    
+
                     error += buf.toString();
                 }
-                
+
             }
-            
-            try {               
-                if(!WeblogEntryComment.SPAM.equals(comment.getStatus()) ||
-                        !WebloggerRuntimeConfig.getBooleanProperty("comments.ignoreSpam.enabled")) {
-                    
-                    WeblogEntryManager mgr = WebloggerFactory.getWeblogger().getWeblogEntryManager();
+
+            try {
+                if (!WeblogEntryComment.SPAM.equals(comment.getStatus())
+                        || !WebloggerRuntimeConfig
+                                .getBooleanProperty("comments.ignoreSpam.enabled")) {
+
+                    WeblogEntryManager mgr = WebloggerFactory.getWeblogger()
+                            .getWeblogEntryManager();
                     mgr.saveComment(comment);
                     WebloggerFactory.getWeblogger().flush();
-                    
-                    // Send email notifications only to subscribers if comment is 100% valid
+
+                    // Send email notifications only to subscribers if comment
+                    // is 100% valid
                     boolean notifySubscribers = (validationScore == 100);
-                    MailUtil.sendEmailNotification(comment, messages, messageUtils, notifySubscribers);
-                    
-                    // only re-index/invalidate the cache if comment isn't moderated
-                    if(!weblog.getCommentModerationRequired()) {
-                        IndexManager manager = WebloggerFactory.getWeblogger().getIndexManager();
-                        
-                        // remove entry before (re)adding it, or in case it isn't Published
+                    MailUtil.sendEmailNotification(comment, messages,
+                            messageUtils, notifySubscribers);
+
+                    // only re-index/invalidate the cache if comment isn't
+                    // moderated
+                    if (!weblog.getCommentModerationRequired()) {
+                        IndexManager manager = WebloggerFactory.getWeblogger()
+                                .getIndexManager();
+
+                        // remove entry before (re)adding it, or in case it
+                        // isn't Published
                         manager.removeEntryIndexOperation(entry);
-                        
+
                         // if published, index the entry
                         if (entry.isPublished()) {
                             manager.addEntryIndexOperation(entry);
                         }
-                        
+
                         // Clear all caches associated with comment
                         CacheManager.invalidate(comment);
                     }
-                    
+
                     // comment was successful, clear the comment form
                     cf = new WeblogEntryCommentForm();
                 }
-                
+
             } catch (WebloggerException re) {
                 log.error("Error saving comment", re);
                 error = re.getMessage();
             }
         }
-        
-        
+
         // the work has been done, now send the user back to the entry page
         if (error != null) {
             cf.setError(error);
@@ -368,11 +400,11 @@ public class CommentServlet extends Http
             cf.setMessage(message);
         }
         request.setAttribute("commentForm", cf);
-        
-        log.debug("comment processed, forwarding to "+dispatch_url);
-        RequestDispatcher dispatcher =
-                request.getRequestDispatcher(dispatch_url);
+
+        log.debug("comment processed, forwarding to " + dispatch_url);
+        RequestDispatcher dispatcher = request
+                .getRequestDispatcher(dispatch_url);
         dispatcher.forward(request, response);
     }
-    
+
 }

Modified: roller/trunk/app/src/main/java/org/apache/roller/weblogger/util/Utilities.java
URL: http://svn.apache.org/viewvc/roller/trunk/app/src/main/java/org/apache/roller/weblogger/util/Utilities.java?rev=1508393&r1=1508392&r2=1508393&view=diff
==============================================================================
--- roller/trunk/app/src/main/java/org/apache/roller/weblogger/util/Utilities.java (original)
+++ roller/trunk/app/src/main/java/org/apache/roller/weblogger/util/Utilities.java Tue Jul 30 11:38:12 2013
@@ -26,6 +26,9 @@ import java.util.regex.Pattern;
 
 import javax.activation.FileTypeMap;
 import javax.activation.MimetypesFileTypeMap;
+import javax.mail.internet.AddressException;
+import javax.mail.internet.InternetAddress;
+
 import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
@@ -1039,4 +1042,49 @@ public class Utilities {
         return map.getContentType(fileName);
     }
     
+    /**
+     * Validate the form of an email address.
+     * 
+     * <P>
+     * Return <tt>true</tt> only if
+     * <ul>
+     * <li> <tt>aEmailAddress</tt> can successfully construct an
+     * {@link javax.mail.internet.InternetAddress}
+     * <li>when parsed with "@" as delimiter, <tt>aEmailAddress</tt> contains
+     * two tokens which satisfy
+     * </ul>
+     * <P>
+     * The second condition arises since local email addresses, simply of the
+     * form "<tt>albert</tt>", for example, are valid for
+     * {@link javax.mail.internet.InternetAddress}, but almost always undesired.
+     */
+    public static boolean isValidEmailAddress(String aEmailAddress) {
+        if (aEmailAddress == null)
+            return false;
+        boolean result = true;
+        try {
+            // See if its valid
+            new InternetAddress(aEmailAddress);
+            if (!hasNameAndDomain(aEmailAddress)) {
+                result = false;
+            }
+        } catch (AddressException ex) {
+            result = false;
+        }
+        return result;
+    }
+    
+    /**
+     * Checks for name and domain.
+     * 
+     * @param aEmailAddress
+     *            the a email address
+     * @return true, if successful
+     */
+    private static boolean hasNameAndDomain(String aEmailAddress) {
+        String[] tokens = aEmailAddress.split("@");
+        return tokens.length == 2 && StringUtils.isNotEmpty(tokens[0])
+                && StringUtils.isNotEmpty(tokens[1]);
+    }
+    
 }

Modified: roller/trunk/app/src/main/resources/ApplicationResources.properties
URL: http://svn.apache.org/viewvc/roller/trunk/app/src/main/resources/ApplicationResources.properties?rev=1508393&r1=1508392&r2=1508393&view=diff
==============================================================================
--- roller/trunk/app/src/main/resources/ApplicationResources.properties (original)
+++ roller/trunk/app/src/main/resources/ApplicationResources.properties Tue Jul 30 11:38:12 2013
@@ -225,7 +225,9 @@ comments.mathAuthenticatorQuestion=Pleas
 comments.ldapAuthenticatorUserName=Please provide your Active Directory Username.
 comments.ldapAuthenticatorPassword=Please provide your Active Directory Password.
 # end not translated!
-error.commentAuthFailed=Comment authentication failed!
+
+error.commentAuthFailed=The response {0} is not correct.  Please try again.
+error.commentPostFailedEmailAddress=The e-mail address is invalid.
 
 # -------------------------------------------------------- comment validators
 
@@ -318,7 +320,8 @@ commentManagement.searchString=Search st
 commentManagement.sidebarTitle=Filter comments
 commentManagement.sidebarDescription=Filter comments by search string, status, and/or date
 
-commentManagement.commentBy=Posted by 
+commentManagement.commentBy=Posted by
+commentManagement.commentByURL=Posted url
 commentManagement.commentByBoth={0} (<a href="mailto:{1}">{2}</a>) from IP address {3}
 commentManagement.commentByName={0} from IP address {1}
 commentManagement.commentByIP=User from IP address {0}

Modified: roller/trunk/app/src/main/webapp/WEB-INF/jsps/admin/GlobalCommentManagement.jsp
URL: http://svn.apache.org/viewvc/roller/trunk/app/src/main/webapp/WEB-INF/jsps/admin/GlobalCommentManagement.jsp?rev=1508393&r1=1508392&r2=1508393&view=diff
==============================================================================
--- roller/trunk/app/src/main/webapp/WEB-INF/jsps/admin/GlobalCommentManagement.jsp (original)
+++ roller/trunk/app/src/main/webapp/WEB-INF/jsps/admin/GlobalCommentManagement.jsp Tue Jul 30 11:38:12 2013
@@ -253,72 +253,75 @@ function handleCommentResponse() {
     </s:else>
     
     <%-- comment details table in table --%>
-    <table style="border:none; padding:0px; margin:0px">                         
+    <table class="innertable" >
         <tr>
-            <td style="border: none; padding:0px;">
-            <s:text name="commentManagement.entryTitled" /></td>
-            <td class="details" style="border: none; padding:0px;">  
-                <a href='<s:property value="#comment.weblogEntry.permalink" />'>
-                <s:property value="#comment.weblogEntry.title" /></a>
+            <td class="viewbody">
+                <div class="viewdetails bot">
+                    <div class="details">
+                        <s:text name="commentManagement.entryTitled" />&nbsp;:&nbsp;
+                        <a href='<s:property value="#comment.weblogEntry.permalink" />'><s:property value="#comment.weblogEntry.title" /></a>
+                    </div>
+                    <div class="details">
+                        <s:text name="commentManagement.commentBy" />&nbsp;:&nbsp;
+                        <s:if test="#comment.email != null && #comment.name != null">
+                            <s:text name="commentManagement.commentByBoth" >
+                                <s:param><s:property value="#comment.name" /></s:param>
+                                <s:param><s:property value="#comment.email" /></s:param>
+                                <s:param><s:property value="#comment.email" /></s:param>
+                                <s:param><s:property value="#comment.remoteHost" /></s:param>
+                            </s:text>
+                        </s:if>
+                        <s:elseif test="#comment.email == null && #comment.name == null">
+                            <s:text name="commentManagement.commentByIP" >
+                                <s:param><s:property value="#comment.remoteHost" /></s:param>
+                            </s:text>
+                        </s:elseif>
+                        <s:else>
+                            <s:text name="commentManagement.commentByName" >
+                                <s:param><s:property value="#comment.name" /></s:param>
+                                <s:param><s:property value="#comment.remoteHost" /></s:param>
+                            </s:text>
+                        </s:else>
+                    </div>
+                    <s:if test="#comment.url != null && !#comment.url.equals('')">
+                        <div class="details">
+                            <s:text name="commentManagement.commentByURL" />&nbsp;:&nbsp;
+                            <a href='<s:property value="#comment.url" />'>
+                            <str:truncateNicely upper="60" appendToEnd="..."><s:property value="#comment.url" /></str:truncateNicely></a>
+                        </div>
+                    </s:if>
+                    <div class="details">
+                        <s:text name="commentManagement.postTime" />&nbsp;:&nbsp;
+                        <s:property value="#comment.postTime" />
+                    </div>
+                </div>
+                <div class="viewdetails bot">
+                    <div class="details">
+                        <%-- comment content --%>
+                        <s:if test="#comment.content.length() > 1000">
+                            <div class="bot" id="comment-<s:property value="#comment.id"/>">
+                                <str:wordWrap width="72">
+                                    <str:truncateNicely upper="1000" appendToEnd="...">
+                                        <s:property value="#comment.content" escape="true" />
+                                    </str:truncateNicely>
+                                </str:wordWrap>
+                            </div>
+                            <div id="link-<s:property value="#comment.id"/>">
+                                <a onclick='readMoreComment("<s:property value="#comment.id"/>")'>
+                                    <s:text name="commentManagement.readmore" />
+                                </a>
+                            </div>
+                        </s:if>
+                        <s:else>
+                            <str:wordWrap>
+                                <s:property value="#comment.content" escape="true" />
+                            </str:wordWrap>
+                        </s:else>
+                    </div>
+                </div>
             </td>
-        </tr>  
-        
-        <tr>
-            <td style="border: none; padding:0px;">
-            <s:text name="commentManagement.commentBy" /></td>
-            <td class="details" style="border: none; padding:0px;">
-                <s:if test="#comment.email != null && #comment.name != null">
-                    <s:text name="commentManagement.commentByBoth" >
-                        <s:param><s:property value="#comment.name" /></s:param>
-                        <s:param><s:property value="#comment.email" /></s:param>
-                        <s:param><s:property value="#comment.email" /></s:param>
-                        <s:param><s:property value="#comment.remoteHost" /></s:param>
-                    </s:text>
-                </s:if>
-                <s:elseif test="#comment.email == null && #comment.name == null">
-                    <s:text name="commentManagement.commentByIP" >
-                        <s:param><s:property value="#comment.remoteHost" /></s:param>
-                    </s:text>
-                </s:elseif>
-                <s:else>
-                    <s:text name="commentManagement.commentByName" >
-                        <s:param><s:property value="#comment.name" /></s:param>
-                        <s:param><s:property value="#comment.remoteHost" /></s:param>
-                    </s:text>
-                </s:else>
-                
-                <s:if test="#comment.url != null">
-                    <br /><a href='<s:property value="#comment.url" />'>
-                    <str:truncateNicely upper="60" appendToEnd="..."><s:property value="#comment.url" /></str:truncateNicely></a>
-                </s:if>
-            </td>
-        </tr>                                
-        <tr>
-            <td style="border: none; padding:0px;">
-            <s:text name="commentManagement.postTime" /></td>
-            <td class="details" style="border: none; padding:0px;">
-            <s:property value="#comment.postTime" /></td>
-        </tr>                                       
+        </tr>
     </table> <%-- end comment details table in table --%>
-                
-    <%-- comment content --%>
-    <br />
-    <span class="details">
-        
-    <s:if test="#comment.content.length() > 1000">
-        <pre><div id="comment-<s:property value="#comment.id"/>"><str:wordWrap width="72"><str:truncateNicely upper="1000" appendToEnd="..."><s:property value="#comment.content" escape="true" /></str:truncateNicely></str:wordWrap></div></pre>                                    
-        <div id="link-<s:property value="#comment.id"/>">
-            <a onclick='readMoreComment("<s:property value="#comment.id"/>")'>
-                <s:text name="commentManagement.readmore" />
-            </a>
-        </div>
-    </s:if>
-    <s:else>
-        <pre><str:wordWrap><s:property value="#comment.content" escape="true" /></str:wordWrap></pre>   
-    </s:else>
-        
-    </span>
-    
     </td>
 </tr>
 </s:iterator>

Modified: roller/trunk/app/src/main/webapp/WEB-INF/jsps/editor/Comments.jsp
URL: http://svn.apache.org/viewvc/roller/trunk/app/src/main/webapp/WEB-INF/jsps/editor/Comments.jsp?rev=1508393&r1=1508392&r2=1508393&view=diff
==============================================================================
--- roller/trunk/app/src/main/webapp/WEB-INF/jsps/editor/Comments.jsp (original)
+++ roller/trunk/app/src/main/webapp/WEB-INF/jsps/editor/Comments.jsp Tue Jul 30 11:38:12 2013
@@ -238,95 +238,84 @@
                     </s:elseif>
                     <s:else>
                         <td>
-                        </s:else>
+                    </s:else>
 
                         <%-- comment details table in table --%>
-                        <table style="border:none; padding:0px; margin:0px">
+                        <table class="innertable" >
                             <tr>
-                                <td style="border: none; padding:0px;">
-                                <s:text name="commentManagement.entryTitled" /></td>
-                                <td class="details" style="border: none; padding:0px;">
-                                    <a href='<s:property value="#comment.weblogEntry.permalink" />'>
-                                    <s:property value="#comment.weblogEntry.title" /></a>
-                                </td>
-                            </tr>
-
-                            <tr>
-                                <td style="border: none; padding:0px;">
-                                <s:text name="commentManagement.commentBy" /></td>
-                                <td class="details" style="border: none; padding:0px;">
-                                    <s:if test="#comment.email != null && #comment.name != null">
+                                <td class="viewbody">
+                                <div class="viewdetails bot">
+                                    <div class="details">
+                                        <s:text name="commentManagement.entryTitled" />&nbsp;:&nbsp;
+                                        <a href='<s:property value="#comment.weblogEntry.permalink" />'>
+                                        <s:property value="#comment.weblogEntry.title" /></a>
+                                    </div>
+                                    <div class="details">
+                                        <s:text name="commentManagement.commentBy" />&nbsp;:&nbsp;
+                                        <s:if test="#comment.email != null && #comment.name != null">
                                         <s:text name="commentManagement.commentByBoth" >
                                             <s:param><s:property value="#comment.name" /></s:param>
                                             <s:param><s:property value="#comment.email" /></s:param>
                                             <s:param><s:property value="#comment.email" /></s:param>
                                             <s:param><s:property value="#comment.remoteHost" /></s:param>
                                         </s:text>
+                                        </s:if>
+                                        <s:elseif test="#comment.email == null && #comment.name == null">
+                                            <s:text name="commentManagement.commentByIP" >
+                                                <s:param><s:property value="#comment.remoteHost" /></s:param>
+                                            </s:text>
+                                        </s:elseif>
+                                        <s:else>
+                                            <s:text name="commentManagement.commentByName" >
+                                                <s:param><s:property value="#comment.name" /></s:param>
+                                                <s:param><s:property value="#comment.remoteHost" /></s:param>
+                                            </s:text>
+                                        </s:else>
+                                    </div>
+                                    <s:if test="#comment.url != null && !#comment.url.equals('')">
+                                        <div class="details">
+                                            <s:text name="commentManagement.commentByURL" />&nbsp;:&nbsp;
+                                            <a href='<s:property value="#comment.url" />'>
+                                            <str:truncateNicely upper="60" appendToEnd="..."><s:property value="#comment.url" /></str:truncateNicely></a>
+                                        </div>
                                     </s:if>
-                                    <s:elseif test="#comment.email == null && #comment.name == null">
-                                        <s:text name="commentManagement.commentByIP" >
-                                            <s:param><s:property value="#comment.remoteHost" /></s:param>
-                                        </s:text>
-                                    </s:elseif>
-                                    <s:else>
-                                        <s:text name="commentManagement.commentByName" >
-                                            <s:param><s:property value="#comment.name" /></s:param>
-                                            <s:param><s:property value="#comment.remoteHost" /></s:param>
-                                        </s:text>
-                                    </s:else>
-
-                                    <s:if test="#comment.url != null">
-                                        <br /><a href='<s:property value="#comment.url" />'>
-                                        <str:truncateNicely upper="60" appendToEnd="..."><s:property value="#comment.url" /></str:truncateNicely></a>
-                                    </s:if>
-                                </td>
-                            </tr>
-                            <tr>
-                                <td style="border: none; padding:0px;">
-                                <s:text name="commentManagement.postTime" /></td>
-                                <td class="details" style="border: none; padding:0px;">
-                                <s:property value="#comment.postTime" /></td>
+                                    <div class="details">
+                                        <s:text name="commentManagement.postTime" />&nbsp;:&nbsp;
+                                        <s:property value="#comment.postTime" />
+                                    </div>
+                                </div>
+                                <div class="viewdetails bot">
+                                     <div class="details bot">
+                                          <s:if test="#comment.content.length() > 1000">
+                                               <div class="bot" id="comment-<s:property value="#comment.id"/>">
+                                                   <str:truncateNicely upper="1000" appendToEnd="...">
+                                                       <s:property value="#comment.content" escape="true" />
+                                                   </str:truncateNicely>
+                                               </div>
+                                               <div id="link-<s:property value="#comment.id"/>">
+                                                    <a onclick='readMoreComment("<s:property value="#comment.id"/>")'><s:text name="commentManagement.readmore" /></a>
+                                               </div>
+                                          </s:if>
+                                          <s:else>
+                                               <span width="200px" id="comment-<s:property value="#comment.id"/>"><s:property value="#comment.content" escape="true" /></span>
+                                          </s:else>
+                                     </div>
+                                     <div class="details">
+                                          <a id="editlink-<s:property value="#comment.id"/>" onclick='editComment("<s:property value="#comment.id"/>")'>
+                                               <s:text name="commentManagement.editComment" />
+                                          </a>
+                                     </div>
+                                     <div class="details">
+                                          <span id="savelink-<s:property value="#comment.id"/>" style="display: none">
+                                               <a onclick='saveComment("<s:property value="#comment.id"/>")'><s:text name="commentManagement.saveComment" /></a> &nbsp;|&nbsp;
+                                          </span>
+                                          <span id="cancellink-<s:property value="#comment.id"/>" style="display: none">
+                                               <a onclick='editCommentCancel("<s:property value="#comment.id"/>")'><s:text name="commentManagement.cancelComment" /></a>
+                                          </span>
+                                      </div>
+                                </div>
                             </tr>
                         </table> <%-- end comment details table in table --%>
-
-                        <%-- comment content --%>
-                        <br />
-                        <span class="details">
-
-                            <s:if test="#comment.content.length() > 1000">
-                                <span id="comment-<s:property value="#comment.id"/>"><str:truncateNicely upper="1000" appendToEnd="..."><s:property value="#comment.content" escape="true" /></str:truncateNicely></span>
-                                <div id="link-<s:property value="#comment.id"/>">
-                                    <a onclick='readMoreComment("<s:property value="#comment.id"/>")'>
-                                        <s:text name="commentManagement.readmore" />
-                                    </a>
-                                </div>
-                            </s:if>
-                            <s:else>
-                                <span width="200px" id="comment-<s:property value="#comment.id"/>"><s:property value="#comment.content" escape="true" /></span>
-                            </s:else>
-
-                        <br />
-                        <br />
-                            <div>
-                                <a id="editlink-<s:property value="#comment.id"/>" onclick='editComment("<s:property value="#comment.id"/>")'>
-                                    <s:text name="commentManagement.editComment" />
-                                </a>
-                            </div>
-
-                            <span id="savelink-<s:property value="#comment.id"/>" style="display: none">
-                                <a onclick='saveComment("<s:property value="#comment.id"/>")'>
-                                    <s:text name="commentManagement.saveComment" />
-                                </a> &nbsp;|&nbsp;
-                            </span>
-                            
-                            <span id="cancellink-<s:property value="#comment.id"/>" style="display: none">
-                                <a onclick='editCommentCancel("<s:property value="#comment.id"/>")'>
-                                    <s:text name="commentManagement.cancelComment" />
-                                </a>
-                            </span>
-
-                        </span>
-
                     </td>
                 </tr>
             </s:iterator>

Modified: roller/trunk/app/src/main/webapp/roller-ui/styles/roller.css
URL: http://svn.apache.org/viewvc/roller/trunk/app/src/main/webapp/roller-ui/styles/roller.css?rev=1508393&r1=1508392&r2=1508393&view=diff
==============================================================================
--- roller/trunk/app/src/main/webapp/roller-ui/styles/roller.css (original)
+++ roller/trunk/app/src/main/webapp/roller-ui/styles/roller.css Tue Jul 30 11:38:12 2013
@@ -278,6 +278,11 @@ table.rollertable {
     border-collapse: collapse;
     width: 100%;
 }
+table.innertable {
+    border-collapse: collapse;
+    width: 100%;
+    margin-bottom: 0;
+}
 table.rollertable th {
     border: 1px solid #ccc;
     font-size: 110%;
@@ -292,9 +297,24 @@ table.rollertable td, table.rollertable 
 table.rollertable tbody td {
     padding: 3px;
 }
+table.innertable tbody td {
+    padding: 0;
+}
 table.rollertable td.center {
     text-align: center;
 }
+table.rollertable .innertable td {
+	border: none;
+}
+table.innertable td.viewbody {
+	padding: 5px;
+}
+table.innertable tr .bot {
+	margin-bottom: 5px;
+}
+table.innertable tr .viewbody .bot {
+	padding-bottom: 10px;
+}
 td.field span.fixedAttr {
     font-style: italic;
     font-weight: bold;
@@ -528,6 +548,13 @@ div.controlToggle {
     width: 100%;
     height: 25px;
 }
+div.viewdetails {
+    border: 1px dotted #CCCCCC;
+    color: #000000;
+    margin-left: 5px;
+    margin-right: 5px;
+    padding: 5px 5px 5px 7px;
+}
 .control input {
     margin: 0.3em;
 }