Author: dbkr
Date: 2006-03-05 21:35:39 +0000 (Sun, 05 Mar 2006)
New Revision: 8169

Added:
   trunk/freenet/src/freenet/clients/http/PageMaker.java
   trunk/freenet/src/freenet/clients/http/RedirectException.java
   trunk/freenet/src/freenet/clients/http/StaticToadlet.java
   trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java
   trunk/freenet/src/freenet/clients/http/staticfiles/
   trunk/freenet/src/freenet/clients/http/staticfiles/themes/
   trunk/freenet/src/freenet/clients/http/staticfiles/themes/default/
   
trunk/freenet/src/freenet/clients/http/staticfiles/themes/default/background.png
   trunk/freenet/src/freenet/clients/http/staticfiles/themes/default/logo.png
   trunk/freenet/src/freenet/clients/http/staticfiles/themes/default/theme.css
Modified:
   trunk/freenet/src/freenet/clients/http/FproxyToadlet.java
   trunk/freenet/src/freenet/clients/http/Toadlet.java
   trunk/freenet/src/freenet/clients/http/ToadletContext.java
   trunk/freenet/src/freenet/clients/http/ToadletContextImpl.java
   trunk/freenet/src/freenet/clients/http/TrivialToadlet.java
   trunk/freenet/src/freenet/node/Version.java
   trunk/freenet/src/freenet/pluginmanager/PproxyToadlet.java
Log:
500: A web interface is born.
Lots of changes here:
- Creation of WelcomeToadlet and StaticToadlet
- Addition of images and css in src/freenet/clients/http/staticfiles
- Redirect support for Toadlets via RedirectException
- PproxyToadlet changed to be valid XHTML and use Location instead of Meta 
refresh
- Addition of the PageMaker XHTML Page Engine (not as fancy as I've just made 
it sound)

Enjoy!


Modified: trunk/freenet/src/freenet/clients/http/FproxyToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/FproxyToadlet.java   2006-03-05 
21:34:05 UTC (rev 8168)
+++ trunk/freenet/src/freenet/clients/http/FproxyToadlet.java   2006-03-05 
21:35:39 UTC (rev 8169)
@@ -5,6 +5,7 @@
 import java.io.StringWriter;
 import java.net.MalformedURLException;
 import java.net.URI;
+import java.net.URISyntaxException;

 import freenet.client.FetchException;
 import freenet.client.FetchResult;
@@ -19,22 +20,49 @@
 import freenet.node.Node;
 import freenet.node.RequestStarter;
 import freenet.pluginmanager.PproxyToadlet;
+import freenet.pluginmanager.PluginHTTPRequest;
 import freenet.support.Bucket;
 import freenet.support.HTMLEncoder;
 import freenet.support.Logger;
+import freenet.support.MultiValueTable;

 public class FproxyToadlet extends Toadlet {

        public FproxyToadlet(HighLevelSimpleClient client) {
                super(client);
        }
+       
+       public String supportedMethods() {
+               return "GET";
+       }

-       public void handleGet(URI uri, ToadletContext ctx)
-                       throws ToadletContextClosedException, IOException {
+       public void handleGet(URI uri, ToadletContext ctx) 
+                       throws ToadletContextClosedException, IOException, 
RedirectException {
                //String ks = uri.toString();
                String ks = uri.getPath();
+               
+               if (ks.equals("/")) {
+                       PluginHTTPRequest httprequest = new 
PluginHTTPRequest(uri);
+                       if (httprequest.isParameterSet("key")) {
+                               MultiValueTable headers = new MultiValueTable();
+                               
+                               headers.put("Location", 
"/"+httprequest.getParam("key"));
+                               ctx.sendReplyHeaders(302, "Found", headers, 
null, 0);
+                               return;
+                       }
+                       
+                       RedirectException re = new RedirectException();
+                       try {
+                               re.newuri = new URI("/welcome/");
+                       } catch (URISyntaxException e) {
+                               // HUH!?!
+                       }
+                       throw re;
+               }
+               
                if(ks.startsWith("/"))
                        ks = ks.substring(1);
+               
                FreenetURI key;
                try {
                        key = new FreenetURI(ks);
@@ -65,15 +93,6 @@
                }
        }

-       public void handlePut(URI uri, Bucket data, ToadletContext ctx)
-                       throws ToadletContextClosedException, IOException {
-               String notSupported = "<html><head><title>Not 
supported</title></head><body>"+
-               "Operation not supported</body>";
-               // FIXME should be 405? Need to let toadlets indicate what is 
allowed maybe in a callback?
-               this.writeReply(ctx, 200, "text/html", "OK", notSupported);
-       }
-
-
        static class FproxyEnabledCallback implements BooleanCallback {

                final Node node;
@@ -161,8 +180,16 @@
         FproxyToadlet fproxy = new 
FproxyToadlet(node.makeClient(RequestStarter.INTERACTIVE_PRIORITY_CLASS));
         node.setFproxy(fproxy);
         server.register(fproxy, "/", false);
+       
         PproxyToadlet pproxy = new 
PproxyToadlet(node.makeClient(RequestStarter.INTERACTIVE_PRIORITY_CLASS), 
node.pluginManager);
         server.register(pproxy, "/plugins/", true);
+       
+       WelcomeToadlet welcometoadlet = new 
WelcomeToadlet(node.makeClient(RequestStarter.INTERACTIVE_PRIORITY_CLASS));
+       server.register(welcometoadlet, "/welcome/", true);
+       
+       StaticToadlet statictoadlet = new 
StaticToadlet(node.makeClient(RequestStarter.INTERACTIVE_PRIORITY_CLASS));
+       server.register(statictoadlet, "/static/", true);
+       
         fproxyConfig.finishedInitialization();
         System.out.println("Starting fproxy on port "+(port));
         Logger.normal(node,"Starting fproxy on "+bind_ip+":"+port); 

Added: trunk/freenet/src/freenet/clients/http/PageMaker.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/PageMaker.java       2006-03-05 
21:34:05 UTC (rev 8168)
+++ trunk/freenet/src/freenet/clients/http/PageMaker.java       2006-03-05 
21:35:39 UTC (rev 8169)
@@ -0,0 +1,52 @@
+package freenet.clients.http;
+
+/** Simple class to output standard heads and tail for web interface pages. 
+*/
+public class PageMaker {
+       // TODO: make this...err... not a constant.
+       private final String theme = new String("default");
+
+       public void makeTopHead(StringBuffer buf) {
+               buf.append("<!DOCTYPE\n"
+                               + "     html PUBLIC \"-//W3C//DTD XHTML 
1.1//EN\"\n"
+                               + "     
\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\";>\n"
+                               + "<html xmlns=\"http://www.w3.org/1999/xhtml\"; 
xml:lang=\"en\">\n"
+                               + "<head>\n"
+                               + "<meta http-equiv=\"Content-Type\" 
content=\"text/html;\" />\n"
+                               + "<link rel=\"stylesheet\" 
href=\"/static/themes/"+theme+"/theme.css\" type=\"text/css\" />\n");
+       }
+       
+       public void makeBottomHead(StringBuffer buf, String title) {
+               buf.append("<title>"+title+" - Freenet</title>\n"
+                               + "</head>\n"
+                               + "<body>\n"
+                               + "<div id=\"page\">\n"
+                               + "<div id=\"topbar\">\n"
+                               + "<h1>"+title+"</h1>\n"
+                               + "</div>\n");
+               this.makeNavBar(buf);
+               buf.append("<div id=\"content\">\n");
+       }
+       
+       public void makeHead(StringBuffer buf, String title) {
+               makeTopHead(buf);
+               makeBottomHead(buf, title);
+       }
+       
+       public void makeTail(StringBuffer buf) {
+               buf.append("<br style=\"clear: all;\"/>"
+                               + "</div>\n"
+                               +"</div>\n"
+                               +"</body>\n"
+                               + "</html>\n");
+       }
+       
+       private void makeNavBar(StringBuffer buf) {
+               buf.append("<div id=\"navbar\">\n"
+                               + "<ul id=\"navlist\">\n"
+                               + "<li><a href=\"/\" 
title=\"Homepage\">Home</a></li>\n"
+                               + "<li><a href=\"/plugins/\" title=\"Configure 
Plugins\">Plugins</a></li>\n"
+                               + "</ul>\n"
+                               + "</div>\n");
+       }
+}

Added: trunk/freenet/src/freenet/clients/http/RedirectException.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/RedirectException.java       
2006-03-05 21:34:05 UTC (rev 8168)
+++ trunk/freenet/src/freenet/clients/http/RedirectException.java       
2006-03-05 21:35:39 UTC (rev 8169)
@@ -0,0 +1,7 @@
+package freenet.clients.http;
+
+import java.net.URI;
+
+class RedirectException extends Exception {
+       URI newuri;
+}

Added: trunk/freenet/src/freenet/clients/http/StaticToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/StaticToadlet.java   2006-03-05 
21:34:05 UTC (rev 8168)
+++ trunk/freenet/src/freenet/clients/http/StaticToadlet.java   2006-03-05 
21:35:39 UTC (rev 8169)
@@ -0,0 +1,65 @@
+package freenet.clients.http;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.FileNameMap;
+import java.net.URLConnection;
+import freenet.client.HighLevelSimpleClient;
+import freenet.support.MultiValueTable;
+
+/**
+ * Static Toadlet.
+ * Serve up static files
+ */
+public class StaticToadlet extends Toadlet {
+       StaticToadlet(HighLevelSimpleClient client) {
+               super(client);
+       }
+       
+       final String rootURL = new String("/static/");
+       final String rootPath = new String("staticfiles/");
+       
+       public void handleGet(URI uri, ToadletContext ctx) throws 
ToadletContextClosedException, IOException {
+               String path = uri.getPath();
+               byte[] buf = new byte[1024];
+               int len;
+               
+               if (!path.startsWith(rootURL)) {
+                       // we should never get any other path anyway
+                       return;
+               }
+               try {
+                       path = path.substring(rootURL.length());
+               } catch (IndexOutOfBoundsException ioobe) {
+                       this.sendErrorPage(ctx, 404, "Path not found", "The 
path you specified doesn't exist");
+                       return;
+               }
+               
+               // be very strict about what characters we allow in the path, 
since
+               if (!path.matches("^[A-Za-z0-9\\._\\/\\-]*$") || 
path.indexOf("..") != -1) {
+                       this.sendErrorPage(ctx, 404, "Path not found", "The 
given URI contains disallowed characters.");
+                       return;
+               }
+               
+               
+               InputStream strm = 
getClass().getResourceAsStream(rootPath+path);
+               if (strm == null) {
+                       this.sendErrorPage(ctx, 404, "Path not found", "The 
specified path does not exist.");
+                       return;
+               }
+               
+               
+               FileNameMap map = URLConnection.getFileNameMap();
+               
+               ctx.sendReplyHeaders(200, "OK", null, 
map.getContentTypeFor(path), strm.available());
+               
+               while ( (len = strm.read(buf)) > 0) {
+                       ctx.writeData(buf, 0, len);
+               }
+       }
+       
+       public String supportedMethods() {
+               return "GET";
+       }
+}

Modified: trunk/freenet/src/freenet/clients/http/Toadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/Toadlet.java 2006-03-05 21:34:05 UTC 
(rev 8168)
+++ trunk/freenet/src/freenet/clients/http/Toadlet.java 2006-03-05 21:35:39 UTC 
(rev 8169)
@@ -10,6 +10,7 @@
 import freenet.client.InserterException;
 import freenet.keys.FreenetURI;
 import freenet.support.Bucket;
+import freenet.support.MultiValueTable;

 /**
  * Replacement for servlets. Just an easy to use HTTP interface, which is
@@ -38,20 +39,53 @@

        /**
         * Handle a GET request.
-        * Must be implemented by the client.
+        * If not overridden by the client, send 'Method not supported'
         * @param uri The URI (relative to this client's document root) to
         * be fetched.
         * @throws IOException 
         * @throws ToadletContextClosedException 
         */
-       abstract public void handleGet(URI uri, ToadletContext ctx) throws 
ToadletContextClosedException, IOException;
+       public void handleGet(URI uri, ToadletContext ctx) throws 
ToadletContextClosedException, IOException, RedirectException {
+               StringBuffer buf = new StringBuffer();
+               
+               ctx.getPageMaker().makeHead(buf, "Not supported");
+               
+               buf.append("Operation not supported");
+               ctx.getPageMaker().makeTail(buf);
+               
+               MultiValueTable hdrtbl = new MultiValueTable();
+               hdrtbl.put("Allow", this.supportedMethods());
+               ctx.sendReplyHeaders(405, "Operation not Supported", hdrtbl, 
"text/html", buf.length());
+               ctx.writeData(buf.toString().getBytes(), 0, buf.length());
+       }
+       

        /**
         * Likewise for a PUT request.
         */
-       abstract public void handlePut(URI uri, Bucket data, ToadletContext 
ctx) throws ToadletContextClosedException, IOException;
+       public void handlePut(URI uri, Bucket data, ToadletContext ctx) throws 
ToadletContextClosedException, IOException, RedirectException {
+               StringBuffer buf = new StringBuffer();
+               
+               ctx.getPageMaker().makeHead(buf, "Not supported");
+               
+               buf.append("Operation not supported");
+               ctx.getPageMaker().makeTail(buf);
+               
+               MultiValueTable hdrtbl = new MultiValueTable();
+               hdrtbl.put("Allow", this.supportedMethods());
+               ctx.sendReplyHeaders(405, "Operation not Supported", hdrtbl, 
"text/html", buf.length());
+               ctx.writeData(buf.toString().getBytes(), 0, buf.length());
+       }

        /**
+        * Which methods are supported by this Toadlet.
+        * Should return a string containing the methods supported, separated 
by commas
+        * For example: "GET, PUT" (in which case both 'handleGet()' and 
'handlePut()'
+        * must be overridden).
+        */                                     
+       abstract public String supportedMethods();
+       
+       /**
         * Client calls from the above messages to run a freenet request.
         * This method may block (or suspend).
         */
@@ -88,6 +122,18 @@
        }

        /**
+        * Send a simple error page.
+        */
+       protected void sendErrorPage(ToadletContext ctx, int code, String desc, 
String message) throws ToadletContextClosedException, IOException {
+               StringBuffer buf = new StringBuffer();
+                       
+               ctx.getPageMaker().makeHead(buf, desc);
+               buf.append(message);
+               ctx.getPageMaker().makeTail(buf);
+               writeReply(ctx, code, "text/html", desc, buf.toString());
+       }
+       
+       /**
         * Get the client impl. DO NOT call the blocking methods on it!!
         * Just use it for configuration etc.
         */

Modified: trunk/freenet/src/freenet/clients/http/ToadletContext.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/ToadletContext.java  2006-03-05 
21:34:05 UTC (rev 8168)
+++ trunk/freenet/src/freenet/clients/http/ToadletContext.java  2006-03-05 
21:35:39 UTC (rev 8169)
@@ -30,5 +30,10 @@
         * Write data from a bucket. You must send reply headers first.
         */
        void writeData(Bucket data) throws ToadletContextClosedException, 
IOException;
+       
+       /**
+        * Get the page maker object.
+        */
+       PageMaker getPageMaker();
+}

-}

Modified: trunk/freenet/src/freenet/clients/http/ToadletContextImpl.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/ToadletContextImpl.java      
2006-03-05 21:34:05 UTC (rev 8168)
+++ trunk/freenet/src/freenet/clients/http/ToadletContextImpl.java      
2006-03-05 21:35:39 UTC (rev 8169)
@@ -29,6 +29,7 @@
        private final Socket sock;
        private final MultiValueTable headers;
        private final OutputStream sockOutputStream;
+       private final PageMaker pagemaker;
        /** Is the context closed? If so, don't allow any more writes. This is 
because there
         * may be later requests.
         */
@@ -39,6 +40,7 @@
                this.headers = headers;
                this.closed = false;
                sockOutputStream = sock.getOutputStream();
+               pagemaker = new PageMaker();
        }

        private void close() {
@@ -78,6 +80,10 @@
                if(closed) throw new ToadletContextClosedException();
                sendReplyHeaders(sockOutputStream, replyCode, replyDescription, 
mvt, mimeType, contentLength);
        }
+       
+       public PageMaker getPageMaker() {
+               return pagemaker;
+       }

        static void sendReplyHeaders(OutputStream sockOutputStream, int 
replyCode, String replyDescription, MultiValueTable mvt, String mimeType, long 
contentLength) throws IOException {
                // Construct headers
@@ -163,38 +169,50 @@
                                        headers.put(before, after);
                                }

-                               // Handle it.
+                               boolean shouldDisconnect = 
shouldDisconnectAfterHandled(split[2].equals("HTTP/1.0"), headers);

-                               Toadlet t = container.findToadlet(uri);
-                               
                                ToadletContextImpl ctx = new 
ToadletContextImpl(sock, headers);

-                               boolean shouldDisconnect = 
shouldDisconnectAfterHandled(split[2].equals("HTTP/1.0"), headers);
-                               
-                               if(t == null)
-                                       
ctx.sendNoToadletError(shouldDisconnect);
-                               
-                               if(method.equals("GET")) {
+                               // Handle it.
+                               boolean redirect = true;
+                               while (redirect) {
+                                       // don't go around the loop unless set 
explicitly
+                                       redirect = false;

-                                       t.handleGet(uri, ctx);
-                                       ctx.close();
+                                       Toadlet t = container.findToadlet(uri);

-                               } else if(method.equals("PUT")) {
-                       
-                                       t.handlePut(uri, null, ctx);
-                                       ctx.close();
-
-                               } else if(method.equals("POST")) {
+                                       if(t == null)
+                                               
ctx.sendNoToadletError(shouldDisconnect);

-                                       Logger.error(ToadletContextImpl.class, 
"POST not supported");
-                                       ctx.sendMethodNotAllowed(method, 
shouldDisconnect);
-                                       ctx.close();
-                                       
-                               } else {
-                                       ctx.sendMethodNotAllowed(method, 
shouldDisconnect);
-                                       ctx.close();
+                                       if(method.equals("GET")) {
+                                               try {
+                                                       t.handleGet(uri, ctx);
+                                                       ctx.close();
+                                               } catch (RedirectException re) {
+                                                       uri = re.newuri;
+                                                       redirect = true;
+                                               }
+                                               
+                                       } else if(method.equals("PUT")) {
+                                               try {
+                                                       t.handlePut(uri, null, 
ctx);
+                                                       ctx.close();
+                                               } catch (RedirectException re) {
+                                                       uri = re.newuri;
+                                                       redirect = true;
+                                               }
+       
+                                       } else if(method.equals("POST")) {
+                                               
+                                               
Logger.error(ToadletContextImpl.class, "POST not supported");
+                                               
ctx.sendMethodNotAllowed(method, shouldDisconnect);
+                                               ctx.close();
+                                               
+                                       } else {
+                                               
ctx.sendMethodNotAllowed(method, shouldDisconnect);
+                                               ctx.close();
+                                       }
                                }
-                               
                                if(shouldDisconnect) {
                                        sock.close();
                                        return;

Modified: trunk/freenet/src/freenet/clients/http/TrivialToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/TrivialToadlet.java  2006-03-05 
21:34:05 UTC (rev 8168)
+++ trunk/freenet/src/freenet/clients/http/TrivialToadlet.java  2006-03-05 
21:35:39 UTC (rev 8169)
@@ -21,12 +21,8 @@
                        encFetched+"</a>.</body></html>";
                this.writeReply(ctx, 200, "text/html", "OK", reply);
        }
-
-       public void handlePut(URI uri, Bucket data, ToadletContext ctx) throws 
ToadletContextClosedException, IOException {
-               String notSupported = "<html><head><title>Not 
supported</title></head><body>"+
-                       "Operation not supported</body>";
-               // This really should be 405, but then we'd have to put an 
Allow header in.
-               this.writeReply(ctx, 200, "text/html", "OK", notSupported);
+       
+       public String supportedMethods() {
+               return "GET";
        }
-
 }

Added: trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java  2006-03-05 
21:34:05 UTC (rev 8168)
+++ trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java  2006-03-05 
21:35:39 UTC (rev 8169)
@@ -0,0 +1,51 @@
+package freenet.clients.http;
+
+import java.io.IOException;
+import java.net.URI;
+
+import freenet.client.HighLevelSimpleClient;
+import freenet.support.Bucket;
+import freenet.support.HTMLEncoder;
+import freenet.support.MultiValueTable;
+import freenet.support.SimpleFieldSet;
+import freenet.node.Version;
+
+public class WelcomeToadlet extends Toadlet {
+       WelcomeToadlet(HighLevelSimpleClient client) {
+               super(client);
+       }
+
+       public void handleGet(URI uri, ToadletContext ctx) throws 
ToadletContextClosedException, IOException {
+               StringBuffer buf = new StringBuffer();
+               
+               ctx.getPageMaker().makeHead(buf, "Freenet FProxy Homepage");
+               
+               // Version info
+               buf.append("<div class=\"infobox\">\n");
+               buf.append("<h2>Version</h2>");
+               buf.append("Freenet version "+Version.nodeVersion+" build 
#"+Version.buildNumber());
+               if(Version.buildNumber() < Version.highestSeenBuild) {
+                       buf.append("<br />");
+                       buf.append("<b>A newer version is available! (Build 
#"+Version.highestSeenBuild+")</b>");
+               }
+               buf.append("</div>\n");
+               
+               // Fetch-a-key box
+               buf.append("<br style=\"clear: all; \" />\n");
+               buf.append("<form action=\"/\" method=\"get\">\n");
+               buf.append("<div class=\"infobox\">\n");
+               buf.append("<h2>Fetch a Key</h2>\n");
+               buf.append("Key: <input type=\"text\" size=\"100\" 
name=\"key\"/>\n");
+               buf.append("<input type=\"submit\" value=\"Fetch\" />\n");
+               buf.append("</div>\n");
+               buf.append("</form>\n");
+               
+               ctx.getPageMaker().makeTail(buf);
+               
+               this.writeReply(ctx, 200, "text/html", "OK", buf.toString());
+       }
+       
+       public String supportedMethods() {
+               return "GET";
+       }
+}
\ No newline at end of file

Added: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/default/background.png
===================================================================
(Binary files differ)


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

Added: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/default/logo.png
===================================================================
(Binary files differ)


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

Added: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/default/theme.css
===================================================================
--- trunk/freenet/src/freenet/clients/http/staticfiles/themes/default/theme.css 
2006-03-05 21:34:05 UTC (rev 8168)
+++ trunk/freenet/src/freenet/clients/http/staticfiles/themes/default/theme.css 
2006-03-05 21:35:39 UTC (rev 8169)
@@ -0,0 +1,66 @@
+body {
+       margin: 10px;
+       border: 3px double #356ace;
+       background-image: url(/static/themes/default/background.png);
+       background-repeat: repeat;
+       padding: 10px;
+       padding-top: 0px;
+       min-height: 400px;
+}
+
+#topbar {
+       margin: 0px;
+       margin-bottom: 10px;
+       background-image: url(/static/themes/default/logo.png);
+       background-repeat: no-repeat;
+       background-position: top left;
+       min-height: 51px;
+       padding-left: 100px;
+}
+
+#navbar {
+       float: left;
+       border: 2px solid #5e88d8;
+       margin-right: 10px;
+       text-align: center;
+       padding: 5px;
+}
+
+#navlist {
+       display: inline;
+       margin: 0;
+       padding: 0;
+       text-align: center;
+}
+
+#navlist li {
+       display: inline;
+       margin: 0;
+       padding: 0;
+       list-style-type: none;
+       list-style-position: outside;
+       font-weight: bold;
+}
+
+#navlist a {
+       display: block;
+       color: black;
+}
+
+#navlist a:visited {
+       display: block;
+       color: black;
+}
+
+#navlist a:active {
+       display: block;
+       color: black;
+}
+
+.infobox {
+       border: 1px solid #5e88d8;
+       padding: 5px;
+       float: left;
+       margin-bottom: 10px;
+}
+

Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-03-05 21:34:05 UTC (rev 
8168)
+++ trunk/freenet/src/freenet/node/Version.java 2006-03-05 21:35:39 UTC (rev 
8169)
@@ -20,7 +20,7 @@
        public static final String protocolVersion = "1.0";

        /** The build number of the current revision */
-       private static final int buildNumber = 499;
+       private static final int buildNumber = 500;

        /** Oldest build of Fred we will talk to */
        private static final int lastGoodBuild = 475;

Modified: trunk/freenet/src/freenet/pluginmanager/PproxyToadlet.java
===================================================================
--- trunk/freenet/src/freenet/pluginmanager/PproxyToadlet.java  2006-03-05 
21:34:05 UTC (rev 8168)
+++ trunk/freenet/src/freenet/pluginmanager/PproxyToadlet.java  2006-03-05 
21:35:39 UTC (rev 8169)
@@ -18,11 +18,13 @@
 import freenet.clients.http.Toadlet;
 import freenet.clients.http.ToadletContext;
 import freenet.clients.http.ToadletContextClosedException;
+import freenet.clients.http.PageMaker;
 import freenet.keys.FreenetURI;
 import freenet.support.Bucket;
 import freenet.support.Logger;
 import freenet.support.URLDecoder;
 import freenet.support.URLEncodedFormatException;
+import freenet.support.MultiValueTable;

 public class PproxyToadlet extends Toadlet {
        private PluginManager pm = null;
@@ -31,20 +33,11 @@
                super(client);
                this.pm = pm;
        }
+       
+       public String supportedMethods() {
+               return "GET";
+       }

-       /**
-        * TODO: Remove me eventually!!!!
-        * 
-        * @param title
-        * @param content
-        * @return
-        */
-       private String mkPage(String title, String content) {
-               if (content == null) content = "null";
-               return "<html><head><title>" + title + 
"</title></head><body><h1>"+
-               title +"</h1>" + content + "</body>";
-       }
-       
        private String mkForwardPage(String title, String content, String 
nextpage, int interval) {
                if (content == null) content = "null";
                return "<html><head><title>" + title + "</title>"+
@@ -61,7 +54,7 @@
                        ks = URLDecoder.decode(uri.toString());
                } catch (URLEncodedFormatException e) {
                        // TODO Auto-generated catch block
-                       writeReply(ctx, 500, "text/html", "OK", 
mkPage("Internal Server Error", "Could not parse URI"));
+                       this.sendErrorPage(ctx, 500, "Internal Server Error", 
"Could not parse URI");
                        return;
                }

@@ -72,12 +65,13 @@
                try {
                        if (ks.equals("")) {
                                StringBuffer out = new StringBuffer();
+                               ctx.getPageMaker().makeHead(out, "Plugin List");
                                out.append("<table style=\"border: 1pt solid 
#c0c0c0;\">");
                                out.append("  <tr>\n");
-                               out.append("    <td 
align=\"center\">Name</td>\n");
-                               out.append("    <td 
align=\"center\">ID</td>\n");
-                               out.append("    <td 
align=\"center\">Started</td>\n");
-                               out.append("    <td align=\"center\"></td>\n");
+                               out.append("    <th>Name</th>\n");
+                               out.append("    <th>ID</th>\n");
+                               out.append("    <th>Started</th>\n");
+                               out.append("    <th></th>\n");
                                out.append("  </tr>\n");
                                Iterator it = pm.getPlugins().iterator();
                                while (it.hasNext()) {
@@ -88,26 +82,48 @@
                                        out.append("    <td style=\"border: 1pt 
solid #c0c0c0;\">" + (new Date(pi.getStarted())) + "</td>\n");
                                        out.append("    <td style=\"border: 1pt 
solid #c0c0c0;\">");
                                        if (pi.isPproxyPlugin())
-                                               out.append("&nbsp;<A 
HREF=\""+pi.getPluginClassName()+"/\">[VISIT]</A>&nbsp;");
-                                       out.append("&nbsp;<A 
HREF=\"?remove="+pi.getThreadName()+"\">[UNLOAD]</A>&nbsp;");
+                                               out.append("&nbsp;<a 
href=\""+pi.getPluginClassName()+"/\">[VISIT]</a>&nbsp;");
+                                       out.append("&nbsp;<a 
href=\"?remove="+pi.getThreadName()+"\">[UNLOAD]</a>&nbsp;");
                                        out.append("</td>\n");
                                        out.append("  </tr>\n");
                                }
+                               
+                               if (pm.getPlugins().isEmpty()) {
+                                       out.append("<tr>\n");
+                                       out.append("<td colspan=\"4\"\n");
+                                       out.append("<i>No plugins 
loaded</i>\n");
+                                       out.append("</td>\n");
+                                       out.append("</tr>\n");
+                               }
+                               
                                out.append("</table>");
-                               String ret = "<hr/>" + out.toString();
+                               //String ret = "<hr/>" + out.toString();
                                //ret = pm.dumpPlugins().replaceAll(",", 
"\n&nbsp; &nbsp; ").replaceAll("\"", " \" ");
-                               if (ret.length() < 6)
+                               /*if (ret.length() < 6)
                                        ret += "<i>No plugins loaded</i>\n";
-                               ret += "<hr/>";
-                               ret += "<form method=\"GET\">Remove plugin: 
(enter ID) <input type=text name=\"remove\" size=40/><input type=submit 
value=\"Remove\"/></form>\n";
-                               ret += "<form method=\"GET\">Load plugin: 
<input type=text name=\"load\" size=40/><input type=submit value=\"Load\" 
/></form>\n";
-                               writeReply(ctx, 200, "text/html", "OK", 
mkPage("Plugin list", ret));
+                               ret += "<hr/>";*/
+                               
+                               
+                               // Obsolete
+                               //out.append("<form method=\"get\"><div>Remove 
plugin: (enter ID) <input type=\"text\" name=\"remove\" size=40/><input 
type=\"submit\" value=\"Remove\"/></div></form>\n");
+                               out.append("<form method=\"get\" 
action=\".\"><div>Load plugin: <input type=\"text\" name=\"load\" 
size=\"40\"/><input type=\"submit\" value=\"Load\" /></div></form>\n");
+                               ctx.getPageMaker().makeTail(out);
+                               writeReply(ctx, 200, "text/html", "OK", 
out.toString());
                        } else if (ks.startsWith("?remove=")) {
                                
pm.killPlugin(ks.substring("?remove=".length()));
-                               writeReply(ctx, 200, "text/html", "OK", 
mkForwardPage("Removing plugin", "Removing plugin...", ".", 5));
+                               
+                               MultiValueTable headers = new MultiValueTable();
+                               
+                               headers.put("Location", ".");
+                               ctx.sendReplyHeaders(302, "Found", headers, 
null, 0);
+                               //writeReply(ctx, 200, "text/html", "OK", 
mkForwardPage("Removing plugin", "Removing plugin...", ".", 5));
                        } else if (ks.startsWith("?load=")) {
                                pm.startPlugin(ks.substring("?load=".length()));
-                               writeReply(ctx, 200, "text/html", "OK", 
mkForwardPage("Loading plugin", "Loading plugin...", ".", 5));
+                               //writeReply(ctx, 200, "text/html", "OK", 
mkForwardPage("Loading plugin", "Loading plugin...", ".", 5));
+                               MultiValueTable headers = new MultiValueTable();
+                               
+                               headers.put("Location", ".");
+                               ctx.sendReplyHeaders(302, "Found", headers, 
null, 0);
                        } else {
                                int to = ks.indexOf("/");
                                String plugin, data;
@@ -145,13 +161,4 @@
                        this.writeReply(ctx, 500, "text/html", "Internal 
Error", msg);
                }
        }
-
-       public void handlePut(URI uri, Bucket data, ToadletContext ctx)
-                       throws ToadletContextClosedException, IOException {
-               String notSupported = "<html><head><title>Not 
supported</title></head><body>"+
-               "Operation not supported</body>";
-               // FIXME should be 405? Need to let toadlets indicate what is 
allowed maybe in a callback?
-               super.writeReply(ctx, 200, "text/html", "OK", notSupported);
-       }
-
 }


Reply via email to