2005-12-05 jrandom

* Added an RDF and XML thread export to Syndie, reachable at
      .../threadnav/rdf or .../threadnav/xml, accepting the parameters
      count=$numThreads and offset=$threadIndex.  If the $numThreads is -1, it
      displays all threads.
This commit is contained in:
jrandom
2005-12-05 06:14:15 +00:00
committed by zzz
parent 5966fcf5ff
commit 19bba048f2
5 changed files with 170 additions and 1 deletions

View File

@ -981,6 +981,13 @@ public class HTMLRenderer extends EventReceiverImpl {
else
return orig.toString();
}
public static final String sanitizeStrippedXML(String orig) {
if (orig == null) return "";
orig = orig.replaceAll("&", "&");
orig = orig.replaceAll("<", "&lt;");
orig = orig.replaceAll(">", "&gt;");
return orig;
}
private static final String STYLE_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
public static String sanitizeStyle(String style) {

View File

@ -163,6 +163,9 @@ public abstract class BaseServlet extends HttpServlet {
_log.info("New filtered index created (forced? " + forceNewIndex + ", tagsChanged? " + tagsChanged + ", authorsChanged? " + authorsChanged + ")");
}
render(user, req, resp, index);
}
protected void render(User user, HttpServletRequest req, HttpServletResponse resp, ThreadIndex index) throws IOException, ServletException {
render(user, req, resp.getWriter(), index);
}

View File

@ -0,0 +1,144 @@
package net.i2p.syndie.web;
import java.io.*;
import java.util.*;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.i2p.I2PAppContext;
import net.i2p.client.naming.*;
import net.i2p.data.*;
import net.i2p.syndie.*;
import net.i2p.syndie.data.*;
import net.i2p.syndie.sml.*;
/**
* Export the thread nav as either RDF or XML
*
*/
public class ThreadNavServlet extends BaseServlet {
public static final String PARAM_COUNT = "count";
public static final String PARAM_OFFSET = "offset";
public static final String PARAM_FORMAT = "format";
public static final String FORMAT_RDF = "rdf";
public static final String FORMAT_XML = "xml";
protected void render(User user, HttpServletRequest req, HttpServletResponse resp, ThreadIndex index) throws ServletException, IOException {
int threadCount = empty(req, PARAM_COUNT) ? index.getRootCount() : getInt(req, PARAM_COUNT);
int offset = getInt(req, PARAM_OFFSET);
String uri = req.getRequestURI();
if (uri.endsWith(FORMAT_XML)) {
resp.setContentType("text/xml; charset=UTF-8");
render(user, index, resp.getWriter(), threadCount, offset, FORMAT_XML);
} else {
resp.setContentType("application/rdf+xml; charset=UTF-8");
render(user, index, resp.getWriter(), threadCount, offset, FORMAT_RDF);
}
}
private int getInt(HttpServletRequest req, String param) {
String val = req.getParameter(param);
if (val != null) {
try {
return Integer.parseInt(val);
} catch (NumberFormatException nfe) {
// ignore
}
}
return -1;
}
private static final int DEFAULT_THREADCOUNT = 10;
private static final int DEFAULT_THREADOFFSET = 0;
private void render(User user, ThreadIndex index, PrintWriter out, int threadCount, int offset, String format) throws IOException {
int startRoot = DEFAULT_THREADOFFSET;
if (offset >= 0)
startRoot = offset;
renderStart(out, format);
int endRoot = startRoot + (threadCount > 0 ? threadCount : DEFAULT_THREADCOUNT);
if (endRoot >= index.getRootCount())
endRoot = index.getRootCount() - 1;
for (int i = startRoot; i <= endRoot; i++) {
ThreadNode node = index.getRoot(i);
if (FORMAT_XML.equals(format))
out.write(node.toString());
else
render(user, node, out);
}
renderEnd(out, format);
}
private void renderStart(PrintWriter out, String format) throws IOException {
out.write("<?xml version=\"1.0\" ?>\n");
if (FORMAT_XML.equals(format)) {
out.write("<threadTree>");
} else {
out.write("<rdf:rdf xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" " +
" xmlns:syndie=\"http://syndie.i2p.net/syndie.ns\">\n");
}
}
private void renderEnd(PrintWriter out, String format) throws IOException {
if (FORMAT_XML.equals(format)) {
out.write("</threadTree>");
} else {
out.write("</rdf:rdf>\n");
}
}
private void render(User user, ThreadNode node, PrintWriter out) throws IOException {
Archive archive = BlogManager.instance().getArchive();
String blog = node.getEntry().getKeyHash().toBase64();
out.write("<rdf:Description rdf:about=\"entry://" + blog + "/" + node.getEntry().getEntryId() + "\">");
PetName pn = user.getPetNameDB().getByLocation(blog);
String name = null;
if (pn != null) {
if (pn.isMember(FilteredThreadIndex.GROUP_FAVORITE))
out.write("<syndie:favoriteauthor />\n");
if (pn.isMember(FilteredThreadIndex.GROUP_IGNORE))
out.write("<syndie:ignoredauthor />\n");
name = pn.getName();
} else {
BlogInfo info = archive.getBlogInfo(node.getEntry().getKeyHash());
if (info != null)
name = info.getProperty(BlogInfo.NAME);
if ( (name == null) || (name.trim().length() <= 0) )
name = node.getEntry().getKeyHash().toBase64().substring(0,6);
}
out.write("<syndie:author syndie:blog=\"" + blog + "\" syndie:name=\"" + HTMLRenderer.sanitizeStrippedXML(name) + "\" />\n");
if ( (user.getBlog() != null) && (node.containsAuthor(user.getBlog())) )
out.write("<syndie:threadself />\n");
EntryContainer entry = archive.getEntry(node.getEntry());
if (entry == null) throw new RuntimeException("Unable to fetch the entry " + node.getEntry());
SMLParser parser = new SMLParser(I2PAppContext.getGlobalContext());
HeaderReceiver rec = new HeaderReceiver();
parser.parse(entry.getEntry().getText(), rec);
String subject = rec.getHeader(HTMLRenderer.HEADER_SUBJECT);
if ( (subject == null) || (subject.trim().length() <= 0) )
subject = "(no subject)";
out.write("<syndie:subject>" + HTMLRenderer.sanitizeStrippedXML(subject) + "</syndie:subject>\n");
long dayBegin = BlogManager.instance().getDayBegin();
long postId = node.getEntry().getEntryId();
int daysAgo = (int)((dayBegin - postId + 24*60*60*1000-1)/(24*60*60*1000));
out.write("<syndie:age>" + daysAgo + "</syndie:age>\n");
out.write("<syndie:children>");
for (int i = 0; i < node.getChildCount(); i++)
render(user, node.getChild(i), out);
out.write("</syndie:children>\n");
out.write("</rdf:Description>\n");
}
protected void renderServletDetails(User user, HttpServletRequest req, PrintWriter out, ThreadIndex index,
int threadOffset, BlogURI visibleEntry, Archive archive) throws IOException {
throw new UnsupportedOperationException("Not relvent...");
}
}

View File

@ -59,6 +59,11 @@
<servlet-class>net.i2p.syndie.web.ExternalLinkServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>net.i2p.syndie.web.ThreadNavServlet</servlet-name>
<servlet-class>net.i2p.syndie.web.ThreadNavServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>net.i2p.syndie.UpdaterServlet</servlet-name>
<servlet-class>net.i2p.syndie.UpdaterServlet</servlet-class>
@ -117,6 +122,10 @@
<servlet-name>net.i2p.syndie.web.ExternalLinkServlet</servlet-name>
<url-pattern>/externallink.jsp</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>net.i2p.syndie.web.ThreadNavServlet</servlet-name>
<url-pattern>/threadnav/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>

View File

@ -1,4 +1,10 @@
$Id: history.txt,v 1.346 2005/12/04 15:02:25 jrandom Exp $
$Id: history.txt,v 1.347 2005/12/04 15:12:19 jrandom Exp $
2005-12-05 jrandom
* Added an RDF and XML thread export to Syndie, reachable at
.../threadnav/rdf or .../threadnav/xml, accepting the parameters
count=$numThreads and offset=$threadIndex. If the $numThreads is -1, it
displays all threads.
2005-12-04 TLorD
* Patch for the C SAM library to null terminate strings on copy (thanks!)