source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/URLFilter.java@ 30482

Last change on this file since 30482 was 30482, checked in by davidb, 8 years ago

Changes to help with compiling and running this for Android

  • Property svn:executable set to *
File size: 14.9 KB
Line 
1package org.greenstone.gsdl3.core;
2
3import java.io.File;
4import java.io.IOException;
5import java.util.ArrayList;
6import java.util.HashMap;
7import java.util.Map;
8
9import javax.servlet.Filter;
10import javax.servlet.FilterChain;
11import javax.servlet.FilterConfig;
12import javax.servlet.ServletContext;
13import javax.servlet.ServletException;
14import javax.servlet.ServletOutputStream;
15import javax.servlet.ServletRequest;
16import javax.servlet.ServletResponse;
17import javax.servlet.http.HttpSession;
18import javax.servlet.http.HttpServletRequest;
19import javax.servlet.http.HttpServletRequestWrapper;
20
21import org.apache.commons.io.FileUtils;
22import org.apache.log4j.Logger;
23import org.greenstone.gsdl3.util.GSParams;
24import org.greenstone.gsdl3.util.GSXML;
25import org.greenstone.gsdl3.util.UserContext;
26import org.greenstone.gsdl3.util.XMLConverter;
27import org.w3c.dom.Document;
28import org.w3c.dom.Element;
29import org.w3c.dom.NodeList;
30
31public class URLFilter implements Filter
32{
33 private FilterConfig _filterConfig = null;
34 private static Logger _logger = Logger.getLogger(org.greenstone.gsdl3.core.URLFilter.class.getName());
35
36 //Restricted URLs
37 protected static final String SITECONFIG_URL = "sites/[^/]+/siteConfig.xml";
38 protected static final String USERS_DB_URL = "etc/usersDB/.*";
39 protected static final ArrayList<String> _restrictedURLs;
40 static
41 {
42 ArrayList<String> restrictedURLs = new ArrayList<String>();
43 restrictedURLs.add(SITECONFIG_URL);
44 restrictedURLs.add(USERS_DB_URL);
45 _restrictedURLs = restrictedURLs;
46 }
47
48 //Constants
49 protected static final String DOCUMENT_PATH = "document";
50 protected static final String COLLECTION_PATH = "collection";
51 protected static final String PAGE_PATH = "page";
52 protected static final String SYSTEM_PATH = "system";
53
54 protected static final String METADATA_RETRIEVAL_SERVICE = "DocumentMetadataRetrieve";
55 protected static final String ASSOCIATED_FILE_PATH = "/index/assoc/";
56 protected static final String COLLECTION_FILE_PATH = "/collect/";
57 protected static final String INTERFACE_PATH = "/interfaces/";
58
59 protected static final String SYSTEM_SUBACTION_CONFIGURE = "configure";
60 protected static final String SYSTEM_SUBACTION_RECONFIGURE = "reconfigure";
61 protected static final String SYSTEM_SUBACTION_ACTIVATE = "activate";
62 protected static final String SYSTEM_SUBACTION_DEACTIVATE = "deactivate";
63
64 public void init(FilterConfig filterConfig) throws ServletException
65 {
66 this._filterConfig = filterConfig;
67 }
68
69 public void destroy()
70 {
71 this._filterConfig = null;
72 }
73
74 @SuppressWarnings("deprecation")
75 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
76 {
77 if (request instanceof HttpServletRequest)
78 {
79 HttpServletRequest hRequest = ((HttpServletRequest) request);
80 HttpSession hSession = hRequest.getSession();
81 ServletContext context = hSession.getServletContext();
82
83 GSHttpServletRequestWrapper gRequest = new GSHttpServletRequestWrapper(hRequest);
84
85 String url = hRequest.getRequestURI().toString();
86
87 if (isURLRestricted(url))
88 {
89 response.getWriter().println("Access to this page is forbidden.");
90 return;
91 }
92
93 //If the user is trying to access a collection file we need to run a security check
94 if (url.contains(ASSOCIATED_FILE_PATH))
95 {
96 String dir = null;
97 int dirStart = url.indexOf(ASSOCIATED_FILE_PATH) + ASSOCIATED_FILE_PATH.length();
98 int dirEnd = -1;
99 if (dirStart < url.length() && url.indexOf("/", dirStart) != -1)
100 {
101 dirEnd = url.indexOf("/", dirStart);
102 }
103 if (dirEnd != -1)
104 {
105 dir = url.substring(dirStart, dirEnd);
106 }
107 if (dir == null)
108 {
109 return;
110 }
111
112 String collection = null;
113 int colStart = url.indexOf(COLLECTION_FILE_PATH) + COLLECTION_FILE_PATH.length();
114 int colEnd = -1;
115 if (colStart < url.length() && url.indexOf("/", colStart) != -1)
116 {
117 colEnd = url.indexOf("/", colStart);
118 }
119 if (colEnd != -1)
120 {
121 collection = url.substring(colStart, colEnd);
122 }
123 if (collection == null)
124 {
125 return;
126 }
127
128 //MessageRouter gsRouter = (MessageRouter) request.getServletContext().getAttribute("GSRouter");
129 // The above line didn't work in i-jetty (failed to find class)
130 // (See node below about ServletContext for more details)
131 // // Changed to the following (but hasn't been exhaustively tested)
132 MessageRouter gsRouter = (MessageRouter) context.getAttribute("GSRouter");
133
134 if (gsRouter == null)
135 {
136 _logger.error("Receptionist is null, stopping filter");
137 return;
138 }
139
140 Document gsDoc = XMLConverter.newDOM();
141
142 Element metaMessage = gsDoc.createElement(GSXML.MESSAGE_ELEM);
143 Element metaRequest = GSXML.createBasicRequest(gsDoc, GSXML.REQUEST_TYPE_PROCESS, collection + "/" + METADATA_RETRIEVAL_SERVICE, new UserContext());
144 metaMessage.appendChild(metaRequest);
145
146 Element paramList = gsDoc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
147 metaRequest.appendChild(paramList);
148
149 Element param = gsDoc.createElement(GSXML.PARAM_ELEM);
150 paramList.appendChild(param);
151
152 param.setAttribute(GSXML.NAME_ATT, "metadata");
153 param.setAttribute(GSXML.VALUE_ATT, "contains");
154
155 Element docList = gsDoc.createElement(GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER);
156 metaRequest.appendChild(docList);
157
158 Element doc = gsDoc.createElement(GSXML.DOC_NODE_ELEM);
159 docList.appendChild(doc);
160
161 doc.setAttribute(GSXML.NODE_ID_ATT, dir);
162
163 Element metaResponse = (Element) gsRouter.process(metaMessage);
164
165 NodeList metadataList = metaResponse.getElementsByTagName(GSXML.METADATA_ELEM);
166 if (metadataList.getLength() == 0)
167 {
168 _logger.error("Could not find the document related to this url");
169 }
170 else
171 {
172 Element metadata = (Element) metadataList.item(0);
173 String document = metadata.getTextContent();
174
175 //Get the security info for this collection
176 Element securityMessage = gsDoc.createElement(GSXML.MESSAGE_ELEM);
177 Element securityRequest = GSXML.createBasicRequest(gsDoc, GSXML.REQUEST_TYPE_SECURITY, collection, new UserContext());
178 securityMessage.appendChild(securityRequest);
179 if (document != null && !document.equals(""))
180 {
181 securityRequest.setAttribute(GSXML.NODE_OID, document);
182 }
183
184 Element securityResponse = (Element) GSXML.getChildByTagName(gsRouter.process(securityMessage), GSXML.RESPONSE_ELEM);
185 ArrayList<String> groups = GSXML.getGroupsFromSecurityResponse(securityResponse);
186
187 if (!groups.contains(""))
188 {
189 boolean found = false;
190 for (String group : groups)
191 {
192 if (((HttpServletRequest) request).isUserInRole(group))
193 {
194 found = true;
195 break;
196 }
197 }
198
199 if (!found)
200 {
201 return;
202 }
203 }
204 }
205 }
206 else if (url.contains(INTERFACE_PATH))
207 {
208 ////String fileURL = url.replaceFirst(request.getServletContext().getContextPath(), "");
209 //
210 // The above line was changed to the line below to work on i-jetty. The above caused
211 // an exception to be thrown trying to load in the class at init time:
212 // javax.servlet.http.ServletContext
213 //
214 // And then later in the life-time the servlet, the above line fails when run
215 // The following (older) way to do this was found to work as a replacment
216
217 String fileURL = url.replaceFirst(context.getContextPath(), "");
218
219 // A different theory is that the problem could be to do with version of Servlet
220 // Container implemented by the web-server:
221 // http://stackoverflow.com/questions/7860782/request-getservletcontext-not-found-even-with-new-jar
222
223 // Similar change in the following needed also ...
224
225 // Replacement line known to be deprecated, but very useful for us to use in this situation
226 //
227 // If this method is every offically removed, and the newer getServletContext()
228 // still can't be relied upon to work in all web servers Greenstone uses,
229 // then an alternative approach would be to get the core information (servlet context name,
230 // and where it is on the file system) from the gsdl properties file
231
232 ////File requestedFile = new File(request.getServletContext().getRealPath(fileURL));
233 File requestedFile = new File(context.getRealPath(fileURL));
234 if (!requestedFile.exists())
235 {
236 int interfaceNameStart = fileURL.indexOf(INTERFACE_PATH) + INTERFACE_PATH.length();
237 int interfaceNameEnd = fileURL.indexOf("/", interfaceNameStart);
238 String interfaceName = fileURL.substring(interfaceNameStart, interfaceNameEnd);
239 String interfacesDir = fileURL.substring(0, interfaceNameStart);
240 File interfaceConfigFile = new File(context.getRealPath(interfacesDir + interfaceName + "/interfaceConfig.xml"));
241
242 if (interfaceConfigFile.exists())
243 {
244 Document interfaceConfigDoc = XMLConverter.getDOM(interfaceConfigFile);
245
246 String baseInterface = interfaceConfigDoc.getDocumentElement().getAttribute("baseInterface");
247 if (baseInterface.length() > 0)
248 {
249 File baseInterfaceFile = new File(context.getRealPath(fileURL.replace("/" + interfaceName + "/", "/" + baseInterface + "/")));
250 if (baseInterfaceFile.exists())
251 {
252 ServletOutputStream out = response.getOutputStream();
253 out.write(FileUtils.readFileToByteArray(baseInterfaceFile));
254 out.flush();
255 out.close();
256 return;
257 }
258 }
259 }
260 }
261 }
262 else
263 {
264 //If we have a jsessionid on the end of our URL we want to ignore it
265 int index;
266 if ((index = url.indexOf(";jsessionid")) != -1)
267 {
268 url = url.substring(0, index);
269 }
270 String[] segments = url.split("/");
271 for (int i = 0; i < segments.length; i++)
272 {
273 String[] additionalParameters = null;
274 String[] defaultParamValues = null;
275
276 //COLLECTION
277 if (segments[i].equals(COLLECTION_PATH) && (i + 1) < segments.length)
278 {
279 gRequest.setParameter(GSParams.COLLECTION, segments[i + 1]);
280 }
281 //DOCUMENT
282 else if (segments[i].equals(DOCUMENT_PATH) && (i + 1) < segments.length)
283 {
284 gRequest.setParameter(GSParams.DOCUMENT, segments[i + 1]);
285
286 additionalParameters = new String[] { GSParams.ACTION };
287 defaultParamValues = new String[] { "d" };
288 }
289 //PAGE
290 else if (segments[i].equals(PAGE_PATH) && (i + 1) < segments.length)
291 {
292 gRequest.setParameter(GSParams.SUBACTION, segments[i + 1]);
293
294 additionalParameters = new String[] { GSParams.ACTION };
295 defaultParamValues = new String[] { "p" };
296 }
297 //SYSTEM
298 else if (segments[i].equals(SYSTEM_PATH) && (i + 1) < segments.length)
299 {
300 String sa = segments[i + 1];
301 if (sa.equals(SYSTEM_SUBACTION_CONFIGURE) || sa.equals(SYSTEM_SUBACTION_RECONFIGURE))
302 {
303 sa = "c";
304 }
305 else if (sa.equals(SYSTEM_SUBACTION_ACTIVATE))
306 {
307 sa = "a";
308 }
309 else if (sa.equals(SYSTEM_SUBACTION_DEACTIVATE))
310 {
311 sa = "d";
312 }
313
314 if (sa.equals("c") && (i + 2) < segments.length)
315 {
316 gRequest.setParameter(GSParams.SYSTEM_CLUSTER, segments[i + 2]);
317 }
318
319 if (sa.equals("a") && (i + 2) < segments.length)
320 {
321 gRequest.setParameter(GSParams.SYSTEM_MODULE_TYPE, "collection");
322 gRequest.setParameter(GSParams.SYSTEM_MODULE_NAME, segments[i + 2]);
323 }
324
325 if (sa.equals("d") && (i + 2) < segments.length)
326 {
327 gRequest.setParameter(GSParams.SYSTEM_CLUSTER, segments[i + 2]);
328 }
329
330 gRequest.setParameter(GSParams.SUBACTION, sa);
331
332 additionalParameters = new String[] { GSParams.ACTION };
333 defaultParamValues = new String[] { "s" };
334 }
335 //ADMIN
336 else if (segments[i].equals("admin") && (i + 1) < segments.length)
337 {
338 String pageName = segments[i + 1];
339
340 gRequest.setParameter("s1.authpage", pageName);
341
342 additionalParameters = new String[] { GSParams.ACTION, GSParams.REQUEST_TYPE, GSParams.SUBACTION, GSParams.SERVICE };
343 defaultParamValues = new String[] { "g", "r", "authen", "Authentication" };
344 }
345 //BROWSE
346 else if (segments[i].equals("browse") && (i + 1) < segments.length)
347 {
348 String cl = "";
349 for (int j = 1; (i + j) < segments.length; j++)
350 {
351 String currentSegment = segments[i + j].replace("CL", "").replace("cl", "");
352 if (currentSegment.contains("."))
353 {
354 String[] subsegments = currentSegment.split("\\.");
355 for (String subsegment : subsegments)
356 {
357 subsegment = subsegment.replace("CL", "").replace("cl", "");
358
359 if (cl.length() > 0)
360 {
361 cl += ".";
362 }
363
364 if (subsegment.length() > 0)
365 {
366 cl += subsegment;
367 }
368 }
369 continue;
370 }
371 if (!currentSegment.matches("^(CL|cl)?\\d+$"))
372 {
373 continue;
374 }
375
376 if (cl.length() > 0)
377 {
378 cl += ".";
379 }
380
381 cl += currentSegment;
382 }
383
384 gRequest.setParameter("cl", "CL" + cl);
385
386 additionalParameters = new String[] { GSParams.ACTION, GSParams.REQUEST_TYPE, GSParams.SERVICE };
387 defaultParamValues = new String[] { "b", "s", "ClassifierBrowse" };
388 }
389 //QUERY
390 else if (segments[i].equals("search"))
391 {
392 String serviceName = "";
393 if ((i + 1) < segments.length)
394 {
395 serviceName = segments[i + 1];
396 gRequest.setParameter("s", serviceName);
397
398 additionalParameters = new String[] { GSParams.ACTION, GSParams.SUBACTION, GSParams.REQUEST_TYPE };
399 defaultParamValues = new String[] { "q", "", "d" };
400 }
401 if ((i + 2) < segments.length)
402 {
403 if (serviceName.equals("TextQuery") || serviceName.equals("RawQuery"))
404 {
405
406 gRequest.setParameter("s1.query", segments[i + 2]);
407 }
408 else if (serviceName.equals("FieldQuery"))
409 {
410 gRequest.setParameter("s1.fqv", segments[i + 2]);
411 }
412 else if (serviceName.equals("AdvancedFieldQuery"))
413 {
414 gRequest.setParameter("s1.fqv", segments[i + 2]);
415 }
416 }
417 }
418 if (additionalParameters != null)
419 {
420 for (int j = 0; j < additionalParameters.length; j++)
421 {
422 if (gRequest.getParameter(additionalParameters[j]) == null)
423 {
424 gRequest.setParameter(additionalParameters[j], defaultParamValues[j]);
425 }
426 }
427 }
428 }
429 }
430
431 chain.doFilter(gRequest, response);
432 }
433 else
434 {
435 //Will this ever happen?
436 System.err.println("The request was not an HttpServletRequest");
437 }
438 }
439
440 private boolean isURLRestricted(String url)
441 {
442 for (String restrictedURL : _restrictedURLs)
443 {
444 if (url.matches(".*" + restrictedURL + ".*"))
445 {
446 return true;
447 }
448 }
449
450 return false;
451 }
452
453}
Note: See TracBrowser for help on using the repository browser.