2005-01-09 jrandom

* Bugfix for a rare SSU error (thanks cervantes!)
    * More progress on the blog interface, allowing customizable blog-wide
      links.
This commit is contained in:
jrandom
2006-01-09 06:33:29 +00:00
committed by zzz
parent 66e6dbec33
commit 1ca27ffd39
11 changed files with 462 additions and 182 deletions

View File

@ -102,6 +102,7 @@ public class BlogInfoData {
prevGroup = pn.getGroup(0); prevGroup = pn.getGroup(0);
} }
} }
line.setLength(0);
if (!ok) if (!ok)
break; break;
} }

View File

@ -61,6 +61,8 @@ public class FilteredThreadIndex extends ThreadIndex {
} }
private boolean isIgnored(ThreadNode node, List ignoredAuthors, Collection requestedTags, Collection filteredAuthors, boolean filterAuthorsByRoot) { private boolean isIgnored(ThreadNode node, List ignoredAuthors, Collection requestedTags, Collection filteredAuthors, boolean filterAuthorsByRoot) {
if (node.getTags().contains(BlogInfoData.TAG))
return true; // its a fake post, containing some updated metadata for the blog
if (filteredAuthors.size() <= 0) { if (filteredAuthors.size() <= 0) {
boolean allAuthorsIgnored = true; boolean allAuthorsIgnored = true;
for (Iterator iter = node.getRecursiveAuthorIterator(); iter.hasNext(); ) { for (Iterator iter = node.getRecursiveAuthorIterator(); iter.hasNext(); ) {

View File

@ -1102,7 +1102,7 @@ public class HTMLRenderer extends EventReceiverImpl {
+ "&" + SyndicateServlet.PARAM_SCHEMA + "=" + sanitizeTagParam(archiveLocation.getSchema()) + "&" + SyndicateServlet.PARAM_SCHEMA + "=" + sanitizeTagParam(archiveLocation.getSchema())
+ "&" + SyndicateServlet.PARAM_LOCATION + "=" + sanitizeTagParam(archiveLocation.getLocation()); + "&" + SyndicateServlet.PARAM_LOCATION + "=" + sanitizeTagParam(archiveLocation.getLocation());
} }
public String getBookmarkURL(String name, String location, String schema, String protocol) { public static String getBookmarkURL(String name, String location, String schema, String protocol) {
return "addresses.jsp?" + AddressesServlet.PARAM_NAME + '=' + sanitizeTagParam(name) return "addresses.jsp?" + AddressesServlet.PARAM_NAME + '=' + sanitizeTagParam(name)
+ "&" + AddressesServlet.PARAM_NET + '=' + sanitizeTagParam(schema) + "&" + AddressesServlet.PARAM_NET + '=' + sanitizeTagParam(schema)
+ "&" + AddressesServlet.PARAM_PROTO + '=' + sanitizeTagParam(protocol) + "&" + AddressesServlet.PARAM_PROTO + '=' + sanitizeTagParam(protocol)

View File

@ -23,7 +23,7 @@ import net.i2p.util.Log;
*/ */
public abstract class BaseServlet extends HttpServlet { public abstract class BaseServlet extends HttpServlet {
protected static final String PARAM_AUTH_ACTION = "syndie.auth"; protected static final String PARAM_AUTH_ACTION = "syndie.auth";
private static long _authNonce; protected static long _authNonce;
protected I2PAppContext _context; protected I2PAppContext _context;
protected Log _log; protected Log _log;
@ -141,6 +141,7 @@ public abstract class BaseServlet extends HttpServlet {
forceNewIndex = handleBookmarking(user, req) || forceNewIndex; forceNewIndex = handleBookmarking(user, req) || forceNewIndex;
forceNewIndex = handleManageTags(user, req) || forceNewIndex; forceNewIndex = handleManageTags(user, req) || forceNewIndex;
handleUpdateProfile(user, req); handleUpdateProfile(user, req);
req.setAttribute(BaseServlet.class.getName() + ".auth", "true");
} }
// the 'dataImported' flag is set by successful fetches in the SyndicateServlet/RemoteArchiveBean // the 'dataImported' flag is set by successful fetches in the SyndicateServlet/RemoteArchiveBean
@ -176,6 +177,10 @@ public abstract class BaseServlet extends HttpServlet {
protected void render(User user, HttpServletRequest req, HttpServletResponse resp, ThreadIndex index) throws IOException, ServletException { protected void render(User user, HttpServletRequest req, HttpServletResponse resp, ThreadIndex index) throws IOException, ServletException {
render(user, req, resp.getWriter(), index); render(user, req, resp.getWriter(), index);
} }
protected boolean isAuthed(HttpServletRequest req) {
String auth = (String)req.getAttribute(BaseServlet.class.getName() + ".auth");
return (auth != null) && (Boolean.valueOf(auth).booleanValue());
}
private boolean handleBookmarking(User user, HttpServletRequest req) { private boolean handleBookmarking(User user, HttpServletRequest req) {
if (!user.getAuthenticated()) if (!user.getAuthenticated())

View File

@ -33,6 +33,8 @@ public class BlogConfigBean {
_styleOverrides = new Properties(); _styleOverrides = new Properties();
} }
public boolean isUpdated() { return _updated; }
public User getUser() { return _user; } public User getUser() { return _user; }
public void setUser(User user) { public void setUser(User user) {
_user = user; _user = user;
@ -74,6 +76,8 @@ public class BlogConfigBean {
PetName pn = (PetName)grp.get(0); PetName pn = (PetName)grp.get(0);
if ( (pn.getGroupCount() == 0) && ( (name == null) || (name.length() <= 0) ) ) if ( (pn.getGroupCount() == 0) && ( (name == null) || (name.length() <= 0) ) )
return grp; return grp;
if (pn.getGroupCount() == 0)
continue;
String curGroup = pn.getGroup(0); String curGroup = pn.getGroup(0);
if (curGroup.equals(name)) if (curGroup.equals(name))
return grp; return grp;
@ -94,6 +98,7 @@ public class BlogConfigBean {
} else { } else {
group.add(pn); group.add(pn);
} }
_updated = true;
} }
public void remove(PetName pn) { public void remove(PetName pn) {
String groupName = null; String groupName = null;
@ -105,6 +110,7 @@ public class BlogConfigBean {
if (group.size() <= 0) if (group.size() <= 0)
_groups.remove(group); _groups.remove(group);
} }
_updated = true;
} }
public void remove(String name) { public void remove(String name) {
for (int i = 0; i < getGroupCount(); i++) { for (int i = 0; i < getGroupCount(); i++) {
@ -115,6 +121,7 @@ public class BlogConfigBean {
group.remove(j); group.remove(j);
if (group.size() <= 0) if (group.size() <= 0)
_groups.remove(group); _groups.remove(group);
_updated = true;
return; return;
} }
} }
@ -140,7 +147,7 @@ public class BlogConfigBean {
_logo = logo; _logo = logo;
_updated = true; _updated = true;
} }
public boolean hasPendingChanges() { return _updated; } public boolean hasPendingChanges() { return _loaded && _updated; }
private void load() { private void load() {
Archive archive = BlogManager.instance().getArchive(); Archive archive = BlogManager.instance().getArchive();
@ -175,7 +182,9 @@ public class BlogConfigBean {
add(pn); add(pn);
} }
} }
_styleOverrides.putAll(data.getStyleOverrides()); Properties overrides = data.getStyleOverrides();
if (overrides != null)
_styleOverrides.putAll(overrides);
} catch (IOException ioe) { } catch (IOException ioe) {
_log.warn("Unable to load the blog info data from " + uri, ioe); _log.warn("Unable to load the blog info data from " + uri, ioe);
} }
@ -183,9 +192,10 @@ public class BlogConfigBean {
} }
} }
_loaded = true; _loaded = true;
_updated = false;
} }
public boolean publishChanges() throws IOException { public boolean publishChanges() {
FileInputStream logo = null; FileInputStream logo = null;
try { try {
if (_logo != null) if (_logo != null)
@ -229,6 +239,7 @@ public class BlogConfigBean {
if (updated) { if (updated) {
// ok great, published locally, though should we push it to others? // ok great, published locally, though should we push it to others?
_log.info("Blog summary updated for " + _user + " in " + uri.toString()); _log.info("Blog summary updated for " + _user + " in " + uri.toString());
setUser(_user);
return true; return true;
} }
} else { } else {
@ -239,6 +250,8 @@ public class BlogConfigBean {
_log.error("Error creating the summary entry"); _log.error("Error creating the summary entry");
return false; return false;
} }
} catch (IOException ioe) {
_log.error("Error publishing", ioe);
} finally { } finally {
if (logo != null) try { logo.close(); } catch (IOException ioe) {} if (logo != null) try { logo.close(); } catch (IOException ioe) {}
// the other streams are in-memory, drop with the scope // the other streams are in-memory, drop with the scope

View File

@ -22,8 +22,8 @@ import net.i2p.syndie.sml.*;
public class BlogConfigServlet extends BaseServlet { public class BlogConfigServlet extends BaseServlet {
private static final String ATTR_CONFIG_BEAN = "__blogConfigBean"; private static final String ATTR_CONFIG_BEAN = "__blogConfigBean";
public static final String PARAM_CONFIG_SCREEN = "screen"; public static final String PARAM_CONFIG_SCREEN = "screen";
public static final String SCREEN_GENERAL = "general";
public static final String SCREEN_REFERENCES = "references"; public static final String SCREEN_REFERENCES = "references";
public static final String SCREEN_IMAGES = "images";
protected void renderServletDetails(User user, HttpServletRequest req, PrintWriter out, ThreadIndex index, protected void renderServletDetails(User user, HttpServletRequest req, PrintWriter out, ThreadIndex index,
int threadOffset, BlogURI visibleEntry, Archive archive) throws IOException { int threadOffset, BlogURI visibleEntry, Archive archive) throws IOException {
if ( (user == null) || (!user.getAuthenticated() && !BlogManager.instance().isSingleUser())) { if ( (user == null) || (!user.getAuthenticated() && !BlogManager.instance().isSingleUser())) {
@ -34,6 +34,7 @@ public class BlogConfigServlet extends BaseServlet {
if (bean == null) { if (bean == null) {
bean = new BlogConfigBean(); bean = new BlogConfigBean();
bean.setUser(user); bean.setUser(user);
req.getSession().setAttribute(ATTR_CONFIG_BEAN, bean);
} }
// handle actions here... // handle actions here...
@ -41,191 +42,329 @@ public class BlogConfigServlet extends BaseServlet {
String screen = req.getParameter(PARAM_CONFIG_SCREEN); String screen = req.getParameter(PARAM_CONFIG_SCREEN);
if (screen == null) if (screen == null)
screen = SCREEN_GENERAL; screen = SCREEN_REFERENCES;
out.write("todo: Display screen " + screen); out.write("<tr><td colspan=\"3\">\n");
/* showConfigNav(req, out);
if (SCREEN_REFERENCES.equals(screen)) {
displayReferencesScreen(req, out, bean); if (isAuthed(req)) {
StringBuffer buf = handleOtherAuthedActions(user, req, bean);
if (buf != null) out.write(buf.toString());
} else { } else {
displayGeneralScreen(req, out, bean);
} }
*/ if (bean.isUpdated())
} showCommitForm(req, out);
/*
private void renderMyProfile(User user, String baseURI, PrintWriter out, Archive archive) throws IOException {
BlogInfo info = archive.getBlogInfo(user.getBlog());
if (info == null)
return;
out.write("<!-- " + info.toString() + "-->\n"); if (SCREEN_REFERENCES.equals(screen)) {
out.write("<form action=\"" + baseURI + "\" method=\"POST\">\n"); displayReferencesScreen(req, out, user, bean);
} else {
displayUnknownScreen(out, screen);
}
out.write("</td></tr>\n");
}
private void showCommitForm(HttpServletRequest req, PrintWriter out) throws IOException {
out.write("<form action=\"" + req.getRequestURI() + "\" method=\"GET\">\n");
writeAuthActionFields(out); writeAuthActionFields(out);
// now add the form to update out.write("<i>Note: Uncommitted changes outstanding</a> <input type=\"submit\" name=\"action\" " +
out.write("<tr><td colspan=\"3\">Your profile</td></tr>\n"); "value=\"Publish blog configuration\" />\n</form>\n");
out.write("<tr><td colspan=\"3\">Name: <input type=\"text\" name=\"" }
+ ThreadedHTMLRenderer.PARAM_PROFILE_NAME + "\" value=\""
+ HTMLRenderer.sanitizeTagParam(info.getProperty(BlogInfo.NAME)) + "\"></td></tr>\n"); private void showConfigNav(HttpServletRequest req, PrintWriter out) throws IOException {
out.write("<tr><td colspan=\"3\">Account description: <input type=\"text\" name=\"" out.write("<span class=\"syndieBlogConfigNav\"><a href=\"" + getScreenURL(req, SCREEN_REFERENCES, false)
+ ThreadedHTMLRenderer.PARAM_PROFILE_DESC + "\" value=\"" + "\" title=\"Configure the blog's references\">References</a> "
+ HTMLRenderer.sanitizeTagParam(info.getProperty(BlogInfo.DESCRIPTION)) + "\"></td></tr>\n"); + "<a href=\"" + getScreenURL(req, SCREEN_IMAGES, false)
out.write("<tr><td colspan=\"3\">Contact information: <input type=\"text\" name=\"" + "\" title=\"Configure the images used on the blog\">Images</a></span><hr />\n");
+ ThreadedHTMLRenderer.PARAM_PROFILE_URL + "\" value=\"" }
+ HTMLRenderer.sanitizeTagParam(info.getProperty(BlogInfo.CONTACT_URL)) + "\"></td></tr>\n");
out.write("<tr><td colspan=\"3\">Other attributes:<br /><textarea rows=\"3\" name=\"" private String getScreenURL(HttpServletRequest req, String screen, boolean wantAuth) {
+ ThreadedHTMLRenderer.PARAM_PROFILE_OTHER + "\" cols=\"60\">"); StringBuffer buf = new StringBuffer(128);
String props[] = info.getProperties(); buf.append(req.getRequestURI()).append("?").append(PARAM_CONFIG_SCREEN).append("=");
if (props != null) { buf.append(screen).append("&amp;");
for (int i = 0; i < props.length; i++) { if (wantAuth)
if (!BlogInfo.NAME.equals(props[i]) && buf.append(PARAM_AUTH_ACTION).append('=').append(_authNonce).append("&amp;");
!BlogInfo.DESCRIPTION.equals(props[i]) && return buf.toString();
!BlogInfo.EDITION.equals(props[i]) && }
!BlogInfo.OWNER_KEY.equals(props[i]) &&
!BlogInfo.POSTERS.equals(props[i]) && private void displayUnknownScreen(PrintWriter out, String screen) throws IOException {
!BlogInfo.SIGNATURE.equals(props[i]) && out.write("<br /><hr />The screen " + HTMLRenderer.sanitizeString(screen) + " has not yet been implemented");
!BlogInfo.CONTACT_URL.equals(props[i])) { }
out.write(HTMLRenderer.sanitizeString(props[i], false) + ": " private void displayReferencesScreen(HttpServletRequest req, PrintWriter out, User user, BlogConfigBean bean) throws IOException {
+ HTMLRenderer.sanitizeString(info.getProperty(props[i]), false) + "\n"); out.write("<form action=\"" + getScreenURL(req, SCREEN_REFERENCES, false) + "\" method=\"POST\">\n");
} writeAuthActionFields(out);
} out.write("<ol class=\"syndieReferenceGroupList\">\n");
} boolean defaultFound = false;
out.write("</textarea></td></tr>\n"); for (int i = 0; i < bean.getGroupCount(); i++) {
List group = bean.getGroup(i);
if (user.getAuthenticated()) { String groupName = null;
if ( (user.getUsername() == null) || (user.getUsername().equals(BlogManager.instance().getDefaultLogin())) ) { PetName pn = (PetName)group.get(0);
// this is the default user, don't let them change the password if (pn.getGroupCount() <= 0) {
groupName = ViewBlogServlet.DEFAULT_GROUP_NAME;
defaultFound = true;
} else { } else {
out.write("<tr><td colspan=\"3\">Old Password: <input type=\"password\" name=\"oldPassword\" /></td></tr>\n"); groupName = pn.getGroup(0);
out.write("<tr><td colspan=\"3\">Password: <input type=\"password\" name=\"password\" /></td></tr>\n");
out.write("<tr><td colspan=\"3\">Password again: <input type=\"password\" name=\"passwordConfirm\" /></td></tr>\n");
} }
if (!BlogManager.instance().authorizeRemote(user)) { out.write("<li><b>Group:</b> " + HTMLRenderer.sanitizeString(groupName) + "\n");
out.write("<tr><td colspan=\"3\">To access the remote functionality, please specify the administrative password: <br />\n" + if (i > 0)
"<input type=\"password\" name=\"adminPass\" /></td></tr>\n"); out.write(" <a href=\"" + getScreenURL(req, SCREEN_REFERENCES, true) + "moveFrom=" + i +
"&amp;moveTo=" + (i-1) + "\" title=\"Move higher\">^</a>");
if (i + 1 < bean.getGroupCount())
out.write(" <a href=\"" + getScreenURL(req, SCREEN_REFERENCES, true) + "moveFrom=" + i +
"&amp;moveTo=" + (i+1) + "\" title=\"Move lower\">v</a>");
out.write(" <a href=\"" + getScreenURL(req, SCREEN_REFERENCES, true) + "delete=" + i + "\" title=\"Delete\">X</a>");
out.write("<ol class=\"syndieReferenceGroupElementList\">\n");
for (int j = 0; j < group.size(); j++) {
out.write("<li>" + ViewBlogServlet.renderLink(user.getBlog(), (PetName)group.get(j)));
if (j > 0)
out.write(" <a href=\"" + getScreenURL(req, SCREEN_REFERENCES, true) + "moveRefFrom=" + i + "." + j +
"&amp;moveRefTo=" + i + "." + (j-1) + "\" title=\"Move higher\">^</a>");
if (j + 1 < group.size())
out.write(" <a href=\"" + getScreenURL(req, SCREEN_REFERENCES, true) + "moveRefFrom=" + i + "." + j +
"&amp;moveRefTo=" + i + "." + (j+1) + "\" title=\"Move lower\">v</a>");
out.write(" <a href=\"" + getScreenURL(req, SCREEN_REFERENCES, true) + "delete=" + i + "." + j
+ "\" title=\"Delete\">X</a>");
out.write("</li>\n");
} }
out.write("</ol><!-- end of the syndieReferenceGroupElementList -->\n");
out.write("</li>\n");
} }
out.write("</ol><!-- end of the syndieReferenceGroupList -->\n");
out.write("<tr><td colspan=\"3\"><input type=\"submit\" name=\"action\" value=\"Update profile\" /></td></tr>\n");
out.write("Add a new element: <br />Group: <select name=\"new.group\"><option value=\"\">Select a group...</option>");
for (int i = 0; i < bean.getGroupCount(); i++) {
List group = bean.getGroup(i);
String groupName = null;
PetName pn = (PetName)group.get(0);
if (pn.getGroupCount() <= 0)
groupName = ViewBlogServlet.DEFAULT_GROUP_NAME;
else
groupName = pn.getGroup(0);
if (groupName != null)
out.write("<option value=\"" + HTMLRenderer.sanitizeTagParam(groupName) + "\">" +
HTMLRenderer.sanitizeString(groupName) + "</option>\n");
}
if (!defaultFound)
out.write("<option value=\"" + ViewBlogServlet.DEFAULT_GROUP_NAME + "\">"
+ ViewBlogServlet.DEFAULT_GROUP_NAME + "</option>\n");
out.write("</select> or <input type=\"text\" size=\"12\" name=\"new.groupOther\" /><br />" +
"Type: <select name=\"new.type\"><option value=\"blog\">Syndie blog</option>\n" +
"<option value=\"blogpost\">Post within a syndie blog</option>\n" +
"<option value=\"blogpostattachment\">Attachment within a syndie blog</option>\n" +
"<option value=\"eepsite\">Eepsite</option>\n" +
"<option value=\"website\">Website</option>\n</select><br />\n" +
"Name: <input type=\"text\" size=\"20\" name=\"new.name\" /><br /> " +
"Location: <input type=\"text\" name=\"new.location\" size=\"40\" />\n" +
"<ul><li>Blogs should be specified as <code>$base64Key</code></li>\n" +
"<li>Blog posts should be specified as <code>$base64Key/$postEntryId</code></li>\n" +
"<li>Blog post attachments should be specified as <code>$base64Key/$postEntryId/$attachmentNum</code></li>\n" +
"</ul><hr />\n");
out.write("<input type=\"submit\" name=\"action\" value=\"Save changes\">\n");
out.write("</form>\n"); out.write("</form>\n");
} }
private void renderProfile(User user, String baseURI, PrintWriter out, Hash author, Archive archive) throws IOException { private void writePetnameDropdown(PrintWriter out, PetNameDB db) throws IOException {
out.write("<tr><td colspan=\"3\">Profile for "); Set names = db.getNames();
PetName pn = user.getPetNameDB().getByLocation(author.toBase64()); TreeSet ordered = new TreeSet(names);
String name = null; for (Iterator iter = ordered.iterator(); iter.hasNext(); ) {
BlogInfo info = archive.getBlogInfo(author); String name = (String)iter.next();
PetName pn = db.getByName(name);
String proto = pn.getProtocol();
if ("syndietag".equals(proto))
continue;
out.write("<option value=\"" + HTMLRenderer.sanitizeTagParam(pn.getName()) + "\">");
if ("syndieblog".equals(proto))
out.write("Blog: ");
else if ("syndiearchive".equals(proto))
out.write("Archive: ");
else if ("eep".equals(proto))
out.write("Eepsite: ");
else
out.write(HTMLRenderer.sanitizeString(proto) + ": ");
out.write(HTMLRenderer.sanitizeString(pn.getName()) + "</option>\n");
}
}
protected StringBuffer handleOtherAuthedActions(User user, HttpServletRequest req, BlogConfigBean bean) {
StringBuffer buf = new StringBuffer();
req.setAttribute(getClass().getName() + ".output", buf);
String action = req.getParameter("action");
if ("Publish blog configuration".equals(action)) {
if (bean.publishChanges()) {
buf.append("Changes published<br />\n");
} else {
buf.append("Changes could not be published (please check the log)<br />\n");
}
} else {
if ("Save changes".equals(action)) {
String newGroup = req.getParameter("new.group");
if ( (newGroup == null) || (newGroup.trim().length() <= 0) )
newGroup = req.getParameter("new.groupOther");
if ( (newGroup != null) && (newGroup.trim().length() > 0) ) {
addElement(req, user, newGroup, buf, bean);
} else {
}
} else {
}
handleDelete(req, user, bean, buf);
handleReorderGroup(req, user, bean, buf);
handleReorderRef(req, user, bean, buf);
}
return buf;
}
private void addElement(HttpServletRequest req, User user, String newGroup, StringBuffer actionOutputHTML, BlogConfigBean bean) {
String type = req.getParameter("new.type");
String loc = req.getParameter("new.location");
String name = req.getParameter("new.name");
if (empty(type) || empty(loc) || empty(name)) return;
PetName pn = null;
if ("blog".equals(type))
pn = new PetName(name, "syndie", "syndieblog", loc);
else if ("blogpost".equals(type))
pn = new PetName(name, "syndie", "syndieblogpost", loc);
else if ("blogpostattachment".equals(type))
pn = new PetName(name, "syndie", "syndieblogattachment", loc);
else if ("eepsite".equals(type))
pn = new PetName(name, "i2p", "http", loc);
else if ("website".equals(type))
pn = new PetName(name, "web", "http", loc);
else {
// unknown type
}
if (pn != null) { if (pn != null) {
out.write(pn.getName()); if (!ViewBlogServlet.DEFAULT_GROUP_NAME.equals(newGroup))
name = null; pn.addGroup(newGroup);
if (info != null) bean.add(pn);
name = info.getProperty(BlogInfo.NAME); actionOutputHTML.append("Reference '").append(HTMLRenderer.sanitizeString(name));
actionOutputHTML.append("' for ").append(HTMLRenderer.sanitizeString(loc)).append(" added to ");
if ( (name == null) || (name.trim().length() <= 0) ) actionOutputHTML.append(HTMLRenderer.sanitizeString(newGroup)).append("<br />\n");
name = author.toBase64().substring(0, 6);
out.write(" (" + name + ")");
} else {
if (info != null)
name = info.getProperty(BlogInfo.NAME);
if ( (name == null) || (name.trim().length() <= 0) )
name = author.toBase64().substring(0, 6);
out.write(name);
} }
out.write("</a>"); }
if (info != null)
out.write(" [edition " + info.getEdition() + "]"); private void handleDelete(HttpServletRequest req, User user, BlogConfigBean bean, StringBuffer actionOutputHTML) {
out.write("<br />\n"); // control parameters:
out.write("<a href=\"" + getControlTarget() + "?" + ThreadedHTMLRenderer.PARAM_AUTHOR // delete=$i removes group # $i
+ '=' + author.toBase64() + "&" + ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR + "=true&\"" // delete=$i.$j removes element $j in group $i
+ " title=\"View '" + HTMLRenderer.sanitizeTagParam(name) + "'s blog\">View their blog</a> or "); String del = req.getParameter("delete");
out.write("<a href=\"" + getControlTarget() + "?" + ThreadedHTMLRenderer.PARAM_AUTHOR if (empty(del)) return;
+ '=' + author.toBase64() + "&\">threads they have participated in</a>\n"); int split = del.indexOf('.');
out.write("</td></tr>\n"); int group = -1;
int elem = -1;
out.write("<tr><td colspan=\"3\"><hr /></td></tr>\n"); if (split <= 0) {
if (pn == null) { try { group = Integer.parseInt(del); } catch (NumberFormatException nfe) {}
out.write("<tr><td colspan=\"3\">Not currently bookmarked. Add them to your ");
String addFav = getAddToGroupLink(user, author, FilteredThreadIndex.GROUP_FAVORITE,
baseURI, "", "", "", "", "", author.toBase64());
String addIgnore = getAddToGroupLink(user, author, FilteredThreadIndex.GROUP_IGNORE,
baseURI, "", "", "", "", "", author.toBase64());
out.write("<a href=\"" + addFav + "\" title=\"Threads by favorite authors are shown specially\">favorites</a> or ");
out.write("<a href=\"" + addIgnore + "\" title=\"Threads by ignored authors are hidden from view\">ignored</a> ");
out.write("</td></tr>\n");
} else if (pn.isMember(FilteredThreadIndex.GROUP_IGNORE)) {
out.write("<tr><td colspan=\"3\">Currently ignored - threads they create are hidden.</td></tr>\n");
String remIgnore = getRemoveFromGroupLink(user, pn.getName(), FilteredThreadIndex.GROUP_IGNORE,
baseURI, "", "", "", "", "", author.toBase64());
out.write("<tr><td colspan=\"3\"><a href=\"" + remIgnore + "\">Unignore " + pn.getName() + "</a></td></tr>\n");
String remCompletely = getRemoveFromGroupLink(user, pn.getName(), "",
baseURI, "", "", "", "", "", author.toBase64());
out.write("<tr><td colspan=\"3\"><a href=\"" + remCompletely + "\">Forget about " + pn.getName() + " entirely</a></td></tr>\n");
} else if (pn.isMember(FilteredThreadIndex.GROUP_FAVORITE)) {
out.write("<tr><td colspan=\"3\">Currently marked as a favorite author - threads they participate in " +
"are highlighted.</td></tr>\n");
String remIgnore = getRemoveFromGroupLink(user, pn.getName(), FilteredThreadIndex.GROUP_FAVORITE,
baseURI, "", "", "", "", "", author.toBase64());
out.write("<tr><td colspan=\"3\"><a href=\"" + remIgnore + "\">Remove " + pn.getName() + " from the list of favorite authors</a></td></tr>\n");
String addIgnore = getAddToGroupLink(user, author, FilteredThreadIndex.GROUP_IGNORE,
baseURI, "", "", "", "", "", author.toBase64());
out.write("<tr><td colspan=\"3\"><a href=\"" + addIgnore + "\" title=\"Threads by ignored authors are hidden from view\">Ignore the author</a></td></tr>");
String remCompletely = getRemoveFromGroupLink(user, pn.getName(), "",
baseURI, "", "", "", "", "", author.toBase64());
out.write("<tr><td colspan=\"3\"><a href=\"" + remCompletely + "\">Forget about " + pn.getName() + " entirely</a></td></tr>\n");
} else { } else {
out.write("<tr><td colspan=\"3\">Currently bookmarked. Add them to your "); try {
String addFav = getAddToGroupLink(user, author, FilteredThreadIndex.GROUP_FAVORITE, group = Integer.parseInt(del.substring(0, split));
baseURI, "", "", "", "", "", author.toBase64()); elem = Integer.parseInt(del.substring(split+1));
String addIgnore = getAddToGroupLink(user, author, FilteredThreadIndex.GROUP_IGNORE, } catch (NumberFormatException nfe) {
baseURI, "", "", "", "", "", author.toBase64()); group = -1;
out.write("<a href=\"" + addFav + "\" title=\"Threads by favorite authors are shown specially\">favorites</a> or "); elem = -1;
out.write("<a href=\"" + addIgnore + "\" title=\"Threads by ignored authors are hidden from view\">ignored</a> list</td></tr>"); }
String remCompletely = getRemoveFromGroupLink(user, pn.getName(), "",
baseURI, "", "", "", "", "", author.toBase64());
out.write("<tr><td colspan=\"3\"><a href=\"" + remCompletely + "\">Forget about " + pn.getName() + " entirely</a></td></tr>\n");
} }
if ( (elem >= 0) && (group >= 0) ) {
if (info != null) { List l = bean.getGroup(group);
String descr = info.getProperty(BlogInfo.DESCRIPTION); if (elem < l.size()) {
if ( (descr != null) && (descr.trim().length() > 0) ) PetName pn = (PetName)l.get(elem);
out.write("<tr><td colspan=\"3\">Account description: " + HTMLRenderer.sanitizeString(descr) + "</td></tr>\n"); bean.remove(pn);
actionOutputHTML.append("Reference '").append(HTMLRenderer.sanitizeString(pn.getName()));
actionOutputHTML.append("' for ").append(HTMLRenderer.sanitizeString(pn.getLocation()));
actionOutputHTML.append(" removed<br />\n");
}
} else if ( (elem == -1) && (group >= 0) ) {
List l = bean.getGroup(group);
for (int i = 0; i < l.size(); i++) {
PetName pn = (PetName)l.get(i);
bean.remove(pn);
}
actionOutputHTML.append("All references in the selected group were removed<br />\n");
} else {
// noop
}
}
private void handleReorderGroup(HttpServletRequest req, User user, BlogConfigBean bean, StringBuffer actionOutputHTML) {
// control parameters:
// moveFrom=$i & moveTo=$j moves group $i to position $j
int from = -1;
int to = -1;
try {
String str = req.getParameter("moveFrom");
if (str != null)
from = Integer.parseInt(str);
str = req.getParameter("moveTo");
if (str != null)
to = Integer.parseInt(str);
String contactURL = info.getProperty(BlogInfo.CONTACT_URL); if ( (from >= 0) && (to >= 0) ) {
if ( (contactURL != null) && (contactURL.trim().length() > 0) ) List src = bean.getGroup(from);
out.write("<tr><td colspan=\"3\">Contact information: " List dest = bean.getGroup(to);
+ HTMLRenderer.sanitizeString(contactURL) + "</td></tr>\n"); List orig = new ArrayList(dest);
dest.clear();
String props[] = info.getProperties(); dest.addAll(src);
int altCount = 0; src.clear();
if (props != null) src.addAll(orig);
for (int i = 0; i < props.length; i++) bean.groupsUpdated();
if (!BlogInfo.NAME.equals(props[i]) && actionOutputHTML.append("Reference group moved<br />\n");
!BlogInfo.DESCRIPTION.equals(props[i]) && }
!BlogInfo.EDITION.equals(props[i]) && } catch (NumberFormatException nfe) {
!BlogInfo.OWNER_KEY.equals(props[i]) && // ignore
!BlogInfo.POSTERS.equals(props[i]) && }
!BlogInfo.SIGNATURE.equals(props[i]) && }
!BlogInfo.CONTACT_URL.equals(props[i]))
altCount++; private void handleReorderRef(HttpServletRequest req, User user, BlogConfigBean bean, StringBuffer actionOutputHTML) {
if (altCount > 0) { // control parameters:
for (int i = 0; i < props.length; i++) { // moveRefFrom=$i.$j & moveRefTo=$k.$l moves element $j in group $i to position $l in group l
if (!BlogInfo.NAME.equals(props[i]) && // (i == k)
!BlogInfo.DESCRIPTION.equals(props[i]) && int from = -1;
!BlogInfo.EDITION.equals(props[i]) && int fromElem = -1;
!BlogInfo.OWNER_KEY.equals(props[i]) && int to = -1; // ignored
!BlogInfo.POSTERS.equals(props[i]) && int toElem = -1;
!BlogInfo.SIGNATURE.equals(props[i]) && try {
!BlogInfo.CONTACT_URL.equals(props[i])) { String str = req.getParameter("moveRefFrom");
out.write("<tr><td colspan=\"3\">"); if (str != null) {
out.write(HTMLRenderer.sanitizeString(props[i]) + ": " int split = str.indexOf('.');
+ HTMLRenderer.sanitizeString(info.getProperty(props[i]))); if (split > 0) {
out.write("</td></tr>\n"); try {
from = Integer.parseInt(str.substring(0, split));
fromElem = Integer.parseInt(str.substring(split+1));
} catch (NumberFormatException nfe) {
from = -1;
fromElem = -1;
} }
} }
} }
str = req.getParameter("moveRefTo");
if (str != null) {
int split = str.indexOf('.');
if (split > 0) {
try {
to = Integer.parseInt(str.substring(0, split));
toElem = Integer.parseInt(str.substring(split+1));
} catch (NumberFormatException nfe) {
to = -1;
toElem = -1;
}
}
}
if ( (from >= 0) && (fromElem >= 0) && (toElem >= 0) ) {
List src = bean.getGroup(from);
PetName pn = (PetName)src.remove(fromElem);
src.add(toElem, pn);
bean.groupsUpdated();
actionOutputHTML.append("Reference element moved<br />\n");
}
} catch (NumberFormatException nfe) {
// ignore
} }
} }
*/
protected String getTitle() { return "Syndie :: Configure blog"; } protected String getTitle() { return "Syndie :: Configure blog"; }
} }

View File

@ -104,6 +104,7 @@ public class ProfileServlet extends BaseServlet {
out.write("<tr><td colspan=\"3\"><input type=\"submit\" name=\"action\" value=\"Update profile\" /></td></tr>\n"); out.write("<tr><td colspan=\"3\"><input type=\"submit\" name=\"action\" value=\"Update profile\" /></td></tr>\n");
out.write("</form>\n"); out.write("</form>\n");
out.write("<tr><td colspan=\"3\"><a href=\"configblog.jsp\">Configure your blog</a></td></tr>\n");
} }
private void renderProfile(User user, String baseURI, PrintWriter out, Hash author, Archive archive) throws IOException { private void renderProfile(User user, String baseURI, PrintWriter out, Hash author, Archive archive) throws IOException {

View File

@ -79,6 +79,20 @@ public class ViewBlogServlet extends BaseServlet {
private List getPosts(User user, Archive archive, BlogInfo info, HttpServletRequest req, ThreadIndex index) { private List getPosts(User user, Archive archive, BlogInfo info, HttpServletRequest req, ThreadIndex index) {
List rv = new ArrayList(1); List rv = new ArrayList(1);
if (info == null) return rv; if (info == null) return rv;
String entrySelected = req.getParameter(PARAM_ENTRY);
if (entrySelected != null) {
// $blogKey/$entryId
BlogURI uri = null;
if (entrySelected.startsWith("blog://"))
uri = new BlogURI(entrySelected);
else
uri = new BlogURI("blog://" + entrySelected.trim());
if (uri.getEntryId() >= 0) {
rv.add(uri);
return rv;
}
}
ArchiveIndex aindex = archive.getIndex(); ArchiveIndex aindex = archive.getIndex();
@ -188,7 +202,7 @@ public class ViewBlogServlet extends BaseServlet {
out.write("</div>\n"); out.write("</div>\n");
} }
private static final String DEFAULT_GROUP_NAME = "References"; public static final String DEFAULT_GROUP_NAME = "References";
private void renderReferences(PrintWriter out, BlogInfo info, BlogInfoData data) throws IOException { private void renderReferences(PrintWriter out, BlogInfo info, BlogInfoData data) throws IOException {
out.write("<div class=\"syndieBlogLinks\">\n"); out.write("<div class=\"syndieBlogLinks\">\n");
if (data != null) { if (data != null) {
@ -207,23 +221,118 @@ public class ViewBlogServlet extends BaseServlet {
out.write("<ul>\n"); out.write("<ul>\n");
for (int j = 0; j < group.size(); j++) { for (int j = 0; j < group.size(); j++) {
pn = (PetName)group.get(j); pn = (PetName)group.get(j);
out.write("<li>" + renderLink(pn) + "</li>\n"); out.write("<li>" + renderLink(info.getKey().calculateHash(), pn) + "</li>\n");
} }
out.write("</ul>\n</div>\n<!-- end " + name + " -->\n"); out.write("</ul>\n</div>\n<!-- end " + name + " -->\n");
} }
} }
out.write("<div class=\"syndieBlogLinkGroup\">\n"); //out.write("<div class=\"syndieBlogLinkGroup\">\n");
out.write("<span class=\"syndieBlogLinkGroupName\">Custom links</span>\n"); //out.write("<span class=\"syndieBlogLinkGroupName\">Custom links</span>\n");
out.write("<ul><li><a href=\"\">are not yet implemented</a></li><li><a href=\"\">but are coming soon</a></li></ul>\n"); //out.write("<ul><li><a href=\"\">are not yet implemented</a></li><li><a href=\"\">but are coming soon</a></li></ul>\n");
out.write("</div><!-- end fake group -->"); //out.write("</div><!-- end fake group -->");
out.write("<div class=\"syndieBlogMeta\">"); out.write("<div class=\"syndieBlogMeta\">");
out.write("Secured by <a href=\"http://syndie.i2p.net/\">Syndie</a>"); out.write("Secured by <a href=\"http://syndie.i2p.net/\">Syndie</a>");
out.write("</div>\n"); out.write("</div>\n");
out.write("</div><!-- end syndieBlogLinks -->\n\n"); out.write("</div><!-- end syndieBlogLinks -->\n\n");
} }
private String renderLink(PetName pn) { /** generate a link for the given petname within the scope of the given blog */
return "<a href=\"\" title=\"go somewhere\">" + HTMLRenderer.sanitizeString(pn.getName()) + "</a>"; public static String renderLink(Hash blogFrom, PetName pn) {
StringBuffer buf = new StringBuffer(64);
String type = pn.getProtocol();
if ("syndieblog".equals(type)) {
String loc = pn.getLocation();
if (loc != null) {
buf.append("<a href=\"blog.jsp?").append(PARAM_BLOG).append("=");
buf.append(HTMLRenderer.sanitizeTagParam(pn.getLocation()));
buf.append("\" title=\"View ").append(HTMLRenderer.sanitizeTagParam(pn.getName())).append("\">");
}
buf.append(HTMLRenderer.sanitizeString(pn.getName()));
if (loc != null) {
buf.append("</a>");
//buf.append(" <a href=\"").append(HTMLRenderer.getBookmarkURL(pn.getName(), pn.getLocation(), "syndie", "syndieblog"));
//buf.append("\" title=\"Bookmark ").append(HTMLRenderer.sanitizeTagParam(pn.getName())).append("\"><image src=\"images/addToFavorites.png\" alt=\"\" /></a>\n");
}
} else if ("syndieblogpost".equals(type)) {
String loc = pn.getLocation();
if (loc != null) {
buf.append("<a href=\"blog.jsp?").append(PARAM_BLOG).append("=");
buf.append(blogFrom.toBase64()).append("&amp;");
buf.append(PARAM_ENTRY).append("=").append(HTMLRenderer.sanitizeTagParam(pn.getLocation()));
buf.append("\" title=\"View the specified post\">");
}
buf.append(HTMLRenderer.sanitizeString(pn.getName()));
if (loc != null) {
buf.append("</a>");
}
} else if ("syndieblogattachment".equals(type)) {
String loc = pn.getLocation();
if (loc != null) {
int split = loc.lastIndexOf('/');
try {
int attachmentId = -1;
if (split > 0)
attachmentId = Integer.parseInt(loc.substring(split+1));
if (attachmentId < 0) {
loc = null;
} else {
BlogURI post = null;
if (loc.startsWith("blog://"))
post = new BlogURI(loc.substring(0, split));
else
post = new BlogURI("blog://" + loc.substring(0, split));
EntryContainer entry = BlogManager.instance().getArchive().getEntry(post);
if (entry != null) {
Attachment attachments[] = entry.getAttachments();
if (attachmentId < attachments.length) {
buf.append("<a href=\"blog.jsp?").append(PARAM_BLOG).append("=");
buf.append(blogFrom.toBase64()).append("&amp;");
buf.append(PARAM_ATTACHMENT).append("=").append(HTMLRenderer.sanitizeTagParam(loc));
buf.append("\" title=\"");
buf.append("'");
buf.append(HTMLRenderer.sanitizeTagParam(attachments[attachmentId].getName()));
buf.append("', ");
buf.append(attachments[attachmentId].getDataLength()/1024).append("KB, ");
buf.append("of type ").append(HTMLRenderer.sanitizeTagParam(attachments[attachmentId].getMimeType()));
buf.append("\">");
buf.append(HTMLRenderer.sanitizeString(pn.getName()));
buf.append("</a>");
} else {
loc = null;
}
} else {
loc = null;
}
}
} catch (Exception e) {
e.printStackTrace();
loc = null;
}
}
if (loc == null)
buf.append(HTMLRenderer.sanitizeString(pn.getName()));
} else if ( ("eepsite".equals(type)) || ("i2p".equals(type)) ||
("website".equals(type)) || ("http".equals(type)) || ("web".equals(type)) ) {
String loc = pn.getLocation();
if (loc != null) {
buf.append("<a href=\"externallink.jsp?");
if (pn.getNetwork() != null)
buf.append("schema=").append(Base64.encode(pn.getNetwork())).append("&amp;");
if (pn.getLocation() != null)
buf.append("location=").append(Base64.encode(pn.getLocation())).append("&amp;");
buf.append("\" title=\"View ").append(HTMLRenderer.sanitizeTagParam(pn.getLocation())).append("\">");
}
buf.append(HTMLRenderer.sanitizeString(pn.getName()));
if (loc != null) {
buf.append("</a>");
}
} else {
buf.append("<a href=\"\" title=\"go somewhere? ").append(HTMLRenderer.sanitizeString(pn.toString())).append("\">");
buf.append(HTMLRenderer.sanitizeString(pn.getName())).append("</a>");
}
return buf.toString();
} }
private static final int POSTS_PER_PAGE = 5; private static final int POSTS_PER_PAGE = 5;
@ -410,7 +519,7 @@ public class ViewBlogServlet extends BaseServlet {
"}\n" + "}\n" +
".syndieBlogLinkGroup li a {\n" + ".syndieBlogLinkGroup li a {\n" +
" display: block;\n" + " display: block;\n" +
" width: 100%;\n" + //" width: 100%;\n" +
"}\n" + "}\n" +
".syndieBlogLinkGroupName {\n" + ".syndieBlogLinkGroupName {\n" +
" font-size: 80%;\n" + " font-size: 80%;\n" +

View File

@ -1,4 +1,9 @@
$Id: history.txt,v 1.378 2006/01/04 21:48:17 jrandom Exp $ $Id: history.txt,v 1.379 2006/01/08 15:54:39 jrandom Exp $
2005-01-09 jrandom
* Bugfix for a rare SSU error (thanks cervantes!)
* More progress on the blog interface, allowing customizable blog-wide
links.
2006-01-08 jrandom 2006-01-08 jrandom
* First pass of the new blog interface, though without much of the useful * First pass of the new blog interface, though without much of the useful

View File

@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
* *
*/ */
public class RouterVersion { public class RouterVersion {
public final static String ID = "$Revision: 1.324 $ $Date: 2006/01/01 12:23:29 $"; public final static String ID = "$Revision: 1.325 $ $Date: 2006/01/04 21:48:17 $";
public final static String VERSION = "0.6.1.8"; public final static String VERSION = "0.6.1.8";
public final static long BUILD = 8; public final static long BUILD = 9;
public static void main(String args[]) { public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD); System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID); System.out.println("Router ID: " + RouterVersion.ID);

View File

@ -473,6 +473,7 @@ public class OutboundMessageFragments {
// ok, simplest possible thing is to always tack on the bitfields if // ok, simplest possible thing is to always tack on the bitfields if
List msgIds = peer.getCurrentFullACKs(); List msgIds = peer.getCurrentFullACKs();
if (msgIds == null) msgIds = new ArrayList();
List partialACKBitfields = new ArrayList(); List partialACKBitfields = new ArrayList();
peer.fetchPartialACKs(partialACKBitfields); peer.fetchPartialACKs(partialACKBitfields);
int piggybackedPartialACK = partialACKBitfields.size(); int piggybackedPartialACK = partialACKBitfields.size();
@ -482,6 +483,10 @@ public class OutboundMessageFragments {
for (int i = 0; i < fragments; i++) { for (int i = 0; i < fragments; i++) {
if (state.needsSending(i)) { if (state.needsSending(i)) {
rv[i] = _builder.buildPacket(state, i, peer, remaining, partialACKBitfields); rv[i] = _builder.buildPacket(state, i, peer, remaining, partialACKBitfields);
if (rv[i] == null) {
sparseCount++;
continue;
}
rv[i].setFragmentCount(fragments); rv[i].setFragmentCount(fragments);
OutNetMessage msg = state.getMessage(); OutNetMessage msg = state.getMessage();
if (msg != null) if (msg != null)