[freenet-cvs] r12908 - in trunk/freenet/src/freenet: clients/http clients/http/bookmark clients/http/staticfiles clients/http/staticfiles/icon clients/http/staticfiles/themes/boxed clients/http/staticfiles/themes/clean clients/http/staticfiles/themes/grayandblue clients/http/staticfiles/themes/sky node

fred at freenetproject.org fred at freenetproject.org
Mon Apr 23 22:41:07 UTC 2007


Author: fred
Date: 2007-04-23 22:41:07 +0000 (Mon, 23 Apr 2007)
New Revision: 12908

Added:
   trunk/freenet/src/freenet/clients/http/BookmarkEditorToadlet.java
   trunk/freenet/src/freenet/clients/http/bookmark/
   trunk/freenet/src/freenet/clients/http/bookmark/Bookmark.java
   trunk/freenet/src/freenet/clients/http/bookmark/BookmarkCategories.java
   trunk/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java
   trunk/freenet/src/freenet/clients/http/bookmark/BookmarkItem.java
   trunk/freenet/src/freenet/clients/http/bookmark/BookmarkItems.java
   trunk/freenet/src/freenet/clients/http/bookmark/BookmarkManager.java
   trunk/freenet/src/freenet/clients/http/staticfiles/bookmark.css
   trunk/freenet/src/freenet/clients/http/staticfiles/icon/
   trunk/freenet/src/freenet/clients/http/staticfiles/icon/bookmark-new.png
   trunk/freenet/src/freenet/clients/http/staticfiles/icon/delete.png
   trunk/freenet/src/freenet/clients/http/staticfiles/icon/edit-delete.png
   trunk/freenet/src/freenet/clients/http/staticfiles/icon/edit.png
   trunk/freenet/src/freenet/clients/http/staticfiles/icon/folder-new.png
   trunk/freenet/src/freenet/clients/http/staticfiles/icon/go-down.png
   trunk/freenet/src/freenet/clients/http/staticfiles/icon/go-up.png
Removed:
   trunk/freenet/src/freenet/clients/http/Bookmark.java
   trunk/freenet/src/freenet/clients/http/BookmarkManager.java
Modified:
   trunk/freenet/src/freenet/clients/http/FProxyToadlet.java
   trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java
   trunk/freenet/src/freenet/clients/http/staticfiles/themes/boxed/theme.css
   trunk/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css
   trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/theme.css
   trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/theme.css
   trunk/freenet/src/freenet/node/NodeClientCore.java
Log:
Bookmarks are now organized by categories, new bookmark editor

Deleted: trunk/freenet/src/freenet/clients/http/Bookmark.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/Bookmark.java	2007-04-23 22:28:38 UTC (rev 12907)
+++ trunk/freenet/src/freenet/clients/http/Bookmark.java	2007-04-23 22:41:07 UTC (rev 12908)
@@ -1,143 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.clients.http;
-
-import freenet.keys.FreenetURI;
-import freenet.keys.USK;
-import freenet.node.NodeClientCore;
-import freenet.node.useralerts.UserAlert;
-import freenet.node.useralerts.UserAlertManager;
-import freenet.support.HTMLNode;
-
-import java.net.MalformedURLException;
-
-public class Bookmark {
-	
-	private FreenetURI key;
-	private String desc;
-	private boolean updated;
-	private final BookmarkUpdatedUserAlert alert;
-	private UserAlertManager alerts;
-
-	private class BookmarkUpdatedUserAlert implements UserAlert {
-
-		public boolean userCanDismiss() {
-			return true;
-		}
-
-		public String getTitle() {
-			return "Bookmark updated: "+desc;
-		}
-
-		public String getText() {
-			return "The bookmarked site "+desc+" has been updated to edition "+key.getSuggestedEdition();
-		}
-
-		public HTMLNode getHTMLText() {
-			HTMLNode n = new HTMLNode("div");
-			n.addChild("#", "The bookmarked site ");
-			n.addChild("a", "href", '/'+key.toString()).addChild("#", desc);
-			n.addChild("#", " has been updated to edition "+key.getSuggestedEdition()+".");
-			return n;
-		}
-
-		public short getPriorityClass() {
-			return UserAlert.MINOR;
-		}
-
-		public boolean isValid() {
-			synchronized(Bookmark.this) {
-				return updated;
-			}
-		}
-
-		public void isValid(boolean validity) {
-			if(validity) return;
-			disableBookmark();
-		}
-
-		public String dismissButtonText() {
-			return "Delete notification";
-		}
-
-		public boolean shouldUnregisterOnDismiss() {
-			return true;
-		}
-
-		public void onDismiss() {
-			disableBookmark();
-		}
-		
-	}
-	
-	private synchronized void disableBookmark() {
-		updated = false;
-		alerts.unregister(alert);
-	}
-	
-	private synchronized void enableBookmark() {
-		if(updated) return;
-		updated = true;
-		alerts.register(alert);
-	}
-
-	Bookmark(String k, String d, UserAlertManager uam) throws MalformedURLException {
-		this.key = new FreenetURI(k);
-		this.desc = d;
-		alert = new BookmarkUpdatedUserAlert();
-		this.alerts = uam;
-	}
-
-	Bookmark(String from, UserAlertManager uam) throws MalformedURLException {
-		int eqpos = from.indexOf("=");
-
-		if (eqpos < 0) {
-			this.key = new FreenetURI(from);
-			this.desc = from;
-		} else {
-			this.key = new FreenetURI(from.substring(0, eqpos));
-			this.desc = from.substring(eqpos + 1);
-		}
-		alert = new BookmarkUpdatedUserAlert();
-		this.alerts = uam;
-	}
-
-	public String getKey() {
-		return key.toString();
-	}
-	
-	public synchronized FreenetURI getURI() {
-		return key;
-	}
-	
-	public synchronized void setKey(FreenetURI uri) {
-		key = uri;
-	}
-
-	public synchronized String getKeyType() {
-		return key.getKeyType();
-	}
-
-	public String getDesc() {
-		if (desc.equals("")) {
-			return "Unnamed Bookmark";
-		} else {
-			return desc;
-		}
-	}
-
-	public String toString() {
-		return this.key.toString() + '=' + this.desc;
-	}
-
-	public synchronized void setEdition(long ed, NodeClientCore node) {
-		if(key.getSuggestedEdition() >= ed) return;
-		key = key.setSuggestedEdition(ed);
-		enableBookmark();
-	}
-
-	public USK getUSK() throws MalformedURLException {
-		return USK.create(key);
-	}
-}
\ No newline at end of file

Added: trunk/freenet/src/freenet/clients/http/BookmarkEditorToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/BookmarkEditorToadlet.java	                        (rev 0)
+++ trunk/freenet/src/freenet/clients/http/BookmarkEditorToadlet.java	2007-04-23 22:41:07 UTC (rev 12908)
@@ -0,0 +1,272 @@
+package freenet.clients.http;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import freenet.node.Node;
+
+import freenet.clients.http.bookmark.Bookmark;
+import freenet.clients.http.bookmark.BookmarkItem;
+import freenet.clients.http.bookmark.BookmarkItems;
+import freenet.clients.http.bookmark.BookmarkCategory;
+import freenet.clients.http.bookmark.BookmarkCategories;
+import freenet.clients.http.bookmark.BookmarkManager;
+
+import freenet.node.useralerts.UserAlertManager;
+import freenet.keys.FreenetURI;
+import freenet.node.NodeClientCore;
+import freenet.client.HighLevelSimpleClient;
+import freenet.support.HTMLEncoder;
+import freenet.support.HTMLNode;
+import freenet.support.api.HTTPRequest;
+
+public class BookmarkEditorToadlet extends Toadlet {
+
+	private static final int MAX_ACTION_LENGTH = 20;
+	private static final int MAX_KEY_LENGTH = QueueToadlet.MAX_KEY_LENGTH;
+	private static final int MAX_NAME_LENGTH = 500;
+	private static final int MAX_BOOKMARK_PATH_LENGTH = 10 * MAX_NAME_LENGTH;
+
+	private final Node node;
+	private final NodeClientCore core;
+	private final BookmarkManager bookmarkManager;
+
+	
+	BookmarkEditorToadlet(HighLevelSimpleClient client, Node node)
+	{
+		super(client);
+		this.node = node;
+		this.core = node.clientCore;
+		this.bookmarkManager = core.bookmarkManager;		
+	}
+	
+	private void addCategoryToList(BookmarkCategory cat, String path, HTMLNode list)
+	{
+		BookmarkItems items = cat.getItems();
+		
+		for(int i = 0; i < items.size(); i++) {
+
+			String itemPath = path + items.get(i).getName();
+			HTMLNode li = new HTMLNode("li", "class","item" , items.get(i).getName());
+
+			HTMLNode actions = new HTMLNode("span", "class", "actions");
+			actions.addChild("a", "href", "?action=edit&bookmark=" + itemPath).addChild("img", new String[] {"src", "alt", "title"}, new String[] {"/static/icon/edit.png", "edit", "Edit"});
+			
+			actions.addChild("a", "href", "?action=del&bookmark=" + itemPath).addChild("img", new String[] {"src", "alt", "title"}, new String[] {"/static/icon/delete.png", "delete", "Delete"});
+			
+			if(i != 0)
+				actions.addChild("a", "href", "?action=up&bookmark=" + itemPath).addChild("img", new String[] {"src", "alt", "title"}, new String[] {"/static/icon/go-up.png", "up", "Go up"});
+			
+			if(i != items.size()-1)
+				actions.addChild("a", "href", "?action=down&bookmark=" + itemPath).addChild("img", new String[] {"src", "alt", "title"}, new String[] {"/static/icon/go-down.png", "down", "Go down"});
+			
+			li.addChild(actions);
+			list.addChild(li);
+		}
+
+		BookmarkCategories cats = cat.getSubCategories();
+		for(int i = 0; i < cats.size(); i++) {
+
+			String catPath = path + cats.get(i).getName() + "/";
+			
+			HTMLNode subCat = list.addChild("li", "class", "cat", cats.get(i).getName());
+
+			HTMLNode actions = new HTMLNode("span", "class", "actions");
+			
+			actions.addChild("a", "href", "?action=edit&bookmark=" + catPath).addChild("img", new String[] {"src", "alt", "title"}, new String[] {"/static/icon/edit.png", "edit", "Edit"});
+			
+			actions.addChild("a", "href", "?action=del&bookmark=" + catPath).addChild("img", new String[] {"src", "alt", "title"}, new String[] {"/static/icon/delete.png", "delete", "Delete"});
+			
+			actions.addChild("a", "href", "?action=addItem&bookmark=" + catPath).addChild("img", new String[] {"src", "alt", "title"}, new String[] {"/static/icon/bookmark-new.png", "add bookmark", "Add bookmark"});
+			
+			actions.addChild("a", "href", "?action=addCat&bookmark=" + catPath).addChild("img", new String[] {"src", "alt", "title"}, new String[] {"/static/icon/folder-new.png", "add category", "Add category"});
+			
+			if(i != 0)
+				actions.addChild("a", "href", "?action=up&bookmark=" + catPath).addChild("img", new String[] {"src", "alt", "title"}, new String[] {"/static/icon/go-up.png", "up", "Go up"});
+			
+			if(i != cats.size() -1)
+				actions.addChild("a", "href", "?action=down&bookmark=" + catPath).addChild("img", new String[] {"src", "alt", "title"}, new String[] {"/static/icon/go-down.png", "down", "Go down"});
+			
+			subCat.addChild(actions);
+			addCategoryToList(cats.get(i), catPath, list.addChild("li").addChild("ul"));
+		}
+	}
+
+	public HTMLNode getBookmarksList()
+	{
+		HTMLNode bookmarks = new HTMLNode("ul", "id", "bookmarks");
+		
+		HTMLNode root = bookmarks.addChild("li", "class", "cat,root", "/");
+		HTMLNode actions = new HTMLNode("span", "class", "actions");
+		actions.addChild("a", "href", "?action=addItem&bookmark=/").addChild("img", new String[] {"src", "alt", "title"}, new String[] {"/static/icon/bookmark-new.png", "add bookmark", "Add bookmark"});
+		actions.addChild("a", "href", "?action=addCat&bookmark=/").addChild("img", new String[] {"src", "alt", "title"}, new String[] {"/static/icon/folder-new.png", "add category", "Add category"});
+		root.addChild(actions);
+		
+		addCategoryToList(bookmarkManager.getMainCategory(), "/", root.addChild("li").addChild("ul"));
+		
+		return bookmarks;
+	}
+	
+	public void handleGet(URI uri, HTTPRequest req, ToadletContext ctx) 
+			throws ToadletContextClosedException, IOException 
+	{
+		
+		HTMLNode pageNode = ctx.getPageMaker().getPageNode("Bookmark Editor", ctx);
+		HTMLNode content = ctx.getPageMaker().getContentNode(pageNode);
+		
+		if (req.getParam("action").length() > 0 && req.getParam("bookmark").length() > 0) {
+			String action = req.getParam("action");
+			String bookmarkPath = req.getParam("bookmark");
+			Bookmark bookmark;
+			
+			if (bookmarkPath.endsWith("/"))
+				bookmark = bookmarkManager.getCategoryByPath(bookmarkPath);
+			else
+				bookmark = bookmarkManager.getItemByPath(bookmarkPath);
+				
+			if(bookmark == null) {
+				HTMLNode errorBox = content.addChild(ctx.getPageMaker().getInfobox("infobox-error", "Error"));
+				errorBox.addChild("#", "Bookmark \""+ bookmarkPath + "\" does not exists.");
+			} else {
+			
+			if(action.equals("del")){
+				
+				HTMLNode infoBox = content.addChild(ctx.getPageMaker().getInfobox("infobox-query", "Delete " + (bookmark instanceof BookmarkItem ? "bookmark" : "category")));
+				
+				String query = "Are you sure you wish to delete " + bookmarkPath;
+				if(bookmark instanceof BookmarkCategory)
+					query+= " and all its children";
+				query+= " ?";
+				infoBox.addChild("p").addChild("#", query);
+				
+				HTMLNode confirmForm = ctx.addFormChild(infoBox.addChild("p"), "", "confirmDeleteForm");
+				confirmForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "hidden", "bookmark", bookmarkPath});
+				confirmForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "submit", "cancel", "Cancel" });
+				confirmForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "submit", "confirmdelete", "Delete" });
+				
+				
+			} else if (action.equals("edit") || action.equals("addItem") || action.equals("addCat")) {
+				
+				String header;
+				if(action.equals("edit"))
+					header = "Edit "+(bookmark instanceof BookmarkItem ? "bookmark" : "category");
+				else if(action.equals("addItem"))
+					header = "Add a new bookmark";
+				else
+					header = "Add a new category";
+				
+				HTMLNode actionBox = content.addChild(ctx.getPageMaker().getInfobox("infobox-query", header));
+				
+				HTMLNode form = ctx.addFormChild(actionBox, "", "editBookmarkForm");
+				
+				form.addChild("label", "for", "name", "Name : ");
+				form.addChild("input", new String[]{"type", "id", "name", "size", "value"}, new String []{"text", "name", "name", "20", action.equals("edit")?bookmark.getName():""});
+				
+				form.addChild("br");
+				if ((action.equals("edit") && bookmark instanceof BookmarkItem) || action.equals("addItem")) {
+					String key = (action.equals("edit") ? ((BookmarkItem) bookmark).getKey() : "");
+					form.addChild("label", "for", "key", "Key : ");
+					form.addChild("input", new String[]{"type", "id", "name", "size", "value"}, new String []{"text", "key", "key", "50", key});
+				}
+				
+				form.addChild("input", new String[] {"type", "name", "value"}, new String[] {"hidden", "bookmark",bookmarkPath});
+				
+				form.addChild("input", new String[] {"type", "name", "value"}, new String[] {"hidden", "action",req.getParam("action")});
+				
+				form.addChild("br");
+				form.addChild("input", new String[]{"type", "value"}, new String[]{"submit", "Save"});
+			} else if (action.equals("up") || action.equals("down")) {
+				if(action.equals("up"))
+					bookmarkManager.moveBookmarkUp(bookmarkPath, true);
+				else
+					bookmarkManager.moveBookmarkDown(bookmarkPath, true);
+			}
+			}
+			
+		}
+		
+		HTMLNode bookmarksBox = content.addChild(ctx.getPageMaker().getInfobox("infobox-normal", "My Bookmarks"));
+		bookmarksBox.addChild(getBookmarksList());
+
+		this.writeReply(ctx, 200, "text/html", "OK", pageNode.generate());
+	}
+
+	
+	public void handlePost(URI uri, HTTPRequest req, ToadletContext ctx) 
+		throws ToadletContextClosedException, IOException 
+	{
+		HTMLNode pageNode = ctx.getPageMaker().getPageNode("Bookmark Editor", ctx);
+		HTMLNode content = ctx.getPageMaker().getContentNode(pageNode);
+		
+		String passwd = req.getPartAsString("formPassword", 32);
+		boolean noPassword = (passwd == null) || !passwd.equals(core.formPassword);
+		if(noPassword) 
+			return;
+		
+		
+		String bookmarkPath = req.getPartAsString("bookmark", MAX_BOOKMARK_PATH_LENGTH);
+		try {
+			
+			Bookmark bookmark;
+			if(bookmarkPath.endsWith("/"))
+				bookmark = bookmarkManager.getCategoryByPath(bookmarkPath);
+			else
+				bookmark = bookmarkManager.getItemByPath(bookmarkPath);
+			
+			String action = req.getPartAsString("action", MAX_ACTION_LENGTH);
+			
+			if (req.isPartSet("confirmdelete")) {
+				bookmarkManager.removeBookmark(bookmarkPath, true);
+				HTMLNode successBox = content.addChild(ctx.getPageMaker().getInfobox("infobox-success", "Delete succeeded"));
+				successBox.addChild("p", "The bookmark has been deleted successfully");
+				
+			} else if (action.equals("edit") || action.equals("addItem") || action.equals("addCat")) {
+				
+				String name = "unnamed";
+				if (req.getPartAsString("name", MAX_NAME_LENGTH).length() > 0)
+					name = req.getPartAsString("name", MAX_NAME_LENGTH);
+				
+				if(action.equals("edit")) {
+					bookmarkManager.renameBookmark(bookmarkPath, name);
+					if(bookmark instanceof BookmarkItem)
+						((BookmarkItem) bookmark).setKey(new FreenetURI(req.getPartAsString("key", MAX_KEY_LENGTH)));
+					
+					HTMLNode successBox = content.addChild(ctx.getPageMaker().getInfobox("infobox-success", "Modifications saved"));
+					successBox.addChild("p", "The changes has been saved successfully");
+						
+				} else if (action.equals("addItem") || action.equals("addCat")) {
+					
+					Bookmark newBookmark;
+					if(action.equals("addItem")) {
+						FreenetURI key = new FreenetURI(req.getPartAsString("key", MAX_KEY_LENGTH));
+						newBookmark = new BookmarkItem(key, name, core.alerts);
+					} else
+						newBookmark = new BookmarkCategory(name);
+					
+					bookmarkManager.addBookmark(bookmarkPath, newBookmark, true);
+					
+					HTMLNode successBox =  content.addChild(ctx.getPageMaker().getInfobox("infobox-success", "New bookmark added"));
+					successBox.addChild("p", "The new bookmark has been added successfully");
+					
+				}
+				
+			}
+
+		} catch (NullPointerException npo) {
+			HTMLNode errorBox = content.addChild(ctx.getPageMaker().getInfobox("infobox-error", "Error"));
+			errorBox.addChild("#", "Bookmark \""+ bookmarkPath + "\" does not exists.");
+		} catch (MalformedURLException mue) {
+			HTMLNode errorBox = content.addChild(ctx.getPageMaker().getInfobox("infobox-error", "Invalid key"));
+			errorBox.addChild("#", "Invalid Freenet Key");
+		}
+		HTMLNode bookmarksBox = content.addChild(ctx.getPageMaker().getInfobox("infobox-normal", "My Bookmarks"));
+		bookmarksBox.addChild(getBookmarksList());
+		
+		this.writeReply(ctx, 200, "text/html", "OK", pageNode.generate());
+	}
+	
+	public String supportedMethods()
+	{
+		return "GET, POST";
+	}
+}

Deleted: trunk/freenet/src/freenet/clients/http/BookmarkManager.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/BookmarkManager.java	2007-04-23 22:28:38 UTC (rev 12907)
+++ trunk/freenet/src/freenet/clients/http/BookmarkManager.java	2007-04-23 22:41:07 UTC (rev 12908)
@@ -1,181 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.clients.http;
-
-import java.net.MalformedURLException;
-import java.util.Enumeration;
-import java.util.Vector;
-
-import freenet.client.async.USKCallback;
-import freenet.config.InvalidConfigValueException;
-import freenet.config.SubConfig;
-import freenet.keys.FreenetURI;
-import freenet.keys.USK;
-import freenet.node.NodeClientCore;
-import freenet.support.api.StringArrCallback;
-
-public class BookmarkManager {
-	private static final String[] DEFAULT_TESTNET_BOOKMARKS = {
-		"USK at 60I8H8HinpgZSOuTSD66AVlIFAy-xsppFr0YCzCar7c,NzdivUGCGOdlgngOGRbbKDNfSCnjI0FXjHLzJM4xkJ4,AQABAAE/index/4/=INDEX.7-freesite"
-	};
-	private static final String[] DEFAULT_DARKNET_BOOKMARKS = {
-		"USK at c55vMxUl-T-lD3nv0iOaXF~G1hnY6pOMRbzZSwACMmY,yd8~uwUmGm164-ipStoiBOJVjkbbYXJMlD~H5ftPxIA,AQABAAE/Indicia/55/=Indicia (Lots of freesites - web sites hosted on freenet)",
-		"USK at 7H66rhYmxIFgMyw5Dl11JazXGHPhp7dSN7WMa1pbtEo,jQHUQUPTkeRcjmjgrc7t5cDRdDkK3uKkrSzuw5CO9uk,AQACAAE/ENTRY.POINT/19/=Entry Point (Lots of freesites - web sites hosted on freenet)",
-		"USK at PFeLTa1si2Ml5sDeUy7eDhPso6TPdmw-2gWfQ4Jg02w,3ocfrqgUMVWA2PeorZx40TW0c-FiIOL-TWKQHoDbVdE,AQABAAE/Index/42/=Darknet Index (Older freesite index)"
-	};
-	private Vector bookmarks;
-	private final NodeClientCore node;
-	private USKUpdatedCallback uskcb;
-	private boolean started;
-	
-	public class BookmarkCallback implements StringArrCallback {
-		public String[] get() {
-			synchronized(BookmarkManager.this) {
-				String[] values = new String[bookmarks.size()];
-				for(int i=0;i<bookmarks.size();i++)
-					values[i] = bookmarks.get(i).toString();
-				return values;
-			}
-		}
-		
-		public void set(String[] newvals) throws InvalidConfigValueException {
-			bookmarks.clear();
-			for (int i = 0; i < newvals.length; i++) {
-				try {
-					bookmarks.add(new Bookmark(newvals[i], node.alerts));
-				} catch (MalformedURLException mue) {
-					throw new InvalidConfigValueException(mue.getMessage());
-				}
-			}
-		}
-	}
-	
-	private class USKUpdatedCallback implements USKCallback {
-		public void onFoundEdition(long edition, USK key) {
-			
-			for (Enumeration e = bookmarks.elements(); e.hasMoreElements(); ) {
-				Bookmark b = (Bookmark) e.nextElement();
-				
-				if (!b.getKeyType().equals("USK")) continue;
-				
-				try {
-					FreenetURI furi = new FreenetURI(b.getKey());
-					USK usk = USK.create(furi);
-					
-					if (usk.equals(key, false)) {
-						b.setEdition(key.suggestedEdition, node);
-						break;
-					}
-				} catch (MalformedURLException mue) {
-				}
-			}
-			node.storeConfig();
-		}
-	}
-	
-	public BookmarkManager(NodeClientCore n, SubConfig sc) {
-		this.bookmarks = new Vector();
-		this.node = n;
-		this.uskcb = new USKUpdatedCallback();
-		sc.register("bookmarks", n.isTestnetEnabled() ? DEFAULT_TESTNET_BOOKMARKS : DEFAULT_DARKNET_BOOKMARKS, 0, true, false, "BookmarkManager.list", "BookmarkManager.listLong", makeCB());
-		
-		String[] initialbookmarks = sc.getStringArr("bookmarks");
-		for (int i = 0; i < initialbookmarks.length; i++) {
-			try {
-				addBookmark(new Bookmark(initialbookmarks[i], n.alerts), false);
-			} catch (MalformedURLException mue) {
-				// just ignore that one
-			}
-		}
-		synchronized(this) {
-			started = true;
-		}
-	}
-	
-	public BookmarkCallback makeCB() {
-		return new BookmarkCallback();
-	}
-	
-	public Enumeration getBookmarks() {
-		return this.bookmarks.elements();
-	}
-	
-	public FreenetURI[] getBookmarkURIs() {
-		Bookmark[] b = (Bookmark[]) bookmarks.toArray(new Bookmark[bookmarks.size()]);
-		FreenetURI[] uris = new FreenetURI[b.length];
-		for(int i=0;i<uris.length;i++) {
-			uris[i] = b[i].getURI();
-		}
-		return uris;
-	}
-	
-	public void clear() {
-		for (Enumeration e = this.bookmarks.elements(); e.hasMoreElements(); ) {
-			Bookmark i = (Bookmark)e.nextElement();
-			
-			if (!i.getKeyType().equals("USK")) continue;
-			
-			try {
-				USK u = i.getUSK();
-				this.node.uskManager.unsubscribe(u, this.uskcb, true);
-			} catch (MalformedURLException mue) {
-				
-			}
-		}
-		this.bookmarks.clear();
-	}
-	
-	public void addBookmark(Bookmark b, boolean store) {
-		this.bookmarks.add(b);
-		if (b.getKeyType().equals("USK")) {
-			try {
-				USK u = b.getUSK();
-				this.node.uskManager.subscribe(u, this.uskcb, true, this);
-			} catch (MalformedURLException mue) {
-				
-			}
-		}
-		if(store && started) node.storeConfig();
-	}
-	
-	public void removeBookmark(Bookmark b, boolean store) {
-		if (b.getKeyType().equals("USK")) {
-			try {
-				USK u = b.getUSK();
-				this.node.uskManager.unsubscribe(u, this.uskcb, true);
-			} catch (MalformedURLException mue) {
-			
-			}
-		}
-		this.bookmarks.remove(b);
-		if(store && started) node.storeConfig();
-	}
-	
-	public void moveBookmarkDown (Bookmark b, boolean store) {		
-		int i = this.bookmarks.indexOf(b);
-		if (i == -1) return;
-		
-		Bookmark bk = (Bookmark)this.bookmarks.get(i);
-		this.bookmarks.remove(i);
-		this.bookmarks.add((i+1)%(this.bookmarks.size()+1), bk);
-		
-		if(store && started) node.storeConfig();
-	}
-
-	public void moveBookmarkUp (Bookmark b, boolean store) {
-		int i = this.bookmarks.indexOf(b);
-		if (i == -1) return;
-		
-		Bookmark bk = (Bookmark)this.bookmarks.get(i);
-		this.bookmarks.remove(i);
-		if (--i < 0) i = this.bookmarks.size();
-		this.bookmarks.add(i, bk);
-		
-		if(store && started) node.storeConfig();
-	}
-	
-	public int getSize() {
-		return this.bookmarks.size();
-	}
-}

Modified: trunk/freenet/src/freenet/clients/http/FProxyToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/FProxyToadlet.java	2007-04-23 22:28:38 UTC (rev 12907)
+++ trunk/freenet/src/freenet/clients/http/FProxyToadlet.java	2007-04-23 22:41:07 UTC (rev 12908)
@@ -609,6 +609,9 @@
 			
 			LocalFileInsertToadlet localFileInsertToadlet = new LocalFileInsertToadlet(core, client);
 			server.register(localFileInsertToadlet, "/files/", true, false);
+			
+			BookmarkEditorToadlet bookmarkEditorToadlet = new BookmarkEditorToadlet(client, node);
+			server.register(bookmarkEditorToadlet, "/bookmarkEditor/", true, false);
 
 			BrowserTestToadlet browsertTestToadlet = new BrowserTestToadlet(client, core);
 			server.register(browsertTestToadlet, "/test/", true, false);

Modified: trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java	2007-04-23 22:28:38 UTC (rev 12907)
+++ trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java	2007-04-23 22:41:07 UTC (rev 12908)
@@ -20,6 +20,11 @@
 import freenet.client.InsertBlock;
 import freenet.client.InserterException;
 import freenet.clients.http.filter.GenericReadFilterCallback;
+import freenet.clients.http.bookmark.BookmarkItem;
+import freenet.clients.http.bookmark.BookmarkItems;
+import freenet.clients.http.bookmark.BookmarkCategory;
+import freenet.clients.http.bookmark.BookmarkCategories;
+import freenet.clients.http.bookmark.BookmarkManager;
 import freenet.keys.FreenetURI;
 import freenet.node.Node;
 import freenet.node.NodeClientCore;
@@ -32,9 +37,12 @@
 import freenet.support.api.Bucket;
 import freenet.support.api.HTTPRequest;
 
+
 import freenet.frost.message.*;
 
 
+
+
 public class WelcomeToadlet extends Toadlet {
 	private final static int MODE_ADD = 1;
 	private final static int MODE_EDIT = 2;
@@ -43,13 +51,13 @@
 	private static final int MAX_NAME_LENGTH = 1024 * 1024;
 	final NodeClientCore core;
 	final Node node;
-	final BookmarkManager bookmarks;
+	final BookmarkManager bookmarkManager;
 	
 	WelcomeToadlet(HighLevelSimpleClient client, Node node) {
 		super(client);
 		this.node = node;
 		this.core = node.clientCore;
-		this.bookmarks = core.bookmarkManager;
+		this.bookmarkManager = core.bookmarkManager;
 		try {
 			manageBookmarksURI = new URI("/welcome/?managebookmarks");
 		} catch (URISyntaxException e) {
@@ -66,6 +74,22 @@
 
 	URI manageBookmarksURI;
 	
+	
+	private void addCategoryToList(BookmarkCategory cat, HTMLNode list)
+	{
+		BookmarkItems items = cat.getItems();
+		for(int i = 0; i < items.size(); i++) {
+			HTMLNode li = list.addChild("li", "class","item");
+			li.addChild("a", "href", "/" + items.get(i).getKey(), items.get(i).getName());
+		}
+
+		BookmarkCategories cats = cat.getSubCategories();
+		for (int i = 0; i < cats.size(); i++) {			
+			HTMLNode subCat = list.addChild("li", "class", "cat", cats.get(i).getName());
+			addCategoryToList(cats.get(i), list.addChild("li").addChild("ul"));
+		}
+	}
+	
 	public void handlePost(URI uri, HTTPRequest request, ToadletContext ctx) throws ToadletContextClosedException, IOException {
 		
 		if(!ctx.isAllowedFullAccess()) {
@@ -147,58 +171,6 @@
 
 			ctx.getPageMaker().getContentNode(infobox).addChild("#", "Runtime database statistics have been written to the wrapper logfile");
 			this.writeReply(ctx, 200, "text/html", "OK", pageNode.generate());
-		}else if (request.isPartSet("addbookmark")) {
-			if(noPassword) {
-				redirectToRoot(ctx);
-				return;
-			}
-			String key = request.getPartAsString("key", MAX_KEY_LENGTH);
-			String name = request.getPartAsString("name", MAX_NAME_LENGTH);
-			try {
-				bookmarks.addBookmark(new Bookmark(key, name, core.alerts), true);
-			} catch (MalformedURLException mue) {
-				this.sendBookmarkEditPage(ctx, MODE_ADD, null, key, name, "Given key does not appear to be a valid Freenet key.");
-				return;
-			}
-			
-			this.handleGet(manageBookmarksURI, new HTTPRequestImpl(manageBookmarksURI), ctx);
-		} else if (request.isPartSet("managebookmarks")) {
-			if(noPassword) {
-				redirectToRoot(ctx);
-				return;
-			}
-			Enumeration e = bookmarks.getBookmarks();
-			while (e.hasMoreElements()) {
-				Bookmark b = (Bookmark)e.nextElement();
-			
-				if (request.isPartSet("delete_"+b.hashCode())) {
-					bookmarks.removeBookmark(b, true);
-					break;
-				} else if (request.isPartSet("movedown_"+b.hashCode())) {
-					bookmarks.moveBookmarkDown(b, true);
-					break;
-				} else if (request.isPartSet("moveup_"+b.hashCode())) {
-					bookmarks.moveBookmarkUp(b, true);
-					break;
-				} else if (request.isPartSet("edit_"+b.hashCode())) {
-					this.sendBookmarkEditPage(ctx, b);
-					return;
-				} else if (request.isPartSet("update_"+b.hashCode())) {
-					// removing it and adding means that any USK subscriptions are updated properly
-					String key = request.getPartAsString("key", MAX_KEY_LENGTH);
-					String name = request.getPartAsString("name", MAX_NAME_LENGTH);
-					try {
-						Bookmark newbkmk = new Bookmark(key, name, core.alerts);
-						bookmarks.removeBookmark(b, false);
-						bookmarks.addBookmark(newbkmk, true);
-					} catch (MalformedURLException mue) {
-						this.sendBookmarkEditPage(ctx, MODE_EDIT, b, key, name, "Given key does not appear to be a valid freenet key.");
-						return;
-					}
-					this.handleGet(manageBookmarksURI, new HTTPRequestImpl(manageBookmarksURI), ctx);
-				}
-			}
-			this.handleGet(manageBookmarksURI, new HTTPRequestImpl(manageBookmarksURI), ctx);
 		}else if(request.isPartSet("disable")){
 			if(noPassword) {
 				redirectToRoot(ctx);
@@ -477,19 +449,7 @@
 				writeReply(ctx, 200, "text/html; charset=utf-8", "OK", pageNode.generate());
 				Logger.normal(this, "Node is restarting");
 				return;
-			}else if (request.getParam("newbookmark").length() > 0) {
-				HTMLNode pageNode = ctx.getPageMaker().getPageNode("Add a Bookmark", ctx);
-				HTMLNode contentNode = ctx.getPageMaker().getContentNode(pageNode);
-				HTMLNode infobox = contentNode.addChild(ctx.getPageMaker().getInfobox("Confirm Bookmark Addition"));
-				HTMLNode addForm = ctx.addFormChild(ctx.getPageMaker().getContentNode(infobox), "/", "bookmarkAddForm");
-				addForm.addChild("#", "Please confirm that you want to add the key " + request.getParam("newbookmark") + " to your bookmarks and enter the description that you would prefer:");
-				addForm.addChild("br");
-				addForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "hidden", "key", request.getParam("newbookmark") });
-				addForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "text", "name", request.getParam("desc") });
-				addForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "submit", "addbookmark", "Add bookmark" });
-				this.writeReply(ctx, 200, "text/html", "OK", pageNode.generate());
-				return;
-			} else if (request.getParam(GenericReadFilterCallback.magicHTTPEscapeString).length() > 0) {
+			}else if (request.getParam(GenericReadFilterCallback.magicHTTPEscapeString).length() > 0) {
 				HTMLNode pageNode = ctx.getPageMaker().getPageNode("Link to external resources", ctx);
 				HTMLNode contentNode = ctx.getPageMaker().getContentNode(pageNode);
 				HTMLNode warnbox = contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-warning", "External link"));
@@ -503,38 +463,7 @@
 				externalLinkForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "submit", "Go", "Go to the specified link" });
 				this.writeReply(ctx, 200, "text/html", "OK", pageNode.generate());
 				return;
-			} else if (request.isParameterSet("managebookmarks")) {
-				HTMLNode pageNode = ctx.getPageMaker().getPageNode("Bookmark Manager", ctx);
-				HTMLNode contentNode = ctx.getPageMaker().getContentNode(pageNode);
-				HTMLNode infobox = contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-normal", "My Bookmarks"));
-				HTMLNode infoboxContent = ctx.getPageMaker().getContentNode(infobox);
-
-				Enumeration e = bookmarks.getBookmarks();
-				boolean moveButtonsEnabled = (bookmarks.getSize() > 1); // activate move{up|down} buttons
-
-				if (!e.hasMoreElements()) {
-					infoboxContent.addChild("#", "You currently do not have any bookmarks defined.");
-				} else {
-					HTMLNode manageForm = ctx.addFormChild(infoboxContent, ".", "manageBookmarksForm");
-					HTMLNode bookmarkList = manageForm.addChild("ul", "id", "bookmarks");
-					while (e.hasMoreElements()) {
-						Bookmark b = (Bookmark)e.nextElement();
-
-						HTMLNode bookmark = bookmarkList.addChild("li", "style", "clear: right;"); /* TODO */
-						bookmark.addChild("input", new String[] { "type", "name", "value", "style" }, new String[] { "submit", "delete_" + b.hashCode(), "Delete", "float: right;" });
-						bookmark.addChild("input", new String[] { "type", "name", "value", "style" }, new String[] { "submit", "edit_" + b.hashCode(), "Edit", "float: right;" });
-						if (moveButtonsEnabled) {
-							bookmark.addChild("input", new String[] { "type", "name", "value", "style" }, new String[] { "submit", "movedown_" + b.hashCode(), "Down", "float: right;" });
-							bookmark.addChild("input", new String[] { "type", "name", "value", "style" }, new String[] { "submit", "moveup_" + b.hashCode(), "Up", "float: right;" });
-						}
-						bookmark.addChild("a", "href", '/' + b.getKey(), b.getDesc());
-					}
-					manageForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "hidden", "managebookmarks", "yes" });
-				}
-				contentNode.addChild(createBookmarkEditForm(ctx, MODE_ADD, null, "", ""));
-				this.writeReply(ctx, 200, "text/html", "OK", pageNode.generate());
-				return;
-			}else if (request.isParameterSet("exit")) {
+			} else if (request.isParameterSet("exit")) {
 				HTMLNode pageNode = ctx.getPageMaker().getPageNode("Node Shutdown", ctx);
 				HTMLNode contentNode = ctx.getPageMaker().getContentNode(pageNode);
 				HTMLNode infobox = contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-query", "Node Shutdown"));
@@ -598,23 +527,14 @@
 		bookmarkBoxHeader.addChild("#", "My Bookmarks");
 		if(ctx.isAllowedFullAccess()){
 			bookmarkBoxHeader.addChild("#", " [");
-			bookmarkBoxHeader.addChild("span", "id", "bookmarkedit").addChild("a", new String[] { "href", "class" }, new String[] { "?managebookmarks", "interfacelink" }, (bookmarks.getSize() == 0) ? "Add" : "Edit");
+			bookmarkBoxHeader.addChild("span", "id", "bookmarkedit").addChild("a", new String[] { "href", "class" }, new String[] { "/bookmarkEditor/", "interfacelink" },"Edit");
 			bookmarkBoxHeader.addChild("#", "]");
 		}
 
 		HTMLNode bookmarkBoxContent = bookmarkBox.addChild("div", "class", "infobox-content");
+		HTMLNode bookmarksList = bookmarkBoxContent.addChild("ul", "id", "bookmarks");
+		addCategoryToList(bookmarkManager.getMainCategory(), bookmarksList);
 
-		Enumeration e = bookmarks.getBookmarks();
-		if (!e.hasMoreElements()) {
-			bookmarkBoxContent.addChild("#", "You currently do not have any bookmarks defined.");
-		} else {
-			HTMLNode bookmarkList = bookmarkBoxContent.addChild("ul", "id", "bookmarks");
-			while (e.hasMoreElements()) {
-				Bookmark b = (Bookmark)e.nextElement();
-				bookmarkList.addChild("li").addChild("a", "href", '/' + b.getKey(), b.getDesc());
-			}
-		}
-
 		// Version info and Quit Form
 		HTMLNode versionBox = contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-information", "Version Information & Node Control"));
 		HTMLNode versionContent = ctx.getPageMaker().getContentNode(versionBox);
@@ -651,45 +571,6 @@
 		this.writeReply(ctx, 200, "text/html", "OK", pageNode.generate());
 	}
 	
-	private void sendBookmarkEditPage(ToadletContext ctx, Bookmark b) throws ToadletContextClosedException, IOException {
-		this.sendBookmarkEditPage(ctx, MODE_EDIT, b, b.getKey(), b.getDesc(), null);
-	}
-	
-	private void sendBookmarkEditPage(ToadletContext ctx, int mode, Bookmark b, String origKey, String origDesc, String message) throws ToadletContextClosedException, IOException {
-		HTMLNode pageNode = ctx.getPageMaker().getPageNode((mode == MODE_ADD) ? "Add a Bookmark" : "Edit a Bookmark", ctx);
-		HTMLNode contentNode = ctx.getPageMaker().getContentNode(pageNode);
-		
-		if (message != null) {  // only used for error messages so far...
-			HTMLNode errorBox = contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-error", "An Error Occured"));
-			ctx.getPageMaker().getContentNode(errorBox).addChild("#", message);
-		}
-		
-		contentNode.addChild(createBookmarkEditForm(ctx, mode, b, origKey, origDesc));
-		
-		this.writeReply(ctx, 200, "text/html", "OK", pageNode.generate());
-	}
-	
-	private HTMLNode createBookmarkEditForm(ToadletContext ctx, int mode, Bookmark b, String origKey, String origDesc) {
-		PageMaker pageMaker = ctx.getPageMaker();
-		HTMLNode infobox = pageMaker.getInfobox("infobox-normal bookmark-edit", (mode == MODE_ADD) ? "New Bookmark" : "Update Bookmark");
-		HTMLNode content = pageMaker.getContentNode(infobox);
-		HTMLNode editForm = ctx.addFormChild(content, ".", mode == MODE_ADD ? "addBookmarkForm" : "editBookmarkForm");
-		editForm.addChild("#", "Key: ");
-		editForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "text", "key", origKey });
-		editForm.addChild("br");
-		editForm.addChild("#", "Description: ");
-		editForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "text", "name", origDesc });
-		editForm.addChild("br");
-		if (mode == MODE_ADD) {
-			editForm.addChild("input", new String[] { "type", "name", "value", "class" }, new String[] { "submit", "addbookmark", "Add bookmark", "confirm" });
-		} else {
-			editForm.addChild("input", new String[] { "type", "name", "value", "class" }, new String[] { "submit", "update_" + b.hashCode(), "Update bookmark", "confirm" });
-                        editForm.addChild("input", new String[] { "type", "value", "class" }, new String[] { "submit", "Cancel", "cancel" });
-		}
-		editForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "hidden", "managebookmarks", "yes" });
-		return infobox;
-	}
-	
 	public String supportedMethods() {
 		return "GET, POST";
 	}

Copied: trunk/freenet/src/freenet/clients/http/bookmark/Bookmark.java (from rev 12707, trunk/freenet/src/freenet/clients/http/Bookmark.java)
===================================================================
--- trunk/freenet/src/freenet/clients/http/bookmark/Bookmark.java	                        (rev 0)
+++ trunk/freenet/src/freenet/clients/http/bookmark/Bookmark.java	2007-04-23 22:41:07 UTC (rev 12908)
@@ -0,0 +1,35 @@
+package freenet.clients.http.bookmark;
+
+public abstract class Bookmark
+{
+	protected boolean privateBookmark;
+	protected String name;
+	protected String desc;
+	
+	public boolean isPrivate()
+	{
+		return privateBookmark;
+	}
+
+	public abstract void setPrivate(boolean bool);
+		
+	public String getName()
+	{
+		return name;
+	}
+
+	protected void setName(String s)
+	{
+		name = s;
+	}
+
+	public String getDesc()
+	{
+		return desc;
+	}
+
+	public void setDesc(String s)
+	{
+		desc = s;
+	}
+}

Added: trunk/freenet/src/freenet/clients/http/bookmark/BookmarkCategories.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/bookmark/BookmarkCategories.java	                        (rev 0)
+++ trunk/freenet/src/freenet/clients/http/bookmark/BookmarkCategories.java	2007-04-23 22:41:07 UTC (rev 12908)
@@ -0,0 +1,43 @@
+
+package freenet.clients.http.bookmark;
+
+import java.util.Vector;
+import java.util.Iterator;
+
+
+public final class BookmarkCategories implements Iterable
+{
+
+	Vector categories;
+
+	public BookmarkCategories()
+	{
+		categories = new Vector();
+	}
+
+	public BookmarkCategory get(int i)
+	{
+		return (BookmarkCategory) categories.get(i);
+	}
+
+	public void add(BookmarkCategory bc)
+	{
+		categories.add(bc);
+	}
+
+	protected void extend(BookmarkCategories bc)
+	{
+		for(int i = 0; i < bc.size(); i++)
+			add(bc.get(i));
+	}
+	
+	public int size()
+	{
+		return categories.size();
+	}
+	
+	public Iterator iterator()
+	{
+		return categories.iterator();
+	}
+}

Added: trunk/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java	                        (rev 0)
+++ trunk/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java	2007-04-23 22:41:07 UTC (rev 12908)
@@ -0,0 +1,155 @@
+package freenet.clients.http.bookmark;
+
+import java.util.Vector;
+import java.util.Iterator;
+
+import freenet.support.StringArray;
+
+
+public class BookmarkCategory extends Bookmark implements Iterable
+{
+
+	private final Vector bookmarks;
+	
+	public BookmarkCategory(String name)
+	{
+		bookmarks = new Vector();
+		setName(name);	
+	}
+	
+	public BookmarkCategory(String name, String desc)
+	{
+		bookmarks = new Vector();
+		setName(name);
+		setDesc(desc);
+	}	
+	
+	protected Bookmark addBookmark(Bookmark b)
+	{
+		bookmarks.add(b);
+		return b;	
+	}
+
+	protected void removeBookmark(Bookmark b)
+	{
+		bookmarks.remove(b);
+	}
+
+	public Bookmark get(int i)
+	{
+		return (Bookmark) bookmarks.get(i);
+	}
+	
+	protected void moveBookmarkUp(Bookmark b)
+	{
+		int index = bookmarks.indexOf(b);
+		if(index == -1)
+			return;
+			
+		Bookmark bk = get(index);
+		bookmarks.remove(index);
+		bookmarks.add((--index < 0) ? 0 : index , bk);
+	}
+	
+	protected void moveBookmarkDown(Bookmark b)
+	{
+		int index = bookmarks.indexOf(b);
+		if(index == -1)
+			return;
+		
+		Bookmark bk = get(index);
+		bookmarks.remove(index);
+		bookmarks.add((++index > size()) ? size() : index, bk);
+	}
+	
+	public int size()
+	{
+		return bookmarks.size();
+	}
+	
+	public BookmarkItems getItems()
+	{
+		BookmarkItems items = new BookmarkItems();
+		for(int i = 0; i < size();  i++) {
+			if(get(i) instanceof BookmarkItem)
+				items.add((BookmarkItem) get(i));
+		}
+
+		return items;
+	}
+	
+	public BookmarkItems getAllItems()
+	{
+		BookmarkItems items = getItems();
+		BookmarkCategories subCategories = getSubCategories();
+		
+		for(int i = 0; i < subCategories.size(); i++) {
+			items.extend(subCategories.get(i).getAllItems());
+		}
+		return items;
+	}
+
+	
+	public BookmarkCategories getSubCategories()
+	{
+		BookmarkCategories categories = new BookmarkCategories();
+		for(int i = 0; i < size();  i++) {
+			if(get(i) instanceof BookmarkCategory)
+				categories.add((BookmarkCategory) get(i));
+		}
+		
+		return categories;
+	}
+	
+	public BookmarkCategories getAllSubCategories()
+	{
+		BookmarkCategories categories = getSubCategories();
+		BookmarkCategories subCategories = getSubCategories();
+		
+		for(int i = 0; i < subCategories.size(); i++) {
+			categories.extend(subCategories.get(i).getAllSubCategories());
+		}
+
+		return categories;
+	}
+	
+
+	public String[] toStrings()
+	{
+		return StringArray.toArray(toStrings("").toArray());
+	}
+	
+	// Iternal use only
+	private Vector toStrings(String prefix)
+	{
+		Vector strings = new Vector();
+		BookmarkItems items = getItems();
+		BookmarkCategories subCategories = getSubCategories();
+		prefix += this.name + "/";
+			
+		for(int i = 0; i < items.size(); i++)
+			strings.add(prefix + items.get(i).toString());
+		
+		for(int i = 0; i < subCategories.size(); i++)
+			strings.addAll(subCategories.get(i).toStrings(prefix));
+
+		return strings;
+		
+	}
+	
+	public void setPrivate(boolean bool)
+	{
+		privateBookmark = bool;
+		
+		BookmarkCategories subCategories = getSubCategories();
+		for(int i = 0; i < size(); i++)
+			subCategories.get(i).setPrivate(bool);
+	}
+	
+	public Iterator iterator()
+	{
+		return bookmarks.iterator();
+	}
+	
+}
+

Added: trunk/freenet/src/freenet/clients/http/bookmark/BookmarkItem.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/bookmark/BookmarkItem.java	                        (rev 0)
+++ trunk/freenet/src/freenet/clients/http/bookmark/BookmarkItem.java	2007-04-23 22:41:07 UTC (rev 12908)
@@ -0,0 +1,143 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.clients.http.bookmark;
+
+import freenet.keys.FreenetURI;
+import freenet.keys.USK;
+import freenet.node.NodeClientCore;
+import freenet.node.useralerts.UserAlert;
+import freenet.node.useralerts.UserAlertManager;
+import freenet.support.HTMLNode;
+
+import java.net.MalformedURLException;
+
+public class BookmarkItem extends Bookmark{
+	
+	private FreenetURI key;
+	private boolean updated;
+	private final BookmarkUpdatedUserAlert alert;
+	private UserAlertManager alerts;
+	
+	
+	public BookmarkItem(FreenetURI k, String n, UserAlertManager uam) throws MalformedURLException {
+		this.key = k;
+		this.name = n;
+		this.alerts = uam;
+		alert = new BookmarkUpdatedUserAlert();
+	}
+
+	public BookmarkItem(FreenetURI k, String n, String d,  UserAlertManager uam) throws MalformedURLException {
+	
+		this.key = k;
+		this.name = n;
+		this.desc = d;
+		this.alerts = uam;
+		alert = new BookmarkUpdatedUserAlert();
+	}
+	
+	private class BookmarkUpdatedUserAlert implements UserAlert {
+
+		public boolean userCanDismiss() {
+			return true;
+		}
+
+		public String getTitle() {
+			return "Bookmark updated: "+ name;
+		}
+
+		public String getText() {
+			return "The bookmarked site "+ name +" has been updated to edition "+key.getSuggestedEdition();
+		}
+
+		public HTMLNode getHTMLText() {
+			HTMLNode n = new HTMLNode("div");
+			n.addChild("#", "The bookmarked site ");
+			n.addChild("a", "href", '/'+key.toString()).addChild("#", name);
+			n.addChild("#", " has been updated to edition "+key.getSuggestedEdition()+".");
+			return n;
+		}
+
+		public short getPriorityClass() {
+			return UserAlert.MINOR;
+		}
+
+		public boolean isValid() {
+			synchronized(BookmarkItem.this) {
+				return updated;
+			}
+		}
+
+		public void isValid(boolean validity) {
+			if(validity) return;
+			disableBookmark();
+		}
+
+		public String dismissButtonText() {
+			return "Delete notification";
+		}
+
+		public boolean shouldUnregisterOnDismiss() {
+			return true;
+		}
+
+		public void onDismiss() {
+			disableBookmark();
+		}
+		
+	}
+	
+	private synchronized void disableBookmark() {
+		updated = false;
+		alerts.unregister(alert);
+	}
+	
+	private synchronized void enableBookmark() {
+		if(updated) return;
+		updated = true;
+		alerts.register(alert);
+	}
+	
+	public String getKey() {
+		return key.toString();
+	}
+	
+	public synchronized FreenetURI getURI() {
+		return key;
+	}
+	
+	public synchronized void setKey(FreenetURI uri) {
+		key = uri;
+	}
+
+	public synchronized String getKeyType() {
+		return key.getKeyType();
+	}
+
+	public String getName() {
+		if (name.equals("")) {
+			return "Unnamed Bookmark";
+		} else {
+			return name;
+		}
+	}
+	
+	public void setPrivate(boolean bool)
+	{
+		privateBookmark = bool;
+	}
+	
+	public String toString() {
+		return this.name + "=" + this.key.toString();
+	}
+
+	public synchronized void setEdition(long ed, NodeClientCore node) {
+		if(key.getSuggestedEdition() >= ed) return;
+		key = key.setSuggestedEdition(ed);
+		enableBookmark();
+	}
+
+	public USK getUSK() throws MalformedURLException {
+		return USK.create(key);
+	}
+}

Added: trunk/freenet/src/freenet/clients/http/bookmark/BookmarkItems.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/bookmark/BookmarkItems.java	                        (rev 0)
+++ trunk/freenet/src/freenet/clients/http/bookmark/BookmarkItems.java	2007-04-23 22:41:07 UTC (rev 12908)
@@ -0,0 +1,43 @@
+package freenet.clients.http.bookmark;
+
+import java.util.Vector;
+import java.util.Iterator;
+
+
+public class BookmarkItems implements Iterable
+{
+
+	Vector items;
+	
+
+	public BookmarkItems()
+	{
+		items = new Vector();
+	}
+
+	public BookmarkItem get(int i)
+	{
+		return (BookmarkItem) items.get(i);
+	}
+
+	public void add(BookmarkItem bi)
+	{
+		items.add(bi);
+	}
+
+	protected void extend(BookmarkItems bi)
+	{
+		for(int i = 0; i < bi.size(); i++)
+			add(bi.get(i));
+	}
+	
+	public int size()
+	{
+		return items.size();
+	}
+	
+	public Iterator iterator()
+	{
+		return (items).iterator();
+	}
+}

Copied: trunk/freenet/src/freenet/clients/http/bookmark/BookmarkManager.java (from rev 12707, trunk/freenet/src/freenet/clients/http/BookmarkManager.java)
===================================================================
--- trunk/freenet/src/freenet/clients/http/bookmark/BookmarkManager.java	                        (rev 0)
+++ trunk/freenet/src/freenet/clients/http/bookmark/BookmarkManager.java	2007-04-23 22:41:07 UTC (rev 12908)
@@ -0,0 +1,338 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+
+
+package freenet.clients.http.bookmark;
+
+import java.net.MalformedURLException;
+import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import freenet.client.async.USKCallback;
+import freenet.config.InvalidConfigValueException;
+import freenet.config.SubConfig;
+import freenet.keys.FreenetURI;
+import freenet.keys.USK;
+import freenet.node.NodeClientCore;
+import freenet.support.api.StringArrCallback;
+
+
+public class BookmarkManager {
+
+	private final NodeClientCore node;
+	private USKUpdatedCallback uskcb;
+	private boolean started;
+	private BookmarkCategory mainCategory;
+	private HashMap bookmarks;
+	
+	public BookmarkManager(NodeClientCore n, SubConfig sc)
+	{
+
+		bookmarks = new HashMap();
+		mainCategory = new BookmarkCategory("/");
+		bookmarks.put("/", mainCategory);
+
+		this.uskcb = new USKUpdatedCallback();
+		this.node = n;
+				
+		try {
+			
+			BookmarkCategory defaultRoot = new BookmarkCategory("/");
+			
+			BookmarkCategory indexes = (BookmarkCategory) defaultRoot.addBookmark(new BookmarkCategory("Indicies"));
+			indexes.addBookmark(new BookmarkItem(new FreenetURI("USK at 7H66rhYmxIFgMyw5Dl11JazXGHPhp7dSN7WMa1pbtEo,jQHUQUPTkeRcjmjgrc7t5cDRdDkK3uKkrSzuw5CO9uk,AQACAAE/ENTRY.POINT/20/full/page1.html"),"Entry point", node.alerts));
+			indexes.addBookmark(new BookmarkItem(new FreenetURI("USK at BPZppy07RyID~NGihHgs4AAw3fUXxgtKIrwRu5rtpWE,k5yjkAFJC93JkydKl6vpY0Zy9D8ec1ymv2XP4Tx5Io0,AQABAAE/FreeHoo/6/"),"Free Hoo", node.alerts));
+	
+			BookmarkCategory flog = (BookmarkCategory) defaultRoot.addBookmark(new BookmarkCategory("Freenet devel's flog"));
+			flog.addBookmark(new BookmarkItem(new FreenetURI("USK at J585KtAJ7UN2~4i17hf7C9XbufMnticJeUDYLcB0dvo,lxZhX2snsExxemocIlI~ZJRFVdVLBLIFZhqV3yswR9U,AQABAAE/toad/10/"),"Toad", node.alerts));
+			flog.addBookmark(new BookmarkItem(new FreenetURI("USK at hM9XRwjXIzU8xTSBXNZvTn2KuvTSRFnVn4EER9FQnpM,gsth24O7ud4gL4NwNuYJDUqfaWASOG2zxZY~ChtgPxc,AQACAAE/Flog/2/"), "Nextgen$", node.alerts));
+			
+			BookmarkCategory apps = (BookmarkCategory) defaultRoot.addBookmark(new BookmarkCategory("Software"));
+			apps.addBookmark(new BookmarkItem(new FreenetURI("USK at XeMBryjuEaxqazEuxwnn~G7wCUOXFOZlVWbscdCOUFs,209eycYVidlZvhgL5V2a3INFxrofxzQctEZvyJaFL7I,AQABAAE/frost/2/"),"Frost", node.alerts));
+				
+			sc.register("bookmarks",defaultRoot.toStrings() , 0, true, false, "List of bookmarks", "A list of bookmarked freesites", makeCB());
+	
+			makeCB().set((sc.getStringArr("bookmarks").length == 0 ? defaultRoot.toStrings() : sc.getStringArr("bookmarks")));
+			
+		
+		} catch (MalformedURLException mue) {
+			// just ignore that one
+		} catch (InvalidConfigValueException icve){
+			//TODO
+			icve.printStackTrace();
+		}
+		
+		synchronized(this) {
+			started = true;
+		}
+	}
+	
+	public class BookmarkCallback implements StringArrCallback 
+	{
+		public String[] get() 
+		{
+
+			synchronized(BookmarkManager.this) {
+
+				return mainCategory.toStrings();
+				
+			}
+		}
+
+		public void set(String[] newVals) throws InvalidConfigValueException 
+		{
+			clear();
+			Pattern pattern = Pattern.compile("/(.*/)([^/]*)=([A-Z]{3}@.*).*");
+
+			FreenetURI key;
+			for (int i = 0; i < newVals.length; i++) {
+				try {
+					Matcher matcher = pattern.matcher(newVals[i]);
+					if(matcher.matches() && matcher.groupCount() == 3) {
+
+						makeParents(matcher.group(1));
+						key  = new FreenetURI(matcher.group(3));
+						addBookmark(matcher.group(1),new BookmarkItem(key, matcher.group(2), node.alerts), false);
+					
+					}else
+						throw new InvalidConfigValueException("Malformed Bookmark");	
+					
+				} catch (MalformedURLException mue) {
+					throw new InvalidConfigValueException(mue.getMessage());
+				}
+			}
+		}
+	}
+	
+	private class USKUpdatedCallback implements USKCallback {
+		public void onFoundEdition(long edition, USK key) {
+			BookmarkItems items = mainCategory.getAllItems();
+			for (int i = 0; i < items.size(); i++) {
+				
+				
+				if (!items.get(i).getKeyType().equals("USK")) 
+					continue;
+				
+				try {
+					FreenetURI furi = new FreenetURI(items.get(i).getKey());
+					USK usk = USK.create(furi);
+					
+					if (usk.equals(key, false)) {
+						items.get(i).setEdition(key.suggestedEdition, node);
+						break;
+					}
+				} catch (MalformedURLException mue) {
+				}
+			}
+			node.storeConfig();
+		}
+	}
+
+	public BookmarkCallback makeCB() {
+		return new BookmarkCallback();
+	}
+
+	public BookmarkCategory getMainCategory()
+	{
+		return mainCategory;
+	}
+
+	public String parentPath(String path)
+	{
+		if(path.equals("/"))
+			return "/";
+
+		return path.substring(0, path.substring(0,path.length() -1).lastIndexOf("/")) + "/";
+	}
+
+	public Bookmark getBookmarkByPath(String path)
+	{
+		return (Bookmark) bookmarks.get(path);
+	}
+
+	public BookmarkCategory getCategoryByPath(String path)
+	{
+		if(getBookmarkByPath(path) instanceof BookmarkCategory)
+			return (BookmarkCategory) getBookmarkByPath(path);
+
+		return null;
+	}
+
+	public BookmarkItem getItemByPath(String path)
+	{
+		if(getBookmarkByPath(path) instanceof BookmarkItem)
+			return (BookmarkItem) getBookmarkByPath(path);
+
+		return null;
+	}
+
+	public void addBookmark(String parentPath, Bookmark b,  boolean store) throws NullPointerException
+	{
+		BookmarkCategory parent = getCategoryByPath(parentPath);
+		if(parent == null)
+			 throw new NullPointerException();
+		else {
+			parent.addBookmark(b);
+			bookmarks.put(parentPath + b.getName() + ((b instanceof BookmarkCategory) ? "/" : ""), b);
+		}	
+			
+		if(store)
+			node.storeConfig();
+	}
+	
+	// TODO
+	public void renameBookmark(String path, String newName)
+	{
+		Bookmark bookmark = getBookmarkByPath(path);
+		bookmark.setName(newName);
+		if(bookmark instanceof BookmarkCategory) {
+			try {
+				makeCB().set(makeCB().get());
+				
+			} catch (InvalidConfigValueException icve) {	}
+		}
+	
+	}
+
+	public void removeBookmark(String path, boolean store)
+	{
+		Bookmark bookmark = getBookmarkByPath(path);
+		if(bookmark == null)
+			return;
+		
+		if(bookmark instanceof BookmarkCategory) {
+			BookmarkCategory cat = (BookmarkCategory) bookmark;
+			for(int i = 0; i < cat.size(); i++) {
+				removeBookmark(path + cat.get(i).getName() + ((cat.get(i) instanceof BookmarkCategory) ? "/" : ""), false);
+			}
+		} else {
+			if(((BookmarkItem) bookmark).getKeyType().equals("USK")) {
+				try {
+					USK u = ((BookmarkItem) bookmark).getUSK();
+					this.node.uskManager.subscribe(u, this.uskcb, true, this);
+				} catch (MalformedURLException mue) { }
+			}
+		}
+
+		getCategoryByPath(parentPath(path)).removeBookmark(getBookmarkByPath(path));
+		bookmarks.remove(path);
+		
+		if(store)
+			node.storeConfig();
+
+	}
+
+	public void moveBookmarkUp(String path, boolean store)
+	{
+		BookmarkCategory parent = getCategoryByPath(parentPath(path));
+		parent.moveBookmarkUp(getBookmarkByPath(path));
+		
+		if(store)
+			node.storeConfig();
+	}
+		
+	public void moveBookmarkDown(String path, boolean store)
+	{
+		BookmarkCategory parent = getCategoryByPath(parentPath(path));
+		parent.moveBookmarkDown(getBookmarkByPath(path));
+		
+		if(store)
+			node.storeConfig();
+	}
+
+	private BookmarkCategory makeParents(String path)
+	{
+		if(bookmarks.containsKey(path))
+			return getCategoryByPath(path);
+		else {
+			
+			int index =  path.substring(0, path.length()-1).lastIndexOf("/");
+			String name = path.substring(index +1, path.length() -1);
+
+			BookmarkCategory cat = new BookmarkCategory(name);
+			makeParents(parentPath(path));
+			addBookmark(parentPath(path), cat, false);
+	
+			return cat;
+		}	
+	}
+	
+	public void clear()
+	{
+
+		removeBookmark("/", false);
+		bookmarks.clear();
+
+		mainCategory = new BookmarkCategory("/");
+		bookmarks.put("/", mainCategory);
+
+	}
+	
+	public FreenetURI[] getBookmarkURIs() 
+	{
+		BookmarkItems items = mainCategory.getAllItems();
+		FreenetURI[] uris = new FreenetURI[items.size()];
+		for(int i = 0; i < items.size(); i++) {
+			uris[i] = items.get(i).getURI();
+		}
+		
+		return uris;
+	}
+	
+	
+	
+/*
+	public void addBookmark(Bookmark b, boolean store) {
+		this.bookmarks.add(b);
+		if (b.getKeyType().equals("USK")) {
+			try {
+				USK u = b.getUSK();
+				this.node.uskManager.subscribe(u, this.uskcb, true, this);
+			} catch (MalformedURLException mue) {
+				
+			}
+		}
+		if(store && started) node.storeConfig();
+	}
+	
+	public void removeBookmark(Bookmark b, boolean store) {
+		if (b.getKeyType().equals("USK")) {
+			try {
+				USK u = b.getUSK();
+				this.node.uskManager.unsubscribe(u, this.uskcb, true);
+			} catch (MalformedURLException mue) {
+			
+			}
+		}
+		this.bookmarks.remove(b);
+		if(store && started) node.storeConfig();
+	}
+	
+	public void moveBookmarkDown (Bookmark b, boolean store) {		
+		int i = this.bookmarks.indexOf(b);
+		if (i == -1) return;
+		
+		Bookmark bk = (Bookmark)this.bookmarks.get(i);
+		this.bookmarks.remove(i);
+		this.bookmarks.add((i+1)%(this.bookmarks.size()+1), bk);
+		
+		if(store && started) node.storeConfig();
+	}
+
+	public void moveBookmarkUp (Bookmark b, boolean store) {
+		int i = this.bookmarks.indexOf(b);
+		if (i == -1) return;
+		
+		Bookmark bk = (Bookmark)this.bookmarks.get(i);
+		this.bookmarks.remove(i);
+		if (--i < 0) i = this.bookmarks.size();
+		this.bookmarks.add(i, bk);
+		
+		if(store && started) node.storeConfig();
+	}
+	
+	public int getSize() {
+		return this.bookmarks.size();
+	}*/
+}

Added: trunk/freenet/src/freenet/clients/http/staticfiles/bookmark.css
===================================================================
--- trunk/freenet/src/freenet/clients/http/staticfiles/bookmark.css	                        (rev 0)
+++ trunk/freenet/src/freenet/clients/http/staticfiles/bookmark.css	2007-04-23 22:41:07 UTC (rev 12908)
@@ -0,0 +1,19 @@
+ul#bookmarks ul {
+	padding-left: 20px;
+}
+
+ul#bookmarks li {
+	list-style-type: none;
+	margin-top: 1px;
+	margin-bottom: 1px;
+}
+
+ul#bookmarks li.cat {
+	font-weight: bold;
+	margin-top: 7px;
+}
+
+ul#bookmarks span.actions img {
+	border: 0;
+	margin-left: 3px;
+}
\ No newline at end of file

Added: trunk/freenet/src/freenet/clients/http/staticfiles/icon/bookmark-new.png
===================================================================
(Binary files differ)


Property changes on: trunk/freenet/src/freenet/clients/http/staticfiles/icon/bookmark-new.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/freenet/src/freenet/clients/http/staticfiles/icon/delete.png
===================================================================
(Binary files differ)


Property changes on: trunk/freenet/src/freenet/clients/http/staticfiles/icon/delete.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/freenet/src/freenet/clients/http/staticfiles/icon/edit-delete.png
===================================================================
(Binary files differ)


Property changes on: trunk/freenet/src/freenet/clients/http/staticfiles/icon/edit-delete.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/freenet/src/freenet/clients/http/staticfiles/icon/edit.png
===================================================================
(Binary files differ)


Property changes on: trunk/freenet/src/freenet/clients/http/staticfiles/icon/edit.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/freenet/src/freenet/clients/http/staticfiles/icon/folder-new.png
===================================================================
(Binary files differ)


Property changes on: trunk/freenet/src/freenet/clients/http/staticfiles/icon/folder-new.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/freenet/src/freenet/clients/http/staticfiles/icon/go-down.png
===================================================================
(Binary files differ)


Property changes on: trunk/freenet/src/freenet/clients/http/staticfiles/icon/go-down.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/freenet/src/freenet/clients/http/staticfiles/icon/go-up.png
===================================================================
(Binary files differ)


Property changes on: trunk/freenet/src/freenet/clients/http/staticfiles/icon/go-up.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: trunk/freenet/src/freenet/clients/http/staticfiles/themes/boxed/theme.css
===================================================================
--- trunk/freenet/src/freenet/clients/http/staticfiles/themes/boxed/theme.css	2007-04-23 22:28:38 UTC (rev 12907)
+++ trunk/freenet/src/freenet/clients/http/staticfiles/themes/boxed/theme.css	2007-04-23 22:41:07 UTC (rev 12908)
@@ -1,3 +1,6 @@
+/* Bookmarks & bookmark editor */
+ at import url(/static/bookmark.css);
+
 body {
 	font-family: tahoma;
 	font-size: 11px;

Modified: trunk/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css
===================================================================
--- trunk/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css	2007-04-23 22:28:38 UTC (rev 12907)
+++ trunk/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css	2007-04-23 22:41:07 UTC (rev 12908)
@@ -1,3 +1,6 @@
+/* Bookmarks & bookmark editor */
+ at import url(/static/bookmark.css);
+
 /* overall settings */
 
 p, span, div, td, th, li, h1, h2, h3, h4, h5 {
@@ -582,3 +585,6 @@
 td.n2ntm-send-failed {
 	background-color: #ffb7b7;
 }
+
+
+

Modified: trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/theme.css
===================================================================
--- trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/theme.css	2007-04-23 22:28:38 UTC (rev 12907)
+++ trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/theme.css	2007-04-23 22:41:07 UTC (rev 12908)
@@ -1,3 +1,5 @@
+/* Bookmarks & bookmark editor */
+ at import url(/static/bookmark.css);
 
 /* [edward at rnahost.com] */
 

Modified: trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/theme.css
===================================================================
--- trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/theme.css	2007-04-23 22:28:38 UTC (rev 12907)
+++ trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/theme.css	2007-04-23 22:41:07 UTC (rev 12908)
@@ -1,3 +1,6 @@
+/* Bookmarks & bookmark editor */
+ at import url(/static/bookmark.css);
+
 /* overall settings */
 
 p, span, div, td, th, li, h1, h2, h3, h4, h5 {

Modified: trunk/freenet/src/freenet/node/NodeClientCore.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeClientCore.java	2007-04-23 22:28:38 UTC (rev 12907)
+++ trunk/freenet/src/freenet/node/NodeClientCore.java	2007-04-23 22:41:07 UTC (rev 12908)
@@ -13,7 +13,7 @@
 import freenet.client.async.SimpleHealingQueue;
 import freenet.client.async.USKManager;
 import freenet.client.events.SimpleEventProducer;
-import freenet.clients.http.BookmarkManager;
+import freenet.clients.http.bookmark.BookmarkManager;
 import freenet.clients.http.FProxyToadlet;
 import freenet.clients.http.SimpleToadletServer;
 import freenet.clients.http.filter.FilterCallback;




More information about the cvs mailing list