Author: toad
Date: 2006-05-17 20:58:53 +0000 (Wed, 17 May 2006)
New Revision: 8751

Modified:
   trunk/freenet/src/freenet/clients/http/FproxyToadlet.java
   trunk/freenet/src/freenet/clients/http/filter/ContentFilter.java
   trunk/freenet/src/freenet/clients/http/filter/FilterCallback.java
   trunk/freenet/src/freenet/clients/http/filter/GenericReadFilterCallback.java
   trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java
   trunk/freenet/src/freenet/clients/http/filter/NullFilterCallback.java
   trunk/freenet/src/freenet/node/Version.java
Log:
720: Fix relative links in HTML filter (hopefully).

Modified: trunk/freenet/src/freenet/clients/http/FproxyToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/FproxyToadlet.java   2006-05-17 
19:42:55 UTC (rev 8750)
+++ trunk/freenet/src/freenet/clients/http/FproxyToadlet.java   2006-05-17 
20:58:53 UTC (rev 8751)
@@ -163,7 +163,7 @@

                        try {
                                if(!force && !forcedownload) {
-                                       data = ContentFilter.filter(data, 
ctx.getBucketFactory(), typeName);
+                                       data = ContentFilter.filter(data, 
ctx.getBucketFactory(), typeName, uri);
                                }

                                if (forcedownload) {

Modified: trunk/freenet/src/freenet/clients/http/filter/ContentFilter.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/filter/ContentFilter.java    
2006-05-17 19:42:55 UTC (rev 8750)
+++ trunk/freenet/src/freenet/clients/http/filter/ContentFilter.java    
2006-05-17 20:58:53 UTC (rev 8751)
@@ -4,6 +4,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
+import java.net.URI;
 import java.util.HashMap;
 import java.util.Hashtable;

@@ -103,7 +104,7 @@
         * Filter some data.
         * @throws IOException If an internal error involving buckets occurred.
         */
-       public static Bucket filter(Bucket data, BucketFactory bf, String 
typeName) throws UnsafeContentTypeException, IOException {
+       public static Bucket filter(Bucket data, BucketFactory bf, String 
typeName, URI baseURI) throws UnsafeContentTypeException, IOException {
                String type = typeName;
                String options = "";
                String charset = null;
@@ -153,7 +154,7 @@
                                        charset = detectCharset(data, handler);
                                }

-                               return handler.readFilter.readFilter(data, bf, 
charset, otherParams, new GenericReadFilterCallback());
+                               return handler.readFilter.readFilter(data, bf, 
charset, otherParams, new GenericReadFilterCallback(baseURI));
                        }
                        handler.throwUnsafeContentTypeException();
                        return null;

Modified: trunk/freenet/src/freenet/clients/http/filter/FilterCallback.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/filter/FilterCallback.java   
2006-05-17 19:42:55 UTC (rev 8750)
+++ trunk/freenet/src/freenet/clients/http/filter/FilterCallback.java   
2006-05-17 20:58:53 UTC (rev 8751)
@@ -21,5 +21,11 @@
         * Should we allow POST forms?
         */
        public boolean allowPostForms();
+
+       /**
+        * Process a base URI in the page. Not only is this filtered, it 
affects all
+        * relative uri's on the page.
+        */
+       public String onBaseHref(String baseHref);

 }

Modified: 
trunk/freenet/src/freenet/clients/http/filter/GenericReadFilterCallback.java
===================================================================
--- 
trunk/freenet/src/freenet/clients/http/filter/GenericReadFilterCallback.java    
    2006-05-17 19:42:55 UTC (rev 8750)
+++ 
trunk/freenet/src/freenet/clients/http/filter/GenericReadFilterCallback.java    
    2006-05-17 20:58:53 UTC (rev 8751)
@@ -6,12 +6,25 @@

 import freenet.clients.http.HTTPRequest;
 import freenet.keys.FreenetURI;
+import freenet.support.HTMLEncoder;
 import freenet.support.Logger;
-import freenet.support.HTMLEncoder;
-import freenet.support.URLEncoder;

 public class GenericReadFilterCallback implements FilterCallback {

+       private URI baseURI;
+       
+       public GenericReadFilterCallback(URI uri) {
+               this.baseURI = uri;
+       }
+       
+       public GenericReadFilterCallback(FreenetURI uri) {
+               try {
+                       this.baseURI = new URI("/" + uri.toString(false));
+               } catch (URISyntaxException e) {
+                       throw new Error(e);
+               }
+       }
+       
        public boolean allowGetForms() {
                return false;
        }
@@ -21,21 +34,26 @@
        }

        public String processURI(String u, String overrideType) {
+               return processURI(u, overrideType, false);
+       }
+       
+       public String processURI(String u, String overrideType, boolean 
noRelative) {
                URI uri;
+               URI resolved;
                try {
-                       uri = new URI(u);
+                       uri = new URI(u).normalize();
+                       Logger.minor(this, "Processing "+uri);
+                       if(!noRelative)
+                               resolved = baseURI.resolve(uri);
+                       else
+                               resolved = uri;
+                       Logger.minor(this, "Resolved: "+resolved);
                } catch (URISyntaxException e1) {
                        return null;
                }
                String path = uri.getPath();
-               if (path == null) {
-                       // Only fragment?
-                       if(uri.getScheme() == null && uri.getFragment() != null 
&& 
-                                       uri.getHost() == null) {
-                               return "#" + 
URLEncoder.encode(uri.getFragment());
-                       }
-                       return null;
-               }
+               
+               // Normal protocols should go to /__CHECKED_HTTP_ for POST-form 
verification.
                // mailto: not supported yet - FIXME what to do with it? what 
queries are allowed? can it possibly hurt us? how to construct safely? etc

                HTTPRequest req = new HTTPRequest(uri);
@@ -48,35 +66,28 @@
                        bookmark_desc = HTMLEncoder.encode(bookmark_desc);

                        return 
"/?newbookmark="+bookmark_key+"&desc="+bookmark_desc;
-               } else if(path.startsWith("/") || path.indexOf('@') != -1) {
-                       // Try to make it into a FreenetURI
-                       try {
-                               String p = path;
-                               while(p.startsWith("/")) p = p.substring(1);
-                               FreenetURI furi = new FreenetURI(p);
-                               return processURI(furi, uri, overrideType);
-                       } catch (MalformedURLException e) {
-                               // Obviously not a Freenet URI!
-                       }
                }
-               if(path.startsWith("/")) {
-                       // Still here. It's an absolute URI and *NOT* a freenet 
URI.
-                       // Kill it.
-                       Logger.normal(this, "Unrecognized URI, dropped: "+uri);
-                       return null;
-               } else if(path.startsWith("../")) {
-                       // Kill it, for now. FIXME we need to deal with 
relative URIs properly!
-                       return null;
-               } else {
-                       // Relative URI
-                       // FIXME resolve it
-                       // FIXME Note that we allow links to / inlines from 
fproxy services.
-                       // This is okay because we don't allow forms.
-                       return finishProcess(req, overrideType, path, uri);
+               
+               // Probably a relative URI.
+               
+               String rpath = resolved.getPath();
+               Logger.minor(this, "Resolved URI: "+rpath);
+               
+               // Valid FreenetURI?
+               try {
+                       String p = rpath;
+                       while(p.startsWith("/")) p = p.substring(1);
+                       FreenetURI furi = new FreenetURI(p);
+                       Logger.minor(this, "Parsed: "+furi);
+                       return processURI(furi, uri, overrideType, noRelative);
+               } catch (MalformedURLException e) {
+                       // Not a FreenetURI
                }
+               
+               return null;
        }

-       private String finishProcess(HTTPRequest req, String overrideType, 
String path, URI u) {
+       private String finishProcess(HTTPRequest req, String overrideType, 
String path, URI u, boolean noRelative) {
                String typeOverride = req.getParam("type", null);
                if(overrideType != null)
                        typeOverride = overrideType;
@@ -88,14 +99,40 @@
                        ret = ret + "?type=" + typeOverride;
                if(u.getFragment() != null)
                        ret = ret + "#" + u.getFragment();
-               return ret;
+               ret = ret.trim(); // URI does wierd things with trailing spaces
+               Logger.minor(this, "ret = "+ret);
+               try {
+                       URI out = new URI(ret);
+                       if(!noRelative)
+                               return baseURI.relativize(out).toASCIIString();
+                       else
+                               return ret;
+               } catch (URISyntaxException e) {
+                       Logger.error(this, "Could not parse own URI: "+ret+" : 
"+e, e);
+                       return null;
+               }
        }

-       private String processURI(FreenetURI furi, URI uri, String 
overrideType) {
+       private String processURI(FreenetURI furi, URI uri, String 
overrideType, boolean noRelative) {
                // Valid freenet URI, allow it
                // Now what about the queries?
                HTTPRequest req = new HTTPRequest(uri);
-               return finishProcess(req, overrideType, "/" + 
furi.toString(false), uri);
+               return finishProcess(req, overrideType, "/" + 
furi.toString(false), uri, noRelative);
        }
+
+       public String onBaseHref(String baseHref) {
+               String ret = processURI(baseHref, null, true);
+               if(ret == null) {
+                       Logger.error(this, "onBaseHref() failed: cannot 
sanitize "+baseHref);
+                       return null;
+               } else {
+                       try {
+                               baseURI = new URI(ret);
+                       } catch (URISyntaxException e) {
+                               throw new Error(e); // Impossible
+                       }
+                       return baseURI.toASCIIString();
+               }
+       }

 }

Modified: trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java       
2006-05-17 19:42:55 UTC (rev 8750)
+++ trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java       
2006-05-17 20:58:53 UTC (rev 8751)
@@ -869,10 +869,10 @@
                                emptyStringArray));
                allowedTagsVerifiers.put(
                        "base",
-                       new TagVerifier(
+                       new BaseHrefTagVerifier(
                                "base",
                                new String[] { "id", "target" },
-                               new String[] { "href" }));
+                               new String[] { /* explicitly sanitized by class 
*/ }));
                allowedTagsVerifiers.put(
                        "img",
                        new CoreTagVerifier(
@@ -1820,6 +1820,29 @@
                }
        }

+       static class BaseHrefTagVerifier extends TagVerifier {
+
+               BaseHrefTagVerifier(String string, String[] strings, String[] 
strings2) {
+                       super(string, strings, strings2);
+               }
+               
+               Hashtable sanitizeHash(
+                               Hashtable h,
+                               ParsedTag p,
+                               HTMLParseContext pc) throws DataFilterException 
{
+                       Hashtable hn = super.sanitizeHash(h, p, pc);
+                       // Get the already-sanitized version.
+                       String baseHref = getHashString(hn, "href");
+                       if(baseHref != null) {
+                               String ref = pc.cb.onBaseHref(baseHref);
+                               if(ref != null)
+                                       hn.put("href", ref);
+                       }
+                       return hn;
+               }
+
+       }
+       
        static String sanitizeStyle(String style, FilterCallback cb) throws 
DataFilterException {
                if(style == null) return null;
                Reader r = new StringReader(style);

Modified: trunk/freenet/src/freenet/clients/http/filter/NullFilterCallback.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/filter/NullFilterCallback.java       
2006-05-17 19:42:55 UTC (rev 8750)
+++ trunk/freenet/src/freenet/clients/http/filter/NullFilterCallback.java       
2006-05-17 20:58:53 UTC (rev 8751)
@@ -15,4 +15,8 @@
                return null;
        }

+       public String onBaseHref(String baseHref) {
+               return null;
+       }
+
 }

Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-05-17 19:42:55 UTC (rev 
8750)
+++ trunk/freenet/src/freenet/node/Version.java 2006-05-17 20:58:53 UTC (rev 
8751)
@@ -18,7 +18,7 @@
        public static final String protocolVersion = "1.0";

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

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


Reply via email to