blob: 59214703776523c3e95376087bd96b5620608aa7 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5
6/*
7 * Copyright 1999-2004 The Apache Software Foundation.
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 */
22package com.sun.org.apache.xml.internal.security.utils.resolver.implementations;
23
24import java.io.ByteArrayOutputStream;
25import java.io.IOException;
26import java.io.InputStream;
27import java.net.MalformedURLException;
28import java.net.URL;
29import java.net.URLConnection;
30
31import com.sun.org.apache.xml.internal.utils.URI;
32import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
33import com.sun.org.apache.xml.internal.security.utils.Base64;
34import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException;
35import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverSpi;
36import org.w3c.dom.Attr;
37
38
39/**
40 * A simple ResourceResolver for HTTP requests. This class handles only 'pure'
41 * HTTP URIs which means without a fragment. The Fragment handling is done by the
42 * {@link ResolverFragment} class.
43 * <BR>
44 * If the user has a corporate HTTP proxy which is to be used, the usage can be
45 * switched on by setting properties for the resolver:
46 * <PRE>
47 * resourceResolver.setProperty("http.proxy.host", "proxy.company.com");
48 * resourceResolver.setProperty("http.proxy.port", "8080");
49 *
50 * // if we need a password for the proxy
51 * resourceResolver.setProperty("http.proxy.username", "proxyuser3");
52 * resourceResolver.setProperty("http.proxy.password", "secretca");
53 * </PRE>
54 *
55 *
56 * @author $Author: mullan $
57 * @see <A HREF="http://www.javaworld.com/javaworld/javatips/jw-javatip42_p.html">Java Tip 42: Write Java apps that work with proxy-based firewalls</A>
58 * @see <A HREF="http://java.sun.com/j2se/1.4/docs/guide/net/properties.html">SUN J2SE docs for network properties</A>
59 * @see <A HREF="http://metalab.unc.edu/javafaq/javafaq.html#proxy">The JAVA FAQ Question 9.5: How do I make Java work with a proxy server?</A>
60 * $todo$ the proxy behaviour seems not to work; if a on-existing proxy is set, it works ?!?
61 */
62public class ResolverDirectHTTP extends ResourceResolverSpi {
63
64 /** {@link java.util.logging} logging facility */
65 static java.util.logging.Logger log =
66 java.util.logging.Logger.getLogger(
67 ResolverDirectHTTP.class.getName());
68
69 /** Field properties[] */
70 static final String properties[] = { "http.proxy.host", "http.proxy.port",
71 "http.proxy.username",
72 "http.proxy.password",
73 "http.basic.username",
74 "http.basic.password" };
75
76 /** Field HttpProxyHost */
77 private static final int HttpProxyHost = 0;
78
79 /** Field HttpProxyPort */
80 private static final int HttpProxyPort = 1;
81
82 /** Field HttpProxyUser */
83 private static final int HttpProxyUser = 2;
84
85 /** Field HttpProxyPass */
86 private static final int HttpProxyPass = 3;
87
88 /** Field HttpProxyUser */
89 private static final int HttpBasicUser = 4;
90
91 /** Field HttpProxyPass */
92 private static final int HttpBasicPass = 5;
93
94 /**
95 * Method resolve
96 *
97 * @param uri
98 * @param BaseURI
99 *
100 * @throws ResourceResolverException
101 * @return
102 * $todo$ calculate the correct URI from the attribute and the BaseURI
103 */
104 public XMLSignatureInput engineResolve(Attr uri, String BaseURI)
105 throws ResourceResolverException {
106
107 try {
108 boolean useProxy = false;
109 String proxyHost =
110 engineGetProperty(ResolverDirectHTTP
111 .properties[ResolverDirectHTTP.HttpProxyHost]);
112 String proxyPort =
113 engineGetProperty(ResolverDirectHTTP
114 .properties[ResolverDirectHTTP.HttpProxyPort]);
115
116 if ((proxyHost != null) && (proxyPort != null)) {
117 useProxy = true;
118 }
119
120 // switch on proxy usage
121 String oldProxySet = null;
122 String oldProxyHost = null;
123 String oldProxyPort = null;
124 if (useProxy) {
125 if (log.isLoggable(java.util.logging.Level.FINE)) {
126 log.log(java.util.logging.Level.FINE,
127 "Use of HTTP proxy enabled: " + proxyHost + ":"
128 + proxyPort);
129 }
130 oldProxySet = System.getProperty("http.proxySet");
131 oldProxyHost = System.getProperty("http.proxyHost");
132 oldProxyPort = System.getProperty("http.proxyPort");
133 System.setProperty("http.proxySet", "true");
134 System.setProperty("http.proxyHost", proxyHost);
135 System.setProperty("http.proxyPort", proxyPort);
136 }
137
138 boolean switchBackProxy = ((oldProxySet != null)
139 && (oldProxyHost != null)
140 && (oldProxyPort != null));
141
142 // calculate new URI
143 URI uriNew = getNewURI(uri.getNodeValue(), BaseURI);
144
145 // if the URI contains a fragment, ignore it
146 URI uriNewNoFrag = new URI(uriNew);
147
148 uriNewNoFrag.setFragment(null);
149
150 URL url = new URL(uriNewNoFrag.toString());
151 URLConnection urlConnection = url.openConnection();
152
153 {
154
155 // set proxy pass
156 String proxyUser =
157 engineGetProperty(ResolverDirectHTTP
158 .properties[ResolverDirectHTTP.HttpProxyUser]);
159 String proxyPass =
160 engineGetProperty(ResolverDirectHTTP
161 .properties[ResolverDirectHTTP.HttpProxyPass]);
162
163 if ((proxyUser != null) && (proxyPass != null)) {
164 String password = proxyUser + ":" + proxyPass;
165 String encodedPassword = Base64.encode(password.getBytes());
166
167 // or was it Proxy-Authenticate ?
168 urlConnection.setRequestProperty("Proxy-Authorization",
169 encodedPassword);
170 }
171 }
172
173 {
174
175 // check if Basic authentication is required
176 String auth = urlConnection.getHeaderField("WWW-Authenticate");
177
178 if (auth != null) {
179
180 // do http basic authentication
181 if (auth.startsWith("Basic")) {
182 String user =
183 engineGetProperty(ResolverDirectHTTP
184 .properties[ResolverDirectHTTP.HttpBasicUser]);
185 String pass =
186 engineGetProperty(ResolverDirectHTTP
187 .properties[ResolverDirectHTTP.HttpBasicPass]);
188
189 if ((user != null) && (pass != null)) {
190 urlConnection = url.openConnection();
191
192 String password = user + ":" + pass;
193 String encodedPassword =
194 Base64.encode(password.getBytes());
195
196 // set authentication property in the http header
197 urlConnection.setRequestProperty("Authorization",
198 "Basic "
199 + encodedPassword);
200 }
201 }
202 }
203 }
204
205 String mimeType = urlConnection.getHeaderField("Content-Type");
206 InputStream inputStream = urlConnection.getInputStream();
207 ByteArrayOutputStream baos = new ByteArrayOutputStream();
208 byte buf[] = new byte[4096];
209 int read = 0;
210 int summarized = 0;
211
212 while ((read = inputStream.read(buf)) >= 0) {
213 baos.write(buf, 0, read);
214
215 summarized += read;
216 }
217
218 if (log.isLoggable(java.util.logging.Level.FINE)) {
219 log.log(java.util.logging.Level.FINE,
220 "Fetched " + summarized + " bytes from URI "
221 + uriNew.toString());
222 }
223
224 XMLSignatureInput result = new XMLSignatureInput(baos.toByteArray());
225
226 // XMLSignatureInput result = new XMLSignatureInput(inputStream);
227 result.setSourceURI(uriNew.toString());
228 result.setMIMEType(mimeType);
229
230 // switch off proxy usage
231 if (useProxy && switchBackProxy) {
232 System.setProperty("http.proxySet", oldProxySet);
233 System.setProperty("http.proxyHost", oldProxyHost);
234 System.setProperty("http.proxyPort", oldProxyPort);
235 }
236
237 return result;
238 } catch (MalformedURLException ex) {
239 throw new ResourceResolverException("generic.EmptyMessage", ex, uri,
240 BaseURI);
241 } catch (IOException ex) {
242 throw new ResourceResolverException("generic.EmptyMessage", ex, uri,
243 BaseURI);
244 }
245 }
246
247 /**
248 * We resolve http URIs <I>without</I> fragment...
249 *
250 * @param uri
251 * @param BaseURI
252 * @return true if can be resolved
253 */
254 public boolean engineCanResolve(Attr uri, String BaseURI) {
255 if (uri == null) {
256 if (log.isLoggable(java.util.logging.Level.FINE)) {
257 log.log(java.util.logging.Level.FINE, "quick fail, uri == null");
258 }
259 return false;
260 }
261
262 String uriNodeValue = uri.getNodeValue();
263
264 if (uriNodeValue.equals("") || (uriNodeValue.charAt(0)=='#')) {
265 if (log.isLoggable(java.util.logging.Level.FINE)) {
266 log.log(java.util.logging.Level.FINE,
267 "quick fail for empty URIs and local ones");
268 }
269 return false;
270 }
271
272 if (log.isLoggable(java.util.logging.Level.FINE)) {
273 log.log(java.util.logging.Level.FINE,
274 "I was asked whether I can resolve " + uriNodeValue);
275 }
276 if ( uriNodeValue.startsWith("http:") ||
277 BaseURI.startsWith("http:")) {
278 if (log.isLoggable(java.util.logging.Level.FINE)) {
279 log.log(java.util.logging.Level.FINE,
280 "I state that I can resolve " + uriNodeValue);
281 }
282 return true;
283 }
284
285 if (log.isLoggable(java.util.logging.Level.FINE)) {
286 log.log(java.util.logging.Level.FINE,
287 "I state that I can't resolve " + uriNodeValue);
288 }
289 return false;
290 }
291
292 /**
293 * @inheritDoc
294 */
295 public String[] engineGetPropertyKeys() {
296 return (String[]) ResolverDirectHTTP.properties.clone();
297 }
298
299 private URI getNewURI(String uri, String BaseURI)
300 throws URI.MalformedURIException {
301
302 if ((BaseURI == null) || "".equals(BaseURI)) {
303 return new URI(uri);
304 }
305 return new URI(new URI(BaseURI), uri);
306 }
307}