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