From ca391097a99161ca96c7b3224634527f2670213e Mon Sep 17 00:00:00 2001
From: jrandom <jrandom>
Date: Fri, 11 Nov 2005 09:39:48 +0000
Subject: [PATCH] onwards, christian soldiers

---
 .../src/net/i2p/syndie/sml/HTMLRenderer.java  |  14 +-
 .../net/i2p/syndie/web/ArchiveViewerBean.java |  15 +-
 .../src/net/i2p/syndie/web/RSSServlet.java    |   7 +-
 .../net/i2p/syndie/web/RemoteArchiveBean.java |  16 +-
 .../i2p/syndie/web/ViewThreadedServlet.java   | 559 +++++-------------
 apps/syndie/jsp/_topnav.jsp                   |   6 +-
 apps/syndie/jsp/images/self.png               | Bin 0 -> 155 bytes
 apps/syndie/jsp/post.jsp                      |  14 +-
 8 files changed, 195 insertions(+), 436 deletions(-)
 create mode 100644 apps/syndie/jsp/images/self.png

diff --git a/apps/syndie/java/src/net/i2p/syndie/sml/HTMLRenderer.java b/apps/syndie/java/src/net/i2p/syndie/sml/HTMLRenderer.java
index d67231b079..7f8de09b9d 100644
--- a/apps/syndie/java/src/net/i2p/syndie/sml/HTMLRenderer.java
+++ b/apps/syndie/java/src/net/i2p/syndie/sml/HTMLRenderer.java
@@ -1001,7 +1001,7 @@ public class HTMLRenderer extends EventReceiverImpl {
                Base64.encode(blog.getData());
     }
 
-    public static String getPostURL(Hash blog) {
+    public String getPostURL(Hash blog) {
         return "post.jsp?" + ArchiveViewerBean.PARAM_BLOG + "=" + Base64.encode(blog.getData());
     }
     public String getPostURL(Hash blog, boolean asReply, String subject, String tags) { 
@@ -1022,8 +1022,8 @@ public class HTMLRenderer extends EventReceiverImpl {
     }
 
     public String getPageURL(String selector) { return getPageURL(_user, selector); }
-    public static String getPageURL(User user, String selector) { return getPageURL(user, selector, -1, -1); }
-    public static String getPageURL(User user, String selector, int numPerPage, int pageNum) {
+    public String getPageURL(User user, String selector) { return getPageURL(user, selector, -1, -1); }
+    public String getPageURL(User user, String selector, int numPerPage, int pageNum) {
         StringBuffer buf = new StringBuffer(128);
         buf.append("index.jsp?");
         buf.append("selector=").append(sanitizeTagParam(selector)).append("&");
@@ -1038,10 +1038,10 @@ public class HTMLRenderer extends EventReceiverImpl {
         return buf.toString();
     }
     
-    public static String getPageURL(Hash blog, String tag, long entryId, int numPerPage, int pageNum, boolean expandEntries, boolean showImages) {
+    public String getPageURL(Hash blog, String tag, long entryId, int numPerPage, int pageNum, boolean expandEntries, boolean showImages) {
         return getPageURL(blog, tag, entryId, null, numPerPage, pageNum, expandEntries, showImages);
     }
-    public static String getPageURL(Hash blog, String tag, long entryId, String group, int numPerPage, int pageNum, boolean expandEntries, boolean showImages) {
+    public String getPageURL(Hash blog, String tag, long entryId, String group, int numPerPage, int pageNum, boolean expandEntries, boolean showImages) {
         StringBuffer buf = new StringBuffer(128);
         buf.append("index.jsp?");
         if (blog != null)
@@ -1060,13 +1060,13 @@ public class HTMLRenderer extends EventReceiverImpl {
         buf.append(ArchiveViewerBean.PARAM_SHOW_IMAGES).append('=').append(showImages).append('&');
         return buf.toString();
     }
-    public static String getArchiveURL(Hash blog, SafeURL archiveLocation) {
+    public String getArchiveURL(Hash blog, SafeURL archiveLocation) {
         return "remote.jsp?" 
                //+ "action=Continue..." // should this be the case?
                + "&schema=" + sanitizeTagParam(archiveLocation.getSchema()) 
                + "&location=" + sanitizeTagParam(archiveLocation.getLocation());
     }
-    public static String getBookmarkURL(String name, String location, String schema, String protocol) {
+    public String getBookmarkURL(String name, String location, String schema, String protocol) {
         return "addresses.jsp?name=" + sanitizeTagParam(name)
                + "&network=" + sanitizeTagParam(schema)
                + "&protocol=" + sanitizeTagParam(protocol)
diff --git a/apps/syndie/java/src/net/i2p/syndie/web/ArchiveViewerBean.java b/apps/syndie/java/src/net/i2p/syndie/web/ArchiveViewerBean.java
index a724933c27..4a969535cd 100644
--- a/apps/syndie/java/src/net/i2p/syndie/web/ArchiveViewerBean.java
+++ b/apps/syndie/java/src/net/i2p/syndie/web/ArchiveViewerBean.java
@@ -405,15 +405,16 @@ public class ArchiveViewerBean {
                 start = 0;
                 end = entries.size() - 1;
             } else {
+                HTMLRenderer rend = new ThreadedHTMLRenderer(I2PAppContext.getGlobalContext());
                 pages = entries.size() / numPerPage;
                 if (numPerPage * pages < entries.size())
                     pages++;
                 if (pageNum > 0) {
                     String prevURL = null;
                     if ( (selector == null) || (selector.trim().length() <= 0) )
-                        prevURL = HTMLRenderer.getPageURL(blog, tag, entryId, group, numPerPage, pageNum-1, expandEntries, showImages);
+                        prevURL = rend.getPageURL(blog, tag, entryId, group, numPerPage, pageNum-1, expandEntries, showImages);
                     else
-                        prevURL = HTMLRenderer.getPageURL(user, selector, numPerPage, pageNum-1);
+                        prevURL = rend.getPageURL(user, selector, numPerPage, pageNum-1);
                     //System.out.println("prevURL: " + prevURL);
                     out.write(" <a class=\"b_selectorPrevMore\" href=\"" + prevURL + "\">&lt;&lt;</a>");
                 } else {
@@ -423,9 +424,9 @@ public class ArchiveViewerBean {
                 if (pageNum + 1 < pages) {
                     String nextURL = null;
                     if ( (selector == null) || (selector.trim().length() <= 0) )
-                        nextURL = HTMLRenderer.getPageURL(blog, tag, entryId, group, numPerPage, pageNum+1, expandEntries, showImages);
+                        nextURL = rend.getPageURL(blog, tag, entryId, group, numPerPage, pageNum+1, expandEntries, showImages);
                     else
-                        nextURL = HTMLRenderer.getPageURL(user, selector, numPerPage, pageNum+1);
+                        nextURL = rend.getPageURL(user, selector, numPerPage, pageNum+1);
                     //System.out.println("nextURL: " + nextURL);
                     out.write(" <a class=\"b_selectorNextMore\" href=\"" + nextURL + "\">&gt;&gt;</a>");
                 } else {
@@ -749,8 +750,7 @@ public class ArchiveViewerBean {
             for (int i = 0; i < props.length; i++) {
                 if (props[i].equals(BlogInfo.OWNER_KEY)) {
                     out.write("<tr class=\"b_metaBlog\"><td class=\"b_metaBlog\"><span class=\"b_metaBlog\">Blog:</span></td>");
-                    String blogURL = HTMLRenderer.getPageURL(blog, null, -1, -1, -1, false, false);
-                    out.write("<td class=\"b_metaBlog\"><a class=\"b_metaBlog\" href=\"" + blogURL + "\">" + Base64.encode(blog.getData()) + "</td></tr>\n");
+                    out.write("<td class=\"b_metaBlog\">" + Base64.encode(blog.getData()) + "</td></tr>\n");
                 } else if (props[i].equals(BlogInfo.SIGNATURE)) {
                     continue;
                 } else if (props[i].equals(BlogInfo.POSTERS)) {
@@ -782,7 +782,8 @@ public class ArchiveViewerBean {
                 out.write("<tr class=\"b_metaTags\"><td class=\"b_metaTags\"><span class=\"b_metaTags\">Known tags:</span></td><td class=\"b_metaTags\">");
                 for (int i = 0; i < tags.size(); i++) {
                     String tag = (String)tags.get(i);
-                    out.write("<a class=\"b_metaTag\" href=\"" + HTMLRenderer.getPageURL(blog, tag, -1, -1, -1, false, false) + "\">" +
+                    HTMLRenderer rend = new HTMLRenderer(I2PAppContext.getGlobalContext());
+                    out.write("<a class=\"b_metaTag\" href=\"" + rend.getPageURL(blog, tag, -1, -1, -1, false, false) + "\">" +
                               HTMLRenderer.sanitizeString(tag) + "</a> ");
                 }
                 out.write("</td></tr>");
diff --git a/apps/syndie/java/src/net/i2p/syndie/web/RSSServlet.java b/apps/syndie/java/src/net/i2p/syndie/web/RSSServlet.java
index 67fe340516..5c6a3a1055 100644
--- a/apps/syndie/java/src/net/i2p/syndie/web/RSSServlet.java
+++ b/apps/syndie/java/src/net/i2p/syndie/web/RSSServlet.java
@@ -58,7 +58,12 @@ public class RSSServlet extends HttpServlet {
         out.write("<rss version=\"2.0\">\n");
         out.write(" <channel>\n");
         out.write("  <title>Syndie feed</title>\n");
-        out.write("  <link>" + urlPrefix + HTMLRenderer.sanitizeXML(HTMLRenderer.getPageURL(sel.blog, sel.tag, sel.entry, sel.group, 5, 0, false, false)) +"</link>\n");
+        String page = urlPrefix;
+        if (sel.tag != null)
+            page = page + "threads.jsp?" + ThreadedHTMLRenderer.PARAM_TAGS + '=' + HTMLRenderer.sanitizeXML(sel.tag);
+        else if ( (sel.blog != null) && (sel.entry > 0) )
+            page = page + "threads.jsp?" + ThreadedHTMLRenderer.PARAM_VIEW_POST + '=' + sel.blog.toBase64() + '/' + sel.entry;
+        out.write("  <link>" + page +"</link>\n");
         out.write("  <description>Summary of the latest Syndie posts</description>\n");
         out.write("  <generator>Syndie</generator>\n");
         
diff --git a/apps/syndie/java/src/net/i2p/syndie/web/RemoteArchiveBean.java b/apps/syndie/java/src/net/i2p/syndie/web/RemoteArchiveBean.java
index 7577979596..e5c27a6b63 100644
--- a/apps/syndie/java/src/net/i2p/syndie/web/RemoteArchiveBean.java
+++ b/apps/syndie/java/src/net/i2p/syndie/web/RemoteArchiveBean.java
@@ -637,9 +637,7 @@ public class RemoteArchiveBean {
             buf.append("<tr class=\"b_remBlog\"><td class=\"b_remBlog\" colspan=\"5\" align=\"left\" valign=\"top\">\n");
             BlogInfo info = archive.getBlogInfo(blog);
             if (info != null) {
-                buf.append("<a class=\"b_remBlog\" href=\"");
-                buf.append(HTMLRenderer.getPageURL(blog, null, -1, -1, -1, user.getShowExpanded(), user.getShowImages()));
-                buf.append("\">").append(HTMLRenderer.sanitizeString(info.getProperty(BlogInfo.NAME))).append("</a>: ");
+                buf.append(HTMLRenderer.sanitizeString(info.getProperty(BlogInfo.NAME))).append(": ");
                 buf.append("<span class=\"b_remBlogDesc\">").append(HTMLRenderer.sanitizeString(info.getProperty(BlogInfo.DESCRIPTION)));
                 buf.append("</span>\n");
             } else {
@@ -661,8 +659,7 @@ public class RemoteArchiveBean {
                     newEntries++;
                     shownEntries++;
                 } else {
-                    String page = HTMLRenderer.getPageURL(blog, null, uri.getEntryId(), -1, -1,
-                    user.getShowExpanded(), user.getShowImages());
+                    String page = "threads.jsp?" + ThreadedHTMLRenderer.PARAM_VIEW_POST + '=' + blog.toBase64() + '/' + uri.getEntryId();
                     buf.append("<td class=\"b_remDetail\"><a class=\"b_remLocal\" href=\"" + page + "\">(local)</a></td>\n");
                 }
                 buf.append("<td class=\"b_remDetail\"><span class=\"b_remDate\">" + getDate(uri.getEntryId()) + "</span></td>\n");
@@ -671,7 +668,8 @@ public class RemoteArchiveBean {
                 buf.append("<td class=\"b_remDetail\">");
                 for (Iterator titer = new TreeSet(_remoteIndex.getBlogEntryTags(uri)).iterator(); titer.hasNext(); ) {
                     String tag = (String)titer.next();
-                    buf.append("<a class=\"b_remTag\" href=\"" + HTMLRenderer.getPageURL(blog, tag, -1, -1, -1, user.getShowExpanded(), user.getShowImages()) + "\">" + tag + "</a> \n");
+                    String page = "threads.jsp?" + ThreadedHTMLRenderer.PARAM_TAGS + '=' + HTMLRenderer.sanitizeTagParam(tag);
+                    buf.append("<a class=\"b_remTag\" href=\"" + page + "\">" + HTMLRenderer.sanitizeString(tag) + "</a> \n");
                 }
                 buf.append("</td>\n");
                 buf.append("</tr>\n");
@@ -700,7 +698,8 @@ public class RemoteArchiveBean {
                     buf.append("<td class=\"b_remLocalTags\">");
                     for (Iterator titer = new TreeSet(localIndex.getBlogEntryTags(uri)).iterator(); titer.hasNext(); ) {
                         String tag = (String)titer.next();
-                        buf.append("<a class=\"b_remLocalTag\" href=\"" + HTMLRenderer.getPageURL(blog, tag, -1, -1, -1, user.getShowExpanded(), user.getShowImages()) + "\">" + tag + "</a> \n");
+                        String page = "threads.jsp?" + ThreadedHTMLRenderer.PARAM_TAGS + '=' + HTMLRenderer.sanitizeTagParam(tag);
+                        buf.append("<a class=\"b_remLocalTag\" href=\"" + page + "\">" + HTMLRenderer.sanitizeString(tag) + "</a> \n");
                     }
                     buf.append("</td>\n");
                     buf.append("</tr>\n");
@@ -737,7 +736,8 @@ public class RemoteArchiveBean {
                 buf.append("<td class=\"b_remLocalTags\">");
                 for (Iterator titer = new TreeSet(localIndex.getBlogEntryTags(uri)).iterator(); titer.hasNext(); ) {
                     String tag = (String)titer.next();
-                    buf.append("<a class=\"b_remLocalTag\" href=\"" + HTMLRenderer.getPageURL(blog, tag, -1, -1, -1, user.getShowExpanded(), user.getShowImages()) + "\">" + tag + "</a> \n");
+                    String page = "threads.jsp?" + ThreadedHTMLRenderer.PARAM_TAGS + '=' + HTMLRenderer.sanitizeTagParam(tag);
+                    buf.append("<a class=\"b_remLocalTag\" href=\"" + page + "\">" + HTMLRenderer.sanitizeString(tag) + "</a> \n");
                 }
                 buf.append("</td>\n");
                 buf.append("</tr>\n");
diff --git a/apps/syndie/java/src/net/i2p/syndie/web/ViewThreadedServlet.java b/apps/syndie/java/src/net/i2p/syndie/web/ViewThreadedServlet.java
index fcd5ebaa51..81b4384201 100644
--- a/apps/syndie/java/src/net/i2p/syndie/web/ViewThreadedServlet.java
+++ b/apps/syndie/java/src/net/i2p/syndie/web/ViewThreadedServlet.java
@@ -19,20 +19,6 @@ import net.i2p.syndie.sml.*;
  *
  */
 public class ViewThreadedServlet extends HttpServlet {
-    /** what, if any, post should be rendered */
-    public static final String PARAM_VIEW_POST = "post";
-    /** what, if any, thread should be rendered in its entirety */
-    public static final String PARAM_VIEW_THREAD = "thread";
-    /** what post should be visible in the nav tree */
-    public static final String PARAM_VISIBLE = "visible";
-    public static final String PARAM_ADD_TO_GROUP_LOCATION = "addLocation";
-    public static final String PARAM_ADD_TO_GROUP_NAME = "addGroup";
-    /** index into the nav tree to start displaying */
-    public static final String PARAM_OFFSET = "offset";
-    public static final String PARAM_TAGS = "tags";
-    
-    private static final boolean ALLOW_FILTER_BY_TAG = true;
-    
     public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         req.setCharacterEncoding("UTF-8");
         resp.setCharacterEncoding("UTF-8");
@@ -44,6 +30,9 @@ public class ViewThreadedServlet extends HttpServlet {
         String action = req.getParameter("action");
         boolean forceNewIndex = false;
         
+        if (req.getParameter("regenerateIndex") != null)
+            forceNewIndex = true;
+        
         if (user == null) {
             if ("Login".equals(action)) {
                 user = new User();
@@ -66,8 +55,8 @@ public class ViewThreadedServlet extends HttpServlet {
         req.getSession().setAttribute("user", user);
         
         if (user.getAuthenticated()) {
-            String loc = req.getParameter(PARAM_ADD_TO_GROUP_LOCATION);
-            String group = req.getParameter(PARAM_ADD_TO_GROUP_NAME);
+            String loc = req.getParameter(ThreadedHTMLRenderer.PARAM_ADD_TO_GROUP_LOCATION);
+            String group = req.getParameter(ThreadedHTMLRenderer.PARAM_ADD_TO_GROUP_NAME);
             if ( (loc != null) && (group != null) && (group.trim().length() > 0) ) {
                 try {
                     Hash key = new Hash();
@@ -131,7 +120,7 @@ public class ViewThreadedServlet extends HttpServlet {
         BlogURI visibleEntry = getVisible(req);
         
         int offset = 0;
-        if ( empty(req, PARAM_OFFSET) && (visibleEntry != null) ) {
+        if ( empty(req, ThreadedHTMLRenderer.PARAM_OFFSET) && (visibleEntry != null) ) {
             // we're on a permalink, so jump the tree to the given thread
             threadOffset = index.getRoot(visibleEntry);
             if (threadOffset < 0)
@@ -192,59 +181,60 @@ public class ViewThreadedServlet extends HttpServlet {
     }
     
     private void renderControlBar(User user, HttpServletRequest req, PrintWriter out, ThreadIndex index) throws IOException {
-        if (ALLOW_FILTER_BY_TAG) {
-            out.write("<form action=\"");
-            out.write(req.getRequestURI());
-            out.write("\" method=\"GET\">\n");
-            String tags = "";
-            Enumeration params = req.getParameterNames();
-            while (params.hasMoreElements()) {
-                String param = (String)params.nextElement();
-                String val = req.getParameter(param);
-                if (PARAM_TAGS.equals(param)) {
-                    tags = val;
-                } else if (SKIP_TAGS.contains(param)) {
-                    // skip
-                } else if (param.length() <= 0) {
-                    // skip
-                } else {
-                    out.write("<input type=\"hidden\" name=\"" + param + "\" value=\"" + val + "\" />\n");
-                }
+        out.write("<form action=\"");
+        out.write(req.getRequestURI());
+        out.write("\" method=\"GET\">\n");
+        String tags = "";
+        Enumeration params = req.getParameterNames();
+        while (params.hasMoreElements()) {
+            String param = (String)params.nextElement();
+            String val = req.getParameter(param);
+            if (ThreadedHTMLRenderer.PARAM_TAGS.equals(param)) {
+                tags = val;
+            } else if (SKIP_TAGS.contains(param)) {
+                // skip
+            } else if (param.length() <= 0) {
+                // skip
+            } else {
+                out.write("<input type=\"hidden\" name=\"" + param + "\" value=\"" + val + "\" />\n");
             }
-            out.write("<tr class=\"controlBar\"><td colspan=\"2\">\n");
-            out.write("<!-- control bar begin -->\n");
-            out.write("Filter: <select name=\"filter\" disabled=\"true\" >\n");
-            out.write(" <option value=\"all\">All posts in all threads</option>\n");
-            out.write(" <option value=\"self\">Threads you have posted in</option>\n");
-            out.write(" <option value=\"favorites\">Threads your friends have posted in</option>\n");
-            out.write(" </select>\n");
-            out.write("Tags: <input type=\"text\" name=\"" + PARAM_TAGS + "\" size=\"30\" value=\"" + tags + "\" />\n");
-            out.write("<input type=\"submit\" name=\"action\" value=\"Go\" />\n");
-            out.write("</td><td class=\"controlBarRight\"><a href=\"#threads\" title=\"Jump to the thread navigation\">Threads</a></td>\n");
-            out.write("<!-- control bar end -->\n");
-            out.write("</tr>\n");
-            out.write("</form>\n");
-        } else {
-            out.write(CONTROL_BAR_WITHOUT_TAGS);
         }
+        out.write("<tr class=\"controlBar\"><td colspan=\"2\">\n");
+        out.write("<!-- control bar begin -->\n");
+        out.write("Filter: <select name=\"filter\" disabled=\"true\" >\n");
+        out.write(" <option value=\"all\">All posts in all threads</option>\n");
+        out.write(" <option value=\"self\">Threads you have posted in</option>\n");
+        out.write(" <option value=\"favorites\">Threads your friends have posted in</option>\n");
+        out.write(" </select>\n");
+        out.write("Tags: <input type=\"text\" name=\"" + ThreadedHTMLRenderer.PARAM_TAGS + "\" size=\"30\" value=\"" + tags + "\" />\n");
+        out.write("<input type=\"submit\" name=\"action\" value=\"Go\" />\n");
+        out.write("</td><td class=\"controlBarRight\"><a href=\"#threads\" title=\"Jump to the thread navigation\">Threads</a></td>\n");
+        out.write("<!-- control bar end -->\n");
+        out.write("</tr>\n");
+        out.write("</form>\n");
     }
     private void renderBody(User user, HttpServletRequest req, PrintWriter out, ThreadIndex index) throws IOException, ServletException  {
+        ThreadedHTMLRenderer renderer = new ThreadedHTMLRenderer(I2PAppContext.getGlobalContext());
         Archive archive = BlogManager.instance().getArchive();
         List posts = getPosts(archive, req, index);
+        String uri = req.getRequestURI();
+        String off = req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET);
+        String tags = req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS);
+        
         for (int i = 0; i < posts.size(); i++) {
             BlogURI post = (BlogURI)posts.get(i);
-            renderBody(user, req, out, archive, post, posts.size() == 1, index);
+            renderer.render(user, out, archive, post, posts.size() == 1, index, uri, off, tags);
         }
     }
     
     private List getPosts(Archive archive, HttpServletRequest req, ThreadIndex index) {
         List rv = new ArrayList(1);
-        String post = req.getParameter(PARAM_VIEW_POST);
+        String post = req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_POST);
         BlogURI uri = getAsBlogURI(post);
         if ( (uri != null) && (uri.getEntryId() > 0) ) {
             rv.add(uri);
         } else {
-            String thread = req.getParameter(PARAM_VIEW_THREAD);
+            String thread = req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_THREAD);
             uri = getAsBlogURI(thread);
             if ( (uri != null) && (uri.getEntryId() > 0) ) {
                 ThreadNode node = index.getNode(uri);
@@ -270,129 +260,6 @@ public class ViewThreadedServlet extends HttpServlet {
         for (int i = 0; i < node.getChildCount(); i++)
             walkTree(uris, node.getChild(i));
     }
-    
-    private void renderBody(User user, HttpServletRequest req, PrintWriter out, Archive archive, BlogURI post, boolean inlineReply, ThreadIndex index) throws IOException, ServletException {
-        EntryContainer entry = archive.getEntry(post);
-        if (entry == null) return;
-        
-        out.write("<!-- body begin -->\n");
-        out.write("<!-- body meta begin -->\n");
-        out.write("<tr class=\"postMeta\" id=\"" + post.toString() + "\">\n");
-        
-        HeaderReceiver rec = new HeaderReceiver();
-        SMLParser parser = new SMLParser(I2PAppContext.getGlobalContext());
-        HTMLRenderer rend = new HTMLRenderer(I2PAppContext.getGlobalContext());
-        parser.parse(entry.getEntry().getText(), rec);
-        String subject = rec.getHeader(HTMLRenderer.HEADER_SUBJECT);
-        if (subject == null)
-            subject = "";
-        out.write(" <td colspan=\"3\" class=\"postMetaSubject\">");
-        out.write(subject);
-        out.write("</td></tr>\n");
-        out.write("<tr class=\"postMeta\"><td colspan=\"3\" class=\"postMetaLink\">\n");
-        out.write("<a href=\"");
-        out.write(HTMLRenderer.getMetadataURL(post.getKeyHash()));
-        out.write("\" title=\"View the author's profile\">");
-        
-        String author = null;
-        PetName pn = user.getPetNameDB().getByLocation(post.getKeyHash().toBase64());
-        if (pn == null) {
-            BlogInfo info = archive.getBlogInfo(post.getKeyHash());
-            if (info != null)
-                author = info.getProperty(BlogInfo.NAME);
-        } else {
-            author = pn.getName();
-        }
-        if ( (author == null) || (author.trim().length() <= 0) )
-            author = post.getKeyHash().toBase64().substring(0,6);
-        
-        ThreadNode node = index.getNode(post);
-        
-        out.write(author);
-        out.write("</a> @ ");
-        out.write(rend.getEntryDate(post.getEntryId()));
-        
-        Collection tags = node.getTags();
-        if ( (tags != null) && (tags.size() > 0) ) {
-            out.write("\nTags: \n");
-            for (Iterator tagIter = tags.iterator(); tagIter.hasNext(); ) {
-                String tag = (String)tagIter.next();
-                if (ALLOW_FILTER_BY_TAG) {
-                    out.write("<a href=\"");
-                    out.write(getFilterByTagLink(req, node, user, tag));
-                    out.write("\" title=\"Filter threads to only include posts tagged as '");
-                    out.write(tag);
-                    out.write("'\">");
-                }
-                out.write(" " + tag);
-                if (ALLOW_FILTER_BY_TAG)
-                    out.write("</a>\n");
-            }
-        }
-        
-        out.write("\n<a href=\"");
-        out.write(getViewPostLink(req, node, user, true));
-        out.write("\" title=\"Select a shareable link directly to this post\">permalink</a>\n");
-        
-        out.write("</td>\n</tr>\n");
-        out.write("<!-- body meta end -->\n");
-        out.write("<!-- body post begin -->\n");
-        out.write("<tr class=\"postData\">\n");
-        out.write("<td colspan=\"3\">\n");
-        rend.render(user, archive, entry, out, false, true);
-        out.write("</td>\n</tr>\n");
-        out.write("<!-- body post end -->\n");
-        out.write("<!-- body details begin -->\n");
-/*
-"<tr class=\"postDetails\">\n" +
-" <form action=\"viewattachment.jsp\" method=\"GET\">\n" +
-" <td colspan=\"3\">\n" +
-" External links:\n" +
-"  <a href=\"external.jsp?foo\" title=\"View foo.i2p\">http://foo.i2p/</a>\n" +
-"  <a href=\"external.jsp?bar\" title=\"View bar.i2p\">http://bar.i2p/</a>\n" +
-" <br />\n" +
-" Attachments: <select name=\"attachment\">\n" +
-"  <option value=\"0\">sampleRawSML.sml: Sample SML file with headers (4KB, type text/plain)</option>\n" +
-" </select> <input type=\"submit\" name=\"action\" value=\"Download\" />\n" +
-" <br /><a href=\"\" title=\"Expand the entire thread\">Full thread</a>\n" +
-" <a href=\"\" title=\"Previous post in the thread\">Prev in thread</a> \n" +
-" <a href=\"\" title=\"Next post in the thread\">Next in thread</a> \n" +
-" </td>\n" +
-" </form>\n" +
-"</tr>\n" +
- */
-        out.write("<!-- body details end -->\n");
-        if (inlineReply && user.getAuthenticated() ) {
-            String refuseReplies = rec.getHeader(HTMLRenderer.HEADER_REFUSE_REPLIES);
-            // show the reply form if we are the author or replies have not been explicitly rejected
-            if ( (user.getBlog().equals(post.getKeyHash())) ||
-                 (refuseReplies == null) || (!Boolean.valueOf(refuseReplies).booleanValue()) ) {
-                out.write("<!-- body reply begin -->\n");
-                out.write("<form action=\"post.jsp\" method=\"POST\" enctype=\"multipart/form-data\">\n");
-                out.write("<input type=\"hidden\" name=\"inReplyTo\" value=\"");
-                out.write(Base64.encode(post.toString()));
-                out.write("\" />");
-                out.write("<input type=\"hidden\" name=\"entrysubject\" value=\"re: ");
-                out.write(HTMLRenderer.sanitizeTagParam(subject));
-                out.write("\" />");
-                out.write("<tr class=\"postReply\">\n");
-                out.write("<td colspan=\"3\">Reply: (<a href=\"smlref.jsp\" title=\"SML cheatsheet\">SML reference</a>)</td>\n</tr>\n");
-                out.write("<tr class=\"postReplyText\">\n");
-                out.write("<td colspan=\"3\"><textarea name=\"entrytext\" rows=\"2\" cols=\"100\"></textarea></td>\n");
-                out.write("</tr>\n");
-                out.write("<tr class=\"postReplyOptions\">\n");
-                out.write(" <td colspan=\"3\">\n");
-                out.write(" <input type=\"submit\" value=\"Preview...\" name=\"Post\" />\n");
-                out.write(" Tags: <input type=\"text\" size=\"10\" name=\"entrytags\" />\n");
-                out.write(" in a new thread? <input type=\"checkbox\" name=\"replyInNewThread\" />\n");
-                out.write(" allow replies? <input type=\"checkbox\" name=\"allowReplies\" checked=\"true\" />\n");
-                out.write(" attachment: <input type=\"file\" name=\"entryfile0\" />\n");
-                out.write(" </td>\n</tr>\n</form>\n");
-                out.write("<!-- body reply end -->\n");
-            }
-        }
-        out.write("<!-- body end -->\n");
-    }
     private void renderThreadNav(User user, HttpServletRequest req, PrintWriter out, int threadOffset, ThreadIndex index) throws IOException {
         out.write("<tr class=\"threadNav\" id=\"threads\"><td colspan=\"2\" nowrap=\"true\">\n");
         out.write("<!-- thread nav begin -->\n");
@@ -431,7 +298,7 @@ public class ViewThreadedServlet extends HttpServlet {
     }
     
     private static final int getOffset(HttpServletRequest req) {
-        String off = req.getParameter(PARAM_OFFSET);
+        String off = req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET);
         try {
             return Integer.parseInt(off);
         } catch (NumberFormatException nfe) {
@@ -439,7 +306,7 @@ public class ViewThreadedServlet extends HttpServlet {
         }
     }
     private static final BlogURI getVisible(HttpServletRequest req) {
-        return getAsBlogURI(req.getParameter(PARAM_VISIBLE));
+        return getAsBlogURI(req.getParameter(ThreadedHTMLRenderer.PARAM_VISIBLE));
     }
     private static final BlogURI getAsBlogURI(String uri) {
         if (uri != null) {
@@ -464,7 +331,7 @@ public class ViewThreadedServlet extends HttpServlet {
     }
     
     private Collection getFilteredTags(HttpServletRequest req) {
-        String tags = req.getParameter(PARAM_TAGS);
+        String tags = req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS);
         if (tags != null) {
             StringTokenizer tok = new StringTokenizer(tags, "\n\t ");
             ArrayList rv = new ArrayList();
@@ -482,11 +349,13 @@ public class ViewThreadedServlet extends HttpServlet {
     private void renderThreadTree(User user, PrintWriter out, ThreadIndex index, Archive archive, HttpServletRequest req,
                                   int threadOffset, int numThreads, BlogURI visibleEntry) {
         
-        if ( (visibleEntry != null) && (empty(req, PARAM_OFFSET)) ) {
+        if ( (visibleEntry != null) && (empty(req, ThreadedHTMLRenderer.PARAM_OFFSET)) ) {
             // we want to jump to a specific thread in the nav
             threadOffset = index.getRoot(visibleEntry);
         }
-        
+
+        if (threadOffset < 0)
+            threadOffset = 0;
         out.write("<!-- threads begin -->\n");
         if (threadOffset + numThreads > index.getRootCount())
             numThreads = index.getRootCount() - threadOffset;
@@ -501,45 +370,6 @@ public class ViewThreadedServlet extends HttpServlet {
         out.write("<!-- threads begin -->\n");
     }
     
-    /*
-    private void renderThreadTree(User user, PrintWriter out, ThreadIndex index, Archive archive, HttpServletRequest req,
-                                  int threadOffset, int numThreads, BlogURI visibleEntry) {
-
-        List ignored = new ArrayList();
-        for (Iterator iter = user.getPetNameDB().iterator(); iter.hasNext(); ) {
-            PetName pn = (PetName)iter.next();
-            if (pn.isMember(GROUP_IGNORE)) {
-                ignored.add(new Hash(Base64.decode(pn.getLocation())));
-            }
-        }
-        
-        out.write("<!-- threads begin -->\n");
-        if (threadOffset + numThreads > index.getRootCount())
-            numThreads = index.getRootCount() - threadOffset;
-        TreeRenderState state = new TreeRenderState(ignored);
-        
-        Collection requestedTags = getFilteredTags(req);
-        out.write("<!-- requested tags: " + requestedTags + " -->\n");
-        
-        int writtenThreads = 0;
-        int skipped = 0;
-        for (int curRoot = 0; (curRoot < index.getRootCount()) && (writtenThreads < numThreads); curRoot++) {
-            ThreadNode node = index.getRoot(curRoot);
-            boolean isIgnored = isIgnored(node, ignored, requestedTags);
-            out.write("<!-- thread begin (" + curRoot + ", " + writtenThreads + ", " + skipped + ", " + state.getRowsWritten() + ", " + isIgnored + ", " + threadOffset + ") -->\n");
-            if (!isIgnored) {
-                if ( (writtenThreads + skipped >= threadOffset) || ( (visibleEntry != null) && (empty(req, PARAM_OFFSET)) ) ) {
-                    renderThread(user, out, index, archive, req, node, 0, visibleEntry, state, requestedTags);
-                    writtenThreads++;
-                } else {
-                    skipped++;
-                }
-            }
-            out.write("<!-- thread end -->\n");
-        }
-        out.write("<!-- threads begin -->\n");
-    }
-    */
     /**
      * @return true if some post in the thread has been written
      */
@@ -572,16 +402,6 @@ public class ViewThreadedServlet extends HttpServlet {
         boolean showChildren = false;
         
         int childCount = node.getChildCount();
-        /*
-        for (int i = 0; i < node.getChildCount(); i++) {
-            ThreadNode child = node.getChild(i);
-            // we don't actually filter with the tags here, since something in this thread has already
-            // picked it out for rendering, and we don't want to limit it to just the subthreads that are
-            // tagged
-            if (isIgnored(child, state.getIgnoredAuthors(), Collections.EMPTY_LIST))
-                childCount--;
-        }
-        */
         
         if (childCount > 0) {
             boolean allowCollapse = false;
@@ -621,13 +441,15 @@ public class ViewThreadedServlet extends HttpServlet {
                 name = info.getProperty(BlogInfo.NAME);
             if ( (name == null) || (name.trim().length() <= 0) )
                 name = node.getEntry().getKeyHash().toBase64().substring(0,6);
-            out.write(name);
+            out.write(trim(name, 30));
         } else {
-            out.write(pn.getName());
+            out.write(trim(pn.getName(), 30));
         }
         out.write("</a>\n");
 
-        if (isFavorite) {
+        if (node.getEntry().getKeyHash().equals(user.getBlog())) {
+            out.write("<img src=\"images/self.png\" alt=\"You wrote this\" border=\"0\" />\n");
+        } else if (isFavorite) {
             out.write("<img src=\"images/favorites.png\" alt=\"favorites\" border=\"0\" />\n");
         } else {
             if (user.getAuthenticated()) {
@@ -654,7 +476,7 @@ public class ViewThreadedServlet extends HttpServlet {
         String subject = rec.getHeader(HTMLRenderer.HEADER_SUBJECT);
         if (subject == null)
             subject = "";
-        out.write(subject);
+        out.write(trim(subject, 60));
         out.write("</a>\n</td><td class=\"threadRight\">\n");
         out.write("<a href=\"");
         out.write(getViewThreadLink(req, node, user));
@@ -674,8 +496,16 @@ public class ViewThreadedServlet extends HttpServlet {
         return rendered;
     }
     
+    private String trim(String orig, int maxLen) {
+        if ( (orig == null) || (orig.length() <= maxLen) )
+            return orig;
+        return orig.substring(0, maxLen) + "...";
+    }
     
     private String getFlagHTML(User user, ThreadNode node) {
+        if (node.containsAuthor(user.getBlog()))
+            return "<img src=\"images/self.png\" border=\"0\" alt=\"You have posted in the thread\" />";
+        
         // grab all of the peers in the user's favorites group and check to see if 
         // they posted something in the given thread, flagging it if they have
         boolean favoriteFound = false;
@@ -703,175 +533,155 @@ public class ViewThreadedServlet extends HttpServlet {
         return (val == null) || (val.trim().length() <= 0);
     }
     
+    private static final boolean empty(String val) {
+        return (val == null) || (val.trim().length() <= 0);
+    }
+    
     private String getExpandLink(HttpServletRequest req, ThreadNode node) {
+        return getExpandLink(node, req.getRequestURI(), req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_POST), 
+                             req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_THREAD), 
+                             req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET),
+                             req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS));
+    }
+    private static String getExpandLink(ThreadNode node, String uri, String viewPost, String viewThread, 
+                                        String offset, String tags) {
         StringBuffer buf = new StringBuffer(64);
-        buf.append(req.getRequestURI());
+        buf.append(uri);
         buf.append('?');
         // expand node == let one of node's children be visible
         if (node.getChildCount() > 0) {
             ThreadNode child = node.getChild(0);
-            buf.append(PARAM_VISIBLE).append('=');
+            buf.append(ThreadedHTMLRenderer.PARAM_VISIBLE).append('=');
             buf.append(child.getEntry().getKeyHash().toBase64()).append('/');
             buf.append(child.getEntry().getEntryId()).append('&');
         }
         
-        if (!empty(req, PARAM_VIEW_POST))
-            buf.append(PARAM_VIEW_POST).append('=').append(req.getParameter(PARAM_VIEW_POST)).append('&');
-        else if (!empty(req, PARAM_VIEW_THREAD))
-            buf.append(PARAM_VIEW_THREAD).append('=').append(req.getParameter(PARAM_VIEW_THREAD)).append('&');
+        if (!empty(viewPost))
+            buf.append(ThreadedHTMLRenderer.PARAM_VIEW_POST).append('=').append(viewPost).append('&');
+        else if (!empty(viewThread))
+            buf.append(ThreadedHTMLRenderer.PARAM_VIEW_THREAD).append('=').append(viewThread).append('&');
         
-        if (!empty(req, PARAM_OFFSET))
-            buf.append(PARAM_OFFSET).append('=').append(req.getParameter(PARAM_OFFSET)).append('&');
+        if (!empty(offset))
+            buf.append(ThreadedHTMLRenderer.PARAM_OFFSET).append('=').append(offset).append('&');
         
-        if (!empty(req, PARAM_TAGS)) 
-            buf.append(PARAM_TAGS).append('=').append(req.getParameter(PARAM_TAGS)).append('&');
+        if (!empty(tags)) 
+            buf.append(ThreadedHTMLRenderer.PARAM_TAGS).append('=').append(tags).append('&');
         
         return buf.toString();
     }
-    private String getCollapseLink(HttpServletRequest req, ThreadNode node) { 
+    private String getCollapseLink(HttpServletRequest req, ThreadNode node) {
+        return getCollapseLink(node, req.getRequestURI(), 
+                               req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_POST),
+                               req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_THREAD),
+                               req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET),
+                               req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS));
+    }
+
+    private String getCollapseLink(ThreadNode node, String uri, String viewPost, String viewThread, 
+                                   String offset, String tags) { 
         StringBuffer buf = new StringBuffer(64);
-        buf.append(req.getRequestURI());
+        buf.append(uri);
         // collapse node == let the node be visible
-        buf.append('?').append(PARAM_VISIBLE).append('=');
+        buf.append('?').append(ThreadedHTMLRenderer.PARAM_VISIBLE).append('=');
         buf.append(node.getEntry().getKeyHash().toBase64()).append('/');
         buf.append(node.getEntry().getEntryId()).append('&');
 
-        if (!empty(req, PARAM_VIEW_POST))
-            buf.append(PARAM_VIEW_POST).append('=').append(req.getParameter(PARAM_VIEW_POST)).append('&');
-        else if (!empty(req, PARAM_VIEW_THREAD))
-            buf.append(PARAM_VIEW_THREAD).append('=').append(req.getParameter(PARAM_VIEW_THREAD)).append('&');
+        if (!empty(viewPost))
+            buf.append(ThreadedHTMLRenderer.PARAM_VIEW_POST).append('=').append(viewPost).append('&');
+        else if (!empty(viewThread))
+            buf.append(ThreadedHTMLRenderer.PARAM_VIEW_THREAD).append('=').append(viewThread).append('&');
         
-        if (!empty(req, PARAM_OFFSET))
-            buf.append(PARAM_OFFSET).append('=').append(req.getParameter(PARAM_OFFSET)).append('&');
+        if (!empty(offset))
+            buf.append(ThreadedHTMLRenderer.PARAM_OFFSET).append('=').append(offset).append('&');
         
-        if (!empty(req, PARAM_TAGS))
-            buf.append(PARAM_TAGS).append('=').append(req.getParameter(PARAM_TAGS)).append('&');
+        if (!empty(tags))
+            buf.append(ThreadedHTMLRenderer.PARAM_TAGS).append('=').append(tags).append('&');
         
         return buf.toString();
     }
     private String getProfileLink(HttpServletRequest req, Hash author) {
-        return HTMLRenderer.getMetadataURL(author);
+        return getProfileLink(author);
     }
+    private static String getProfileLink(Hash author) { return HTMLRenderer.getMetadataURL(author); }
+    
     private String getAddToGroupLink(HttpServletRequest req, Hash author, User user, String group) {
+        return getAddToGroupLink(user, author, group, req.getRequestURI(), 
+                                 req.getParameter(ThreadedHTMLRenderer.PARAM_VISIBLE),
+                                 req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_POST), 
+                                 req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_THREAD),
+                                 req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET), 
+                                 req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS));
+    }
+    private String getAddToGroupLink(User user, Hash author, String group, String uri, String visible,
+                                     String viewPost, String viewThread, String offset, String tags) {
         StringBuffer buf = new StringBuffer(64);
-        buf.append(req.getRequestURI());
+        buf.append(uri);
         buf.append('?');
-        String visible = req.getParameter(PARAM_VISIBLE);
-        if (visible != null) 
-            buf.append(PARAM_VISIBLE).append('=').append(visible).append('&');
-        buf.append(PARAM_ADD_TO_GROUP_LOCATION).append('=').append(author.toBase64()).append('&');
-        buf.append(PARAM_ADD_TO_GROUP_NAME).append('=').append(group).append('&');
+        if (!empty(visible))
+            buf.append(ThreadedHTMLRenderer.PARAM_VISIBLE).append('=').append(visible).append('&');
+        buf.append(ThreadedHTMLRenderer.PARAM_ADD_TO_GROUP_LOCATION).append('=').append(author.toBase64()).append('&');
+        buf.append(ThreadedHTMLRenderer.PARAM_ADD_TO_GROUP_NAME).append('=').append(group).append('&');
 
-        if (!empty(req, PARAM_VIEW_POST))
-            buf.append(PARAM_VIEW_POST).append('=').append(req.getParameter(PARAM_VIEW_POST)).append('&');
-        else if (!empty(req, PARAM_VIEW_THREAD))
-            buf.append(PARAM_VIEW_THREAD).append('=').append(req.getParameter(PARAM_VIEW_THREAD)).append('&');
+        if (!empty(viewPost))
+            buf.append(ThreadedHTMLRenderer.PARAM_VIEW_POST).append('=').append(viewPost).append('&');
+        else if (!empty(viewThread))
+            buf.append(ThreadedHTMLRenderer.PARAM_VIEW_THREAD).append('=').append(viewThread).append('&');
         
-        if (!empty(req, PARAM_OFFSET))
-            buf.append(PARAM_OFFSET).append('=').append(req.getParameter(PARAM_OFFSET)).append('&');
+        if (!empty(offset))
+            buf.append(ThreadedHTMLRenderer.PARAM_OFFSET).append('=').append(offset).append('&');
 
-        if (!empty(req, PARAM_TAGS))
-            buf.append(PARAM_TAGS).append('=').append(req.getParameter(PARAM_TAGS)).append('&');
+        if (!empty(tags))
+            buf.append(ThreadedHTMLRenderer.PARAM_TAGS).append('=').append(tags).append('&');
         
         return buf.toString();
     }
     private String getViewPostLink(HttpServletRequest req, ThreadNode node, User user, boolean isPermalink) {
-        StringBuffer buf = new StringBuffer(64);
-        buf.append(req.getRequestURI());
-        if (node.getChildCount() > 0) {
-            buf.append('?').append(PARAM_VISIBLE).append('=');
-            ThreadNode child = node.getChild(0);
-            buf.append(child.getEntry().getKeyHash().toBase64()).append('/');
-            buf.append(child.getEntry().getEntryId()).append('&');
-        } else {
-            buf.append('?').append(PARAM_VISIBLE).append('=');
-            buf.append(node.getEntry().getKeyHash().toBase64()).append('/');
-            buf.append(node.getEntry().getEntryId()).append('&');
-        }
-        buf.append(PARAM_VIEW_POST).append('=');
-        buf.append(node.getEntry().getKeyHash().toBase64()).append('/');
-        buf.append(node.getEntry().getEntryId()).append('&');
-        
-        if ( (!isPermalink) && (!empty(req, PARAM_OFFSET)) )
-            buf.append(PARAM_OFFSET).append('=').append(req.getParameter(PARAM_OFFSET)).append('&');
-        
-        if ( (!isPermalink) && (!empty(req, PARAM_TAGS)) )
-            buf.append(PARAM_TAGS).append('=').append(req.getParameter(PARAM_TAGS)).append('&');
-        
-        return buf.toString();
+        return ThreadedHTMLRenderer.getViewPostLink(req.getRequestURI(), node, user, isPermalink, 
+                                                    req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET), 
+                                                    req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS));
     }
     private String getViewThreadLink(HttpServletRequest req, ThreadNode node, User user) {
+        return getViewThreadLink(req.getRequestURI(), node, user,
+                                 req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET),
+                                 req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS));
+    }
+    private static String getViewThreadLink(String uri, ThreadNode node, User user, String offset, String tags) {
         StringBuffer buf = new StringBuffer(64);
-        buf.append(req.getRequestURI());
+        buf.append(uri);
         if (node.getChildCount() > 0) {
-            buf.append('?').append(PARAM_VISIBLE).append('=');
+            buf.append('?').append(ThreadedHTMLRenderer.PARAM_VISIBLE).append('=');
             ThreadNode child = node.getChild(0);
             buf.append(child.getEntry().getKeyHash().toBase64()).append('/');
             buf.append(child.getEntry().getEntryId()).append('&');
         } else {
-            buf.append('?').append(PARAM_VISIBLE).append('=');
+            buf.append('?').append(ThreadedHTMLRenderer.PARAM_VISIBLE).append('=');
             buf.append(node.getEntry().getKeyHash().toBase64()).append('/');
             buf.append(node.getEntry().getEntryId()).append('&');
         }
-        buf.append(PARAM_VIEW_THREAD).append('=');
+        buf.append(ThreadedHTMLRenderer.PARAM_VIEW_THREAD).append('=');
         buf.append(node.getEntry().getKeyHash().toBase64()).append('/');
         buf.append(node.getEntry().getEntryId()).append('&');
         
-        if (!empty(req, PARAM_OFFSET))
-            buf.append(PARAM_OFFSET).append('=').append(req.getParameter(PARAM_OFFSET)).append('&');
+        if (!empty(offset))
+            buf.append(ThreadedHTMLRenderer.PARAM_OFFSET).append('=').append(offset).append('&');
         
-        if (!empty(req, PARAM_TAGS))
-            buf.append(PARAM_TAGS).append('=').append(req.getParameter(PARAM_TAGS)).append('&');
+        if (!empty(tags))
+            buf.append(ThreadedHTMLRenderer.PARAM_TAGS).append('=').append(tags).append('&');
         
         buf.append("#").append(node.getEntry().toString());
         return buf.toString();
     }
     private String getFilterByTagLink(HttpServletRequest req, ThreadNode node, User user, String tag) { 
-        StringBuffer buf = new StringBuffer(64);
-        buf.append(req.getRequestURI()).append('?');
-        /*
-        if (node.getChildCount() > 0) {
-            buf.append('?').append(PARAM_VISIBLE).append('=');
-            ThreadNode child = node.getChild(0);
-            buf.append(child.getEntry().getKeyHash().toBase64()).append('/');
-            buf.append(child.getEntry().getEntryId()).append('&');
-        } else {
-            buf.append('?').append(PARAM_VISIBLE).append('=');
-            buf.append(node.getEntry().getKeyHash().toBase64()).append('/');
-            buf.append(node.getEntry().getEntryId()).append('&');
-        }
-         */
-        if (node != null) {
-            buf.append(PARAM_VIEW_POST).append('=');
-            buf.append(node.getEntry().getKeyHash().toBase64()).append('/');
-            buf.append(node.getEntry().getEntryId()).append('&');
-        }
-        
-        //if (!empty(req, PARAM_OFFSET))
-        //    buf.append(PARAM_OFFSET).append('=').append(req.getParameter(PARAM_OFFSET)).append('&');
-        
-        if ( (tag != null) && (tag.trim().length() > 0) )
-            buf.append(PARAM_TAGS).append('=').append(tag);
-        return buf.toString();
+        return ThreadedHTMLRenderer.getFilterByTagLink(req.getRequestURI(), node, user, tag);
     }
     private String getNavLink(HttpServletRequest req, int offset) {
-        StringBuffer buf = new StringBuffer(64);
-        buf.append(req.getRequestURI());
-        buf.append('?');
-        if (!empty(req, PARAM_VIEW_POST))
-            buf.append(PARAM_VIEW_POST).append('=').append(req.getParameter(PARAM_VIEW_POST)).append('&');
-        else if (!empty(req, PARAM_VIEW_THREAD))
-            buf.append(PARAM_VIEW_THREAD).append('=').append(req.getParameter(PARAM_VIEW_THREAD)).append('&');
-        
-        if (!empty(req, PARAM_TAGS))
-            buf.append(PARAM_TAGS).append('=').append(req.getParameter(PARAM_TAGS)).append('&');
-        
-        buf.append(PARAM_OFFSET).append('=').append(offset).append('&');
-        
-        return buf.toString();
+        return ThreadedHTMLRenderer.getNavLink(req.getRequestURI(), 
+                                               req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_POST), 
+                                               req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_THREAD), 
+                                               req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS), 
+                                               offset);
     }
     
-    
     private void renderEnd(User user, HttpServletRequest req, PrintWriter out, ThreadIndex index) throws IOException {
         out.write(END_HTML);
     }
@@ -951,6 +761,8 @@ public class ViewThreadedServlet extends HttpServlet {
 "	background-color: #BBBBFF;\n" +
 "}\n" +
 "</style>\n" +
+"<link href=\"style.jsp\" rel=\"stylesheet\" type=\"text/css\" >\n" +
+"<link href=\"rss.jsp\" rel=\"alternate\" type=\"application/rss+xml\" >\n" +
 "</head>\n" +
 "<body>\n" +
 "<table border=\"0\" width=\"100%\" class=\"overallTable\">\n";
@@ -969,68 +781,6 @@ public class ViewThreadedServlet extends HttpServlet {
 "</tr>\n" +
 "</form>\n";
 
-   private static final String BODY = "<!-- body begin -->\n" +
-"<!-- body meta begin -->\n" +
-"<tr class=\"postMeta\">\n" +
-" <td colspan=\"2\" class=\"postMetaSubject\">This is my subject</td>\n" +
-" <td class=\"postMetaLink\">\n" +
-" <a href=\"profile.jsp?blog=ovp\" title=\"View the author's profile\">petname</a> @ 2005/11/08\n" +
-" <a href=\"?permalink\" title=\"Select a sharable link directly to this post\">permalink</a>\n" +
-" </td>\n" +
-"</tr>\n" +
-"<!-- body meta end -->\n" +
-"<!-- body post begin -->\n" +
-"<tr class=\"postData\">\n" +
-" <td colspan=\"3\">\n" +
-" Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum iaculis ante ac nisi. \n" +
-" Ut ut justo sed sem venenatis elementum. Donec in erat. Duis felis erat, adipiscing eget, mattis\n" + 
-" sed, volutpat nec, lorem. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur \n" +
-" ridiculus mus. Phasellus porta lacus ac metus. Suspendisse mi. Nulla facilisi. Phasellus metus. \n" +
-" Nam varius elit ut magna. Suspendisse lectus massa, tempus vel, malesuada et, dictum quis, arcu. \n" +
-" Ut auctor enim vel tellus.\n" +
-" </td>\n" +
-"</tr>\n" +
-"<!-- body post end -->\n" +
-"<!-- body details begin -->\n" +
-"<tr class=\"postDetails\">\n" +
-" <form action=\"viewattachment.jsp\" method=\"GET\">\n" +
-" <td colspan=\"3\">\n" +
-" External links:\n" +
-"  <a href=\"external.jsp?foo\" title=\"View foo.i2p\">http://foo.i2p/</a>\n" +
-"  <a href=\"external.jsp?bar\" title=\"View bar.i2p\">http://bar.i2p/</a>\n" +
-" <br />\n" +
-" Attachments: <select name=\"attachment\">\n" +
-"  <option value=\"0\">sampleRawSML.sml: Sample SML file with headers (4KB, type text/plain)</option>\n" +
-" </select> <input type=\"submit\" name=\"action\" value=\"Download\" />\n" +
-" <br /><a href=\"\" title=\"Expand the entire thread\">Full thread</a>\n" +
-" <a href=\"\" title=\"Previous post in the thread\">Prev in thread</a> \n" +
-" <a href=\"\" title=\"Next post in the thread\">Next in thread</a> \n" +
-" </td>\n" +
-" </form>\n" +
-"</tr>\n" +
-"<!-- body details end -->\n" +
-"<!-- body reply begin -->\n" +
-"<form action=\"post.jsp\" method=\"POST\">\n" +
-"<tr class=\"postReply\">\n" +
-" <td colspan=\"3\">Reply: (<a href=\"smlref.jsp\" title=\"SML cheatsheet\">SML reference</a>)</td>\n" +
-"</tr>\n" +
-"<tr class=\"postReplyText\">\n" +
-" <td colspan=\"3\"><textarea name=\"smltext\" rows=\"2\" cols=\"100\"></textarea></td>\n" +
-"</tr>\n" +
-"<tr class=\"postReplyOptions\">\n" +
-" <td colspan=\"3\">\n" +
-" <input type=\"submit\" value=\"Preview...\" name=\"action\" />\n" +
-" Tags: <input type=\"text\" size=\"10\" name=\"tags\" />\n" +
-" in a new thread? <input type=\"checkbox\" name=\"replyInNewThread\" />\n" +
-" allow replies? <input type=\"checkbox\" name=\"allowReplies\" checked=\"true\" />\n" +
-" attachment: <input type=\"file\" name=\"entryfile0\" />\n" +
-" </td>\n" +
-"</tr>\n" +
-"</form>\n" +
-"<!-- body reply end -->\n" +
-"<!-- body end -->\n";
-
-   
    private static final String END_HTML = "</table>\n" +
 "</body>\n";
    
@@ -1049,5 +799,4 @@ public class ViewThreadedServlet extends HttpServlet {
         public void incrementRowsSkipped() { _rowsSkipped++; }
         public List getIgnoredAuthors() { return _ignored; }
     }
-   
 }
diff --git a/apps/syndie/jsp/_topnav.jsp b/apps/syndie/jsp/_topnav.jsp
index f1850c3022..2f3536513b 100644
--- a/apps/syndie/jsp/_topnav.jsp
+++ b/apps/syndie/jsp/_topnav.jsp
@@ -26,9 +26,9 @@ if ( (login != null) && (pass != null) && (loginSubmit != null) && (loginSubmit.
 %>
 <% if (user.getAuthenticated()) { %>
 <span class="b_topnavUsername">Logged in as:</span> <em class="b_topnavUsername"><jsp:getProperty property="username" name="user" />:</em>
-<a class="b_topnavBlog" href="<%=HTMLRenderer.getPageURL(user.getBlog(), null, -1, -1, -1, user.getShowExpanded(), user.getShowImages())%>"><%=HTMLRenderer.sanitizeString(ArchiveViewerBean.getBlogName(user.getBlogStr()))%></a>
-<a class="b_topnavPost" href="<%=HTMLRenderer.getPostURL(user.getBlog())%>">Post</a>
-<a class="b_topnavMeta" href="<%=HTMLRenderer.getMetadataURL(user.getBlog())%>">Metadata</a>
+<a class="b_topnavBlog" href="<%=""/*HTMLRenderer.getPageURL(user.getBlog(), null, -1, -1, -1, user.getShowExpanded(), user.getShowImages())*/%>"><%=HTMLRenderer.sanitizeString(ArchiveViewerBean.getBlogName(user.getBlogStr()))%></a>
+<a class="b_topnavPost" href="<%=""/*HTMLRenderer.getPostURL(user.getBlog())*/%>">Post</a>
+<a class="b_topnavMeta" href="<%=""/*HTMLRenderer.getMetadataURL(user.getBlog())*/%>">Metadata</a>
 <a class="b_topnavAddr" href="addresses.jsp">Addressbook</a>
 <a class="b_topnavLogout" href="index.jsp?logout=true">Logout</a>
 <%} else {%>
diff --git a/apps/syndie/jsp/images/self.png b/apps/syndie/jsp/images/self.png
new file mode 100644
index 0000000000000000000000000000000000000000..f56c8a0df06c47f73c629521d8028be6ddac8970
GIT binary patch
literal 155
zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4u_bxCyD<C*!3BGlPX>x`7I;J!
zGca%qgD@k*tT_@uLG}_)Usv|4+}tc2g5A?5gN)Jeba4!kxSagw{DBYi8#xXfaZpKU
sH0;UON(wCq`)ik}#>d*)6T<J#kh7j$P;RRGVxS%dPgg&ebxsLQ01rbci2wiq

literal 0
HcmV?d00001

diff --git a/apps/syndie/jsp/post.jsp b/apps/syndie/jsp/post.jsp
index ab976002c0..96be47a360 100644
--- a/apps/syndie/jsp/post.jsp
+++ b/apps/syndie/jsp/post.jsp
@@ -25,8 +25,7 @@ if (!user.getAuthenticated()) {
     post.setArchive(archive);
     BlogURI uri = post.postEntry(); 
     if (uri != null) {
-      %><span class="b_postMsgOk">Blog entry <a class="b_postOkLink" href="<%=HTMLRenderer.getPageURL(user.getBlog(), null, uri.getEntryId(), -1, -1, 
-                                                        user.getShowExpanded(), user.getShowImages())%>">posted</a>!</span><%
+      %><span class="b_postMsgOk">Blog entry <a class="b_postOkLink" href="threads.jsp?regenerateIndex=true&post=<%=user.getBlog().toBase64() + '/' + uri.getEntryId()%>">posted</a>!</span><%
     } else {
       %><span class="b_postMsgErro">There was an unknown error posting the entry...</span><%
     }
@@ -135,10 +134,15 @@ for (Iterator iter = names.iterator(); iter.hasNext(); ) {
 
       if (parentURI != null) {
         parentURI = new String(Base64.decode(parentURI), "UTF-8");
-        %><span class="b_postField">Replying to
-        <a href="<%=HTMLRenderer.getPageURL(user, parentURI)%>">parent</a>
-        (text <a href="#parentText">below</a>).</span><br />
+        BlogURI parent = null;
+        try { 
+          parent = new BlogURI(parentURI);
+          %><span class="b_postField">Replying to
+            <a href="thread.jsp?post=<%=parent.getKeyHash().toBase64() + '/' + parent.getEntryId()%>">parent</a>
+            (text <a href="#parentText">below</a>).</span><br />
         <%
+        } catch (Exception e) {}
+        
       }
 %><form action="post.jsp" method="POST" enctype="multipart/form-data"> 
 <span class="b_postField">Post subject:</span> <input class="b_postSubject" type="text" size="80" name="entrysubject" value="<%=post.getSubject()%>" /><br />
-- 
GitLab