/* * Copyright 1998-2014 University Corporation for Atmospheric Research/Unidata * * Portions of this software were developed by the Unidata Program at the * University Corporation for Atmospheric Research. * * Access and use of this software shall impose the following obligations * and understandings on the user. The user is granted the right, without * any fee or cost, to use, copy, modify, alter, enhance and distribute * this software, and any derivative works thereof, and its supporting * documentation for any purpose whatsoever, provided that this entire * notice appears in all copies of the software, derivative works and * supporting documentation. Further, UCAR requests that the user credit * UCAR/Unidata in any publications that result from the use of this * software or in any product that includes this software. The names UCAR * and/or Unidata, however, may not be used in any advertising or publicity * to endorse or promote any products or commercial entity unless specific * written permission is obtained from UCAR/Unidata. The user also * understands that UCAR/Unidata is not obligated to provide the user with * any support, consulting, training or assistance of any kind with regard * to the use, operation and performance of this software nor to provide * the user with any updates, revisions, new versions or "bug fixes." * * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE. */ package thredds.server.dl; import com.coverity.security.Escape; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import thredds.catalog.InvCatalogFactory; import thredds.catalog.InvCatalogImpl; import thredds.catalog.dl.ADNWriter; import thredds.catalog.dl.DIFWriter; import thredds.server.config.TdsContext; import thredds.servlet.HtmlWriter; import thredds.servlet.ServletUtil; import thredds.servlet.ThreddsConfig; import thredds.util.ContentType; import ucar.nc2.constants.CDM; import ucar.nc2.util.IO; import ucar.unidata.util.StringUtil2; import javax.annotation.PostConstruct; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URI; import java.net.URISyntaxException; /** * Servlet handles creating DL records. */ @Controller @RequestMapping("/DLwriter") public class DLwriterController { private static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DLwriterController.class); private static org.slf4j.Logger logServerStartup = org.slf4j.LoggerFactory.getLogger("serverStartup"); @Autowired private TdsContext tdsContext; private String adnDir, difDir; private boolean allow, allowRemote; @PostConstruct public void init() throws ServletException { allow = ThreddsConfig.getBoolean("DLwriter.allow", false); if (!allow) { logServerStartup.info("DLwriterServlet.init(): DLwriter service not enabled in threddsConfig.xml: "); return; } allowRemote = ThreddsConfig.getBoolean("DLwriter.allowRemote", false); String contentPath = tdsContext.getContentRootPath(); adnDir = contentPath + "/adn/"; difDir = contentPath + "/dif/"; File file = new File(adnDir); if(!file.exists() && !file.mkdirs()) logServerStartup.warn("Error creating directory: " + file.getPath()); file = new File(difDir); if(!file.exists() && !file.mkdirs()) logServerStartup.warn("Error creating directory: " + file.getPath()); logServerStartup.info("DLwriterServlet.init() - done: "); } @RequestMapping("**") public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { if (!allow) { res.sendError(HttpServletResponse.SC_FORBIDDEN, "DLwriter service not supported"); log.debug("doGet(): DLwriter service not enabled in threddsConfig.xml."); return; } try { // see if it has a catalog parameter String type = req.getParameter("type"); String catURL = req.getParameter("catalog"); if ((catURL == null) || (catURL.length() == 0)) catURL = ServletUtil.getContextPath() + "/idd/models.xml"; // LOOK WTF ?? URI catUri; try { catUri = new URI(catURL); } catch (URISyntaxException e) { res.sendError(HttpServletResponse.SC_FORBIDDEN, "Given catalog URL not a URL."); log.debug("doGet(): Given catalog URL not a URL", e); return; } if (catUri.isAbsolute()) { if (!allowRemote) { res.sendError(HttpServletResponse.SC_FORBIDDEN, "Given catalog URL not allowed (remote)."); log.debug("doGet(): Given catalog URL was absolute, remote catalog handling not enabled."); return; } } // Default "type" parameter to "DIF" boolean isDIF = type == null || type.equals("DIF"); doit(req, res, catURL, isDIF); } catch (Throwable t) { log.error("doGet(): req= " + ServletUtil.getRequest(req) + " got Exception", t); ServletUtil.handleException(t, res); } } private void doit(HttpServletRequest req, HttpServletResponse res, String catURL, boolean isDIF) throws IOException { URI catURI; try { // Resolve against the request URL. URI reqURI = new URI(req.getRequestURL().toString()); catURI = reqURI.resolve(catURL); } catch (URISyntaxException e) { res.sendError(HttpServletResponse.SC_FORBIDDEN, "Given catalog URL not a URL."); log.debug("doGet(): Given catalog URL not a URL", e); return; } // parse the catalog InvCatalogFactory catFactory = InvCatalogFactory.getDefaultFactory(false); InvCatalogImpl catalog; try { catalog = catFactory.readXML(catURI); } catch (Exception e) { ServletUtil.handleException(e, res); return; } // validate the catalog StringBuilder sb = new StringBuilder(); if (!catalog.check(sb, false)) { res.setContentType(ContentType.html.getContentHeader()); res.setHeader("Validate", "FAIL"); PrintWriter pw = new PrintWriter(new OutputStreamWriter( res.getOutputStream(), CDM.utf8Charset)); showValidationMesssage(catURI.toString(), sb.toString(), pw); pw.flush(); return; } StringBuilder mess = new StringBuilder(); mess.append("Catalog ").append(catURI.toString()).append("\n\n"); if (isDIF) { mess.append("DIF records:" + "\n"); DIFWriter writer = new DIFWriter(); writer.writeDatasetEntries(catalog, difDir, mess); } else { // ADN mess.append("ADN records:" + "\n"); ADNWriter writer = new ADNWriter(); mess.setLength(0); writer.writeDatasetEntries(catalog, adnDir, mess); } res.setContentType(ContentType.html.getContentHeader()); OutputStream out = res.getOutputStream(); out.write(mess.toString().getBytes(CDM.utf8Charset)); out.flush(); } private void showValidationMesssage(String catURL, String mess, java.io.PrintWriter pw) { pw.println(HtmlWriter.getInstance().getHtmlDoctypeAndOpenTag()); pw.println("<head>"); pw.println("<title> Catalog Validation</title>"); pw.println("<meta http-equiv=\"Content-Type\" content=\"text/html\">"); pw.println("</head>"); pw.println("<body bgcolor=\"#FFF0FF\">"); pw.println("<h2> Catalog " + catURL + " has validation errors:</h2>"); pw.println("<b>"); pw.println(Escape.html(mess)); pw.println("</b>"); // show catalog.xml pw.println("<hr><pre>"); String catString = IO.readURLcontents(catURL); pw.println(StringUtil2.quoteHtmlContent(catString)); pw.println("</pre>"); pw.println("</body>"); pw.println("</html>"); } }