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

Last change on this file since 39010 was 39010, checked in by kjdon, 4 weeks ago

added metadata_name param to queryMRforDOCID and renamed it to queryMRforMetadata, so it can be used for both doc_id->assocfilepath and assocfilepath->doc_id lookup. added support for restful assoc file urls - these will be stable unlike filepaths with assocfilepath inthem, which can change between builds. gs doc url is greenstone3/library/collection/demo/document/HASHxxx - add on to this /assoc/yyy.pdf and you can view that document without needing assocfilepath.

  • Property svn:executable set to *
File size: 28.3 KB
Line 
1package org.greenstone.gsdl3.core;
2
3import java.io.File;
4import java.io.IOException;
5import java.util.ArrayList;
6import java.util.Arrays;
7import java.util.HashMap;
8import java.util.Hashtable;
9import java.util.Map;
10
11import javax.servlet.Filter;
12import javax.servlet.FilterChain;
13import javax.servlet.FilterConfig;
14import javax.servlet.ServletContext;
15import javax.servlet.ServletException;
16import javax.servlet.ServletOutputStream;
17import javax.servlet.ServletRequest;
18import javax.servlet.ServletResponse;
19import javax.servlet.http.HttpSession;
20import javax.servlet.http.HttpServletRequest;
21import javax.servlet.http.HttpServletRequestWrapper;
22import javax.servlet.http.HttpServletResponse;
23
24import java.awt.event.ActionEvent;
25import java.awt.event.ActionListener;
26import javax.swing.Timer;
27
28import org.apache.commons.io.FileUtils;
29import org.apache.commons.lang3.StringUtils;
30
31import org.apache.log4j.Logger;
32import org.greenstone.gsdl3.util.GSParams;
33import org.greenstone.gsdl3.util.GSPath;
34import org.greenstone.gsdl3.util.GSXML;
35import org.greenstone.gsdl3.util.UserContext;
36import org.greenstone.gsdl3.util.XMLConverter;
37import org.greenstone.gsdl3.service.Authentication;
38import org.w3c.dom.Document;
39import org.w3c.dom.Element;
40import org.w3c.dom.NodeList;
41
42public class URLFilter implements Filter
43{
44 private FilterConfig _filterConfig = null;
45 private static Logger logger = Logger.getLogger(org.greenstone.gsdl3.core.URLFilter.class.getName());
46
47 //Restricted URLs
48 protected static final String SITECONFIG_URL = "sites/[^/]+/siteConfig.xml";
49 protected static final String USERS_DB_URL = "etc/usersDB/.*";
50 protected static final ArrayList<String> _restrictedURLs;
51
52 static
53 {
54 ArrayList<String> restrictedURLs = new ArrayList<String>();
55 restrictedURLs.add(SITECONFIG_URL);
56 restrictedURLs.add(USERS_DB_URL);
57 _restrictedURLs = restrictedURLs;
58 }
59
60 //Constants
61 protected static final String DOCUMENT_PATH = "document";
62 protected static final String COLLECTION_PATH = "collection";
63 protected static final String GROUP_PATH = "group";
64 protected static final String PAGE_PATH = "page";
65 protected static final String SYSTEM_PATH = "system";
66 protected static final String BROWSE_PATH = "browse";
67 protected static final String SEARCH_PATH = "search";
68 protected static final String ASSOC_PATH = "assoc";
69 protected static final ArrayList<String> _keywords;
70
71 static
72 {
73 ArrayList<String> keywords = new ArrayList<String>();
74 keywords.add(PAGE_PATH);
75 keywords.add(BROWSE_PATH);
76 keywords.add(SEARCH_PATH);
77 keywords.add(DOCUMENT_PATH);
78 _keywords = keywords;
79 }
80
81 protected static final String METADATA_RETRIEVAL_SERVICE = "DocumentMetadataRetrieve";
82 protected static final String ASSOCIATED_FILE_PATH = "/index/assoc/";
83 protected static final String COLLECTION_FILE_PATH = "/collect/";
84 protected static final String INTERFACE_PATH = "/interfaces/";
85 protected static final String SITES_PATH = "/sites/";
86
87 protected static final String SYSTEM_SUBACTION_CONFIGURE = "configure";
88 protected static final String SYSTEM_SUBACTION_RECONFIGURE = "reconfigure";
89 protected static final String SYSTEM_SUBACTION_ACTIVATE = "activate";
90 protected static final String SYSTEM_SUBACTION_DEACTIVATE = "deactivate";
91
92 // if we are showing terms and conditions to user, this remembers who has
93 // accepted already
94 protected Hashtable<String, UserTimer> verifiedUserMap = null;
95 // timeouts are in millisecs
96 // this is for if we have verify=once set in collectionConfig - the user will stay
97 // verified for 24 hours
98 protected static final int verifiedUserTimeout = 24 * 60 * 60 * 1000;
99 // this is a per document timeout - Chrome may make several requests to fetch a fastview pdf,
100 // plus another one if the user clicks download. Need to keep a record for a verified document
101 // so it can be fuly viewed and downloaded - get a network error if end up back at verification page.
102 // the user stays verified for the document for 2 hours.
103 protected static final int tempUserTimeout = 2 * 60 * 60 * 1000;
104
105 public void init(FilterConfig filterConfig) throws ServletException
106 {
107 this._filterConfig = filterConfig;
108 this.verifiedUserMap = new Hashtable<String, UserTimer>();
109 }
110
111 public void destroy()
112 {
113 this._filterConfig = null;
114 }
115
116 @SuppressWarnings("deprecation")
117 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
118 {
119 if (!(request instanceof HttpServletRequest)) {
120 // Can this ever happen?
121 logger.error("The request was not an HttpServletRequest");
122 return;
123 }
124
125
126 HttpServletRequest hRequest = ((HttpServletRequest) request);
127 HttpSession hSession = hRequest.getSession();
128 ServletContext context = hSession.getServletContext();
129
130 GSHttpServletRequestWrapper gRequest = new GSHttpServletRequestWrapper(hRequest);
131
132 // this is the part before the ?
133 String url = hRequest.getRequestURI().toString();
134 if (isURLRestricted(url)) {
135
136 // TODO - should we make this a proper HTML page?
137 response.getWriter().println("ERROR: Access to this page is forbidden.");
138 return;
139 }
140
141
142 // Run security checks on files requested from a collection's index/assoc folder
143 if (url.contains(ASSOCIATED_FILE_PATH)) {
144 // we need to do security checking here in case the documents are private
145 // or if there is a terms and conditions page to be shown.
146 // Also, assoc files urls now contain the library name in them.
147 // e.g. greenstone3/library/sites/localsite/collect/collname/index/assoc/Hashxxx/doc.pdf
148 // so they are not a true link to a file. We remove the
149 // 'library' then forward the request to the new url.
150 securityCheckAssocFiles(url, hRequest, response, null);
151 return;
152 }
153
154 //
155 if (url.contains(SITES_PATH)) {
156 // there are some site/collection images that are not associated files.
157 // these dont need to be security checked, but we need to remove the library name from the url if its there
158 String context_path = context.getContextPath();
159 String regex = context_path+"/.+"+SITES_PATH+".*";
160 if (url.matches(regex)) {
161 // a forward doesn't want the context path
162 String new_url = url.substring(url.indexOf(SITES_PATH));
163 request.getRequestDispatcher(new_url).forward(request, response);
164 return;
165 }
166 // else if it doesn't match, ie the url was /greenstone3/sites/...
167 // we don't do anything and just let it continue
168 }
169
170
171
172 // if we are asking for an interface file, and it doesn't exist, then
173 // try loading up the interfaceConfig file to find out what the base
174 // interface was, then try looking in that interface for the file.
175 if (url.contains(INTERFACE_PATH))
176 {
177 String fileURL = url.replaceFirst(context.getContextPath(), "");
178 File requestedFile = new File(context.getRealPath(fileURL));
179
180 if (!requestedFile.exists()) {
181 String baseURL = getFileInBaseInterface(fileURL, context);
182 if (baseURL != null) {
183 File baseInterfaceFile = new File(context.getRealPath(baseURL));
184 if (baseInterfaceFile.exists()) {
185 request.getRequestDispatcher(baseURL).forward(request, response);
186 // ServletOutputStream out = response.getOutputStream();
187 // out.write(FileUtils.readFileToByteArray(baseInterfaceFile));
188 // out.flush();
189 // out.close();
190 return;
191 }
192 }
193 }
194 }
195 else
196 {
197 //If we have a jsessionid on the end of our URL we want to ignore it
198 int index;
199 if ((index = url.indexOf(";jsessionid")) != -1)
200 {
201 url = url.substring(0, index);
202 }
203
204 // OK, here we split into segments and process bit by bit.
205 String[] segments = url.split("/");
206 for (int i = 0; i < segments.length; i++)
207 {
208 String[] additionalParameters = null;
209 String[] defaultParamValues = null;
210 //COLLECTION
211 if (segments[i].equals(COLLECTION_PATH) && (i + 1) < segments.length) {
212 int j=i+1;
213 while(j+1 < segments.length && !_keywords.contains(segments[j+1])) {
214 j++;
215 }
216
217 if (j>i+1) {
218 // we had a group part
219 String [] groups = Arrays.copyOfRange(segments, i+1, j);
220 String group = StringUtils.join(groups, "/");
221 gRequest.setParameter(GSParams.GROUP, group);
222 }
223 gRequest.setParameter(GSParams.COLLECTION, segments[j]);
224 }
225 // GROUP
226 else if(segments[i].equals(GROUP_PATH) && (i + 1) < segments.length)
227 {
228 // assume for now, no other path parts for group links
229 int j= segments.length - 1;
230 String group;
231 if (j==i+1) {
232 group = segments[j];
233 } else {
234 String [] groups = Arrays.copyOfRange(segments, i+1, j+1);
235 group = StringUtils.join(groups, "/");
236 }
237 gRequest.setParameter(GSParams.GROUP, group);
238 gRequest.setParameter(GSParams.ACTION, "p");
239 gRequest.setParameter(GSParams.SUBACTION, "home");
240
241 }
242 //DOCUMENT
243 else if (segments[i].equals(DOCUMENT_PATH) && (i + 1) < segments.length)
244 {
245 gRequest.setParameter(GSParams.DOCUMENT, segments[i + 1]);
246
247 additionalParameters = new String[] { GSParams.ACTION };
248 defaultParamValues = new String[] { "d" };
249 if ((i+2) < segments.length && segments[i+2].equals("print")) {
250 gRequest.setParameter(GSParams.SUBACTION, "print");
251 gRequest.setParameter("ed", "1");
252
253 } else if ((i+3) < segments.length && segments[i+2].equals("assoc")) {
254 url = generateFileURL(context, url, gRequest.getParameter(GSParams.COLLECTION), gRequest.getParameter(GSParams.DOCUMENT), segments[i+3]);
255
256 securityCheckAssocFiles(url, hRequest, response, gRequest.getParameter(GSParams.DOCUMENT));
257 return;
258 }
259
260
261 }
262 //PAGE
263 else if (segments[i].equals(PAGE_PATH) && (i + 1) < segments.length)
264 {
265 gRequest.setParameter(GSParams.SUBACTION, segments[i + 1]);
266
267 additionalParameters = new String[] { GSParams.ACTION };
268 defaultParamValues = new String[] { "p" };
269 }
270 //SYSTEM
271 else if (segments[i].equals(SYSTEM_PATH) && (i + 1) < segments.length)
272 {
273 String sa = segments[i + 1];
274 if (sa.equals(SYSTEM_SUBACTION_CONFIGURE) || sa.equals(SYSTEM_SUBACTION_RECONFIGURE))
275 {
276 sa = "c";
277 }
278 else if (sa.equals(SYSTEM_SUBACTION_ACTIVATE))
279 {
280 sa = "a";
281 }
282 else if (sa.equals(SYSTEM_SUBACTION_DEACTIVATE))
283 {
284 sa = "d";
285 }
286
287 if (sa.equals("c") && (i + 2) < segments.length)
288 {
289 gRequest.setParameter(GSParams.SYSTEM_CLUSTER, segments[i + 2]);
290 }
291
292 if (sa.equals("a") && (i + 2) < segments.length)
293 {
294 gRequest.setParameter(GSParams.SYSTEM_MODULE_TYPE, "collection");
295 gRequest.setParameter(GSParams.SYSTEM_MODULE_NAME, segments[i + 2]);
296 }
297
298 if (sa.equals("d") && (i + 2) < segments.length)
299 {
300 gRequest.setParameter(GSParams.SYSTEM_CLUSTER, segments[i + 2]);
301 }
302
303 gRequest.setParameter(GSParams.SUBACTION, sa);
304
305 additionalParameters = new String[] { GSParams.ACTION };
306 defaultParamValues = new String[] { "s" };
307 }
308 //ADMIN
309 else if (segments[i].equals("admin") && (i + 1) < segments.length)
310 {
311 String pageName = segments[i + 1];
312
313 gRequest.setParameter("s1.authpage", pageName);
314
315 additionalParameters = new String[] { GSParams.ACTION, GSParams.REQUEST_TYPE, GSParams.SUBACTION, GSParams.SERVICE };
316 defaultParamValues = new String[] { "g", "r", "authen", "Authentication" };
317 }
318 //BROWSE
319 else if (segments[i].equals(BROWSE_PATH) && (i + 1) < segments.length)
320 {
321 String cl = "";
322 for (int j = 1; (i + j) < segments.length; j++)
323 {
324 String currentSegment = segments[i + j].replace("CL", "").replace("cl", "");
325 if (currentSegment.contains("."))
326 {
327 String[] subsegments = currentSegment.split("\\.");
328 for (String subsegment : subsegments)
329 {
330 subsegment = subsegment.replace("CL", "").replace("cl", "");
331
332 if (cl.length() > 0)
333 {
334 cl += ".";
335 }
336
337 if (subsegment.length() > 0)
338 {
339 cl += subsegment;
340 }
341 }
342 continue;
343 }
344 if (!currentSegment.matches("^(CL|cl)?\\d+$"))
345 {
346 continue;
347 }
348
349 if (cl.length() > 0)
350 {
351 cl += ".";
352 }
353
354 cl += currentSegment;
355 }
356
357 gRequest.setParameter("cl", "CL" + cl);
358
359 additionalParameters = new String[] { GSParams.ACTION, GSParams.REQUEST_TYPE, GSParams.SERVICE };
360 defaultParamValues = new String[] { "b", "s", "ClassifierBrowse" };
361 }
362 //QUERY
363 else if (segments[i].equals(SEARCH_PATH))
364 {
365 String serviceName = "";
366 if ((i + 1) < segments.length)
367 {
368 serviceName = segments[i + 1];
369 gRequest.setParameter("s", serviceName);
370
371 additionalParameters = new String[] { GSParams.ACTION, GSParams.SUBACTION, GSParams.REQUEST_TYPE };
372 defaultParamValues = new String[] { "q", "", "d" };
373 }
374 if ((i + 2) < segments.length)
375 {
376 if (serviceName.equals("TextQuery") || serviceName.equals("RawQuery"))
377 {
378
379 gRequest.setParameter("s1.query", segments[i + 2]);
380 }
381 else if (serviceName.equals("FieldQuery"))
382 {
383 gRequest.setParameter("s1.fqv", segments[i + 2]);
384 }
385 else if (serviceName.equals("AdvancedFieldQuery"))
386 {
387 gRequest.setParameter("s1.fqv", segments[i + 2]);
388 }
389 }
390 }
391 if (additionalParameters != null)
392 {
393 for (int j = 0; j < additionalParameters.length; j++)
394 {
395 if (gRequest.getParameter(additionalParameters[j]) == null)
396 {
397 gRequest.setParameter(additionalParameters[j], defaultParamValues[j]);
398 }
399 }
400 }
401 }
402 }
403
404 chain.doFilter(gRequest, response);
405 }
406
407 private boolean isURLRestricted(String url)
408 {
409 for (String restrictedURL : _restrictedURLs)
410 {
411 if (url.matches(".*" + restrictedURL + ".*"))
412 {
413 return true;
414 }
415 }
416
417 return false;
418 }
419
420 private String getFileInBaseInterface(String fileURL, ServletContext context) {
421 int interfaceNameStart = fileURL.indexOf(INTERFACE_PATH) + INTERFACE_PATH.length();
422 int interfaceNameEnd = fileURL.indexOf("/", interfaceNameStart);
423 String interfaceName = fileURL.substring(interfaceNameStart, interfaceNameEnd);
424 String interfacesDir = fileURL.substring(0, interfaceNameStart);
425 File interfaceConfigFile = new File(context.getRealPath(interfacesDir + interfaceName + "/interfaceConfig.xml"));
426
427 if (interfaceConfigFile.exists()) {
428
429 Document interfaceConfigDoc = XMLConverter.getDOM(interfaceConfigFile);
430
431 String baseInterface = interfaceConfigDoc.getDocumentElement().getAttribute("baseInterface");
432 if (baseInterface.length() > 0)
433 {
434 return fileURL.replace("/" + interfaceName + "/", "/" + baseInterface + "/");
435 }
436 }
437 return null;
438 }
439
440 private String generateFileURL(ServletContext context, String url, String collection, String document, String filename) {
441
442 String library_name = url.replaceFirst(context.getContextPath()+"/", "");
443 library_name = library_name.substring(0, library_name.indexOf("/"));
444
445 MessageRouter gsRouter = (MessageRouter) context.getAttribute(library_name+"Router");
446 String site_name = gsRouter.getSiteName();
447 String context_path = context.getContextPath();
448 String assocfilepath = queryMRforMetadata(gsRouter, collection, document, "assocfilepath");
449
450 if (assocfilepath == null) {
451 return null;
452 }
453 return context_path +"/"+ library_name+"/"+
454 "sites/"+ site_name+"/"+
455 "collect/"+collection+"/"+
456 "index/assoc/"+assocfilepath+"/"+filename;
457
458 }
459
460 private void securityCheckAssocFiles(String url, HttpServletRequest request, ServletResponse response, String document) throws IOException, ServletException {
461
462 HttpSession session = request.getSession();
463 String session_id = session.getId();
464 ServletContext context = session.getServletContext();
465
466 // now we need to get library name from the path, which is like
467 // /greenstone3/library/sites/localsite/collect/collname/index/assoc/...
468 String library_name = url.replaceFirst(context.getContextPath(), "");
469 library_name = library_name.substring(0, library_name.indexOf(SITES_PATH));
470 if (library_name.equals("")) {
471 response.getWriter().println("ERROR: Assoc file paths must now contain the library name");
472 return;
473 }
474 // remove initial '/'
475 library_name = library_name.substring(1);
476
477 MessageRouter gsRouter = (MessageRouter) context.getAttribute(library_name+"Router");
478
479 if (gsRouter == null) {
480 logger.error("MR is null, stopping filter");
481 return;
482 }
483 // Sometimes we have a // before the filename - that mucks up the following code, so lets remove them
484 url = url.replaceAll("//","/");
485
486 String dir = null;
487 int dirStart = url.indexOf(ASSOCIATED_FILE_PATH) + ASSOCIATED_FILE_PATH.length();
488 int dirEnd = -1;
489 if (dirStart < url.length() && url.indexOf("/", dirStart) != -1)
490 {
491 dirEnd = url.lastIndexOf("/");
492 }
493 if (dirEnd != -1)
494 {
495 dir = url.substring(dirStart, dirEnd);
496 }
497 if (dir == null)
498 {
499 return;
500 }
501
502 String collection = null;
503 int colStart = url.indexOf(COLLECTION_FILE_PATH) + COLLECTION_FILE_PATH.length();
504 int colEnd = -1;
505 if (colStart < url.length() && url.indexOf("/", colStart) != -1)
506 {
507 colEnd = url.indexOf("/", colStart);
508 }
509 if (colEnd != -1)
510 {
511 collection = url.substring(colStart, colEnd);
512 }
513 if (collection == null)
514 {
515 return;
516 }
517
518 String file_name = url.substring(url.lastIndexOf("/")+1);
519 // if there is ;jsessionid=xxx in the request, it is still here at this stage!!!
520 int semicol = file_name.indexOf(';');
521 if(semicol != -1) {
522 file_name = file_name.substring(0, semicol);
523 }
524
525 if (document == null) {
526 // Query the MR with a request for the contains metadata for node "dir" - where dir is the assocfilepath
527 // In the jdbm db, have entries like
528 // [HASH1552e]
529 // <contains>HASH1552e3sdlkjf7sdfsdfk
530 // mapping assocfilepath to doc id
531 document = queryMRforDOCID(gsRouter, collection, dir);
532 if (document == null) {
533 response.getWriter().println("ERROR: Couldn't find the document associated with assocfilepath: "+dir);
534 return;
535 }
536 }
537
538 //Query the MR for the security info for this document
539 // - can we show the document?
540 // - Or do we need to be logged in?
541 // - Or do we need to throw up the verify page?
542
543 // While we are doing this, query the document for its srclinkFile metadata - then we can determine if the
544 // file we are being asked for is the main doc (eg pdf) or just a supporting image on the page
545
546 //Get the security info for this collection
547 Document gsDoc = XMLConverter.newDOM();
548 Element securityMessage = gsDoc.createElement(GSXML.MESSAGE_ELEM);
549 Element securityRequest = GSXML.createBasicRequest(gsDoc, GSXML.REQUEST_TYPE_SECURITY, collection, new UserContext());
550
551 securityMessage.appendChild(securityRequest);
552 securityRequest.setAttribute(GSXML.NODE_OID, document);
553
554 // get the srclinkFile for the document
555 Element metadata_request = GSXML.createBasicRequest(gsDoc, GSXML.REQUEST_TYPE_PROCESS, GSPath.appendLink(collection, "DocumentMetadataRetrieve"), new UserContext());
556 Element param_list = gsDoc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
557 GSXML.addParameterToList(param_list, "metadata", "srclinkFile");
558 metadata_request.appendChild(param_list);
559 Element doc_list = gsDoc.createElement(GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER);
560 metadata_request.appendChild(doc_list);
561 Element d = gsDoc.createElement(GSXML.DOC_NODE_ELEM);
562 d.setAttribute(GSXML.NODE_ID_ATT, document);
563 doc_list.appendChild(d);
564 securityMessage.appendChild(metadata_request);
565
566
567 Element mr_response = (Element)gsRouter.process(securityMessage);
568 //logger.debug("security response = "+XMLConverter.getPrettyString(mr_response));
569
570 boolean verifiable_file = true;
571 // TODO check for errors
572
573 Element meta_response = (Element) GSXML.getNamedElement(mr_response, GSXML.RESPONSE_ELEM, GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
574 Element metadata_list = (Element)meta_response.getElementsByTagName(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER).item(0);
575 String srcdoc = GSXML.getMetadataValue(metadata_list, "srclinkFile");
576 //logger.debug("srcdoc="+srcdoc+", filename="+file_name+", %20 decoded filename="+file_name.replaceAll("\\%20|\\+", " "));
577 // If file_name is the main file for the document, then it will == srcdoc. Both of these are URL encoded, with the exception of spaces. Spaces will be encoded in file_name, but are not encoded in srcdoc. So need to decode those and check again.
578 // srcdoc.equals(java.net.URLDecoder.decode(file_name, "UTF-8")) - this didn't work as both are URLEncoded except for spaces
579 if (!srcdoc.equals(file_name) && !srcdoc.equals(file_name.replaceAll("\\%20|\\+", " "))){
580 // the specified file is just a supporting file, not the main file.
581 // eg an image in an html doc.
582 verifiable_file = false;
583 }
584
585 Element securityResponse = (Element) GSXML.getNamedElement(mr_response, GSXML.RESPONSE_ELEM, GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_SECURITY);
586 ArrayList<String> groups = GSXML.getGroupsFromSecurityResponse(securityResponse);
587
588 if (!groups.contains(""))
589 {
590 boolean found = false;
591 for (String group : groups)
592 {
593 if (((HttpServletRequest) request).isUserInRole(group))
594 {
595 found = true;
596 break;
597 }
598 }
599
600 if (!found)
601 {
602 // return an error page to the browser
603 String new_url = context.getContextPath()+"/"+ library_name+"?a=p&sa=error&c="+collection+"&ec=wrong_group";
604 ((HttpServletResponse)response).sendRedirect(new_url);
605 return;
606 }
607 }
608
609 // if got here have no groups that we need to belong to
610 // do we have human verify thing?
611 if (verifiable_file) {
612 String verify = securityResponse.getAttribute(GSXML.VERIFY_ATT);
613 if (!verify.equals("")) {
614 // we are asking for the main document, and we have been asked to verify the user
615 // have we done the test previously?
616 String verify_map_key = session_id + ":"+collection;
617 String verify_map_doc_key = verify_map_key + ":" + file_name;
618 boolean already_verified = false;
619 String hmvf_response = request.getParameter(GSParams.VERIFIED);
620 if (hmvf_response != null && hmvf_response.equals("0")) {
621 // manually force the t&c (user has added hmvf=0 to url)
622 // whether we have previously verified or not
623 } else if (verifiedUserMap.containsKey(verify_map_key) || verifiedUserMap.containsKey(verify_map_doc_key)) {
624 already_verified = true;
625 }
626
627 if (!already_verified) {
628 // have we just done the test?
629 // hmvf param will be set by form if the verify page was submitted
630 if (hmvf_response != null && hmvf_response.equals("1")) {
631 if (!securityResponse.getAttribute(GSXML.SITE_KEY_ATT).equals("")) {
632 String recaptcha_response = request.getParameter(Authentication.RECAPTCHA_RESPONSE_PARAM);
633 String secret_key = securityResponse.getAttribute(GSXML.SECRET_KEY_ATT);
634 int result = Authentication.verifyRecaptcha(secret_key, recaptcha_response);
635 if (result == Authentication.NO_ERROR) {
636 already_verified = true;
637 } else {
638 logger.error("something went wrong with recaptcha, error="+result);
639 logger.error(Authentication.getErrorKey(result));
640 // display error page
641 String new_url = context.getContextPath()+"/"+ library_name+"?a=p&sa=error&c="+collection+"&ec=recap_fail";
642 ((HttpServletResponse)response).sendRedirect(new_url);
643 return;
644 }
645 }
646 already_verified = true;
647 // set up a timer for this verification - standard 24hour if
648 // verify==once, short, doc specific one otherwise (browsers seem to be trying to
649 // download prfs twice. Chrome gets stuck if the second time
650 // doesn't get verified. Also Chrome sends a second request if the
651 // user tries to download the document after viewing it. )
652 int delay;
653 String this_key;
654 if (verify.equals("once")) {
655 delay = verifiedUserTimeout;
656 this_key = verify_map_key;
657 } else {
658 delay = tempUserTimeout;
659 this_key = verify_map_doc_key;
660 }
661 UserTimer timer = new UserTimer(delay, this_key);
662 verifiedUserMap.put(this_key, timer);
663 timer.start();
664 // For the verify page, we just return back to the browser, as we have called this
665 // using ajax.
666 return;
667
668 } // hmvf = 1
669 }
670
671 if (!already_verified) {
672 // hmvf param is not set - we haven't shown them the form yet
673 // or we have been asked to force the T&C
674 // we need to display the verify page
675 //Lets encode the url parameter as we need it encoded in the page.
676 String new_url = context.getContextPath()+"/"+ library_name+"?a=p&sa=verify&c="+collection+"&url="+java.net.URLEncoder.encode(url, "UTF-8");
677 ((HttpServletResponse)response).sendRedirect(new_url);
678 return;
679 }
680 } // end verify is set
681 }// end if verifiable file
682
683 // if we got here, we have passed all security checks and just want to view the file.
684 // However, we need to remove the library_name from the URL. As can't change the
685 // existing URL, we need to forward to the new one.
686 // (Can't do redirect as it will come back into this code and fail as there won't be library in the url)
687 // Remove the context and library name parts.
688 // don't know what happens with the rest of the filter chain? Does this bypass that??
689 url = url.replaceFirst(context.getContextPath(), "");
690 url = url.replaceFirst("/"+library_name, "");
691 //logger.info("forwarding to "+url);
692 request.getRequestDispatcher(url).forward(request, response);
693
694 return;
695 }
696
697
698
699
700 private String queryMRforDOCID(MessageRouter gsRouter, String collection, String assocfiledir) {
701 return queryMRforMetadata(gsRouter, collection, assocfiledir, "contains");
702 }
703
704 // set node_id to be a document_id, and metadata_name to be 'assocfilepath' to
705 // get the assocfilepath for a particular doc
706 // set node_id to be the assocfilepath, and metadata_name to be 'contains' to
707 // get the doc_id for a particular assocfilepath
708 private String queryMRforMetadata(MessageRouter gsRouter, String collection, String node_id, String metadata_name) {
709 Document gsDoc = XMLConverter.newDOM();
710
711 Element metaMessage = gsDoc.createElement(GSXML.MESSAGE_ELEM);
712 Element metaRequest = GSXML.createBasicRequest(gsDoc, GSXML.REQUEST_TYPE_PROCESS, collection + "/" + METADATA_RETRIEVAL_SERVICE, new UserContext());
713 metaMessage.appendChild(metaRequest);
714
715 Element paramList = gsDoc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
716 metaRequest.appendChild(paramList);
717
718 Element param = gsDoc.createElement(GSXML.PARAM_ELEM);
719 param.setAttribute(GSXML.NAME_ATT, "metadata");
720 param.setAttribute(GSXML.VALUE_ATT, metadata_name);
721 paramList.appendChild(param);
722
723 Element docList = gsDoc.createElement(GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER);
724 metaRequest.appendChild(docList);
725
726 Element doc = gsDoc.createElement(GSXML.DOC_NODE_ELEM);
727 doc.setAttribute(GSXML.NODE_ID_ATT, node_id);
728 docList.appendChild(doc);
729
730 Element metaResponse = (Element) gsRouter.process(metaMessage);
731
732 NodeList metadataList = metaResponse.getElementsByTagName(GSXML.METADATA_ELEM);
733 if (metadataList.getLength() == 0) {
734
735 logger.error("Could not find the metadata '"+metadata_name+"' for node '"+node_id+"'");
736 return null;
737 }
738
739 Element metadata = (Element) metadataList.item(0);
740 String meta_value = metadata.getTextContent();
741 if (meta_value != null && meta_value.equals("")) {
742 meta_value = null;
743 }
744 return meta_value;
745
746
747 }
748
749 private class UserTimer extends Timer implements ActionListener
750 {
751 String id = "";
752
753 /* delay in milliseconds */
754 public UserTimer(int delay, String id)
755 {
756 super(delay, (ActionListener) null);
757 addActionListener(this);
758 this.id = id;
759 }
760
761 public void actionPerformed(ActionEvent e)
762 {
763 verifiedUserMap.remove(id);
764 stop();
765 }
766
767 }
768
769
770}
Note: See TracBrowser for help on using the repository browser.