1 /*
2 * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
1212
1213 /*
1214 * parse the standard extension dependencies
1215 */
1216 private void parseExtensionsDependencies() throws IOException {
1217 ExtensionDependency.checkExtensionsDependencies(jar);
1218 }
1219
1220 /*
1221 * Parses value of the Class-Path manifest attribute and returns
1222 * an array of URLs relative to the specified base URL.
1223 */
1224 private URL[] parseClassPath(URL base, String value)
1225 throws MalformedURLException
1226 {
1227 StringTokenizer st = new StringTokenizer(value);
1228 URL[] urls = new URL[st.countTokens()];
1229 int i = 0;
1230 while (st.hasMoreTokens()) {
1231 String path = st.nextToken();
1232 URL url = DISABLE_CP_URL_CHECK ? new URL(base, path) : safeResolve(base, path);
1233 if (url != null) {
1234 urls[i] = url;
1235 i++;
1236 }
1237 }
1238 if (i == 0) {
1239 urls = null;
1240 } else if (i != urls.length) {
1241 // Truncate nulls from end of array
1242 urls = Arrays.copyOf(urls, i);
1243 }
1244 return urls;
1245 }
1246
1247 /*
1248 * Return a URL for the given path resolved against the base URL, or
1249 * null if the resulting URL is invalid.
1250 */
1251 static URL safeResolve(URL base, String path) {
1252 String child = path.replace(File.separatorChar, '/');
1253 try {
1254 if (!URI.create(child).isAbsolute()) {
1255 URL url = new URL(base, child);
1256 if (base.getProtocol().equalsIgnoreCase("file")) {
1257 return url;
1258 } else {
1259 String bp = base.getPath();
1260 String urlp = url.getPath();
1261 int pos = bp.lastIndexOf('/');
1262 if (pos == -1) {
1263 pos = bp.length() - 1;
1264 }
1265 if (urlp.regionMatches(0, bp, 0, pos + 1)
1266 && urlp.indexOf("..", pos) == -1) {
1267 return url;
1268 }
1269 }
1270 }
1271 } catch (MalformedURLException | IllegalArgumentException e) {}
1272 if (DEBUG_CP_URL_CHECK) {
1273 System.err.println("Class-Path entry: \"" + path + "\" ignored in JAR file " + base);
1274 }
1275 return null;
1276 }
1277 }
1278
1279 /*
1280 * Inner class used to represent a loader of classes and resources
1281 * from a file URL that refers to a directory.
1282 */
1283 private static class FileLoader extends Loader {
1284 /* Canonicalized File */
1285 private File dir;
1286
1287 FileLoader(URL url) throws IOException {
1288 super(url);
1289 if (!"file".equals(url.getProtocol())) {
1290 throw new IllegalArgumentException("url");
1291 }
1292 String path = url.getFile().replace('/', File.separatorChar);
1293 path = ParseUtil.decode(path);
1294 dir = (new File(path)).getCanonicalFile();
1295 }
|
1 /*
2 * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
1212
1213 /*
1214 * parse the standard extension dependencies
1215 */
1216 private void parseExtensionsDependencies() throws IOException {
1217 ExtensionDependency.checkExtensionsDependencies(jar);
1218 }
1219
1220 /*
1221 * Parses value of the Class-Path manifest attribute and returns
1222 * an array of URLs relative to the specified base URL.
1223 */
1224 private URL[] parseClassPath(URL base, String value)
1225 throws MalformedURLException
1226 {
1227 StringTokenizer st = new StringTokenizer(value);
1228 URL[] urls = new URL[st.countTokens()];
1229 int i = 0;
1230 while (st.hasMoreTokens()) {
1231 String path = st.nextToken();
1232 URL url = DISABLE_CP_URL_CHECK ? new URL(base, path) : tryResolve(base, path);
1233 if (url != null) {
1234 urls[i] = url;
1235 i++;
1236 } else {
1237 if (DEBUG_CP_URL_CHECK) {
1238 System.err.println("Class-Path entry: \"" + path
1239 + "\" ignored in JAR file " + base);
1240 }
1241 }
1242 }
1243 if (i == 0) {
1244 urls = null;
1245 } else if (i != urls.length) {
1246 // Truncate nulls from end of array
1247 urls = Arrays.copyOf(urls, i);
1248 }
1249 return urls;
1250 }
1251
1252 static URL tryResolve(URL base, String input) throws MalformedURLException {
1253 if ("file".equalsIgnoreCase(base.getProtocol())) {
1254 return tryResolveFile(base, input);
1255 } else {
1256 return tryResolveNonFile(base, input);
1257 }
1258 }
1259
1260 /**
1261 * Attempt to return a file URL by resolving input against a base file
1262 * URL. The input is an absolute or relative file URL that encodes a
1263 * file path.
1264 *
1265 * @apiNote Nonsensical input such as a Windows file path with a drive
1266 * letter cannot be disambiguated from an absolute URL so will be rejected
1267 * (by returning null) by this method.
1268 *
1269 * @return the resolved URL or null if the input is an absolute URL with
1270 * a scheme other than file (ignoring case)
1271 * @throws MalformedURLException
1272 */
1273 static URL tryResolveFile(URL base, String input) throws MalformedURLException {
1274 int index = input.indexOf(':');
1275 boolean isFile;
1276 if (index >= 0) {
1277 String scheme = input.substring(0, index);
1278 isFile = "file".equalsIgnoreCase(scheme);
1279 } else {
1280 isFile = true;
1281 }
1282 return (isFile) ? new URL(base, input) : null;
1283 }
1284
1285 /**
1286 * Attempt to return a URL by resolving input against a base URL. Returns
1287 * null if the resolved URL is not contained by the base URL.
1288 *
1289 * @return the resolved URL or null
1290 * @throws MalformedURLException
1291 */
1292 static URL tryResolveNonFile(URL base, String input) throws MalformedURLException {
1293 String child = input.replace(File.separatorChar, '/');
1294 if (isRelative(child)) {
1295 URL url = new URL(base, child);
1296 String bp = base.getPath();
1297 String urlp = url.getPath();
1298 int pos = bp.lastIndexOf('/');
1299 if (pos == -1) {
1300 pos = bp.length() - 1;
1301 }
1302 if (urlp.regionMatches(0, bp, 0, pos + 1)
1303 && urlp.indexOf("..", pos) == -1) {
1304 return url;
1305 }
1306 }
1307 return null;
1308 }
1309
1310 /**
1311 * Returns true if the given input is a relative URI.
1312 */
1313 static boolean isRelative(String child) {
1314 try {
1315 return !URI.create(child).isAbsolute();
1316 } catch (IllegalArgumentException e) {
1317 return false;
1318 }
1319 }
1320 }
1321
1322 /*
1323 * Inner class used to represent a loader of classes and resources
1324 * from a file URL that refers to a directory.
1325 */
1326 private static class FileLoader extends Loader {
1327 /* Canonicalized File */
1328 private File dir;
1329
1330 FileLoader(URL url) throws IOException {
1331 super(url);
1332 if (!"file".equals(url.getProtocol())) {
1333 throw new IllegalArgumentException("url");
1334 }
1335 String path = url.getFile().replace('/', File.separatorChar);
1336 path = ParseUtil.decode(path);
1337 dir = (new File(path)).getCanonicalFile();
1338 }
|