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;