2005-11-11 jrandom

* Add filtering threads by author to Syndie, populated with authors in the
      user's addressbook
    * When creating the default user, add
      "http://syndiemedia.i2p/archive/archive.txt" to their addressbook,
      configured to automatically pull updates.  (what other archives should
      be included?)
    * Tiny servlet to help dole out the new routerconsole themes, and bundle
      the installer/resources/themes/** into ./docs/themes/** on both install
      and update.
This commit is contained in:
jrandom
2005-11-12 05:03:51 +00:00
committed by zzz
parent 807d2d3509
commit 14134694d7
9 changed files with 284 additions and 89 deletions

View File

@@ -0,0 +1,14 @@
<%
String uri = request.getRequestURI();
if (uri.endsWith(".css")) {
response.setContentType("text/css");
} else if (uri.endsWith(".png")) {
response.setContentType("image/png");
} else if (uri.endsWith(".gif")) {
response.setContentType("image/gif");
} else if (uri.endsWith(".jpg")) {
response.setContentType("image/jpeg");
}
net.i2p.util.FileUtil.readFile(uri, "./docs", response.getOutputStream());
%>

View File

@@ -5,6 +5,13 @@
<web-app>
<!-- precompiled servlets -->
<!-- yeah, i'm lazy, using a jsp instead of a servlet.. -->
<servlet-mapping>
<servlet-name>net.i2p.router.web.jsp.viewtheme_jsp</servlet-name>
<url-pattern>/themes/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30

View File

@@ -448,6 +448,15 @@ public class BlogManager {
return pass;
}
/**
* If we are a single user instance, when we create the default user, give them
* addressbook entries for each of the following, *and* schedule them for syndication
*
*/
private static final String DEFAULT_SINGLE_USER_ARCHIVES[] = new String[] {
"http://syndiemedia.i2p/archive/archive.txt"
};
public User getDefaultUser() {
User user = new User(_context);
getDefaultUser(user);
@@ -479,6 +488,10 @@ public class BlogManager {
String ok = register(user, getDefaultLogin(), getDefaultPass(), "", "default", "Default Syndie blog", "");
if (User.LOGIN_OK.equals(ok)) {
_log.info("Default user created: " + user);
for (int i = 0; i < DEFAULT_SINGLE_USER_ARCHIVES.length; i++)
user.getPetNameDB().add(new PetName("DefaultArchive" + i, "syndie", "syndiearchive", DEFAULT_SINGLE_USER_ARCHIVES[i]));
scheduleSyndication(DEFAULT_SINGLE_USER_ARCHIVES);
saveUser(user);
return;
} else {
user.invalidate();
@@ -906,6 +919,20 @@ public class BlogManager {
System.setProperty("syndie.updateArchives", buf.toString());
Updater.wakeup();
}
public void scheduleSyndication(String locations[]) {
String archives[] = getUpdateArchives();
HashSet locs = new HashSet();
for (int i = 0; (archives != null) && (i < archives.length); i++)
locs.add(archives[i]);
for (int i = 0; (locations != null) && (i < locations.length); i++)
locs.add(locations[i]);
StringBuffer buf = new StringBuffer(64);
for (Iterator iter = locs.iterator(); iter.hasNext(); )
buf.append(iter.next().toString().trim()).append(',');
System.setProperty("syndie.updateArchives", buf.toString());
Updater.wakeup();
}
public void unscheduleSyndication(String location) {
String archives[] = getUpdateArchives();
if ( (archives != null) && (archives.length > 0) ) {

View File

@@ -15,11 +15,12 @@ public class FilteredThreadIndex extends ThreadIndex {
private Collection _filteredTags;
private List _roots;
private List _ignoredAuthors;
private Collection _filteredAuthors;
public static final String GROUP_FAVORITE = "Favorite";
public static final String GROUP_IGNORE = "Ignore";
public FilteredThreadIndex(User user, Archive archive, Collection tags) {
public FilteredThreadIndex(User user, Archive archive, Collection tags, Collection authors) {
super();
_user = user;
_archive = archive;
@@ -27,6 +28,9 @@ public class FilteredThreadIndex extends ThreadIndex {
_filteredTags = tags;
if (_filteredTags == null)
_filteredTags = Collections.EMPTY_SET;
_filteredAuthors = authors;
if (_filteredAuthors == null)
_filteredAuthors = Collections.EMPTY_SET;
_ignoredAuthors = new ArrayList();
for (Iterator iter = user.getPetNameDB().iterator(); iter.hasNext(); ) {
@@ -49,13 +53,13 @@ public class FilteredThreadIndex extends ThreadIndex {
_roots = new ArrayList(_baseIndex.getRootCount());
for (int i = 0; i < _baseIndex.getRootCount(); i++) {
ThreadNode node = _baseIndex.getRoot(i);
if (!isIgnored(node, _ignoredAuthors, _filteredTags))
if (!isIgnored(node, _ignoredAuthors, _filteredTags, _filteredAuthors))
_roots.add(node);
}
}
private boolean isIgnored(ThreadNode node, List ignoredAuthors, Collection requestedTags) {
private boolean isIgnored(ThreadNode node, List ignoredAuthors, Collection requestedTags, Collection filteredAuthors) {
if (filteredAuthors.size() <= 0) {
boolean allAuthorsIgnored = true;
for (Iterator iter = node.getRecursiveAuthorIterator(); iter.hasNext(); ) {
Hash author = (Hash)iter.next();
@@ -67,9 +71,26 @@ public class FilteredThreadIndex extends ThreadIndex {
if ( (allAuthorsIgnored) && (ignoredAuthors.size() > 0) )
return true;
} else {
boolean filteredAuthorMatches = false;
for (Iterator iter = filteredAuthors.iterator(); iter.hasNext(); ) {
Hash author = (Hash)iter.next();
if (node.containsAuthor(author)) {
filteredAuthorMatches = true;
break;
}
}
if (!filteredAuthorMatches)
return true;
}
// ok, author checking passed, so only ignore the thread if tags were specified and the
// thread doesn't contain that tag
if (requestedTags.size() > 0) {
Collection nodeTags = node.getRecursiveTags();
for (Iterator iter = requestedTags.iterator(); iter.hasNext(); )
if (node.getRecursiveTags().contains(iter.next()))
if (nodeTags.contains(iter.next()))
return false;
// authors we aren't ignoring have posted in the thread, but the user is filtering
// posts by tags, and this thread doesn't include any of those tags
@@ -85,4 +106,5 @@ public class FilteredThreadIndex extends ThreadIndex {
public ThreadNode getRoot(int index) { return (ThreadNode)_roots.get(index); }
public ThreadNode getNode(BlogURI uri) { return _baseIndex.getNode(uri); }
public Collection getFilteredTags() { return _filteredTags; }
public Collection getFilteredAuthors() { return _filteredAuthors; }
}

View File

@@ -34,8 +34,9 @@ public class ThreadedHTMLRenderer extends HTMLRenderer {
/** index into the nav tree to start displaying */
public static final String PARAM_OFFSET = "offset";
public static final String PARAM_TAGS = "tags";
public static final String PARAM_AUTHOR = "author";
public static String getFilterByTagLink(String uri, ThreadNode node, User user, String tag) {
public static String getFilterByTagLink(String uri, ThreadNode node, User user, String tag, String author) {
StringBuffer buf = new StringBuffer(64);
buf.append(uri).append('?');
if (node != null) {
@@ -44,12 +45,16 @@ public class ThreadedHTMLRenderer extends HTMLRenderer {
buf.append(node.getEntry().getEntryId()).append('&');
}
if ( (tag != null) && (tag.trim().length() > 0) )
buf.append(PARAM_TAGS).append('=').append(tag);
if (!empty(tag))
buf.append(PARAM_TAGS).append('=').append(tag).append('&');
if (!empty(author))
buf.append(PARAM_AUTHOR).append('=').append(author).append('&');
return buf.toString();
}
public static String getNavLink(String uri, String viewPost, String viewThread, String tags, int offset) {
public static String getNavLink(String uri, String viewPost, String viewThread, String tags, String author, int offset) {
StringBuffer buf = new StringBuffer(64);
buf.append(uri);
buf.append('?');
@@ -61,13 +66,16 @@ public class ThreadedHTMLRenderer extends HTMLRenderer {
if (!empty(tags))
buf.append(PARAM_TAGS).append('=').append(tags).append('&');
if (!empty(author))
buf.append(PARAM_AUTHOR).append('=').append(author).append('&');
buf.append(PARAM_OFFSET).append('=').append(offset).append('&');
return buf.toString();
}
public static String getViewPostLink(String uri, ThreadNode node, User user, boolean isPermalink,
String offset, String tags) {
String offset, String tags, String author) {
StringBuffer buf = new StringBuffer(64);
buf.append(uri);
if (node.getChildCount() > 0) {
@@ -84,11 +92,14 @@ public class ThreadedHTMLRenderer extends HTMLRenderer {
buf.append(node.getEntry().getKeyHash().toBase64()).append('/');
buf.append(node.getEntry().getEntryId()).append('&');
if ( (!isPermalink) && (!empty(offset)) )
if (!isPermalink) {
if (!empty(offset))
buf.append(PARAM_OFFSET).append('=').append(offset).append('&');
if ( (!isPermalink) && (!empty(tags)) )
if (!empty(tags))
buf.append(PARAM_TAGS).append('=').append(tags).append('&');
if (!empty(author))
buf.append(PARAM_AUTHOR).append('=').append(author).append('&');
}
return buf.toString();
}
@@ -98,7 +109,7 @@ public class ThreadedHTMLRenderer extends HTMLRenderer {
public void render(User user, Writer out, Archive archive, BlogURI post,
boolean inlineReply, ThreadIndex index, String baseURI,
String offset, String requestTags) throws IOException {
String offset, String requestTags, String filteredAuthor) throws IOException {
EntryContainer entry = archive.getEntry(post);
if (entry == null) return;
_entry = entry;
@@ -126,7 +137,7 @@ public class ThreadedHTMLRenderer extends HTMLRenderer {
String subject = (String)_headers.get(HTMLRenderer.HEADER_SUBJECT);
if (subject == null)
subject = "";
out.write(" <td colspan=\"3\" class=\"postMetaSubject\">");
out.write(" <td colspan=\"3\" class=\"postMetaSubject\" id=\"bodySubject\">");
out.write(subject);
out.write("</td></tr>\n");
out.write("<tr class=\"postMeta\"><td colspan=\"3\" class=\"postMetaLink\">\n");
@@ -158,7 +169,7 @@ public class ThreadedHTMLRenderer extends HTMLRenderer {
for (Iterator tagIter = tags.iterator(); tagIter.hasNext(); ) {
String tag = (String)tagIter.next();
out.write("<a href=\"");
out.write(getFilterByTagLink(baseURI, node, user, tag));
out.write(getFilterByTagLink(baseURI, node, user, tag, filteredAuthor));
out.write("\" title=\"Filter threads to only include posts tagged as '");
out.write(tag);
out.write("'\">");
@@ -168,7 +179,7 @@ public class ThreadedHTMLRenderer extends HTMLRenderer {
}
out.write("\n<a href=\"");
out.write(getViewPostLink(baseURI, node, user, true, offset, requestTags));
out.write(getViewPostLink(baseURI, node, user, true, offset, requestTags, filteredAuthor));
out.write("\" title=\"Select a shareable link directly to this post\">permalink</a>\n");
out.write("</td>\n</tr>\n");

View File

@@ -96,8 +96,9 @@ public class ViewThreadedServlet extends HttpServlet {
FilteredThreadIndex index = (FilteredThreadIndex)req.getSession().getAttribute("threadIndex");
Collection tags = getFilteredTags(req);
if (forceNewIndex || (index == null) || (!index.getFilteredTags().equals(tags)) ) {
index = new FilteredThreadIndex(user, BlogManager.instance().getArchive(), getFilteredTags(req));
Collection filteredAuthors = getFilteredAuthors(req);
if (forceNewIndex || (index == null) || (!index.getFilteredTags().equals(tags)) || (!index.getFilteredAuthors().equals(filteredAuthors))) {
index = new FilteredThreadIndex(user, BlogManager.instance().getArchive(), getFilteredTags(req), filteredAuthors);
req.getSession().setAttribute("threadIndex", index);
}
@@ -129,6 +130,7 @@ public class ViewThreadedServlet extends HttpServlet {
renderNavBar(user, req, out, index);
renderControlBar(user, req, out, index);
renderBody(user, req, out, index);
renderThreadNav(user, req, out, threadOffset, index);
renderThreadTree(user, req, out, threadOffset, visibleEntry, archive, index);
renderThreadNav(user, req, out, threadOffset, index);
@@ -183,12 +185,15 @@ public class ViewThreadedServlet extends HttpServlet {
out.write(req.getRequestURI());
out.write("\" method=\"GET\">\n");
String tags = "";
String author = "";
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 (ThreadedHTMLRenderer.PARAM_AUTHOR.equals(param)) {
author = val;
} else if (SKIP_TAGS.contains(param)) {
// skip
} else if (param.length() <= 0) {
@@ -199,12 +204,30 @@ public class ViewThreadedServlet extends HttpServlet {
}
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("Filter: <select name=\"" + ThreadedHTMLRenderer.PARAM_AUTHOR + "\">\n");
PetNameDB db = user.getPetNameDB();
TreeSet names = new TreeSet(db.getNames());
out.write("<option value=\"\">Any authors</option>\n");
if (author.equals(user.getBlog().toBase64()))
out.write("<option value=\"" + user.getBlog().toBase64() + "\" selected=\"true\">Threads you posted in</option>\n");
else
out.write("<option value=\"" + user.getBlog().toBase64() + "\">Threads you posted in</option>\n");
for (Iterator iter = names.iterator(); iter.hasNext(); ) {
String name = (String) iter.next();
PetName pn = db.getByName(name);
if ("syndieblog".equals(pn.getProtocol())) {
if (author.equals(pn.getLocation()))
out.write("<option value=\"" + pn.getLocation() + "\" selected=\"true\">Threads " + name + " posted in</option>\n");
else
out.write("<option value=\"" + pn.getLocation() + "\">Threads " + name + " posted in</option>\n");
}
}
out.write("</select>\n");
out.write("Tags: <input type=\"text\" name=\"" + ThreadedHTMLRenderer.PARAM_TAGS + "\" size=\"10\" 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");
@@ -215,13 +238,15 @@ public class ViewThreadedServlet extends HttpServlet {
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);
String author = req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR);
for (int i = 0; i < posts.size(); i++) {
BlogURI post = (BlogURI)posts.get(i);
renderer.render(user, out, archive, post, posts.size() == 1, index, uri, off, tags);
renderer.render(user, out, archive, post, posts.size() == 1, index, uri, off, tags, author);
}
}
@@ -261,9 +286,13 @@ public class ViewThreadedServlet extends HttpServlet {
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");
if (threadOffset == 0) {
out.write("&lt;&lt; First Page ");
} else {
out.write("<a href=\"");
out.write(getNavLink(req, 0));
out.write("\">&lt;&lt; First Page</a> ");
}
if (threadOffset > 0) {
out.write("<a href=\"");
int nxt = threadOffset - 10;
@@ -344,6 +373,24 @@ public class ViewThreadedServlet extends HttpServlet {
}
}
private Collection getFilteredAuthors(HttpServletRequest req) {
String authors = req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR);
if (authors != null) {
StringTokenizer tok = new StringTokenizer(authors, "\n\t ");
ArrayList rv = new ArrayList();
while (tok.hasMoreTokens()) {
try {
Hash h = new Hash();
h.fromBase64(tok.nextToken().trim());
rv.add(h);
} catch (DataFormatException dfe) {}
}
return rv;
} else {
return Collections.EMPTY_LIST;
}
}
private void renderThreadTree(User user, PrintWriter out, ThreadIndex index, Archive archive, HttpServletRequest req,
int threadOffset, int numThreads, BlogURI visibleEntry) {
@@ -359,13 +406,19 @@ public class ViewThreadedServlet extends HttpServlet {
numThreads = index.getRootCount() - threadOffset;
TreeRenderState state = new TreeRenderState(new ArrayList());
int written = 0;
for (int curRoot = threadOffset; curRoot < numThreads + threadOffset; curRoot++) {
ThreadNode node = index.getRoot(curRoot);
out.write("<!-- thread begin node=" + node + " curRoot=" + curRoot + " threadOffset=" + threadOffset + " -->\n");
renderThread(user, out, index, archive, req, node, 0, visibleEntry, state);
out.write("<!-- thread end -->\n");
written++;
}
out.write("<!-- threads begin -->\n");
if (written <= 0)
out.write("<tr class=\"threadEven\"><td colspan=\"3\">No matching threads</td></tr>\n");
out.write("<!-- threads end -->\n");
}
/**
@@ -418,11 +471,11 @@ public class ViewThreadedServlet extends HttpServlet {
if (allowCollapse) {
out.write("<a href=\"");
out.write(getCollapseLink(req, node));
out.write("\" title=\"collapse thread\"><img border=\"0\" src=\"images/collapse.png\" alt=\"-\" /></a>\n");
out.write("\" title=\"collapse thread\"><img border=\"0\" src=\"images/collapse.png\" alt=\"collapse\" /></a>\n");
} else {
out.write("<a href=\"");
out.write(getExpandLink(req, node));
out.write("\" title=\"expand thread\"><img border=\"0\" src=\"images/expand.png\" alt=\"+\" /></a>\n");
out.write("\" title=\"expand thread\"><img border=\"0\" src=\"images/expand.png\" alt=\"expand\" /></a>\n");
}
} else {
out.write("<img src=\"images/noSubthread.png\" alt=\"\" border=\"0\" />\n");
@@ -539,10 +592,11 @@ public class ViewThreadedServlet extends HttpServlet {
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));
req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS),
req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR));
}
private static String getExpandLink(ThreadNode node, String uri, String viewPost, String viewThread,
String offset, String tags) {
String offset, String tags, String author) {
StringBuffer buf = new StringBuffer(64);
buf.append(uri);
buf.append('?');
@@ -565,6 +619,9 @@ public class ViewThreadedServlet extends HttpServlet {
if (!empty(tags))
buf.append(ThreadedHTMLRenderer.PARAM_TAGS).append('=').append(tags).append('&');
if (!empty(author))
buf.append(ThreadedHTMLRenderer.PARAM_AUTHOR).append('=').append(author).append('&');
return buf.toString();
}
private String getCollapseLink(HttpServletRequest req, ThreadNode node) {
@@ -572,11 +629,12 @@ public class ViewThreadedServlet extends HttpServlet {
req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_POST),
req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_THREAD),
req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET),
req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS));
req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS),
req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR));
}
private String getCollapseLink(ThreadNode node, String uri, String viewPost, String viewThread,
String offset, String tags) {
String offset, String tags, String author) {
StringBuffer buf = new StringBuffer(64);
buf.append(uri);
// collapse node == let the node be visible
@@ -595,6 +653,9 @@ public class ViewThreadedServlet extends HttpServlet {
if (!empty(tags))
buf.append(ThreadedHTMLRenderer.PARAM_TAGS).append('=').append(tags).append('&');
if (!empty(author))
buf.append(ThreadedHTMLRenderer.PARAM_AUTHOR).append('=').append(author).append('&');
return buf.toString();
}
private String getProfileLink(HttpServletRequest req, Hash author) {
@@ -608,10 +669,11 @@ public class ViewThreadedServlet extends HttpServlet {
req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_POST),
req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_THREAD),
req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET),
req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS));
req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS),
req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR));
}
private String getAddToGroupLink(User user, Hash author, String group, String uri, String visible,
String viewPost, String viewThread, String offset, String tags) {
String viewPost, String viewThread, String offset, String tags, String filteredAuthor) {
StringBuffer buf = new StringBuffer(64);
buf.append(uri);
buf.append('?');
@@ -631,19 +693,25 @@ public class ViewThreadedServlet extends HttpServlet {
if (!empty(tags))
buf.append(ThreadedHTMLRenderer.PARAM_TAGS).append('=').append(tags).append('&');
if (!empty(filteredAuthor))
buf.append(ThreadedHTMLRenderer.PARAM_AUTHOR).append('=').append(filteredAuthor).append('&');
return buf.toString();
}
private String getViewPostLink(HttpServletRequest req, ThreadNode node, User user, boolean isPermalink) {
return ThreadedHTMLRenderer.getViewPostLink(req.getRequestURI(), node, user, isPermalink,
req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET),
req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS));
req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS),
req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR));
}
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));
req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS),
req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR));
}
private static String getViewThreadLink(String uri, ThreadNode node, User user, String offset, String tags) {
private static String getViewThreadLink(String uri, ThreadNode node, User user, String offset,
String tags, String author) {
StringBuffer buf = new StringBuffer(64);
buf.append(uri);
if (node.getChildCount() > 0) {
@@ -666,17 +734,21 @@ public class ViewThreadedServlet extends HttpServlet {
if (!empty(tags))
buf.append(ThreadedHTMLRenderer.PARAM_TAGS).append('=').append(tags).append('&');
if (!empty(author))
buf.append(ThreadedHTMLRenderer.PARAM_AUTHOR).append('=').append(author).append('&');
buf.append("#").append(node.getEntry().toString());
return buf.toString();
}
private String getFilterByTagLink(HttpServletRequest req, ThreadNode node, User user, String tag) {
return ThreadedHTMLRenderer.getFilterByTagLink(req.getRequestURI(), node, user, tag);
private String getFilterByTagLink(HttpServletRequest req, ThreadNode node, User user, String tag, String author) {
return ThreadedHTMLRenderer.getFilterByTagLink(req.getRequestURI(), node, user, tag, author);
}
private String getNavLink(HttpServletRequest req, int offset) {
return ThreadedHTMLRenderer.getNavLink(req.getRequestURI(),
req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_POST),
req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_THREAD),
req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS),
req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR),
offset);
}
@@ -763,22 +835,10 @@ public class ViewThreadedServlet extends HttpServlet {
"<link href=\"rss.jsp\" rel=\"alternate\" type=\"application/rss+xml\" >\n" +
"</head>\n" +
"<body>\n" +
"<span style=\"display: none\"><a href=\"#bodySubject\">Jump to the beginning of the first post rendered, if any</a>\n" +
"<a href=\"#threads\">Jump to the thread navigation</a>\n</span>\n" +
"<table border=\"0\" width=\"100%\" class=\"overallTable\">\n";
private static final String CONTROL_BAR_WITHOUT_TAGS = "<form>\n" +
"<tr class=\"controlBar\"><td colspan=\"2\">\n" +
"<!-- control bar begin -->\n" +
"Filter: <select disabled=\"true\" name=\"filter\">\n" +
" <option value=\"all\">All posts in all threads</option>\n" +
" <option value=\"self\">Threads you have posted in</option>\n" +
" <option value=\"favorites\">Threads your friends have posted in</option>\n" +
" </select>\n" +
"<input type=\"submit\" name=\"action\" value=\"Go\" />\n" +
"</td><td class=\"controlBarRight\"><a href=\"#threads\" title=\"Jump to the thread navigation\">Threads</a></td>\n" +
"<!-- control bar end -->\n" +
"</tr>\n" +
"</form>\n";
private static final String END_HTML = "</table>\n" +
"</body>\n";

View File

@@ -301,6 +301,10 @@
<copy file="installer/resources/dnfb-header.ht" todir="pkg-temp/docs/" />
<copy file="installer/resources/dnfh-header.ht" todir="pkg-temp/docs/" />
<copy file="installer/resources/ahelper-conflict-header.ht" todir="pkg-temp/docs/" />
<mkdir dir="pkg-temp/docs/themes/" />
<copy todir="pkg-temp/docs/themes/" >
<fileset dir="installer/resources/themes/" />
</copy>
<mkdir dir="pkg-temp/eepsite" />
<mkdir dir="pkg-temp/eepsite/webapps" />
<mkdir dir="pkg-temp/eepsite/logs" />
@@ -376,6 +380,12 @@
<copy file="installer/resources/dnfb-header.ht" todir="pkg-temp/docs/" />
<copy file="installer/resources/dnfh-header.ht" todir="pkg-temp/docs/" />
<copy file="installer/resources/ahelper-conflict-header.ht" todir="pkg-temp/docs/" />
<mkdir dir="pkg-temp/docs/themes/" />
<copy todir="pkg-temp/docs/themes/" >
<fileset dir="installer/resources/themes/" />
</copy>
<!-- the addressbook handles this for updates -->
<!-- <copy file="hosts.txt" todir="pkg-temp/" /> -->
<mkdir dir="pkg-temp/eepsite" />

View File

@@ -4,8 +4,10 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Enumeration;
@@ -163,6 +165,37 @@ public class FileUtil {
}
}
/**
* Dump the contents of the given path (relative to the root) to the output
* stream. The path must not go above the root, either - if it does, it will
* throw a FileNotFoundException
*/
public static void readFile(String path, String root, OutputStream out) throws IOException {
File rootDir = new File(root);
while (path.startsWith("/") && (path.length() > 0) )
path = path.substring(1);
if (path.length() <= 0) throw new FileNotFoundException("Not serving up the root dir");
File target = new File(rootDir, path);
if (!target.exists()) throw new FileNotFoundException("Requested file does not exist: " + path);
String targetStr = target.getCanonicalPath();
String rootDirStr = rootDir.getCanonicalPath();
if (!targetStr.startsWith(rootDirStr)) throw new FileNotFoundException("Requested file is outside the root dir: " + path);
byte buf[] = new byte[1024];
FileInputStream in = null;
try {
in = new FileInputStream(target);
int read = 0;
while ( (read = in.read(buf)) != -1)
out.write(buf, 0, read);
out.close();
} finally {
if (in != null)
in.close();
}
}
/** return true if it was copied successfully */
public static boolean copy(String source, String dest, boolean overwriteExisting) {
File src = new File(source);

View File

@@ -1,4 +1,15 @@
$Id: history.txt,v 1.318 2005/11/11 06:29:16 jrandom Exp $
$Id: history.txt,v 1.319 2005/11/11 21:38:56 cervantes Exp $
2005-11-11 jrandom
* Add filtering threads by author to Syndie, populated with authors in the
user's addressbook
* When creating the default user, add
"http://syndiemedia.i2p/archive/archive.txt" to their addressbook,
configured to automatically pull updates. (what other archives should
be included?)
* Tiny servlet to help dole out the new routerconsole themes, and bundle
the installer/resources/themes/** into ./docs/themes/** on both install
and update.
2005-11-11 cervantes
* Initial pass of the routerconsole revamp, starting with I2PTunnel and