View Javadoc
1   /*
2    * This file is part of ***  M y C o R e  ***
3    * See http://www.mycore.de/ for details.
4    *
5    * MyCoRe is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * MyCoRe is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with MyCoRe.  If not, see <http://www.gnu.org/licenses/>.
17   */
18  
19  package org.mycore.frontend.export;
20  
21  import org.apache.logging.log4j.LogManager;
22  import org.apache.logging.log4j.Logger;
23  import org.mycore.common.content.MCRContent;
24  import org.mycore.common.content.transformer.MCRContentTransformer;
25  import org.mycore.frontend.basket.MCRBasket;
26  import org.mycore.frontend.basket.MCRBasketManager;
27  import org.mycore.frontend.servlets.MCRServlet;
28  import org.mycore.frontend.servlets.MCRServletJob;
29  
30  import jakarta.servlet.http.HttpServletRequest;
31  
32  /**
33   * Provides functionality to export content. 
34   * The content to export can be selected by specifying one or more 
35   * URIs to read from, or by giving the ID of a basket to export. 
36   * The selected content is collected as MCRExportCollection thats
37   * root element name can be specified. 
38   * The content is then transformed using an MCRContentTransformer instance
39   * and forwarded to the requesting client.
40   * 
41   * Request Parameters:
42   *   uri=... 
43   *     can be repeated to include content from one or more URIs to read XML from
44   *   basket=...
45   *     the ID of a basket to read XML from  
46   *   root=...
47   *     optional, name of the root element that wraps the selected content
48   *   ns=...
49   *     optional, URI of the namespace of the root element
50   *   transformer=...
51   *     the ID of the transformer to use to export the selected content.
52   *          
53   * @see MCRExportCollection
54   * @see MCRContentTransformer
55   * 
56   * @author Frank L\u00FCtzenkirchen
57   */
58  public class MCRExportServlet extends MCRServlet {
59  
60      private static final Logger LOGGER = LogManager.getLogger(MCRExportServlet.class);
61  
62      /** URIs beginning with these prefixes are forbidden for security reasons */
63      private static final String[] FORBIDDEN_URIS = { "file", "webapp", "resource" };
64  
65      @Override
66      public void doGetPost(MCRServletJob job) throws Exception {
67          MCRExportCollection collection = createCollection(job.getRequest());
68          fillCollection(job.getRequest(), collection);
69          MCRContent content2export = collection.getContent();
70  
71          String filename = getProperty(job.getRequest(), "filename");
72          if (filename == null) {
73              filename = "export-" + System.currentTimeMillis();
74          }
75          job.getResponse().setHeader("Content-Disposition", "inline;filename=\"" + filename + "\"");
76  
77          String transformerID = job.getRequest().getParameter("transformer");
78          job.getRequest().setAttribute("XSL.Transformer", transformerID);
79          getLayoutService().doLayout(job.getRequest(), job.getResponse(), content2export);
80      }
81  
82      /**
83       * Fills the collection with the XML data requested by URIs or basket ID.
84       */
85      private void fillCollection(HttpServletRequest req, MCRExportCollection collection) throws Exception {
86          String basketID = req.getParameter("basket");
87          if (basketID != null) {
88              MCRBasket basket = MCRBasketManager.getOrCreateBasketInSession(basketID);
89              collection.add(basket);
90              LOGGER.info("exporting basket {} via {}", basketID, req.getParameter("transformer"));
91          }
92  
93          if (req.getParameter("uri") != null) {
94              for (String uri : req.getParameterValues("uri")) {
95                  if (isAllowed(uri)) {
96                      collection.add(uri);
97                      LOGGER.info("exporting {} via {}", uri, req.getParameter("transformer"));
98                  }
99              }
100         }
101     }
102 
103     private boolean isAllowed(String uri) {
104         for (String prefix : FORBIDDEN_URIS) {
105             if (uri.startsWith(prefix)) {
106                 LOGGER.warn("URI {} is not allowed for security reasons", uri);
107                 return false;
108             }
109         }
110         return true;
111     }
112 
113     /**
114      * Creates a new, empty MCRExportCollection, optionally with the requested root element name and namespace.
115      */
116     private MCRExportCollection createCollection(HttpServletRequest req) {
117         MCRExportCollection collection = new MCRExportCollection();
118         String root = req.getParameter("root");
119         String ns = req.getParameter("ns");
120         if (!((root == null) || root.isEmpty())) {
121             collection.setRootElement(root, ns);
122         }
123         return collection;
124     }
125 }