You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@abdera.apache.org by jm...@apache.org on 2011/12/22 06:30:32 UTC

svn commit: r1222042 - in /abdera/abdera2: common/src/main/java/org/apache/abdera2/common/http/ common/src/main/java/org/apache/abdera2/common/text/ test/src/main/java/org/apache/abdera2/test/common/http/

Author: jmsnell
Date: Thu Dec 22 05:30:31 2011
New Revision: 1222042

URL: http://svn.apache.org/viewvc?rev=1222042&view=rev
Log:
Test cases and fixes.... 

now we're passing all but one of these: http://greenbytes.de/tech/tc/httplink/

the one we're not is a crazy edge case.. not worried about it for now

Added:
    abdera/abdera2/test/src/main/java/org/apache/abdera2/test/common/http/WebLinkTest.java   (with props)
Modified:
    abdera/abdera2/common/src/main/java/org/apache/abdera2/common/http/Authentication.java
    abdera/abdera2/common/src/main/java/org/apache/abdera2/common/http/Preference.java
    abdera/abdera2/common/src/main/java/org/apache/abdera2/common/http/WebLink.java
    abdera/abdera2/common/src/main/java/org/apache/abdera2/common/text/CharUtils.java
    abdera/abdera2/test/src/main/java/org/apache/abdera2/test/common/http/AuthenticationTest.java

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/http/Authentication.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/http/Authentication.java?rev=1222042&r1=1222041&r2=1222042&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/http/Authentication.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/http/Authentication.java Thu Dec 22 05:30:31 2011
@@ -29,6 +29,7 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.abdera2.common.misc.MoreFunctions;
+import org.apache.abdera2.common.text.CharUtils;
 import org.apache.abdera2.common.text.CharUtils.Profile;
 import org.apache.abdera2.common.text.Codec;
 
@@ -91,13 +92,6 @@ public class Authentication implements I
       }
   };
   
-  public static String unescape(String quoted) {
-    StringBuilder buf = new StringBuilder();
-    for (char c : quoted.toCharArray())
-      if (c != '\\') buf.append(c);
-    return buf.toString();
-  }
-  
   public static Iterable<Authentication> parse(String challenge) {
     checkNotNull(challenge);
     List<Authentication> challenges = new ArrayList<Authentication>();
@@ -119,7 +113,7 @@ public class Authentication implements I
           String name = ps[0];
           if (name.charAt(name.length()-1)=='*')
             name = name.substring(0,name.length()-1);
-          auth.param(name, Codec.decode(unquote(unescape(ps[1]))));
+          auth.param(name, Codec.decode(unquote(CharUtils.unescape(ps[1]))));
         }
       }
       challenges.add(auth.get());

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/http/Preference.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/http/Preference.java?rev=1222042&r1=1222041&r2=1222042&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/http/Preference.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/http/Preference.java Thu Dec 22 05:30:31 2011
@@ -364,7 +364,7 @@ public class Preference implements Seria
           String[] ps = pref.split("\\s*\\*?=\\s*", 2);
           token = ps[0].trim();
           if (ps.length == 2)
-            tokenval = Codec.decode(CharUtils.unquote(Authentication.unescape(ps[1])));
+            tokenval = Codec.decode(CharUtils.unquote(CharUtils.unescape(ps[1])));
         }
         
         Preference.Builder maker = 
@@ -375,7 +375,7 @@ public class Preference implements Seria
             String p = mparams.group(1);
             String[] ps = p.split("\\s*\\*?=\\s*", 2);
             if (ps.length == 2)
-              maker.param(ps[0], Codec.decode(CharUtils.unquote(Authentication.unescape(ps[1]))));
+              maker.param(ps[0], Codec.decode(CharUtils.unquote(CharUtils.unescape(ps[1]))));
             else maker.param(ps[0]);
           }
         }

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/http/WebLink.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/http/WebLink.java?rev=1222042&r1=1222041&r2=1222042&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/http/WebLink.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/http/WebLink.java Thu Dec 22 05:30:31 2011
@@ -426,26 +426,26 @@ public class WebLink implements Serializ
         String name = text.substring(s+1,text.charAt(e-1)=='*'?e-1:e).trim();
         s = scanFor(';', text,e+1,false);
         String val = s!=-1?text.substring(e+1,s).trim():text.substring(e+1).trim();
-        val = Codec.decode(val).toLowerCase(Locale.US);
+        val = unescape(unquote(Codec.decode(val)));
         if (name.equals("rel"))
-          for (String v : unquote(val).split("\\s+"))
+          for (String v : val.toLowerCase(Locale.US).split("\\s+"))
             maker.rel(v);
         else if (name.equals("anchor"))
           maker.anchor(unwrap(val, '<', '>'));
         else if (name.equals("rev"))
-          for (String v : unquote(val).split("\\s+"))
+          for (String v : val.toLowerCase(Locale.US).split("\\s+"))
             maker.rev(v);
         else if (name.equals("hreflang"))
-          maker.lang(unquote(val));
+          maker.lang(val.toLowerCase(Locale.US));
         else if (name.equals("media"))
-          for (String v : unquote(val).split("\\s+"))
+          for (String v : val.toLowerCase(Locale.US).split("\\s+"))
             maker.media(v);
         else if (name.equals("title"))
-          maker.title(unquote(val));
+          maker.title(val);
         else if (name.equals("type"))
-          maker.mediaType(unquote(val));
+          maker.mediaType(val.toLowerCase(Locale.US));
         else
-          maker.param(name,unquote(val));
+          maker.param(name,val);
       }
       links.add(maker.get());
       if (s == -1) break;

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/text/CharUtils.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/text/CharUtils.java?rev=1222042&r1=1222041&r2=1222042&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/text/CharUtils.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/text/CharUtils.java Thu Dec 22 05:30:31 2011
@@ -122,12 +122,20 @@ public final class CharUtils {
     }
     
     public static String unquote(String s) {
-      if (s == null || s.length() == 0)
-        return s;
-      int n = 0, e = s.length();
-      if (s.charAt(0) == '"') n++;
-      if (s.charAt(e-1) == '"' && s.charAt(e-2) != '\\') e--;
-      return s.substring(n,e);
+      StringBuilder buf = new StringBuilder();
+      int i = s.length();
+      boolean quoted = false, escaped = false;
+      for (int n = 0; n < s.length(); n++) {
+        char c = s.charAt(n);
+        if (n == 0 && c == '"') {
+          quoted = true;
+        } else if (!(quoted && n+1==i && !escaped && c == '"')) 
+          buf.append(c);
+        if (escaped) escaped = false;
+        else if (c == '\\' && !escaped) 
+          escaped = true;
+      }
+      return buf.toString();
     }
 
     public static String[] splitAndTrim(
@@ -210,4 +218,18 @@ public final class CharUtils {
   
   public static final Joiner joiner = Joiner.on(',').skipNulls();
 
+  public static String unescape(String quoted) {
+    StringBuilder buf = new StringBuilder();
+    int i = quoted.length();
+    for (int n = 0; n < i; n++) {
+      char c = quoted.charAt(n);
+      if (c != '\\') buf.append(c);
+      else if (n < i-1 && quoted.charAt(n+1) == '\\') {
+        buf.append(c);
+        n++;
+      }
+    }
+    return buf.toString();
+  }
+
 }

Modified: abdera/abdera2/test/src/main/java/org/apache/abdera2/test/common/http/AuthenticationTest.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/test/src/main/java/org/apache/abdera2/test/common/http/AuthenticationTest.java?rev=1222042&r1=1222041&r2=1222042&view=diff
==============================================================================
--- abdera/abdera2/test/src/main/java/org/apache/abdera2/test/common/http/AuthenticationTest.java (original)
+++ abdera/abdera2/test/src/main/java/org/apache/abdera2/test/common/http/AuthenticationTest.java Thu Dec 22 05:30:31 2011
@@ -11,7 +11,7 @@ import org.apache.abdera2.common.http.Au
 import org.junit.Test;
 
 import com.google.common.collect.Iterables;
-
+@SuppressWarnings("unchecked")
 public class AuthenticationTest {
 
   @Test

Added: abdera/abdera2/test/src/main/java/org/apache/abdera2/test/common/http/WebLinkTest.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/test/src/main/java/org/apache/abdera2/test/common/http/WebLinkTest.java?rev=1222042&view=auto
==============================================================================
--- abdera/abdera2/test/src/main/java/org/apache/abdera2/test/common/http/WebLinkTest.java (added)
+++ abdera/abdera2/test/src/main/java/org/apache/abdera2/test/common/http/WebLinkTest.java Thu Dec 22 05:30:31 2011
@@ -0,0 +1,282 @@
+package org.apache.abdera2.test.common.http;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.abdera2.common.http.WebLink;
+import org.apache.abdera2.common.iri.IRI;
+import org.apache.abdera2.common.mediatype.MimeTypeHelper;
+import org.junit.Test;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.*;
+import static org.hamcrest.CoreMatchers.*;
+
+import com.google.common.collect.Iterables;
+import org.apache.abdera2.common.text.InvalidCharacterException;
+
+public class WebLinkTest {
+
+  @Test
+  public void simplecss() {
+    Iterable<WebLink> il = WebLink.parse("<simple.css>; rel=stylesheet");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals(new IRI("simple.css"),link.getIri());
+    assertThat(link.getRel(),hasItem("stylesheet"));
+  }
+  
+  @Test(expected=InvalidCharacterException.class)
+  public void simplecssreversed() {
+    WebLink.parse("rel=stylesheet; <fail.css>");
+  }
+ 
+  @Test
+  public void simplecsssq() {
+    Iterable<WebLink> il = WebLink.parse("<fail.css>; rel='stylesheet'");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertThat(link.getRel(),not(hasItem("stylesheet"))); // it will be 'stylesheet', which is incorrect
+  }
+  
+  @Test
+  public void simplecssmrel() {
+    Iterable<WebLink> il = WebLink.parse("<simple.css>; rel=\"foobar stylesheet\"");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals(new IRI("simple.css"),link.getIri());
+    assertThat(link.getRel(),hasItems("stylesheet","foobar"));
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void simplecssmlink() {
+    Iterable<WebLink> il = WebLink.parse("<foo>; rel=bar, <simple.css>; rel=stylesheet");
+    assertEquals(2,Iterables.size(il));
+    for (WebLink link : il) {
+      assertThat(link.getIri().toString(), anyOf(is("foo"),is("simple.css")));
+      assertThat(link.getRel(), anyOf(hasItems("bar"),hasItems("stylesheet")));
+    }
+  }
+  
+  @Test
+  public void simplecssanchr() {
+    Iterable<WebLink> il = WebLink.parse("<fail.css>; anchor=\"http://example.com/\"; rel=stylesheet");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("fail.css",link.getIri().toString());
+    assertEquals("http://example.com/fail.css",link.getResolvedIri(new IRI("http://foo.com/")).toString());
+    // this is a redflag! this IRI resolved to a different base URI than
+    // what was passed in! applications need to take great care as this
+    // could be a possible attack vector!
+  }
+  
+  @Test
+  public void simplecssanchrsame() {
+    Iterable<WebLink> il = WebLink.parse("<fail.css>; anchor=\"\"; rel=stylesheet");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("fail.css",link.getIri().toString());
+    assertEquals("http://foo.com/fail.css",link.getResolvedIri(new IRI("http://foo.com/")).toString());
+    // this is an appropriate response
+  }
+  
+  @Test
+  public void simplecssanchrsame2() {
+    Iterable<WebLink> il = WebLink.parse("<fail.css>; anchor=\"\"; rel=stylesheet");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("fail.css",link.getIri().toString());
+    assertEquals("http://foo.com/fail.css",link.getResolvedIri(new IRI("http://foo.com/#foo")).toString());
+    // this is an appropriate response
+  }  
+  
+  @Test
+  public void simplecssanchrsamefrag() {
+    Iterable<WebLink> il = WebLink.parse("<fail.css>; anchor=\"#foo\"; rel=stylesheet");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("fail.css",link.getIri().toString());
+    assertEquals("http://foo.com/fail.css",link.getResolvedIri(new IRI("http://foo.com/")).toString());
+    // this is an appropriate response
+  }  
+  
+  @Test
+  public void simplecssanchrsamefrag2() {
+    Iterable<WebLink> il = WebLink.parse("<fail.css>; anchor=\"#foo\"; rel=stylesheet");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("fail.css",link.getIri().toString());
+    assertEquals("http://foo.com/fail.css",link.getResolvedIri(new IRI("http://foo.com/#foo")).toString());
+    // this is an appropriate response
+  }  
+  
+  @Test
+  public void simplexslttypenotype() {
+    Iterable<WebLink> il = WebLink.parse("<simple.xslt>; rel=stylesheet");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("simple.xslt",link.getIri().toString());
+    assertThat(link.getRel(),hasItem("stylesheet"));
+  }
+  
+  @Test
+  public void simplexslttypedepr() {
+    Iterable<WebLink> il = WebLink.parse("<simple.xslt>; rel=stylesheet; type=\"text/xsl\"");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("simple.xslt",link.getIri().toString());
+    assertThat(link.getRel(),hasItem("stylesheet"));
+    assertTrue(MimeTypeHelper.isMatch(link.getMediaType(), MimeTypeHelper.create("text/xsl")));
+  }
+     
+  @Test
+  public void simplexslttypedepr2() {
+    Iterable<WebLink> il = WebLink.parse("<simple.xslt.asis>; rel=stylesheet; type=\"text/xsl\"");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("simple.xslt.asis",link.getIri().toString());
+    assertThat(link.getRel(),hasItem("stylesheet"));
+    assertTrue(MimeTypeHelper.isMatch(link.getMediaType(), MimeTypeHelper.create("text/xsl")));
+  }
+  
+  @Test
+  public void simplexslttypeoff() {
+    Iterable<WebLink> il = WebLink.parse("<simple.xslt>; rel=stylesheet; type=\"application/xslt+xml\"");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("simple.xslt.asis",link.getIri().toString());
+    assertThat(link.getRel(),hasItem("stylesheet"));
+    assertTrue(MimeTypeHelper.isMatch(link.getMediaType(), MimeTypeHelper.create("text/xsl")));
+  }
+  
+  @Test
+  public void simplecsstitle() {
+    Iterable<WebLink> il = WebLink.parse("<simple.css>; rel=stylesheet; title=\"A simple CSS stylesheet\"");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("simple.css",link.getIri().toString());
+    assertThat(link.getRel(),hasItem("stylesheet"));
+    assertEquals(link.getTitle(),"A simple CSS stylesheet");
+  }
+  
+  @Test
+  public void simplecsstitleq() {
+    Iterable<WebLink> il = WebLink.parse("<simple.css>; rel=stylesheet; title=\"title with a DQUOTE \\\" and backslash: \\\\\"");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("title with a DQUOTE \" and backslash: \\",link.getTitle());
+  }
+  
+  @Test
+  public void simplecsstitleq2() {
+    Iterable<WebLink> il = WebLink.parse("<simple.css>; title=\"title with a DQUOTE \\\" and backslash: \\\\\"; rel=stylesheet");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("title with a DQUOTE \" and backslash: \\",link.getTitle());
+  }
+  
+  @Test
+  public void simplecsstitletok() {
+    Iterable<WebLink> il = WebLink.parse("<simple.css>; rel=stylesheet; title=AsimpleCSSstylesheet");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("AsimpleCSSstylesheet",link.getTitle());
+    // not strictly allowed per the spec
+  }
+  
+  @Test
+  public void simplecsstitle5987() {
+    Iterable<WebLink> il = WebLink.parse("<simple.css>; rel=stylesheet; title*=UTF-8''stylesheet-%E2%82%AC");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("stylesheet-\u20AC",link.getTitle());
+  }
+  
+  @Test
+  public void simplecsstitle5987r() {
+    Iterable<WebLink> il = WebLink.parse("<simple.css>; title*=UTF-8''stylesheet-%E2%82%AC; rel=stylesheet");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("stylesheet-\u20AC",link.getTitle());
+  } 
+  
+  @Test
+  public void simplecsstitle5987iso88591() {
+    Iterable<WebLink> il = WebLink.parse("<simple.css>; title*=iso-8859-1''stylesheet-%E4; rel=stylesheet");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("stylesheet-\u00E4",link.getTitle());
+  } 
+  
+  @Test
+  public void simplecsstitle5987noenc() {
+    Iterable<WebLink> il = WebLink.parse("<simple.css>; title*=''A%20simple%20CSS%20stylesheet; title=\"fallback title\"; rel=stylesheet");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("fallback title", link.getTitle());
+    // this passes, but not for the reason its supposed to
+  }
+  
+  @Test
+  public void simplecsstitle5987parseerror() {
+    Iterable<WebLink> il = WebLink.parse("<simple.css>; title*=foobar; title=\"fallback title\"; rel=stylesheet");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("fallback title", link.getTitle());
+ // this passes, but not for the reason its supposed to
+  }
+  
+  @Test
+  public void simplecsstitle5987parseerror2() {
+    Iterable<WebLink> il = WebLink.parse("<simple.css>; title*=UTF-8''foobar%; title=\"fallback title\"; rel=stylesheet");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("fallback title", link.getTitle());
+ // this passes, but not for the reason its supposed to
+  }
+  
+  @Test
+  public void simpleext() {
+    Iterable<WebLink> il = WebLink.parse("<simple.css>; ext=foo; rel=stylesheet");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("foo",link.getParam("ext"));
+  }
+  
+  @Test
+  public void simpleextq() {
+    Iterable<WebLink> il = WebLink.parse("<simple.css>; ext=\"\\\"\"; rel=stylesheet");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertEquals("\"",link.getParam("ext"));
+  }
+  
+// This isn't supported
+//  @Test
+//  public void simpleexta() {
+//    Iterable<WebLink> il = WebLink.parse("<simple.css>; ext1='start; rel=stylesheet; ext2=end'");
+//    assertEquals(1,Iterables.size(il));
+//    WebLink link = il.iterator().next();
+//    System.out.println(link.getParam("ext1"));
+//  }
+  
+  @Test
+  public void simpleextrel() {
+    Iterable<WebLink> il = WebLink.parse("<simple.css>; rel=\"http://example.com/myrel stylesheet\"");
+    assertEquals(1,Iterables.size(il));
+    WebLink link = il.iterator().next();
+    assertThat(link.getRel(),hasItems("stylesheet","http://example.com/myrel"));
+  }
+  
+  @Test
+  public void simplecss2() {
+    Iterable<WebLink> il = WebLink.parse("<ybg.css>; rel=stylesheet, <simple.css>; rel=stylesheet");
+    assertEquals(2, Iterables.size(il));
+  }
+  
+  @Test
+  public void simplecssafterother() {
+    Iterable<WebLink> il = WebLink.parse("<ybf.css>; rel=foobar, <simple.css>; rel=stylesheet");
+    assertEquals(2, Iterables.size(il));
+  }
+}

Propchange: abdera/abdera2/test/src/main/java/org/apache/abdera2/test/common/http/WebLinkTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain