Skip to content

Commit cded940

Browse files
committed
Use the Security Manager only if available.
Closes #2
1 parent 217dd86 commit cded940

File tree

2 files changed

+127
-32
lines changed

2 files changed

+127
-32
lines changed

src/io/sf/carte/doc/xml/dtd/DefaultEntityResolver.java

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
import java.io.InputStream;
1616
import java.io.InputStreamReader;
1717
import java.io.Reader;
18+
import java.lang.reflect.Constructor;
1819
import java.net.HttpURLConnection;
1920
import java.net.URL;
2021
import java.net.URLConnection;
2122
import java.nio.charset.StandardCharsets;
22-
import java.security.PrivilegedActionException;
2323
import java.util.HashMap;
2424
import java.util.HashSet;
2525
import java.util.Iterator;
@@ -77,6 +77,8 @@ public class DefaultEntityResolver implements EntityResolver2 {
7777

7878
private final HashMap<String, String> systemIdToPublicId = new HashMap<String, String>(13);
7979

80+
private static final DTDLoader dtdLoader = createDTDLoader();
81+
8082
private ClassLoader loader = null;
8183

8284
private HashSet<String> whitelist = null;
@@ -331,7 +333,7 @@ public final InputSource resolveEntity(String name, String publicId, String base
331333
String fname = systemIdToFilename.get(systemId);
332334
InputSource isrc = null;
333335
if (fname != null) {
334-
Reader re = loadDTDfromClasspath(fname);
336+
Reader re = dtdLoader.loadDTDfromClasspath(loader, fname);
335337
if (re != null) {
336338
isrc = new InputSource(re);
337339
isrc.setPublicId(publicId);
@@ -480,17 +482,7 @@ protected URLConnection openConnection(URL url) throws IOException {
480482
*/
481483
protected void connect(final URLConnection con) throws IOException {
482484
con.setConnectTimeout(60000);
483-
try {
484-
java.security.AccessController.doPrivileged(new java.security.PrivilegedExceptionAction<Void>() {
485-
@Override
486-
public Void run() throws IOException {
487-
con.connect();
488-
return null;
489-
}
490-
});
491-
} catch (PrivilegedActionException e) {
492-
throw (IOException) e.getException();
493-
}
485+
dtdLoader.connect(con);
494486
}
495487

496488
/**
@@ -519,26 +511,52 @@ public void setClassLoader(ClassLoader loader) {
519511
this.loader = loader;
520512
}
521513

522-
private Reader loadDTDfromClasspath(final String dtdFilename) {
523-
InputStream is = java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<InputStream>() {
524-
@Override
525-
public InputStream run() {
526-
InputStream is;
527-
if (loader != null) {
528-
is = loader.getResourceAsStream(dtdFilename);
529-
} else {
530-
is = DefaultEntityResolver.class.getResourceAsStream(dtdFilename);
531-
}
532-
if (is == null) {
533-
is = ClassLoader.getSystemResourceAsStream(dtdFilename);
534-
}
535-
return is;
514+
private static DTDLoader createDTDLoader() {
515+
DTDLoader loader;
516+
try {
517+
Class<?> cl = Class.forName("io.sf.carte.doc.xml.dtd.SMDTDLoader");
518+
Constructor<?> ctor = cl.getConstructor();
519+
loader = (DTDLoader) ctor.newInstance();
520+
} catch (Exception e) {
521+
loader = new SimpleDTDLoader();
522+
}
523+
return loader;
524+
}
525+
526+
abstract static class DTDLoader {
527+
abstract void connect(URLConnection con) throws IOException;
528+
abstract Reader loadDTDfromClasspath(ClassLoader loader, String dtdFilename);
529+
}
530+
531+
/**
532+
* Load DTDs without a Security Manager.
533+
*/
534+
private static class SimpleDTDLoader extends DTDLoader {
535+
536+
@Override
537+
void connect(final URLConnection con) throws IOException {
538+
con.connect();
539+
}
540+
541+
@Override
542+
Reader loadDTDfromClasspath(final ClassLoader loader, final String dtdFilename) {
543+
InputStream is;
544+
if (loader != null) {
545+
is = loader.getResourceAsStream(dtdFilename);
546+
} else {
547+
is = DefaultEntityResolver.class.getResourceAsStream(dtdFilename);
548+
}
549+
if (is == null) {
550+
is = ClassLoader.getSystemResourceAsStream(dtdFilename);
551+
}
552+
553+
Reader re = null;
554+
if (is != null) {
555+
re = new InputStreamReader(is, StandardCharsets.UTF_8);
536556
}
537-
});
538-
Reader re = null;
539-
if (is != null) {
540-
re = new InputStreamReader(is, StandardCharsets.UTF_8);
557+
return re;
541558
}
542-
return re;
559+
543560
}
561+
544562
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
3+
Copyright (c) 1998-2021, Carlos Amengual.
4+
5+
SPDX-License-Identifier: BSD-3-Clause
6+
7+
Licensed under a BSD-style License. You can find the license here:
8+
https://css4j.github.io/LICENSE.txt
9+
10+
*/
11+
12+
package io.sf.carte.doc.xml.dtd;
13+
14+
import java.io.IOException;
15+
import java.io.InputStream;
16+
import java.io.InputStreamReader;
17+
import java.io.Reader;
18+
import java.net.URLConnection;
19+
import java.nio.charset.StandardCharsets;
20+
import java.security.PrivilegedActionException;
21+
22+
import io.sf.carte.doc.xml.dtd.DefaultEntityResolver.DTDLoader;
23+
24+
/**
25+
* Load DTDs using the privileges granted by a {@code SecurityManager}.
26+
* <p>
27+
* This class uses deprecated methods.
28+
* </p>
29+
*/
30+
class SMDTDLoader extends DTDLoader {
31+
32+
public SMDTDLoader() {
33+
super();
34+
}
35+
36+
@SuppressWarnings({ "deprecation", "removal" })
37+
@Override
38+
void connect(final URLConnection con) throws IOException {
39+
try {
40+
java.security.AccessController.doPrivileged(new java.security.PrivilegedExceptionAction<Void>() {
41+
@Override
42+
public Void run() throws IOException {
43+
con.connect();
44+
return null;
45+
}
46+
});
47+
} catch (PrivilegedActionException e) {
48+
throw (IOException) e.getException();
49+
}
50+
}
51+
52+
@Override
53+
Reader loadDTDfromClasspath(final ClassLoader loader, final String dtdFilename) {
54+
@SuppressWarnings({ "deprecation", "removal" })
55+
InputStream is = java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<InputStream>() {
56+
@Override
57+
public InputStream run() {
58+
InputStream is;
59+
if (loader != null) {
60+
is = loader.getResourceAsStream(dtdFilename);
61+
} else {
62+
is = DefaultEntityResolver.class.getResourceAsStream(dtdFilename);
63+
}
64+
if (is == null) {
65+
is = ClassLoader.getSystemResourceAsStream(dtdFilename);
66+
}
67+
return is;
68+
}
69+
});
70+
Reader re = null;
71+
if (is != null) {
72+
re = new InputStreamReader(is, StandardCharsets.UTF_8);
73+
}
74+
return re;
75+
}
76+
77+
}

0 commit comments

Comments
 (0)