1 /*
2  * reserved comment block
3  * DO NOT REMOVE OR ALTER!
4  */
5 /**
6  * Licensed to the Apache Software Foundation (ASF) under one
7  * or more contributor license agreements. See the NOTICE file
8  * distributed with this work for additional information
9  * regarding copyright ownership. The ASF licenses this file
10  * to you under the Apache License, Version 2.0 (the
11  * "License"); you may not use this file except in compliance
12  * with the License. You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing,
17  * software distributed under the License is distributed on an
18  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19  * KIND, either express or implied. See the License for the
20  * specific language governing permissions and limitations
21  * under the License.
22  */
23 package com.sun.org.apache.xml.internal.security.utils.resolver.implementations;
24 
25 import java.io.InputStream;
26 import java.net.URI;
27 import java.net.URISyntaxException;
28 import java.nio.file.Files;
29 import java.nio.file.Paths;
30 
31 import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
32 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverContext;
33 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException;
34 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverSpi;
35 
36 /**
37  * A simple ResourceResolver for requests into the local filesystem.
38  */
39 public class ResolverLocalFilesystem extends ResourceResolverSpi {
40 
41     private static final int FILE_URI_LENGTH = "file:/".length();
42 
43     private static final com.sun.org.slf4j.internal.Logger LOG =
44         com.sun.org.slf4j.internal.LoggerFactory.getLogger(ResolverLocalFilesystem.class);
45 
46     @Override
engineIsThreadSafe()47     public boolean engineIsThreadSafe() {
48         return true;
49     }
50 
51     /**
52      * {@inheritDoc}
53      */
54     @Override
engineResolveURI(ResourceResolverContext context)55     public XMLSignatureInput engineResolveURI(ResourceResolverContext context)
56         throws ResourceResolverException {
57         try {
58             // calculate new URI
59             URI uriNew = getNewURI(context.uriToResolve, context.baseUri);
60 
61             String fileName =
62                 ResolverLocalFilesystem.translateUriToFilename(uriNew.toString());
63             InputStream inputStream = Files.newInputStream(Paths.get(fileName));
64             XMLSignatureInput result = new XMLSignatureInput(inputStream);
65             result.setSecureValidation(context.secureValidation);
66 
67             result.setSourceURI(uriNew.toString());
68 
69             return result;
70         } catch (Exception e) {
71             throw new ResourceResolverException(e, context.uriToResolve, context.baseUri, "generic.EmptyMessage");
72         }
73     }
74 
75     /**
76      * Method translateUriToFilename
77      *
78      * @param uri
79      * @return the string of the filename
80      */
translateUriToFilename(String uri)81     private static String translateUriToFilename(String uri) {
82 
83         String subStr = uri.substring(FILE_URI_LENGTH);
84 
85         if (subStr.indexOf("%20") > -1) {
86             int offset = 0;
87             int index = 0;
88             StringBuilder temp = new StringBuilder(subStr.length());
89             do {
90                 index = subStr.indexOf("%20",offset);
91                 if (index == -1) {
92                     temp.append(subStr.substring(offset));
93                 } else {
94                     temp.append(subStr.substring(offset, index));
95                     temp.append(' ');
96                     offset = index + 3;
97                 }
98             } while(index != -1);
99             subStr = temp.toString();
100         }
101 
102         if (subStr.charAt(1) == ':') {
103             // we're running M$ Windows, so this works fine
104             return subStr;
105         }
106         // we're running some UNIX, so we have to prepend a slash
107         return "/" + subStr;
108     }
109 
110     /**
111      * {@inheritDoc}
112      */
engineCanResolveURI(ResourceResolverContext context)113     public boolean engineCanResolveURI(ResourceResolverContext context) {
114         if (context.uriToResolve == null) {
115             return false;
116         }
117 
118         if (context.uriToResolve.equals("") || context.uriToResolve.charAt(0) == '#' ||
119             context.uriToResolve.startsWith("http:")) {
120             return false;
121         }
122 
123         try {
124             LOG.debug("I was asked whether I can resolve {}", context.uriToResolve);
125 
126             if (context.uriToResolve.startsWith("file:") || context.baseUri.startsWith("file:")) {
127                 LOG.debug("I state that I can resolve {}", context.uriToResolve);
128                 return true;
129             }
130         } catch (Exception e) {
131             LOG.debug(e.getMessage(), e);
132         }
133 
134         LOG.debug("But I can't");
135 
136         return false;
137     }
138 
getNewURI(String uri, String baseURI)139     private static URI getNewURI(String uri, String baseURI) throws URISyntaxException {
140         URI newUri = null;
141         if (baseURI == null || "".equals(baseURI)) {
142             newUri = new URI(uri);
143         } else {
144             newUri = new URI(baseURI).resolve(uri);
145         }
146 
147         // if the URI contains a fragment, ignore it
148         if (newUri.getFragment() != null) {
149             URI uriNewNoFrag =
150                 new URI(newUri.getScheme(), newUri.getSchemeSpecificPart(), null);
151             return uriNewNoFrag;
152         }
153         return newUri;
154     }
155 }
156