[jboss-cvs] JBossBlog SVN: r322 - in trunk: src/action/org/jboss/blog/session/tools and 6 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Aug 26 07:22:51 EDT 2008


Author: adamw
Date: 2008-08-26 07:22:51 -0400 (Tue, 26 Aug 2008)
New Revision: 322

Added:
   trunk/src/action/org/jboss/blog/session/tools/AdminBean.java
Modified:
   trunk/src/action/org/jboss/blog/session/merge/MergeServiceBean.java
   trunk/src/action/org/jboss/blog/session/view/FeedViewBean.java
   trunk/src/action/org/jboss/blog/session/xml/velocity/tools/XmlTools.java
   trunk/src/model/org/jboss/blog/model/Post.java
   trunk/src/tools/org/jboss/blog/tools/StringTools.java
   trunk/view/manage/index.xhtml
   trunk/view/manage/template/template_mod.xhtml
Log:
JBBLOG-71 fix, removing and checking duplicate posts

Modified: trunk/src/action/org/jboss/blog/session/merge/MergeServiceBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/merge/MergeServiceBean.java	2008-06-27 14:26:06 UTC (rev 321)
+++ trunk/src/action/org/jboss/blog/session/merge/MergeServiceBean.java	2008-08-26 11:22:51 UTC (rev 322)
@@ -4,6 +4,7 @@
 import org.jboss.blog.model.Post;
 import org.jboss.blog.model.Enclosure;
 import org.jboss.blog.model.Image;
+import org.jboss.blog.model.RestrictedPost;
 import org.jboss.blog.service.FeedsService;
 import org.jboss.blog.service.PostNotFoundException;
 import org.jboss.blog.service.LinkService;
@@ -73,6 +74,22 @@
         events.raiseEvent("org.jboss.blog.post.added", post);
     }
 
+    private boolean checkNewPost(Post post, PostsIterator<RestrictedPost> mergeTo, PostsIterator<Post> mergeFrom) {
+        int currentPostSize = entityManager
+                .createQuery("select p from Post p where p.published = :p and p.title = :t")
+                .setParameter("p", post.getPublished())
+                .setParameter("t", post.getTitle())
+                .getResultList().size();
+
+        if (currentPostSize > 0) {
+            log.warn("Trying to save a duplicate post, merge to: #1, merge from: #2!", mergeTo.getCurrent(),
+                    mergeFrom.getCurrent());
+            return false;
+        } else {
+            return true;
+        }
+    }
+
     /**
      * Merges the given posts; checks for changes in:
      * - author
@@ -145,20 +162,24 @@
      * @param posts A <b>sorted</b> list of posts, that should be merged to <code>feed</code>.
      */
     public void merge(Feed feed, List<Post> posts) {
-        ListPostsIterator<Post> mergeFrom = new ListPostsIterator<Post>(posts);
-        FeedsServicePostsIterator mergeTo = new FeedsServicePostsIterator(feedsService, feed, posts.size()+1);
+        PostsIterator<Post> mergeFrom = new ListPostsIterator<Post>(posts);
+        PostsIterator<RestrictedPost> mergeTo = new FeedsServicePostsIterator(feedsService, feed, posts.size()+1);
 
         while (!mergeFrom.finished()) {
             if (mergeTo.finished()) {
                 // no more current posts
-                savePost(feed, mergeFrom.getCurrent());
+                if (checkNewPost(mergeFrom.getCurrent(), mergeTo, mergeFrom)) {
+                    savePost(feed, mergeFrom.getCurrent());
+                }
                 mergeFrom.next();
             } else {
                 int compare = mergeTo.getCurrent().compareTo(mergeFrom.getCurrent());
                 
                 if (compare > 0) {
                     // mergeTo post is before mergeFrom post
-                    savePost(feed, mergeFrom.getCurrent());
+                    if (checkNewPost(mergeFrom.getCurrent(), mergeTo, mergeFrom)) {
+                        savePost(feed, mergeFrom.getCurrent());
+                    }
                     mergeFrom.next();
                 } else if (compare == 0) {
                     try {

Added: trunk/src/action/org/jboss/blog/session/tools/AdminBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/tools/AdminBean.java	                        (rev 0)
+++ trunk/src/action/org/jboss/blog/session/tools/AdminBean.java	2008-08-26 11:22:51 UTC (rev 322)
@@ -0,0 +1,93 @@
+package org.jboss.blog.session.tools;
+
+import org.jboss.seam.annotations.*;
+import org.jboss.seam.annotations.security.Restrict;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.faces.FacesMessages;
+import org.jboss.seam.log.Log;
+import org.jboss.blog.model.Group;
+import org.jboss.blog.model.Post;
+import org.jboss.blog.model.feed.Feed;
+import org.jboss.blog.tools.StringTools;
+import org.jboss.blog.service.GroupsService;
+import org.jboss.blog.session.cache.CacheManager;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Scope(ScopeType.STATELESS)
+ at Name("adminBean")
+ at AutoCreate
+public class AdminBean {
+    @In
+    private GroupsService groupsService;
+
+    @In
+    private EntityManager entityManager;
+
+    @In
+    private CacheManager cacheManager;
+
+    @In
+    private FacesMessages facesMessages;
+
+    @Logger
+    private Log log;
+
+    @Restrict("#{identity.hasPermission('admin', null)}")
+    public void fixHtml() {
+        for (Group group : groupsService.getAllGroups()) {
+            for (Feed feed : groupsService.acceptedFeeds(group)) {
+                for (Post post : feed.getPosts()) {
+                    post.setContent(StringTools.fixHtml(post.getContent()));
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings({"unchecked"})
+    @Restrict("#{identity.hasPermission('admin', null)}")
+    public void removeDuplicates() {
+        List<Object[]> results = (List<Object[]>) entityManager
+                .createQuery("select title, published, count(*) from Post p group by p.title, p.published")
+                .getResultList();
+
+        int removedDuplicates = 0;
+
+        for (Object[] result : results) {
+            if (((Number) result[2]).intValue() > 1) {
+                log.info("Duplicate post with title: " + result[0] + ", published: " + result[1] +
+                    ", count: " + result[2]);
+
+                removedDuplicates += ((Number) result[2]).intValue();
+
+                String titleAsId = StringTools.convertTitleToLink(result[0].toString());
+
+                // Checking that a "first" post exists
+                List firstPostResult = entityManager
+                        .createQuery("select p from Post p where p.titleAsId = :titleAsId")
+                        .setParameter("titleAsId", titleAsId)
+                        .getResultList();
+
+                if (firstPostResult.size() != 1) {
+                    log.info("No first post with titleAsId = " + titleAsId + "!");
+                } else {
+                    entityManager
+                            .createQuery("delete from Post p where p.titleAsId like :titleAsIdLike " +
+                                    "and p.titleAsId != :titleAsId and p.published = :published")
+                            .setParameter("titleAsIdLike", titleAsId + "%")
+                            .setParameter("titleAsId", titleAsId)
+                            .setParameter("published", result[1])
+                            .executeUpdate();
+                }
+            }
+        }
+
+        cacheManager.evictAll();
+
+        facesMessages.add("Removed " + removedDuplicates + " duplicate posts.");
+    }
+}

Modified: trunk/src/action/org/jboss/blog/session/view/FeedViewBean.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/view/FeedViewBean.java	2008-06-27 14:26:06 UTC (rev 321)
+++ trunk/src/action/org/jboss/blog/session/view/FeedViewBean.java	2008-08-26 11:22:51 UTC (rev 322)
@@ -1,17 +1,12 @@
 package org.jboss.blog.session.view;
 
 import org.jboss.blog.model.feed.Feed;
-import org.jboss.blog.model.Post;
 import org.jboss.blog.model.RestrictedPost;
-import org.jboss.blog.model.Group;
 import org.jboss.blog.service.FeedsService;
-import org.jboss.blog.service.GroupsService;
-import org.jboss.blog.tools.StringTools;
 import org.jboss.seam.ScopeType;
 import org.jboss.seam.annotations.In;
 import org.jboss.seam.annotations.Name;
 import org.jboss.seam.annotations.Scope;
-import org.jboss.seam.annotations.security.Restrict;
 
 import java.util.List;
 import java.io.Serializable;
@@ -25,9 +20,6 @@
     @In
     private FeedsService feedsService;
 
-    @In
-    private GroupsService groupsService;
-
     private Feed feed;
     private int from;
 
@@ -72,20 +64,4 @@
     public int getNextFrom() {
         return from + feed.getMaxPostsOnPage();
     }
-
-    /**
-     * TODO
-     * Remove in the future!
-     * @Deprecated
-     */
-    @Restrict("#{identity.hasPermission('admin', null)}")
-    public void fixHtml() {
-        for (Group group : groupsService.getAllGroups()) {
-            for (Feed feed : groupsService.acceptedFeeds(group)) {
-                for (Post post : feed.getPosts()) {
-                    post.setContent(StringTools.fixHtml(post.getContent()));
-                }
-            }
-        }
-    }
 }

Modified: trunk/src/action/org/jboss/blog/session/xml/velocity/tools/XmlTools.java
===================================================================
--- trunk/src/action/org/jboss/blog/session/xml/velocity/tools/XmlTools.java	2008-06-27 14:26:06 UTC (rev 321)
+++ trunk/src/action/org/jboss/blog/session/xml/velocity/tools/XmlTools.java	2008-08-26 11:22:51 UTC (rev 322)
@@ -4,6 +4,7 @@
 import org.jboss.blog.model.Post;
 import org.jboss.blog.model.XmlType;
 import org.jboss.blog.service.LinkService;
+import org.jboss.blog.tools.StringTools;
 import org.jboss.seam.Component;
 
 import java.text.SimpleDateFormat;
@@ -30,6 +31,10 @@
         return cal.getTime();
     }
 
+    public String escape(String toEscape) {
+        return StringTools.escape(toEscape);
+    }
+
     private LinkService getLinkService() {
         return (LinkService) Component.getInstance("linkService");
     }

Modified: trunk/src/model/org/jboss/blog/model/Post.java
===================================================================
--- trunk/src/model/org/jboss/blog/model/Post.java	2008-06-27 14:26:06 UTC (rev 321)
+++ trunk/src/model/org/jboss/blog/model/Post.java	2008-08-26 11:22:51 UTC (rev 322)
@@ -223,4 +223,8 @@
             return result;
         }
     }
+
+    public String toString() {
+        return "Post(title = " + title + ", published = " + published + ", titleAsId = " + titleAsId + ")";
+    }
 }

Modified: trunk/src/tools/org/jboss/blog/tools/StringTools.java
===================================================================
--- trunk/src/tools/org/jboss/blog/tools/StringTools.java	2008-06-27 14:26:06 UTC (rev 321)
+++ trunk/src/tools/org/jboss/blog/tools/StringTools.java	2008-08-26 11:22:51 UTC (rev 322)
@@ -13,6 +13,8 @@
 import javax.xml.parsers.ParserConfigurationException;
 import java.io.IOException;
 import java.io.StringReader;
+import java.text.StringCharacterIterator;
+import java.text.CharacterIterator;
 
 /**
  * @author Adam Warski (adam at warski dot org)
@@ -149,4 +151,87 @@
             return s;
         }
     }
+
+    /**
+     * Escape characters for text appearing in HTML markup.
+     *
+     * <P>This method exists as a defence against Cross Site Scripting (XSS) hacks.
+     * This method escapes all characters recommended by the Open Web App
+     * Security Project -
+     * <a href='http://www.owasp.org/index.php/Cross_Site_Scripting'>link</a>.
+     *
+     * <P>The following characters are replaced with corresponding HTML
+     * character entities :
+     * <table border='1' cellpadding='3' cellspacing='0'>
+     * <tr><th> Character </th><th> Encoding </th></tr>
+     * <tr><td> < </td><td> &lt; </td></tr>
+     * <tr><td> > </td><td> &gt; </td></tr>
+     * <tr><td> & </td><td> &amp; </td></tr>
+     * <tr><td> " </td><td> &quot;</td></tr>
+     * <tr><td> ' </td><td> &#039;</td></tr>
+     * <tr><td> ( </td><td> &#040;</td></tr>
+     * <tr><td> ) </td><td> &#041;</td></tr>
+     * <tr><td> # </td><td> &#035;</td></tr>
+     * <tr><td> % </td><td> &#037;</td></tr>
+     * <tr><td> ; </td><td> &#059;</td></tr>
+     * <tr><td> + </td><td> &#043; </td></tr>
+     * <tr><td> - </td><td> &#045; </td></tr>
+     * </table>
+     *
+     * <P>Note that JSTL's {@code <c:out>} escapes <em>only the first
+     * five</em> of the above characters.
+     *
+     * @author http://www.javapractices.com/topic/TopicAction.do;jsessionid=A293F4E3A21E476DC8488FED3DE883A0?Id=96
+     */
+    public static String escape(String toEscape){
+        final StringBuilder result = new StringBuilder();
+        final StringCharacterIterator iterator = new StringCharacterIterator(toEscape);
+        char character =  iterator.current();
+        while (character != CharacterIterator.DONE ){
+            if (character == '<') {
+                result.append("&lt;");
+            }
+            else if (character == '>') {
+                result.append("&gt;");
+            }
+            else if (character == '&') {
+                result.append("&amp;");
+            }
+            else if (character == '\"') {
+                result.append("&quot;");
+            }
+            else if (character == '\'') {
+                result.append("&#039;");
+            }
+            else if (character == '(') {
+                result.append("&#040;");
+            }
+            else if (character == ')') {
+                result.append("&#041;");
+            }
+            else if (character == '#') {
+                result.append("&#035;");
+            }
+            else if (character == '%') {
+                result.append("&#037;");
+            }
+            else if (character == ';') {
+                result.append("&#059;");
+            }
+            else if (character == '+') {
+                result.append("&#043;");
+            }
+            else if (character == '-') {
+                result.append("&#045;");
+            }
+            else {
+                //the char is not a special one
+                //add it to the result as is
+                result.append(character);
+            }
+            character = iterator.next();
+        }
+        return result.toString();
+    }
+
 }

Modified: trunk/view/manage/index.xhtml
===================================================================
--- trunk/view/manage/index.xhtml	2008-06-27 14:26:06 UTC (rev 321)
+++ trunk/view/manage/index.xhtml	2008-08-26 11:22:51 UTC (rev 322)
@@ -68,7 +68,8 @@
         <s:fragment rendered="#{identity.hasPermission('admin', null)}">
             <dt>Global posts operations:</dt>
             <hr />
-            <dd><s:link value="Fix html in all posts" action="#{feedView.fixHtml}" /></dd>
+            <dd><s:link value="Fix html in all posts" action="#{adminBean.fixHtml}" /></dd>
+            <dd><s:link value="Remove duplicates" action="#{adminBean.removeDuplicates}" /></dd>
             <dd><s:link value="Re-index posts (for search)" action="#{postSearch.reindex}" /></dd>
         </s:fragment>
         <dt>Existing feed operations:</dt>

Modified: trunk/view/manage/template/template_mod.xhtml
===================================================================
--- trunk/view/manage/template/template_mod.xhtml	2008-06-27 14:26:06 UTC (rev 321)
+++ trunk/view/manage/template/template_mod.xhtml	2008-08-26 11:22:51 UTC (rev 322)
@@ -95,6 +95,8 @@
                         a link to a feed of the given type</li>
                     <li>$tools.postLink(org.jboss.blog.model.Post) - generates a link to the html version of the
                         given post</li>
+                    <li>$tools.escape(java.util.String) - escapes special charaters, like &amp;, which can be
+                        found in links</li>
                 </ul>
             </li>
         </ul>




More information about the jboss-cvs-commits mailing list