Author: toad
Date: 2006-12-12 00:24:26 +0000 (Tue, 12 Dec 2006)
New Revision: 11347

Modified:
   trunk/freenet/src/freenet/clients/http/FProxyToadlet.java
   trunk/freenet/src/freenet/clients/http/HTTPRequest.java
   trunk/freenet/src/freenet/clients/http/NinjaSpider.java
   trunk/freenet/src/freenet/clients/http/QueueToadlet.java
   trunk/freenet/src/freenet/clients/http/Spider.java
   trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java
   trunk/freenet/src/freenet/clients/http/filter/GenericReadFilterCallback.java
   trunk/freenet/src/freenet/keys/FreenetURI.java
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/PeerNode.java
   trunk/freenet/src/freenet/node/TextModeClientInterface.java
   trunk/freenet/src/freenet/node/fcp/ClientGet.java
   trunk/freenet/src/freenet/node/fcp/ClientGetMessage.java
   trunk/freenet/src/freenet/node/fcp/ClientPutBase.java
   trunk/freenet/src/freenet/node/fcp/FCPServer.java
   trunk/freenet/src/freenet/node/fcp/GetFailedMessage.java
   trunk/freenet/src/freenet/node/fcp/PersistentGet.java
   trunk/freenet/src/freenet/node/fcp/PersistentPut.java
   trunk/freenet/src/freenet/node/fcp/PersistentPutDir.java
   trunk/freenet/src/freenet/node/fcp/PutFetchableMessage.java
   trunk/freenet/src/freenet/node/updater/NodeUpdaterManager.java
   trunk/freenet/src/freenet/support/URLDecoder.java
   trunk/freenet/src/freenet/support/URLEncoder.java
Log:
Use URL encoding/decoding for Freenet URI's.
They are a kind of URI, therefore they need to adhere to URI syntax.
Fixes #814. If you include a ? in a freenet URI, it will be encoded. You can 
even include a slash in the middle of a manifest component (I think; try it), 
as long as it's encoded.
Better to get this over with sooner rather than later...

Modified: trunk/freenet/src/freenet/clients/http/FProxyToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/FProxyToadlet.java   2006-12-11 
20:59:56 UTC (rev 11346)
+++ trunk/freenet/src/freenet/clients/http/FProxyToadlet.java   2006-12-12 
00:24:26 UTC (rev 11347)
@@ -102,7 +102,7 @@

                try {
                        if((!force) && (!forceDownload)) {
-                               FilterOutput fo = ContentFilter.filter(data, 
bucketFactory, mimeType, new URI(basePath + 
URLEncoder.encode(key.toString(false))), null);
+                               FilterOutput fo = ContentFilter.filter(data, 
bucketFactory, mimeType, key.toURI(basePath), null);
                                data = fo.data;
                                mimeType = fo.type;

@@ -121,20 +121,20 @@
                                        HTMLNode optionList = 
infoboxContent.addChild("ul");
                                        HTMLNode option = 
optionList.addChild("li");

-                                       option.addChild("a", "href", basePath + 
key.toString(false) + "?type=text/plain&force=" + getForceValue(key, 
now)+extras, "Click here");
+                                       option.addChild("a", "href", basePath + 
key.toString() + "?type=text/plain&force=" + getForceValue(key, now)+extras, 
"Click here");
                                        option.addChild("%", " to open the file 
as plain text (this <b>may be dangerous</b> if you are running IE7 or FF2).");
                                        //      FIXME: is this safe? See bug 
#131
                                        option = optionList.addChild("li");
-                                       option.addChild("a", "href", basePath + 
key.toString(false) + "?forcedownload"+extras, "Click here");
+                                       option.addChild("a", "href", basePath + 
key.toString() + "?forcedownload"+extras, "Click here");
                                        option.addChild("%", " to try to force 
your browser to download the file to disk (<b>this may also be dangerous if you 
run Firefox 2.0.0 (2.0.1 should fix this)</b>).");
                                        if(!mimeType.startsWith("text/plain")) {
                                                option = 
optionList.addChild("li");
-                                               option.addChild("a", "href", 
basePath + key.toString(false) + "?force=" + getForceValue(key, now)+extras, 
"Click here");
+                                               option.addChild("a", "href", 
basePath + key.toString() + "?force=" + getForceValue(key, now)+extras, "Click 
here");
                                                option.addChild("#", " to open 
the file as " + mimeType);
                                                option.addChild("%", " (<b>this 
may also be dangerous</b>).");
                                        }
                                        option = optionList.addChild("li");
-                                       option.addChild("a", "href", basePath + 
key.toString(false) + "?type=application/xml+rss&force=" + getForceValue(key, 
now)+extras, "Click here");
+                                       option.addChild("a", "href", basePath + 
key.toString() + "?type=application/xml+rss&force=" + getForceValue(key, 
now)+extras, "Click here");
                                        option.addChild("%", " to open the file 
as RSS (<b>this is dangerous if the site author is malicious</b>).");
                                        if(referrer != null) {
                                                option = 
optionList.addChild("li");
@@ -177,14 +177,14 @@
                        infoboxContent.addChild("p", "Your options are:");
                        HTMLNode optionList = infoboxContent.addChild("ul");
                        HTMLNode option = optionList.addChild("li");
-                       option.addChild("a", "href", basePath + 
key.toString(false) + "?type=text/plain"+extras, "Click here");
+                       option.addChild("a", "href", basePath + key.toString() 
+ "?type=text/plain"+extras, "Click here");
                        option.addChild("#", " to open the file as plain text 
(this should not be dangerous but it may be garbled).");
                        // FIXME: is this safe? See bug #131
                        option = optionList.addChild("li");
-                       option.addChild("a", "href", basePath + 
key.toString(false) + "?forcedownload"+extras, "Click here");
+                       option.addChild("a", "href", basePath + key.toString() 
+ "?forcedownload"+extras, "Click here");
                        option.addChild("#", " to force your browser to 
download the file to disk.");
                        option = optionList.addChild("li");
-                       option.addChild("a", "href", basePath + 
key.toString(false) + "?force=" + getForceValue(key, now)+extras, "Click here");
+                       option.addChild("a", "href", basePath + key.toString() 
+ "?force=" + getForceValue(key, now)+extras, "Click here");
                        option.addChild("#", " to open the file as " + mimeType 
+ '.');
                        if(referrer != null) {
                                option = optionList.addChild("li");
@@ -350,7 +350,7 @@
                        String msg = e.getMessage();
                        String extra = "";
                        if(e.mode == FetchException.NOT_ENOUGH_PATH_COMPONENTS) 
{
-                               this.writePermanentRedirect(ctx, "Not enough 
meta-strings", '/' + key.toString(false) + '/' + override);
+                               this.writePermanentRedirect(ctx, "Not enough 
meta-strings", '/' + key.toString() + '/' + override);
                        } else if(e.newURI != null) {
                                this.writePermanentRedirect(ctx, msg, '/' 
+e.newURI.toString() + override);
                        } else if(e.mode == FetchException.TOO_BIG) {
@@ -363,7 +363,7 @@
                                HTMLNode fileInformationList = 
infoboxContent.addChild("ul");
                                HTMLNode option = 
fileInformationList.addChild("li");
                                option.addChild("#", "Filename: ");
-                               option.addChild("a", "href", '/' + 
key.toString(false), getFilename(e, key, e.getExpectedMimeType()));
+                               option.addChild("a", "href", '/' + 
key.toString(), getFilename(e, key, e.getExpectedMimeType()));

                                boolean finalized = e.finalizedSize();
                                if(e.expectedSize > 0) {
@@ -392,12 +392,12 @@
                                infoboxContent.addChild("#", "The Freenet key 
you requested refers to a large file. Files of this size cannot generally be 
sent directly to your browser since they take too long for your Freenet node to 
retrieve. The following options are available:");
                                HTMLNode optionList = 
infoboxContent.addChild("ul");
                                option = optionList.addChild("li");
-                               HTMLNode optionForm = option.addChild("form", 
new String[] { "action", "method" }, new String[] {'/' + key.toString(false), 
"get" });
+                               HTMLNode optionForm = option.addChild("form", 
new String[] { "action", "method" }, new String[] {'/' + key.toString(), "get" 
});
                                optionForm.addChild("input", new String[] { 
"type", "name", "value" }, new String[] { "hidden", "max-size", 
String.valueOf(e.expectedSize == -1 ? Long.MAX_VALUE : e.expectedSize*2) });
                                optionForm.addChild("input", new String[] { 
"type", "name", "value" }, new String[] { "submit", "fetch", "Fetch anyway and 
display file in browser" });
                                option = optionList.addChild("li");
                                optionForm = ctx.addFormChild(option, 
"/queue/", "tooBigQueueForm");
-                               optionForm.addChild("input", new String[] { 
"type", "name", "value" }, new String[] { "hidden", "key", key.toString(false) 
});
+                               optionForm.addChild("input", new String[] { 
"type", "name", "value" }, new String[] { "hidden", "key", key.toString() });
                                optionForm.addChild("input", new String[] { 
"type", "name", "value" }, new String[] { "hidden", "return-type", "disk" });
                                optionForm.addChild("input", new String[] { 
"type", "name", "value" }, new String[] { "hidden", "persistence", "forever" });
                                if (mime != null) {
@@ -461,7 +461,7 @@
                                FreenetURI furi = new FreenetURI(path);
                                HTTPRequest req = new HTTPRequest(refererURI);
                                String type = req.getParam("type");
-                               referer = "/" + furi.toString(false);
+                               referer = "/" + furi.toString();
                                if(type != null && type.length() > 0)
                                        referer += "?type=" + type;
                        } catch (Throwable t) {
@@ -478,7 +478,7 @@

                try{
                        bos.write(random);
-                       bos.write(key.toString(false).getBytes());
+                       bos.write(key.toString().getBytes("UTF-8"));
                        bos.write(Long.toString(time / 
FORCE_GRAIN_INTERVAL).getBytes());
                } catch (IOException e) {
                        throw new Error(e);

Modified: trunk/freenet/src/freenet/clients/http/HTTPRequest.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/HTTPRequest.java     2006-12-11 
20:59:56 UTC (rev 11346)
+++ trunk/freenet/src/freenet/clients/http/HTTPRequest.java     2006-12-12 
00:24:26 UTC (rev 11347)
@@ -9,6 +9,7 @@
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.net.URLDecoder;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -20,7 +21,6 @@
 import freenet.support.Logger;
 import freenet.support.MultiValueTable;
 import freenet.support.SimpleReadOnlyArrayBucket;
-import freenet.support.URLDecoder;
 import freenet.support.URLEncodedFormatException;
 import freenet.support.io.Bucket;
 import freenet.support.io.BucketFactory;
@@ -193,40 +193,37 @@
                        }

                        // url-decode the name and value
-                       try {
-                               if (doUrlDecoding) {
-                                       name = URLDecoder.decode(name);
-                                       value = URLDecoder.decode(value);
-                                       if(logMINOR) {
-                                               Logger.minor(this, "Decoded 
name: "+name);
-                                               Logger.minor(this, "Decoded 
value: "+value);
-                                       }
-                               }
-
-                               if(asParts) {
-                                       // Store as a part
-                                       byte[] buf;
+                       if (doUrlDecoding) {
                                        try {
-                                               buf = value.getBytes("UTF-8");
+                                               name = 
java.net.URLDecoder.decode(name, "UTF-8");
+                                               value = 
java.net.URLDecoder.decode(value, "UTF-8");
                                        } catch (UnsupportedEncodingException 
e) {
                                                throw new Error(e);
-                                       } // FIXME some other encoding?
-                                       Bucket b = new 
SimpleReadOnlyArrayBucket(buf);
-                                       parts.put(name, b);
-                                       if(logMINOR)
-                                               Logger.minor(this, "Added as 
part: name="+name+" value="+value);
-                               } else {
-                                       // get the list of values for this 
parameter that were parsed so far
-                                       List valueList = 
this.getParameterValueList(name);
-                                       // add this value to the list
-                                       valueList.add(value);
+                                       }
+                               if(logMINOR) {
+                                       Logger.minor(this, "Decoded name: 
"+name);
+                                       Logger.minor(this, "Decoded value: 
"+value);
                                }
-                       } catch (URLEncodedFormatException e) {
-                               // if we fail to decode the name or value we 
fail spectacularly
-                               String msg = "Failed to decode request 
parameter " + name
-                                               + " with value '" + value + 
'\'';
-                               throw new RuntimeException(msg, e);
                        }
+                       
+                       if(asParts) {
+                               // Store as a part
+                               byte[] buf;
+                               try {
+                                       buf = value.getBytes("UTF-8");
+                               } catch (UnsupportedEncodingException e) {
+                                       throw new Error(e);
+                               } // FIXME some other encoding?
+                               Bucket b = new SimpleReadOnlyArrayBucket(buf);
+                               parts.put(name, b);
+                               if(logMINOR)
+                                       Logger.minor(this, "Added as part: 
name="+name+" value="+value);
+                       } else {
+                               // get the list of values for this parameter 
that were parsed so far
+                               List valueList = 
this.getParameterValueList(name);
+                               // add this value to the list
+                               valueList.add(value);
+                       }
                }
        }


Modified: trunk/freenet/src/freenet/clients/http/NinjaSpider.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/NinjaSpider.java     2006-12-11 
20:59:56 UTC (rev 11346)
+++ trunk/freenet/src/freenet/clients/http/NinjaSpider.java     2006-12-12 
00:24:26 UTC (rev 11347)
@@ -117,32 +117,17 @@


        private synchronized void queueURI(FreenetURI uri) {
-               byte[] uriBytes = uri.toString(false).getBytes();
-
                /* Currently we don't handle PDF or other contents,
                   so it's not interresting to download them
                */

+               String tmp = uri.toString().toLowerCase();
+               
                if(htmlOnly
-                  && (uri.toString(false).toLowerCase().indexOf(".htm") < 0)
-                  && (uriBytes[uriBytes.length - 1] != '/'))
+                  && (tmp.indexOf(".htm") < 0)
+                  && (tmp.charAt(tmp.length()-1) != '/'))
                        return;

-               /* We remove HTML targets from URI 
(http://my.server/file#target) */
-               /* Else we re-index already indexed file */
-               String uriStr = null;
-               try {
-                       uriStr = uri.toString(false);
-                       if(uriStr.indexOf("#") > 0)
-                               {
-                                       uriStr = uriStr.substring(0, 
uriStr.indexOf("#"));
-                                       uri = new FreenetURI(uriStr);
-                               }
-               } catch (MalformedURLException e) {
-                       Logger.error(this, "Spider: MalformedURLException: 
"+uriStr+ ':' +e);
-                       return;
-               }
-
                if ((!visitedURIs.contains(uri)) && queuedURISet.add(uri)) {
                        queuedURIList.addLast(uri);
                        visitedURIs.add(uri);
@@ -198,11 +183,11 @@
                Bucket data = result.asBucket();
                String mimeType = cm.getMIMEType();

-               sizeOfURIs.put(uri.toString(false), new Long(data.size()));
-               mimeOfURIs.put(uri.toString(false), mimeType);
+               sizeOfURIs.put(uri.toString(), new Long(data.size()));
+               mimeOfURIs.put(uri.toString(), mimeType);

                try {
-                       ContentFilter.filter(data, ctx.bucketFactory, mimeType, 
new URI("http://127.0.0.1:8888/"; + uri.toString(false)), this);
+                       ContentFilter.filter(data, ctx.bucketFactory, mimeType, 
new URI("http://127.0.0.1:8888/"; + uri.toString()), this);
                } catch (UnsafeContentTypeException e) {
                        return; // Ignore
                } catch (IOException e) {
@@ -257,7 +242,7 @@
                if((type != null) && (type.length() != 0) && 
type.toLowerCase().equals("title")
                   && (s != null) && (s.length() != 0) && (s.indexOf('\n') < 
0)) {
                        /* We should have a correct title */
-                       titlesOfURIs.put(uri.toString(false), s);
+                       titlesOfURIs.put(uri.toString(), s);
                        type = "title";
                }
                else
@@ -268,7 +253,7 @@

                Integer lastPosition = null;

-               lastPosition = 
(Integer)lastPositionByURI.get(uri.toString(false));
+               lastPosition = (Integer)lastPositionByURI.get(uri.toString());

                if(lastPosition == null)
                        lastPosition = new Integer(1); /* We start to count 
from 1 */
@@ -287,7 +272,7 @@

                if(type == null) {
                        lastPosition = new Integer(lastPosition.intValue() + 
words.length);
-                       lastPositionByURI.put(uri.toString(false), 
lastPosition);
+                       lastPositionByURI.put(uri.toString(), lastPosition);
                }
        }

@@ -307,12 +292,12 @@


                /* Word position indexation */
-               HashMap wordPositionsForOneUri = 
(HashMap)positionsByWordByURI.get(uri.toString(false)); /* For a given URI, 
take as key a word, and gives position */
+               HashMap wordPositionsForOneUri = 
(HashMap)positionsByWordByURI.get(uri.toString()); /* For a given URI, take as 
key a word, and gives position */

                if(wordPositionsForOneUri == null) {
                        wordPositionsForOneUri = new HashMap();
                        wordPositionsForOneUri.put(word, new Integer[] { new 
Integer(position) });
-                       positionsByWordByURI.put(uri.toString(false), 
wordPositionsForOneUri);
+                       positionsByWordByURI.put(uri.toString(), 
wordPositionsForOneUri);
                } else {
                        Integer[] positions = 
(Integer[])wordPositionsForOneUri.get(word);

@@ -449,20 +434,20 @@
                        Element fileElement = xmlDoc.createElement("file");

                        fileElement.setAttribute("id", Integer.toString(i));
-                       fileElement.setAttribute("key", 
uris[i].toString(false));
+                       fileElement.setAttribute("key", uris[i].toString());

-                       Long size = 
(Long)sizeOfURIs.get(uris[i].toString(false));
+                       Long size = (Long)sizeOfURIs.get(uris[i].toString());

                        if(size == null) {
                                Logger.error(this, "Spider: size is missing");
                        } else {
                                fileElement.setAttribute("size", 
size.toString());
                        }
-                       fileElement.setAttribute("mime", 
((String)mimeOfURIs.get(uris[i].toString(false))));
+                       fileElement.setAttribute("mime", 
((String)mimeOfURIs.get(uris[i].toString())));

                        Element titleElement = xmlDoc.createElement("option");
                        titleElement.setAttribute("name", "title");
-                       titleElement.setAttribute("value", 
(String)titlesOfURIs.get(uris[i].toString(false)));
+                       titleElement.setAttribute("value", 
(String)titlesOfURIs.get(uris[i].toString()));

                        fileElement.appendChild(titleElement);
                        filesElement.appendChild(fileElement);
@@ -493,7 +478,7 @@
                                uriElement.setAttribute("id", x.toString());

                                /* Position by position */
-                               HashMap positionsForGivenWord = 
(HashMap)positionsByWordByURI.get(uri.toString(false));
+                               HashMap positionsForGivenWord = 
(HashMap)positionsByWordByURI.get(uri.toString());
                                Integer[] positions = 
(Integer[])positionsForGivenWord.get(words[i]);

                                StringBuffer positionList = new StringBuffer();

Modified: trunk/freenet/src/freenet/clients/http/QueueToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/QueueToadlet.java    2006-12-11 
20:59:56 UTC (rev 11346)
+++ trunk/freenet/src/freenet/clients/http/QueueToadlet.java    2006-12-12 
00:24:26 UTC (rev 11347)
@@ -308,7 +308,7 @@
                                        ClientRequest clientRequest = 
clientRequests[requestIndex];
                                        if (clientRequest.hasFinished() && 
(clientRequest instanceof ClientGet)) {
                                                ClientGet clientGet = 
(ClientGet) clientRequest;
-                                               if 
(clientGet.getURI().toString(false).equals(key.toString(false))) {
+                                               if 
(clientGet.getURI().equals(key)) {
                                                        Bucket data = 
clientGet.getBucket();
                                                        String mimeType = 
clientGet.getMIMEType();
                                                        String 
requestedMimeType = request.getParam("type", null);
@@ -767,7 +767,7 @@

        private HTMLNode createDownloadCell(PageMaker pageMaker, ClientGet p) {
                HTMLNode downloadCell = new HTMLNode("td", "class", 
"request-download");
-               downloadCell.addChild("a", "href", p.getURI().toString(false), 
"Download");
+               downloadCell.addChild("a", "href", p.getURI().toString(), 
"Download");
                return downloadCell;
        }

@@ -794,7 +794,7 @@
        private HTMLNode createKeyCell(FreenetURI uri) {
                HTMLNode keyCell = new HTMLNode("td", "class", "request-key");
                if (uri != null) {
-                       keyCell.addChild("span", "class", 
"key_is").addChild("a", "href", '/' + uri.toString(false), uri.toShortString());
+                       keyCell.addChild("span", "class", 
"key_is").addChild("a", "href", '/' + uri.toString(), uri.toShortString());
                } else {
                        keyCell.addChild("span", "class", "key_unknown", 
"unknown");
                }

Modified: trunk/freenet/src/freenet/clients/http/Spider.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/Spider.java  2006-12-11 20:59:56 UTC 
(rev 11346)
+++ trunk/freenet/src/freenet/clients/http/Spider.java  2006-12-12 00:24:26 UTC 
(rev 11347)
@@ -72,23 +72,6 @@
        private boolean stopped = true;

        private synchronized void queueURI(FreenetURI uri) {
-               String uriStr = null;
-               
-               /* We remove HTML targets from URI 
(http://my.server/file#target) */
-               /* Else we re-index already indexed file */
-               try {
-                       uriStr = uri.toString(false);
-                       if(uriStr.indexOf("#") > 0)
-                               {
-                                       uriStr = uriStr.substring(0, 
uriStr.indexOf("#"));
-                                       uri = new FreenetURI(uriStr);
-                               }
-               } catch (MalformedURLException e) {
-                       Logger.error(this, "Spider: MalformedURLException: 
"+uriStr+ ':' +e);
-                       return;
-               }
-
-               
                if ((!visitedURIs.contains(uri)) && queuedURISet.add(uri)) {
                        queuedURIList.addLast(uri);
                        visitedURIs.add(uri);
@@ -152,7 +135,7 @@
                Bucket data = result.asBucket();
                String mimeType = cm.getMIMEType();
                try {
-                       ContentFilter.filter(data, ctx.bucketFactory, mimeType, 
new URI("http://127.0.0.1:8888/"; + uri.toString(false)), this);
+                       ContentFilter.filter(data, ctx.bucketFactory, mimeType, 
uri.toURI("http://127.0.0.1:8888/";), this);
                } catch (UnsafeContentTypeException e) {
                        return; // Ignore
                } catch (IOException e) {
@@ -207,7 +190,7 @@
                if((type != null) && (type.length() != 0) && 
type.toLowerCase().equals("title")
                   && (s != null) && (s.length() != 0) && (s.indexOf('\n') < 
0)) {
                        /* We should have a correct title */
-                       titlesOfURIs.put(uri.toString(false), s);
+                       titlesOfURIs.put(uri.toString(), s);
                }


@@ -266,8 +249,8 @@
                HashMap urisToNumbers = new HashMap();
                for (int i = 0; i < uris.length; i++) {
                        urisToNumbers.put(uris[i], new Integer(i));
-                       bw.write('!' + uris[i].toString(false) + '\n');
-                       bw.write("+" + 
titlesOfURIs.get(uris[i].toString(false)) + '\n');
+                       bw.write('!' + uris[i].toString() + '\n');
+                       bw.write("+" + titlesOfURIs.get(uris[i].toString()) + 
'\n');
                }
                for (int i = 0; i < words.length; i++) {
                        StringBuffer s = new StringBuffer();
@@ -414,7 +397,7 @@
                int itemCount = 0;
                while (collectionItems.hasNext()) {
                        FreenetURI uri = (FreenetURI) collectionItems.next();
-                       listContent.addChild("#", uri.toString(false));
+                       listContent.addChild("#", uri.toString());
                        listContent.addChild("br");
                        if (itemCount++ == maxCount) {
                                listContent.addChild("br");

Modified: trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java  2006-12-11 
20:59:56 UTC (rev 11346)
+++ trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java  2006-12-12 
00:24:26 UTC (rev 11347)
@@ -334,8 +334,9 @@
                                key = this.insert(block, filenameHint, false);
                                HTMLNode infobox = 
contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-success", "Insert 
Succeeded"));
                                content = 
ctx.getPageMaker().getContentNode(infobox);
+                               String u = key.toString();
                                content.addChild("#", "The key ");
-                               content.addChild("a", "href", '/' + 
key.toString(false), key.toString(false));
+                               content.addChild("a", "href", '/' + u, u);
                                content.addChild("#", " has been inserted 
successfully.");
                        } catch (InserterException e) {
                                HTMLNode infobox = 
contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-error", "Insert 
Failed"));

Modified: 
trunk/freenet/src/freenet/clients/http/filter/GenericReadFilterCallback.java
===================================================================
--- 
trunk/freenet/src/freenet/clients/http/filter/GenericReadFilterCallback.java    
    2006-12-11 20:59:56 UTC (rev 11346)
+++ 
trunk/freenet/src/freenet/clients/http/filter/GenericReadFilterCallback.java    
    2006-12-12 00:24:26 UTC (rev 11347)
@@ -44,7 +44,7 @@

        public GenericReadFilterCallback(FreenetURI uri, FoundURICallback cb) {
                try {
-                       this.baseURI = new URI('/' + uri.toString(false));
+                       this.baseURI = uri.toRelativeURI();
                        this.cb = cb;
                } catch (URISyntaxException e) {
                        throw new Error(e);
@@ -196,7 +196,7 @@
                // Now what about the queries?
                HTTPRequest req = new HTTPRequest(uri);
                if(cb != null) cb.foundURI(furi);
-               return finishProcess(req, overrideType, '/' + 
furi.toString(false), uri, noRelative);
+               return finishProcess(req, overrideType, '/' + 
furi.toString(false, false), uri, noRelative);
        }

        public String onBaseHref(String baseHref) {

Modified: trunk/freenet/src/freenet/keys/FreenetURI.java
===================================================================
--- trunk/freenet/src/freenet/keys/FreenetURI.java      2006-12-11 20:59:56 UTC 
(rev 11346)
+++ trunk/freenet/src/freenet/keys/FreenetURI.java      2006-12-12 00:24:26 UTC 
(rev 11347)
@@ -8,7 +8,11 @@
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLDecoder;
 import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.StringTokenizer;
@@ -19,8 +23,7 @@
 import freenet.support.HexUtil;
 import freenet.support.IllegalBase64Exception;
 import freenet.support.Logger;
-import freenet.support.URLDecoder;
-import freenet.support.URLEncodedFormatException;
+import freenet.support.URLEncoder;
 import freenet.client.InserterException;

 /**
@@ -216,12 +219,12 @@
                        throw new MalformedURLException("No URI specified");
                }

-               int percent = URI.indexOf('%');
-               int slash = URI.indexOf('/');
-               if((percent>-1) && ((percent<slash) || (slash<0))){ /* likely 
to be a copy/pasted url from a browser */
-                       try{
-                               URI=URLDecoder.decode(URI);
-                       }catch(URLEncodedFormatException e){
+               if(URI.indexOf('@') < 0 || URI.indexOf('/') < 0) {
+                       // Encoded URL?
+                       try {
+                               URI=URLDecoder.decode(URI, "UTF-8");
+                       } catch (UnsupportedEncodingException e) {
+                               throw new Error(e);
                        }
                }

@@ -246,7 +249,12 @@
                int slash2;
                sv = new Vector();
                while ((slash2 = URI.lastIndexOf("/")) != -1) {
-                       String s = URI.substring(slash2 + "/".length());
+                       String s;
+                       try {
+                               s = URLDecoder.decode(URI.substring(slash2 + 
"/".length()), "UTF-8");
+                       } catch (UnsupportedEncodingException e) {
+                               throw new Error(e);
+                       }
                        if (s != null)
                                sv.addElement(s);
                        URI = URI.substring(0, slash2);
@@ -493,10 +501,14 @@
        }

        public String toString() {
-               return toString(true);
+               return toString(false, false);
        }
+       
+       public String toACIIString() {
+               return toString(true, true);
+       }

-       public String toString(boolean prefix) {
+       public String toString(boolean prefix, boolean pureAscii) {
                StringBuffer b;
                if (prefix)
                        b = new StringBuffer("freenet:");
@@ -517,14 +529,14 @@
                }

                if (docName != null)
-                       b.append(docName);
+                       b.append(URLEncoder.encode(docName, "/", pureAscii));
                if(keyType.equals("USK")) {
                        b.append('/');
                        b.append(suggestedEdition);
                }
                if (metaStr != null) {
                        for (int i = 0; i < metaStr.length; i++) {
-                               b.append('/').append(metaStr[i]);
+                               
b.append('/').append(URLEncoder.encode(metaStr[i], "/", pureAscii));
                        }
                }
                return b.toString();
@@ -542,14 +554,14 @@
                }

                if (docName != null)
-                       b.append(docName);
+                       b.append(URLEncoder.encode(docName, "/", false));
                if(keyType.equals("USK")) {
                        b.append('/');
                        b.append(suggestedEdition);
                }
                if (metaStr != null) {
                        for (int i = 0; i < metaStr.length; i++) {
-                               b.append('/').append(metaStr[i]);
+                               
b.append('/').append(URLEncoder.encode(metaStr[i], "/", false));
                        }
                }
                return b.toString();
@@ -783,4 +795,14 @@

        public static void checkInsertURI(FreenetURI uri) throws 
InserterException { uri.checkInsertURI(); }

+       public URI toRelativeURI() throws URISyntaxException {
+               // Single-argument constructor used because it preserves 
encoded /'es in path.
+               // Hence we can have slashes, question marks etc in the path, 
but they are encoded.
+               return new URI('/' + toString(false, false));
+       }
+
+       public URI toURI(String basePath) throws URISyntaxException {
+               return new URI(basePath + toString(false, false));
+       }
+
 }

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2006-12-11 20:59:56 UTC (rev 
11346)
+++ trunk/freenet/src/freenet/node/Node.java    2006-12-12 00:24:26 UTC (rev 
11347)
@@ -1622,7 +1622,7 @@
        public SimpleFieldSet exportPrivateFieldSet() {
                SimpleFieldSet fs = exportPublicFieldSet(false);
                fs.put("dsaPrivKey", myPrivKey.asFieldSet());
-               fs.put("ark.privURI", 
this.myARK.getInsertURI().toString(false));
+               fs.put("ark.privURI", this.myARK.getInsertURI().toString(false, 
false));
                return fs;
        }

@@ -1662,7 +1662,7 @@
                        fs.put("dsaPubKey", myPubKey.asFieldSet());
                }
                fs.put("ark.number", Long.toString(this.myARKNumber)); // Can 
be changed on setup
-               fs.put("ark.pubURI", this.myARK.getURI().toString(false)); // 
Can be changed on setup
+               fs.put("ark.pubURI", this.myARK.getURI().toString(false, 
false)); // Can be changed on setup

                synchronized (referenceSync) {
                        if(myReferenceSignature == null || mySignedReference == 
null || !mySignedReference.equals(fs.toOrderedString())){

Modified: trunk/freenet/src/freenet/node/PeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNode.java        2006-12-11 20:59:56 UTC 
(rev 11346)
+++ trunk/freenet/src/freenet/node/PeerNode.java        2006-12-12 00:24:26 UTC 
(rev 11347)
@@ -1948,7 +1948,7 @@
                if(myARK != null) {
                        // Decrement it because we keep the number we would 
like to fetch, not the last one fetched.
                        fs.put("ark.number", 
Long.toString(myARK.suggestedEdition - 1));
-                       fs.put("ark.pubURI", 
myARK.getBaseSSK().toString(false));
+                       fs.put("ark.pubURI", myARK.getBaseSSK().toString(false, 
false));
                }
         return fs;
     }

Modified: trunk/freenet/src/freenet/node/TextModeClientInterface.java
===================================================================
--- trunk/freenet/src/freenet/node/TextModeClientInterface.java 2006-12-11 
20:59:56 UTC (rev 11346)
+++ trunk/freenet/src/freenet/node/TextModeClientInterface.java 2006-12-12 
00:24:26 UTC (rev 11347)
@@ -558,13 +558,13 @@
             }
         } else if(uline.startsWith("MAKESSK")) {
                InsertableClientSSK key = InsertableClientSSK.createRandom(r, 
"");
-            outsb.append("Insert URI: 
").append(key.getInsertURI().toString(false)).append("\r\n");
-            outsb.append("Request URI: 
").append(key.getURI().toString(false)).append("\r\n");
+            outsb.append("Insert URI: 
").append(key.getInsertURI().toString(false, false)).append("\r\n");
+            outsb.append("Request URI: ").append(key.getURI().toString(false, 
false)).append("\r\n");
                FreenetURI insertURI = 
key.getInsertURI().setDocName("testsite");
-               String fixedInsertURI = insertURI.toString(false);
+               String fixedInsertURI = insertURI.toString(false, false);
             outsb.append("Note that you MUST add a filename to the end of the 
above URLs e.g.:\r\n").append(fixedInsertURI).append("\r\n");
             outsb.append("Normally you will then do PUTSSKDIR:<insert 
URI>#<directory to upload>, for 
example:\r\nPUTSSKDIR:").append(fixedInsertURI).append("#directoryToUpload/\r\n");
-            outsb.append("This will then produce a manifest site containing 
all the files, the default document can be accessed 
at\r\n").append(key.getURI().toString(false)).append("testsite/");
+            outsb.append("This will then produce a manifest site containing 
all the files, the default document can be accessed 
at\r\n").append(key.getURI().toString(false, false)).append("testsite/");
         } else if(uline.startsWith("PUTSSK:")) {
                String cmd = line.substring("PUTSSK:".length());
                cmd = cmd.trim();

Modified: trunk/freenet/src/freenet/node/fcp/ClientGet.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientGet.java   2006-12-11 20:59:56 UTC 
(rev 11346)
+++ trunk/freenet/src/freenet/node/fcp/ClientGet.java   2006-12-12 00:24:26 UTC 
(rev 11347)
@@ -471,7 +471,7 @@
        public synchronized SimpleFieldSet getFieldSet() {
                SimpleFieldSet fs = new SimpleFieldSet(); // we will need 
multi-level later...
                fs.put("Type", "GET");
-               fs.put("URI", uri.toString(false));
+               fs.put("URI", uri.toString(false, false));
                fs.put("Identifier", identifier);
                fs.put("Verbosity", Integer.toString(verbosity));
                fs.put("PriorityClass", Short.toString(priorityClass));

Modified: trunk/freenet/src/freenet/node/fcp/ClientGetMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientGetMessage.java    2006-12-11 
20:59:56 UTC (rev 11346)
+++ trunk/freenet/src/freenet/node/fcp/ClientGetMessage.java    2006-12-12 
00:24:26 UTC (rev 11347)
@@ -188,7 +188,7 @@
        public SimpleFieldSet getFieldSet() {
                SimpleFieldSet fs = new SimpleFieldSet();
                fs.put("IgnoreDS", Boolean.toString(ignoreDS));
-               fs.put("URI", uri.toString(false));
+               fs.put("URI", uri.toString(false, false));
                fs.put("Identifier", identifier);
                fs.put("Verbosity", Integer.toString(verbosity));
                fs.put("ReturnType", getReturnTypeString());

Modified: trunk/freenet/src/freenet/node/fcp/ClientPutBase.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutBase.java       2006-12-11 
20:59:56 UTC (rev 11346)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutBase.java       2006-12-12 
00:24:26 UTC (rev 11347)
@@ -245,7 +245,7 @@
        public synchronized SimpleFieldSet getFieldSet() {
                SimpleFieldSet fs = new SimpleFieldSet(); // we will need 
multi-level later...
                fs.put("Type", getTypeName());
-               fs.put("URI", uri.toString(false));
+               fs.put("URI", uri.toString(false, false));
                fs.put("Identifier", identifier);
                fs.put("Verbosity", Integer.toString(verbosity));
                fs.put("PriorityClass", Short.toString(priorityClass));
@@ -258,7 +258,7 @@
                fs.put("Succeeded", Boolean.toString(succeeded));
                fs.put("GetCHKOnly", Boolean.toString(getCHKOnly));
                if(generatedURI != null)
-                       fs.put("GeneratedURI", generatedURI.toString(false));
+                       fs.put("GeneratedURI", generatedURI.toString(false, 
false));
                if(finished && (!succeeded))
                        // Should have a putFailedMessage... unless there is a 
race condition.
                        fs.put("PutFailed", 
putFailedMessage.getFieldSet(false));

Modified: trunk/freenet/src/freenet/node/fcp/FCPServer.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FCPServer.java   2006-12-11 20:59:56 UTC 
(rev 11346)
+++ trunk/freenet/src/freenet/node/fcp/FCPServer.java   2006-12-12 00:24:26 UTC 
(rev 11347)
@@ -635,7 +635,7 @@
                                return;
                        } catch (IdentifierCollisionException e) {
                                try {
-                                       
innerMakePersistentGlobalRequest(fetchURI, persistence, returnType, 
"FProxy:"+fetchURI.toString(false), returnFilename, returnTempFilename);
+                                       
innerMakePersistentGlobalRequest(fetchURI, persistence, returnType, 
"FProxy:"+fetchURI.toString(false, false), returnFilename, returnTempFilename);
                                        return;
                                } catch (IdentifierCollisionException e1) {
                                        // FIXME maybe use DateFormat

Modified: trunk/freenet/src/freenet/node/fcp/GetFailedMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/GetFailedMessage.java    2006-12-11 
20:59:56 UTC (rev 11346)
+++ trunk/freenet/src/freenet/node/fcp/GetFailedMessage.java    2006-12-12 
00:24:26 UTC (rev 11347)
@@ -119,7 +119,7 @@
                if(finalizedExpected)
                        sfs.put("FinalizedExpected", "true");
                if(redirectURI != null)
-                       sfs.put("RedirectURI", redirectURI.toString(false));
+                       sfs.put("RedirectURI", redirectURI.toString(false, 
false));
                return sfs;
        }


Modified: trunk/freenet/src/freenet/node/fcp/PersistentGet.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/PersistentGet.java       2006-12-11 
20:59:56 UTC (rev 11346)
+++ trunk/freenet/src/freenet/node/fcp/PersistentGet.java       2006-12-12 
00:24:26 UTC (rev 11347)
@@ -51,7 +51,7 @@
        public SimpleFieldSet getFieldSet() {
                SimpleFieldSet fs = new SimpleFieldSet();
                fs.put("Identifier", identifier);
-               fs.put("URI", uri.toString(false));
+               fs.put("URI", uri.toString(false, false));
                fs.put("Verbosity", verbosity);
                fs.put("ReturnType", 
ClientGetMessage.returnTypeString(returnType));
                fs.put("PersistenceType", 
ClientRequest.persistenceTypeString(persistenceType));

Modified: trunk/freenet/src/freenet/node/fcp/PersistentPut.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/PersistentPut.java       2006-12-11 
20:59:56 UTC (rev 11346)
+++ trunk/freenet/src/freenet/node/fcp/PersistentPut.java       2006-12-12 
00:24:26 UTC (rev 11347)
@@ -53,7 +53,7 @@
        public SimpleFieldSet getFieldSet() {
                SimpleFieldSet fs = new SimpleFieldSet();
                fs.put("Identifier", identifier);
-               fs.put("URI", uri.toString(false));
+               fs.put("URI", uri.toString(false, false));
                fs.put("Verbosity", verbosity);
                fs.put("PriorityClass", priorityClass);
                fs.put("UploadFrom", 
ClientPutMessage.uploadFromString(uploadFrom));

Modified: trunk/freenet/src/freenet/node/fcp/PersistentPutDir.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/PersistentPutDir.java    2006-12-11 
20:59:56 UTC (rev 11346)
+++ trunk/freenet/src/freenet/node/fcp/PersistentPutDir.java    2006-12-12 
00:24:26 UTC (rev 11347)
@@ -49,7 +49,7 @@
        public SimpleFieldSet getFieldSet() {
                SimpleFieldSet fs = new SimpleFieldSet();
                fs.put("Identifier", identifier);
-               fs.put("URI", uri.toString(false));
+               fs.put("URI", uri.toString(false, false));
                fs.put("Verbosity", Integer.toString(verbosity));
                fs.put("PriorityClass", Short.toString(priorityClass));
                fs.put("Persistence", 
ClientRequest.persistenceTypeString(persistenceType));

Modified: trunk/freenet/src/freenet/node/fcp/PutFetchableMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/PutFetchableMessage.java 2006-12-11 
20:59:56 UTC (rev 11346)
+++ trunk/freenet/src/freenet/node/fcp/PutFetchableMessage.java 2006-12-12 
00:24:26 UTC (rev 11347)
@@ -21,7 +21,7 @@
                SimpleFieldSet fs = new SimpleFieldSet();
                fs.put("Identifier", identifier);
                if(uri != null)
-                       fs.put("URI", uri.toString(false));
+                       fs.put("URI", uri.toString(false, false));
                return fs;
        }


Modified: trunk/freenet/src/freenet/node/updater/NodeUpdaterManager.java
===================================================================
--- trunk/freenet/src/freenet/node/updater/NodeUpdaterManager.java      
2006-12-11 20:59:56 UTC (rev 11346)
+++ trunk/freenet/src/freenet/node/updater/NodeUpdaterManager.java      
2006-12-12 00:24:26 UTC (rev 11347)
@@ -705,7 +705,7 @@
                }

                public String get() {
-                       return getURI(isExt).toString(false);
+                       return getURI(isExt).toString(false, false);
                }

                public void set(String val) throws InvalidConfigValueException {
@@ -723,7 +723,7 @@
        public class UpdateRevocationURICallback implements StringCallback {

                public String get() {
-                       return getRevocationURI().toString(false);
+                       return getRevocationURI().toString(false, false);
                }

                public void set(String val) throws InvalidConfigValueException {

Modified: trunk/freenet/src/freenet/support/URLDecoder.java
===================================================================
--- trunk/freenet/src/freenet/support/URLDecoder.java   2006-12-11 20:59:56 UTC 
(rev 11346)
+++ trunk/freenet/src/freenet/support/URLDecoder.java   2006-12-12 00:24:26 UTC 
(rev 11347)
@@ -2,6 +2,7 @@

 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;

 /*
   This code is part of the Java Adaptive Network Client by Ian Clarke. 
@@ -11,28 +12,15 @@


 /**
- * The class contains a utility method for converting a 
- * <code>String</code> out of a MIME format called 
- * "<code>x-www-form-urlencoded</code>" format. 
- * <p>
- * To convert a <code>String</code>, each character is examined in turn:
- * <ul>
- * <li>The ASCII characters '<code>a</code>' through '<code>z</code>', 
- *     '<code>A</code>' through '<code>Z</code>', and '<code>0</code>' 
- *     through '<code>9</code>' remain the same. 
- * <li>The plus sign '<code>+</code>' is converted into a 
- *     space character '<code>&nbsp;</code>'. 
- * <li>The percent sign '<code>%</code>' must be followed by a 
- *     two-digit hexadecimal number, and is converted into the
- *     corresponding 8-bit character.
- * <li>The following "safe" characters [RFC 1738] are passed as is,
- *     if they appear:
- *     <code>$ - _ . + ! * ' ( ) ,</code>
- * <li>Anything else encountered, though strictly speaking illegal, 
- *     is passed as is.
- * </ul>
- *
+ * Decode encoded URLs (or parts of URLs). @see URLEncoder.
+ * This class does NOT decode application/x-www-form-urlencoded
+ * strings, unlike @see java.net.URLDecoder. What it does is
+ * decode bits of URIs, in UTF-8. This simply means that it 
+ * converts encoded characters (assuming a charset of UTF-8).
+ * java.net.URI does similar things internally.
+ * 
  * @author <a href="http://www.doc.ic.ac.uk/~twh1/";>Theodore Hong</a>
+ * Originally!
  **/

 public class URLDecoder
@@ -45,11 +33,6 @@
     }

     /**
-     * Characters which will be passed unaltered.
-     **/
-    private static final String safeCharList = "$-_.+!*'(),";
-
-    /**
         * Translates a string out of x-www-form-urlencoded format.
         *
         * @param s String to be translated.
@@ -66,10 +49,6 @@
                        char c = s.charAt(i);
                        if (Character.isLetterOrDigit(c))
                                decodedBytes.write(c);
-                       else if (c == '+')
-                               decodedBytes.write(' ');
-                       else if (safeCharList.indexOf(c) != -1)
-                               decodedBytes.write(c);
                        else if (c == '%') {
                                if (i >= len - 2) {
                                        throw new URLEncodedFormatException(s);
@@ -88,9 +67,14 @@
                                } catch (NumberFormatException nfe) {
                                        throw new URLEncodedFormatException(s);
                                }
-                       } else
-                               decodedBytes.write(c);
-                       // throw new URLEncodedFormatException(s);
+                       } else {
+                               try {
+                                       byte[] encoded = 
(""+c).getBytes("UTF-8");
+                                       decodedBytes.write(encoded, 0, 
encoded.length);
+                               } catch (UnsupportedEncodingException e) {
+                                       throw new Error(e);
+                               }
+                       }
                }
                try {
                        decodedBytes.close();

Modified: trunk/freenet/src/freenet/support/URLEncoder.java
===================================================================
--- trunk/freenet/src/freenet/support/URLEncoder.java   2006-12-11 20:59:56 UTC 
(rev 11346)
+++ trunk/freenet/src/freenet/support/URLEncoder.java   2006-12-12 00:24:26 UTC 
(rev 11347)
@@ -1,39 +1,52 @@
 package freenet.support;

+import java.io.UnsupportedEncodingException;
+
+/**
+ * Encodes strings for use in URIs. Note that this is <b>NOT</b> the same as 
java.net.URLEncoder, which
+ * encodes strings to application/x-www-urlencoded. This is much closer to 
what java.net.URI does. We 
+ * don't turn spaces into +'s, and we allow through non-ascii characters 
unless told not to.
+ */
 public class URLEncoder {
   // Moved here from FProxy by amphibian
-  final static String safeURLCharacters = 
"@*-./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
+  final static String safeURLCharacters = 
"*-_./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";

   /**
-   * Encode a string for inclusion in HTML tags
+   * Encode a string for inclusion in a URI.
    *
    * @param  URL  String to encode
+   * @param force List of characters (in the form of a string) which must be 
encoded as well as the built-in.
    * @return      HTML-safe version of string
    */
-  public final static String encode(String URL) {
+  public final static String encode(String URL, String force, boolean ascii) {
     StringBuffer enc = new StringBuffer(URL.length());
     for (int i = 0; i < URL.length(); ++i) {
       char c = URL.charAt(i);
-      if (safeURLCharacters.indexOf(c) >= 0) {
+      if (((safeURLCharacters.indexOf(c) >= 0) || ((!ascii) && c >= 0200)) 
+                 && (force == null || force.indexOf(c) < 0)) {
         enc.append(c);
       } else {
-        // Too harsh.
-        // if (c < 0 || c > 255)
-        //    throw new RuntimeException("illegal code "+c+" of char 
'"+URL.charAt(i)+"'");
-        // else
-
-        // Just keep lsb like:
-        // http://java.sun.com/j2se/1.3/docs/api/java/net/URLEncoder.html
-        c = (char) (c & '\u00ff');
-        if (c < 16) {
-          enc.append("%0");
-        } else {
-          enc.append('%');
-        }
-        enc.append(Integer.toHexString(c));
+       try {
+                       byte[] encoded = ("" + c).getBytes("UTF-8");
+                       for(int j=0;j<encoded.length;j++) {
+                               byte b = encoded[j];
+                               int x = b & 0xFF;
+                               if(x < 16)
+                                       enc.append("%0");
+                               else
+                                       enc.append('%');
+                               enc.append(Integer.toHexString(x));
+                       }
+               } catch (UnsupportedEncodingException e) {
+                       throw new Error(e);
+               }
       }
     }
     return enc.toString();
   }

+  public static String encode(String s) {
+       return encode(s, null, false);
+  }
+
 }


Reply via email to