Author: toad
Date: 2006-10-27 23:23:42 +0000 (Fri, 27 Oct 2006)
New Revision: 10717

Added:
   trunk/freenet/src/freenet/clients/http/filter/CommentException.java
Modified:
   trunk/freenet/src/freenet/clients/http/filter/CSSParser.java
   trunk/freenet/src/freenet/clients/http/filter/CSSTokenizerFilter.java
   trunk/freenet/src/freenet/clients/http/filter/CSSTokenizerFilter.jflex
   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
Log:
If a URL is dropped by the filter because it is invalid, return feedback in 
comments explaining why.

Modified: trunk/freenet/src/freenet/clients/http/filter/CSSParser.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/filter/CSSParser.java        
2006-10-27 19:47:14 UTC (rev 10716)
+++ trunk/freenet/src/freenet/clients/http/filter/CSSParser.java        
2006-10-27 23:23:42 UTC (rev 10717)
@@ -41,11 +41,11 @@
                HTMLFilter.throwFilterException(s);
        }

-       String processImportURL(String s) {
+       String processImportURL(String s) throws CommentException {
                return HTMLFilter.sanitizeURI(HTMLFilter.stripQuotes(s), 
"text/css", null, cb);
        }

-       String processURL(String s) {
+       String processURL(String s) throws CommentException {
                return HTMLFilter.sanitizeURI(HTMLFilter.stripQuotes(s), null, 
null, cb);
        }


Modified: trunk/freenet/src/freenet/clients/http/filter/CSSTokenizerFilter.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/filter/CSSTokenizerFilter.java       
2006-10-27 19:47:14 UTC (rev 10716)
+++ trunk/freenet/src/freenet/clients/http/filter/CSSTokenizerFilter.java       
2006-10-27 23:23:42 UTC (rev 10717)
@@ -1,4 +1,4 @@
-/* The following code was generated by JFlex 1.4.1 on 06/10/06 19:33 */
+/* The following code was generated by JFlex 1.4.1 on 28/10/06 00:17 */

 /* This code is part of Freenet. It is distributed under the GNU General
  * Public License, version 2 (or at your option any later version). See
@@ -14,7 +14,7 @@
 /**
  * This class is a scanner generated by 
  * <a href="http://www.jflex.de/";>JFlex</a> 1.4.1
- * on 06/10/06 19:33 from the specification file
+ * on 28/10/06 00:17 from the specification file
  * <tt>freenet/clients/http/filter/CSSTokenizerFilter.jflex</tt>
  */
 class CSSTokenizerFilter {
@@ -852,11 +852,11 @@
                throw new IllegalStateException("You MUST override 
throwError!");
        }

-       String processImportURL(String s) {
+       String processImportURL(String s) throws CommentException {
                throw new IllegalStateException("You MUST override 
processImportURL!");
        }

-       String processURL(String s) {
+       String processURL(String s) throws CommentException {
                throw new IllegalStateException("You MUST override 
processURL!");
        }

@@ -1003,6 +1003,18 @@
                        return sb.toString();
                }
        }
+       
+       String commentEncode(String s) {
+               StringBuffer sb = new StringBuffer(s.length());
+               for(int i=0;i<s.length();i++) {
+                       char c = sb.charAt(i);
+                       if(c == '/')
+                               sb.append("\\/");
+                       else
+                               sb.append(c);
+               }
+               return sb.toString();
+       }


   /**
@@ -1292,30 +1304,63 @@
       zzMarkedPos = zzMarkedPosL;

       switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
+        case 23: 
+          { // This is horrible. However it seems that there is no other way 
to do it with either jflex or CUP, as {URL} cannot be an unambiguous token :(
+       String s = yytext();
+       if(debug) log("Recognized URL: "+s);
+       
+       DecodedStringThingy dst = new DecodedStringThingy(s);
+       
+       if(!dst.url) {
+               throw new IllegalStateException("parsing url().. isn't a 
url()");
+       }
+       if(dst.suffix.length() > 0) {
+               yypushback(dst.suffix.length());
+               dst.suffix = "";
+       }
+       
+       s = dst.data;
+       if(debug) log("URL now: "+s);
+       try {
+               s = processURL(s);
+               dst.data = s;
+               if(s == null || s.equals("")) {
+                       if(debug) log("URL invalid");
+                       w.write("url()");
+               } else {
+                       s = dst.toString();
+                       if(debug) log("Writing: "+s);
+                       w.write(s);
+               }
+       } catch (CommentException e) {
+               w.write("/* "+commentEncode(e.getMessage())+" */");
+       }
+          }
+        case 31: break;
         case 18: 
           { String s = yytext();
        w.write(s);
        if(debug) log("Matched unicode: "+s);
           }
-        case 31: break;
+        case 32: break;
         case 8: 
           { String s = yytext();
        w.write(s);
        if(debug) log("Matched close braces: "+s);
           }
-        case 32: break;
+        case 33: break;
         case 22: 
           { String s = yytext();
        w.write(s);
        if(debug) log("Matched HTML comment: "+s);
           }
-        case 33: break;
+        case 34: break;
         case 16: 
           { String s = yytext();
        w.write(s); 
        if(debug) log("Matched ~=: "+s);
           }
-        case 34: break;
+        case 35: break;
         case 12: 
           { String s = yytext();
        if(debug) log("Matched string: "+s);
@@ -1326,87 +1371,81 @@
                w.write(s);
        }
           }
-        case 35: break;
+        case 36: break;
         case 25: 
           { String s = yytext();
        w.write(s);
        if(debug) log("Matched @page: "+s);
           }
-        case 36: break;
+        case 37: break;
         case 13: 
           { String s = yytext();
        w.write(s);
        if(debug) log("Matched number: "+s);
           }
-        case 37: break;
+        case 38: break;
         case 1: 
           { String s = yytext();
        char c = s.charAt(0);
        log("Matched anything: "+yytext()+" - ignoring");
        w.write("/* ignored unmatched char: "+c+" */"); // single char cannot 
break out of comment
           }
-        case 38: break;
+        case 39: break;
         case 6: 
           { String s = yytext();
        w.write(s);
        if(debug) log("Matched semicolon: "+s);
           }
-        case 39: break;
+        case 40: break;
         case 20: 
           { String s = yytext();
        if(debug) log("Got hexcolor: "+s);
        w.write(s);
           }
-        case 40: break;
+        case 41: break;
         case 7: 
           { String s = yytext();
        w.write(s);
        if(debug) log("Matched open braces: "+s);
           }
-        case 41: break;
+        case 42: break;
         case 26: 
           { String s = yytext();
        s = s.substring("@media".length()).trim();
        w.write("@media "+s+" ");
        if(debug) log("Matched @media: "+s);
           }
-        case 42: break;
+        case 43: break;
         case 2: 
           { String s = yytext();
        w.write(s);
        if(debug) log("Matched ident: "+s);
           }
-        case 43: break;
+        case 44: break;
         case 24: 
           { String s = yytext();
        w.write(s);
        if(debug) log("Matched unicode range: "+s);
           }
-        case 44: break;
+        case 45: break;
         case 28: 
           { String s = yytext();
        w.write(s);
        if(debug) log("Matched @font-face: "+s);
           }
-        case 45: break;
+        case 46: break;
         case 19: 
           { String s = yytext();
        w.write(s); 
        if(debug) log("Matched HTML comment: "+s);
           }
-        case 46: break;
+        case 47: break;
         case 9: 
           { String s = yytext();
        if(s.startsWith("url")) throwError("Invalid contents of url()");
        w.write(s);
        if(debug) log("Matched function start: "+s);
           }
-        case 47: break;
-        case 3: 
-          { String s = yytext();
-       w.write(s);
-       if(debug) log("Matched whitespace: "+s);
-          }
         case 48: break;
         case 27: 
           { String s = yytext();
@@ -1416,25 +1455,35 @@
        DecodedStringThingy dst = new DecodedStringThingy(s);
        s = dst.data;
        if(debug) log("URL: "+s);
-       s = processImportURL(s);
-       dst.data = s;
-       if(debug) log("Processed URL: "+s);
-       if(dst.quote == ' ') dst.quote = '\"';
-       if (!(s == null || s.equals(""))) {
-               if(debug) log("URL now: "+s);
-               s = "@import "+dst.toString();
-               if(debug) log("Writing: "+s);
-               w.write(s);
-       } else
-               if(debug) log("Dropped @import");
+       try {
+               s = processImportURL(s);
+               dst.data = s;
+               if(debug) log("Processed URL: "+s);
+               if(dst.quote == ' ') dst.quote = '\"';
+               if (!(s == null || s.equals(""))) {
+                       if(debug) log("URL now: "+s);
+                       s = "@import "+dst.toString();
+                       if(debug) log("Writing: "+s);
+                       w.write(s);
+               } else
+                       if(debug) log("Dropped @import");
+       } catch (CommentException e) {
+               w.write("/* " + commentEncode(e.getMessage()) + " */");
+       }
           }
         case 49: break;
+        case 3: 
+          { String s = yytext();
+       w.write(s);
+       if(debug) log("Matched whitespace: "+s);
+          }
+        case 50: break;
         case 29: 
           { String s = yytext();
        w.write(s);
        if(debug) log("Matched important: "+s);
           }
-        case 50: break;
+        case 51: break;
         case 21: 
           { String s = yytext();
        StringBuffer sb = new StringBuffer(s.length());
@@ -1459,7 +1508,7 @@
        w.write(sb.toString());
        if(debug) log("Matched comment: "+s+" -> "+sb.toString());
           }
-        case 51: break;
+        case 52: break;
         case 15: 
           { if(!deleteErrors) {
                throwError("Unknown @identifier "+yytext());
@@ -1469,35 +1518,6 @@
                // Ignore
        }
           }
-        case 52: break;
-        case 23: 
-          { // This is horrible. However it seems that there is no other way 
to do it with either jflex or CUP, as {URL} cannot be an unambiguous token :(
-       String s = yytext();
-       if(debug) log("Recognized URL: "+s);
-       
-       DecodedStringThingy dst = new DecodedStringThingy(s);
-       
-       if(!dst.url) {
-               throw new IllegalStateException("parsing url().. isn't a 
url()");
-       }
-       if(dst.suffix.length() > 0) {
-               yypushback(dst.suffix.length());
-               dst.suffix = "";
-       }
-       
-       s = dst.data;
-       if(debug) log("URL now: "+s);
-       s = processURL(s);
-       dst.data = s;
-       if(s == null || s.equals("")) {
-               if(debug) log("URL invalid");
-               w.write("url()");
-       } else {
-               s = dst.toString();
-               if(debug) log("Writing: "+s);
-               w.write(s);
-       }
-          }
         case 53: break;
         case 11: 
           { String s = yytext();

Modified: trunk/freenet/src/freenet/clients/http/filter/CSSTokenizerFilter.jflex
===================================================================
--- trunk/freenet/src/freenet/clients/http/filter/CSSTokenizerFilter.jflex      
2006-10-27 19:47:14 UTC (rev 10716)
+++ trunk/freenet/src/freenet/clients/http/filter/CSSTokenizerFilter.jflex      
2006-10-27 23:23:42 UTC (rev 10717)
@@ -41,11 +41,11 @@
                throw new IllegalStateException("You MUST override 
throwError!");
        }

-       String processImportURL(String s) {
+       String processImportURL(String s) throws CommentException {
                throw new IllegalStateException("You MUST override 
processImportURL!");
        }

-       String processURL(String s) {
+       String processURL(String s) throws CommentException {
                throw new IllegalStateException("You MUST override 
processURL!");
        }

@@ -192,6 +192,18 @@
                        return sb.toString();
                }
        }
+       
+       String commentEncode(String s) {
+               StringBuffer sb = new StringBuffer(s.length());
+               for(int i=0;i<s.length();i++) {
+                       char c = sb.charAt(i);
+                       if(c == '/')
+                               sb.append("\\/");
+                       else
+                               sb.append(c);
+               }
+               return sb.toString();
+       }
 %}

 %class CSSTokenizerFilter
@@ -265,15 +277,19 @@

        s = dst.data;
        if(debug) log("URL now: "+s);
-       s = processURL(s);
-       dst.data = s;
-       if(s == null || s.equals("")) {
-               if(debug) log("URL invalid");
-               w.write("url()");
-       } else {
-               s = dst.toString();
-               if(debug) log("Writing: "+s);
-               w.write(s);
+       try {
+               s = processURL(s);
+               dst.data = s;
+               if(s == null || s.equals("")) {
+                       if(debug) log("URL invalid");
+                       w.write("url()");
+               } else {
+                       s = dst.toString();
+                       if(debug) log("Writing: "+s);
+                       w.write(s);
+               }
+       } catch (CommentException e) {
+               w.write("/* "+commentEncode(e.getMessage())+" */");
        }
 }
 "@import"{W}{W}*({STRING}|{URL}|{REALURL})({W}*{W}{MEDIUMS})?";" {
@@ -284,17 +300,21 @@
        DecodedStringThingy dst = new DecodedStringThingy(s);
        s = dst.data;
        if(debug) log("URL: "+s);
-       s = processImportURL(s);
-       dst.data = s;
-       if(debug) log("Processed URL: "+s);
-       if(dst.quote == ' ') dst.quote = '\"';
-       if (!(s == null || s.equals(""))) {
-               if(debug) log("URL now: "+s);
-               s = "@import "+dst.toString();
-               if(debug) log("Writing: "+s);
-               w.write(s);
-       } else
-               if(debug) log("Dropped @import");
+       try {
+               s = processImportURL(s);
+               dst.data = s;
+               if(debug) log("Processed URL: "+s);
+               if(dst.quote == ' ') dst.quote = '\"';
+               if (!(s == null || s.equals(""))) {
+                       if(debug) log("URL now: "+s);
+                       s = "@import "+dst.toString();
+                       if(debug) log("Writing: "+s);
+                       w.write(s);
+               } else
+                       if(debug) log("Dropped @import");
+       } catch (CommentException e) {
+               w.write("/* " + commentEncode(e.getMessage()) + " */");
+       }
 }
 {W}"{"{W} {
        String s = yytext();

Added: trunk/freenet/src/freenet/clients/http/filter/CommentException.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/filter/CommentException.java 
2006-10-27 19:47:14 UTC (rev 10716)
+++ trunk/freenet/src/freenet/clients/http/filter/CommentException.java 
2006-10-27 23:23:42 UTC (rev 10717)
@@ -0,0 +1,19 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.clients.http.filter;
+
+/**
+ * Thrown when a filter operation cannot complete and the filter has produced 
some error output to help guide the user in
+ * resolving the situation.
+ * 
+ * Note that the message is not yet encoded, and may contain data-dependant 
information; that is the responsibility of the 
+ * catcher.
+ */
+public class CommentException extends Exception {
+       
+       public CommentException(String msg) {
+               super(msg);
+       }
+
+}

Modified: trunk/freenet/src/freenet/clients/http/filter/FilterCallback.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/filter/FilterCallback.java   
2006-10-27 19:47:14 UTC (rev 10716)
+++ trunk/freenet/src/freenet/clients/http/filter/FilterCallback.java   
2006-10-27 23:23:42 UTC (rev 10717)
@@ -1,5 +1,7 @@
 package freenet.clients.http.filter;

+import java.net.MalformedURLException;
+
 /**
  * Callback to be provided to a content filter.
  */
@@ -9,8 +11,9 @@
         * Process a URI.
         * If it cannot be turned into something sufficiently safe, then return 
null.
         * @param overrideType Force the return type.
+        * @throws CommentException If the URI is nvalid or unacceptable in 
some way.
         */
-       public String processURI(String uri, String overrideType);
+       public String processURI(String uri, String overrideType) throws 
CommentException;

        /**
         * Should we allow GET forms?

Modified: 
trunk/freenet/src/freenet/clients/http/filter/GenericReadFilterCallback.java
===================================================================
--- 
trunk/freenet/src/freenet/clients/http/filter/GenericReadFilterCallback.java    
    2006-10-27 19:47:14 UTC (rev 10716)
+++ 
trunk/freenet/src/freenet/clients/http/filter/GenericReadFilterCallback.java    
    2006-10-27 23:23:42 UTC (rev 10717)
@@ -56,11 +56,11 @@
                return false;
        }

-       public String processURI(String u, String overrideType) {
+       public String processURI(String u, String overrideType) throws 
CommentException {
                return processURI(u, overrideType, false);
        }

-       public String processURI(String u, String overrideType, boolean 
noRelative) {
+       public String processURI(String u, String overrideType, boolean 
noRelative) throws CommentException {
                URI uri;
                URI resolved;
                boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
@@ -75,7 +75,7 @@
                        if(logMINOR) Logger.minor(this, "Resolved: "+resolved);
                } catch (URISyntaxException e1) {
                        if(logMINOR) Logger.minor(this, "Failed to parse URI: 
"+e1);
-                       return null;
+                       throw new CommentException("Filter could not parse URI: 
"+e1.getMessage());
                }
                String path = uri.getPath();

@@ -96,11 +96,13 @@
                        }
                }

+               String reason = "";
+               
                // Try as an absolute URI

                String rpath = uri.getPath();
                if(rpath != null) {
-                       if(logMINOR) Logger.minor(this, "Resolved URI: "+rpath);
+                       if(logMINOR) Logger.minor(this, "Resolved URI (rpath 
absolute): "+rpath);

                        // Valid FreenetURI?
                        try {
@@ -111,14 +113,16 @@
                                return processURI(furi, uri, overrideType, 
noRelative);
                        } catch (MalformedURLException e) {
                                // Not a FreenetURI
+                               if(logMINOR) Logger.minor(this, "Malformed URL 
(a): "+e, e);
+                               reason = "Malformed URL (absolute): 
"+e.getMessage();
                        }
                }

                // Probably a relative URI.

                rpath = resolved.getPath();
-               if(rpath == null) return null;
-               if(logMINOR) Logger.minor(this, "Resolved URI: "+rpath);
+               if(rpath == null) throw new CommentException("No URI");
+               if(logMINOR) Logger.minor(this, "Resolved URI (rpath relative): 
"+rpath);

                // Valid FreenetURI?
                try {
@@ -128,13 +132,21 @@
                        if(logMINOR) Logger.minor(this, "Parsed: "+furi);
                        return processURI(furi, uri, overrideType, noRelative);
                } catch (MalformedURLException e) {
+                       if(logMINOR) Logger.minor(this, "Malformed URL (b): 
"+e, e);
+                       if(reason.length() > 0)
+                               reason += " , ";
+                       reason += "Malformed URL (relative): "+e.getMessage();
                        // Not a FreenetURI
                }

                
if(GenericReadFilterCallback.allowedProtocols.contains(uri.getScheme()))
                        return 
"/?"+GenericReadFilterCallback.magicHTTPEscapeString+"="+uri;    
-               else
-                       return null;
+               else {
+                       if(uri.getScheme() == null) {
+                               throw new CommentException("Invalid freenet 
URL: "+reason);
+                       }
+                       throw new CommentException("Not an escaped protocol: 
"+uri.getScheme());
+               }
        }

        private String finishProcess(HTTPRequest req, String overrideType, 
String path, URI u, boolean noRelative) {
@@ -163,7 +175,7 @@
                                }catch (UnsupportedEncodingException e1){
                                }
                        }
-                       return null;
+                       return p;
                }
        }

@@ -176,7 +188,13 @@
        }

        public String onBaseHref(String baseHref) {
-               String ret = processURI(baseHref, null, true);
+               String ret;
+               try {
+                       ret = processURI(baseHref, null, true);
+               } catch (CommentException e1) {
+                       Logger.error(this, "Failed to parse base href: 
"+baseHref+" -> "+e1.getMessage());
+                       ret = null;
+               }
                if(ret == null) {
                        Logger.error(this, "onBaseHref() failed: cannot 
sanitize "+baseHref);
                        return null;

Modified: trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java       
2006-10-27 19:47:14 UTC (rev 10716)
+++ trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java       
2006-10-27 23:23:42 UTC (rev 10717)
@@ -1160,7 +1160,7 @@
                                                // Java's URL handling doesn't 
seem suitable
                                                String uri = (String) o;
                                                uri = HTMLDecoder.decode(uri);
-                                               uri = sanitizeURI(uri, null, 
null, pc.cb);
+                                               uri = htmlSanitizeURI(uri, 
null, null, pc.cb, pc);
                                                if (uri != null) {
                                                        uri = 
HTMLEncoder.encode(uri);
                                                        hn.put(x, uri);
@@ -1529,7 +1529,7 @@
                                //                                      type+" 
and charset "+charset,
                                //                                      
Logger.DEBUG);
                                href = HTMLDecoder.decode(href);
-                               href = sanitizeURI(href, type, charset, pc.cb);
+                               href = htmlSanitizeURI(href, type, charset, 
pc.cb, pc);
                                if (href != null) {
                                        href = HTMLEncoder.encode(href);
                                        hn.put("href", href);
@@ -1864,7 +1864,7 @@
                return null;
        }

-       static String sanitizeURI(String uri, FilterCallback cb) {
+       static String sanitizeURI(String uri, FilterCallback cb) throws 
CommentException {
                return sanitizeURI(uri, null, null, cb);
        }

@@ -1929,11 +1929,25 @@
                }
        }

+       static String htmlSanitizeURI(
+                       String suri,
+                       String overrideType,
+                       String overrideCharset,
+                       FilterCallback cb,
+                       HTMLParseContext pc) {
+               try {
+                       return sanitizeURI(suri, overrideType, overrideCharset, 
cb);
+               } catch (CommentException e) {
+                       pc.writeAfterTag.append("<!-- 
"+HTMLEncoder.encode(e.toString())+" -->");
+                       return null;
+               }
+       }
+       
        static String sanitizeURI(
                String suri,
                String overrideType,
                String overrideCharset,
-               FilterCallback cb) {
+               FilterCallback cb) throws CommentException {
                if(logMINOR)
                        Logger.minor(HTMLFilter.class, "Sanitizing URI: 
"+suri+" ( override type "+overrideType +" override charset "+overrideCharset+" 
)");
                if((overrideCharset != null) && (overrideCharset.length() > 0))


Reply via email to