• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.squareup.okhttp.internal.huc;
18 
19 import com.squareup.okhttp.OkHttpClient;
20 import com.squareup.okhttp.OkUrlFactory;
21 import com.squareup.okhttp.Request;
22 import com.squareup.okhttp.Response;
23 import com.squareup.okhttp.internal.Internal;
24 import com.squareup.okhttp.internal.InternalCache;
25 import com.squareup.okhttp.internal.http.CacheRequest;
26 import com.squareup.okhttp.internal.http.CacheStrategy;
27 
28 import java.io.IOException;
29 import java.net.CacheResponse;
30 import java.net.HttpURLConnection;
31 import java.net.URI;
32 import java.net.URISyntaxException;
33 import java.net.URL;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.concurrent.atomic.AtomicReference;
37 import org.junit.Ignore;
38 import org.junit.Test;
39 
40 import static org.junit.Assert.assertEquals;
41 
42 /**
43  * Exercises HttpURLConnection to convert URL to a URI. Unlike URL#toURI,
44  * HttpURLConnection recovers from URLs with unescaped but unsupported URI
45  * characters like '{' and '|' by escaping these characters.
46  */
47 public final class URLEncodingTest {
48   /**
49    * This test goes through the exhaustive set of interesting ASCII characters
50    * because most of those characters are interesting in some way according to
51    * RFC 2396 and RFC 2732. http://b/1158780
52    */
lenientUrlToUri()53   @Test @Ignore public void lenientUrlToUri() throws Exception {
54     // alphanum
55     testUrlToUriMapping("abzABZ09", "abzABZ09", "abzABZ09", "abzABZ09", "abzABZ09");
56 
57     // control characters
58     testUrlToUriMapping("\u0001", "%01", "%01", "%01", "%01");
59     testUrlToUriMapping("\u001f", "%1F", "%1F", "%1F", "%1F");
60 
61     // ascii characters
62     testUrlToUriMapping("%20", "%20", "%20", "%20", "%20");
63     testUrlToUriMapping("%20", "%20", "%20", "%20", "%20");
64     testUrlToUriMapping(" ", "%20", "%20", "%20", "%20");
65     testUrlToUriMapping("!", "!", "!", "!", "!");
66     testUrlToUriMapping("\"", "%22", "%22", "%22", "%22");
67     testUrlToUriMapping("#", null, null, null, "%23");
68     testUrlToUriMapping("$", "$", "$", "$", "$");
69     testUrlToUriMapping("&", "&", "&", "&", "&");
70     testUrlToUriMapping("'", "'", "'", "'", "'");
71     testUrlToUriMapping("(", "(", "(", "(", "(");
72     testUrlToUriMapping(")", ")", ")", ")", ")");
73     testUrlToUriMapping("*", "*", "*", "*", "*");
74     testUrlToUriMapping("+", "+", "+", "+", "+");
75     testUrlToUriMapping(",", ",", ",", ",", ",");
76     testUrlToUriMapping("-", "-", "-", "-", "-");
77     testUrlToUriMapping(".", ".", ".", ".", ".");
78     testUrlToUriMapping("/", null, "/", "/", "/");
79     testUrlToUriMapping(":", null, ":", ":", ":");
80     testUrlToUriMapping(";", ";", ";", ";", ";");
81     testUrlToUriMapping("<", "%3C", "%3C", "%3C", "%3C");
82     testUrlToUriMapping("=", "=", "=", "=", "=");
83     testUrlToUriMapping(">", "%3E", "%3E", "%3E", "%3E");
84     testUrlToUriMapping("?", null, null, "?", "?");
85     testUrlToUriMapping("@", "@", "@", "@", "@");
86     testUrlToUriMapping("[", null, "%5B", null, "%5B");
87     testUrlToUriMapping("\\", "%5C", "%5C", "%5C", "%5C");
88     testUrlToUriMapping("]", null, "%5D", null, "%5D");
89     testUrlToUriMapping("^", "%5E", "%5E", "%5E", "%5E");
90     testUrlToUriMapping("_", "_", "_", "_", "_");
91     testUrlToUriMapping("`", "%60", "%60", "%60", "%60");
92     testUrlToUriMapping("{", "%7B", "%7B", "%7B", "%7B");
93     testUrlToUriMapping("|", "%7C", "%7C", "%7C", "%7C");
94     testUrlToUriMapping("}", "%7D", "%7D", "%7D", "%7D");
95     testUrlToUriMapping("~", "~", "~", "~", "~");
96     testUrlToUriMapping("~", "~", "~", "~", "~");
97     testUrlToUriMapping("\u007f", "%7F", "%7F", "%7F", "%7F");
98 
99     // beyond ascii
100     testUrlToUriMapping("\u0080", "%C2%80", "%C2%80", "%C2%80", "%C2%80");
101     testUrlToUriMapping("\u20ac", "\u20ac", "\u20ac", "\u20ac", "\u20ac");
102     testUrlToUriMapping("\ud842\udf9f", "\ud842\udf9f", "\ud842\udf9f", "\ud842\udf9f",
103         "\ud842\udf9f");
104   }
105 
lenientUrlToUriNul()106   @Test @Ignore public void lenientUrlToUriNul() throws Exception {
107     testUrlToUriMapping("\u0000", "%00", "%00", "%00", "%00"); // RI fails this
108   }
109 
testUrlToUriMapping(String string, String asAuthority, String asFile, String asQuery, String asFragment)110   private void testUrlToUriMapping(String string, String asAuthority, String asFile, String asQuery,
111       String asFragment) throws Exception {
112     if (asAuthority != null) {
113       assertEquals("http://host" + asAuthority + ".tld/",
114           backdoorUrlToUri(new URL("http://host" + string + ".tld/")).toString());
115     }
116     if (asFile != null) {
117       assertEquals("http://host.tld/file" + asFile + "/",
118           backdoorUrlToUri(new URL("http://host.tld/file" + string + "/")).toString());
119     }
120     if (asQuery != null) {
121       assertEquals("http://host.tld/file?q" + asQuery + "=x",
122           backdoorUrlToUri(new URL("http://host.tld/file?q" + string + "=x")).toString());
123     }
124     assertEquals("http://host.tld/file#" + asFragment + "-x",
125         backdoorUrlToUri(new URL("http://host.tld/file#" + asFragment + "-x")).toString());
126   }
127 
backdoorUrlToUri(URL url)128   private URI backdoorUrlToUri(URL url) throws Exception {
129     final AtomicReference<URI> uriReference = new AtomicReference<>();
130 
131     OkHttpClient client = new OkHttpClient();
132     Internal.instance.setCache(client, new InternalCache() {
133       @Override
134       public Response get(Request request) throws IOException {
135         uriReference.set(request.uri());
136         throw new UnsupportedOperationException();
137       }
138 
139       @Override
140       public CacheRequest put(Response response) throws IOException {
141         return null;
142       }
143 
144       @Override
145       public void remove(Request request) throws IOException {
146 
147       }
148 
149       @Override
150       public void update(Response cached, Response network) throws IOException {
151 
152       }
153 
154       @Override
155       public void trackConditionalCacheHit() {
156 
157       }
158 
159       @Override
160       public void trackResponse(CacheStrategy cacheStrategy) {
161 
162       }
163     });
164 
165     try {
166       HttpURLConnection connection = new OkUrlFactory(client).open(url);
167       connection.getResponseCode();
168     } catch (Exception expected) {
169       if (expected.getCause() instanceof URISyntaxException) {
170         expected.printStackTrace();
171       }
172     }
173 
174     return uriReference.get();
175   }
176 }
177