diff --git a/knowage-core/src/main/java/it/eng/spagobi/analiticalmodel/document/service/ManagePreviewFileAction.java b/knowage-core/src/main/java/it/eng/spagobi/analiticalmodel/document/service/ManagePreviewFileAction.java index 33cccb8c2c0..5306662a4f6 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/analiticalmodel/document/service/ManagePreviewFileAction.java +++ b/knowage-core/src/main/java/it/eng/spagobi/analiticalmodel/document/service/ManagePreviewFileAction.java @@ -30,6 +30,7 @@ import org.json.JSONException; import org.json.JSONObject; +import it.eng.knowage.commons.security.PathTraversalChecker; import it.eng.spagobi.commons.SingletonConfig; import it.eng.spagobi.commons.bo.UserProfile; import it.eng.spagobi.commons.services.AbstractSpagoBIAction; @@ -107,7 +108,7 @@ public void doService() { // checks for path traversal attacks private void checkRequiredFile(String fileName) { File targetDirectory = GeneralUtilities.getPreviewFilesStorageDirectoryPath(); - FileUtils.checkPathTraversalAttack(fileName, targetDirectory); + PathTraversalChecker.get(targetDirectory.getAbsolutePath(), fileName); } private JSONObject uploadFile() throws Exception { diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/DocumentExecutionResource.java b/knowage-core/src/main/java/it/eng/spagobi/api/DocumentExecutionResource.java index 53218570983..a49714bd527 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/DocumentExecutionResource.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/DocumentExecutionResource.java @@ -29,7 +29,6 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; -import java.nio.file.Paths; import java.text.Format; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -1218,18 +1217,17 @@ public Response uploadFile(MultiPartBody input) { try { if (input != null) { + File saveDirectory = PathTraversalChecker.get(SpagoBIUtilities.getResourcePath(), METADATA_DIR, getUserProfile().getUserId().toString()); - java.nio.file.Path saveDirectoryPath = Paths.get(SpagoBIUtilities.getResourcePath(), METADATA_DIR, getUserProfile().getUserId().toString()); final FormFile file = input.getFormFileParameterValues("file")[0]; bytes = file.getContent(); - File saveDirectory = saveDirectoryPath.toFile(); if (!(saveDirectory.exists() && saveDirectory.isDirectory())) { saveDirectory.mkdirs(); } - String tempFile = Paths.get(saveDirectoryPath.toString(), file.getFileName()).toString(); - File tempFileToSave = new File(tempFile); - PathTraversalChecker.preventPathTraversalAttack(tempFileToSave, saveDirectory); + + File tempFileToSave = PathTraversalChecker.get(saveDirectory.getAbsolutePath(), file.getFileName()); + tempFileToSave.createNewFile(); DataOutputStream os = new DataOutputStream(new FileOutputStream(tempFileToSave)); os.write(bytes); diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/DossierActivityResource.java b/knowage-core/src/main/java/it/eng/spagobi/api/DossierActivityResource.java index b64f584ec67..0a6f76e676f 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/DossierActivityResource.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/DossierActivityResource.java @@ -20,7 +20,6 @@ import java.io.File; import java.io.FileOutputStream; import java.nio.file.Files; -import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; @@ -128,19 +127,15 @@ public String loadRandomKeyByProgressId(@PathParam("progressId") Integer progres @GET @Path("/resourcePath") public Response getresourcePath(@QueryParam("templateName") String fileName, @QueryParam("documentId") Integer documentId) throws JSONException { - String separator = File.separator; if (fileName.endsWith("?")) fileName = fileName.substring(0, fileName.length() - 1); - java.nio.file.Path outputPath = Paths.get(SpagoBIUtilities.getResourcePath(), "dossier", String.valueOf(documentId), fileName); - File file = outputPath.toFile(); + File file = PathTraversalChecker.get(SpagoBIUtilities.getResourcePath(), "dossier", "" + documentId, fileName); + ResponseBuilder responseBuilder = null; JSONObject response = new JSONObject(); - File dossierDir = new File(SpagoBIUtilities.getResourcePath() + separator + "dossier" + separator + documentId + separator); try { - PathTraversalChecker.isValidFileName(fileName); - PathTraversalChecker.preventPathTraversalAttack(file, dossierDir); byte[] bytes = Files.readAllBytes(file.toPath()); responseBuilder = Response.ok(bytes); responseBuilder.header("Content-Disposition", "attachment; filename=" + fileName); @@ -162,17 +157,13 @@ public Response getresourcePath(@QueryParam("templateName") String fileName, @Qu @GET @Path("/checkPathFile") public Response checkPathFile(@QueryParam("templateName") String fileName, @QueryParam("documentId") Integer documentId) throws JSONException { - String separator = File.separator; if (fileName.endsWith("?")) fileName = fileName.substring(0, fileName.length() - 1); - String outPath = SpagoBIUtilities.getResourcePath() + separator + "dossier" + separator + documentId + separator + fileName; - byte[] bytes; - File file = new File(outPath); - File dossierDir = new File(SpagoBIUtilities.getResourcePath() + separator + "dossier" + separator + documentId + separator); + + File file = PathTraversalChecker.get(SpagoBIUtilities.getResourcePath(), "dossier", "" + documentId, fileName); + JSONObject response = new JSONObject(); try { - PathTraversalChecker.isValidFileName(fileName); - PathTraversalChecker.preventPathTraversalAttack(file, dossierDir); Files.readAllBytes(file.toPath()); response.put("STATUS", "OK"); } catch (Exception e) { @@ -195,29 +186,28 @@ public Response importTemplateFile(MultiPartBody multipartFormDataInput) throws byte[] archiveBytes = null; JSONObject response = new JSONObject(); try { - String separator = File.separator; final FormFile file = multipartFormDataInput.getFormFileParameterValues("file")[0]; ParameterValue[] documentIdArray = multipartFormDataInput.getParameteValues("documentId"); String identifier = ""; - String path = null; + + String fileName = file.getFileName(); + archiveBytes = file.getContent(); + + File dossierDir = null; if (documentIdArray.length == 1) { identifier = documentIdArray[0].toString(); - path = SpagoBIUtilities.getResourcePath() + separator + "dossier" + separator + identifier + separator; + dossierDir = PathTraversalChecker.get(SpagoBIUtilities.getResourcePath(), "dossier", identifier); } else { identifier = multipartFormDataInput.getParameteValues("uuid")[0].toString(); - path = Files.createTempDirectory("prefix").getParent().resolve(identifier).toString() + separator; + dossierDir = PathTraversalChecker.get(System.getProperty("java.io.tmpdir"), identifier); } - String fileName = file.getFileName(); - archiveBytes = file.getContent(); - - File dossierDir = new File(path); if (!dossierDir.exists()) { dossierDir.mkdir(); } - PathTraversalChecker.isValidFileName(fileName); - File f = new File(path + fileName); - PathTraversalChecker.preventPathTraversalAttack(f, dossierDir); + + File f = PathTraversalChecker.get(dossierDir.getAbsolutePath(), fileName); + try (FileOutputStream outputStream = new FileOutputStream(f)) { outputStream.write(archiveBytes); } diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/SelfServiceDataSetCRUD.java b/knowage-core/src/main/java/it/eng/spagobi/api/SelfServiceDataSetCRUD.java index e9b393bf1db..10c9746dffb 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/SelfServiceDataSetCRUD.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/SelfServiceDataSetCRUD.java @@ -362,9 +362,7 @@ public void deleteDatasetFile(IDataSet dataset) { FileDataSet fileDataset = (FileDataSet) wrappedDataset; String resourcePath = fileDataset.getResourcePath(); String fileName = fileDataset.getFileName(); - String filePath = resourcePath + File.separatorChar + "dataset" + File.separatorChar + "files" + File.separatorChar; - File datasetFile = new File(filePath + fileName); - PathTraversalChecker.preventPathTraversalAttack(datasetFile, new File(filePath)); + File datasetFile = PathTraversalChecker.get(resourcePath, "dataset", "files", fileName); if (datasetFile.exists()) { boolean isDeleted = datasetFile.delete(); if (isDeleted) { @@ -1618,11 +1616,9 @@ private JSONObject getFileDataSetConfig(SelfServiceDataSetDTO selfServiceDataSet // This method rename a file and move it from resources\dataset\files\temp // to resources\dataset\files private void renameAndMoveDatasetFile(String originalFileName, String newFileName, String resourcePath, String fileType) { - String filePath = resourcePath + File.separatorChar + "dataset" + File.separatorChar + "files" + File.separatorChar + "temp" + File.separatorChar; - String fileNewPath = resourcePath + File.separatorChar + "dataset" + File.separatorChar + "files" + File.separatorChar; + File originalDatasetFile = PathTraversalChecker.get(resourcePath, "dataset", "files", "temp", originalFileName); + File newDatasetFile = PathTraversalChecker.get(resourcePath, "dataset", "files", newFileName + "." + fileType.toLowerCase()); - File originalDatasetFile = new File(filePath + originalFileName); - File newDatasetFile = new File(fileNewPath + newFileName + "." + fileType.toLowerCase()); if (originalDatasetFile.exists()) { /* * This method copies the contents of the specified source file to the specified destination file. The directory holding the destination file is @@ -1739,9 +1735,8 @@ private JSONObject getCkanDataSetConfig(SelfServiceDataSetDTO selfServiceDataSet } private void deleteDatasetFile(String fileName, String resourcePath, String fileType) { - String filePath = resourcePath + File.separatorChar + "dataset" + File.separatorChar + "files" + File.separatorChar + "temp" + File.separatorChar; + File datasetFile = PathTraversalChecker.get(resourcePath, "dataset", "files", "temp", fileName); - File datasetFile = new File(filePath + fileName); if (datasetFile.exists()) { datasetFile.delete(); } @@ -1796,10 +1791,7 @@ private Integer getCategoryCode(String category) { try { ICategoryDAO categoryDao = DAOFactory.getCategoryDAO(); - categories = categoryDao.getCategoriesForDataset() - .stream() - .map(Domain::fromCategory) - .collect(toList()); + categories = categoryDao.getCategoriesForDataset().stream().map(Domain::fromCategory).collect(toList()); } catch (Throwable t) { throw new SpagoBIRuntimeException("An unexpected error occured while loading categories types from database", t); } @@ -2174,10 +2166,7 @@ protected List getCategories(IEngUserProfile profile) { ICategoryDAO categoryDao = DAOFactory.getCategoryDAO(); // TODO : Makes sense? - List dialects = categoryDao.getCategoriesForDataset() - .stream() - .map(Domain::fromCategory) - .collect(toList()); + List dialects = categoryDao.getCategoriesForDataset().stream().map(Domain::fromCategory).collect(toList()); if (dialects == null || dialects.size() == 0) { return null; } @@ -2191,10 +2180,7 @@ protected List getCategories(IEngUserProfile profile) { List aRoleCategories = roledao.getMetaModelCategoriesForRole(role.getId()); List resp = new ArrayList<>(); - List array = categoryDao.getCategoriesForDataset() - .stream() - .map(Domain::fromCategory) - .collect(toList()); + List array = categoryDao.getCategoriesForDataset().stream().map(Domain::fromCategory).collect(toList()); for (RoleMetaModelCategory r : aRoleCategories) { for (Domain dom : array) { if (r.getCategoryId().equals(dom.getValueId())) { diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/v2/DataSetResource.java b/knowage-core/src/main/java/it/eng/spagobi/api/v2/DataSetResource.java index dfac5cc0b3b..252c5d15bab 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/v2/DataSetResource.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/v2/DataSetResource.java @@ -240,7 +240,7 @@ public String getDataSets(@QueryParam("includeDerived") String includeDerived, @ ISbiDataSetDAO dsDAO = DAOFactory.getSbiDataSetDAO(); List dataSets = dsDAO.loadSbiDataSets(); - List toBeReturned = new ArrayList(); + List toBeReturned = new ArrayList<>(); for (SbiDataSet dataset : dataSets) { IDataSet iDataSet = DataSetFactory.toDataSet(dataset); @@ -389,10 +389,7 @@ public Response downloadDataSetFile(@QueryParam("dsLabel") String dsLabel, @Quer try { String fileName = getFileNameFromDatasetConfiguration(myDataset); String resourcePath = SpagoBIUtilities.getResourcePath(); - File fileDirectory = new File(resourcePath + File.separatorChar + "dataset" + File.separatorChar + "files"); - file = new File(fileDirectory, fileName); - - PathTraversalChecker.preventPathTraversalAttack(file, fileDirectory); + file = PathTraversalChecker.get(resourcePath, "dataset", "files", fileName); if (file == null || !file.exists()) { logger.error("File cannot be found"); @@ -583,7 +580,7 @@ public Filter getComplexFilter(InFilter inFilter, SimpleFilter anotherFilter) { if (SimpleFilterOperator.EQUALS_TO_MIN.equals(operator) || SimpleFilterOperator.EQUALS_TO_MAX.equals(operator)) { List operands = inFilter.getOperands(); Object result = operands.get(0); - if (result instanceof Comparable == false) { + if (!(result instanceof Comparable)) { throw new SpagoBIRuntimeException("Unable to compare operands of type [" + result.getClass().getName() + "]"); } Comparable comparableResult = (Comparable) result; @@ -728,7 +725,7 @@ public String getDataStorePostWithJsonInBody(@PathParam("label") String label, S Set columns = null; if (jsonIndexes != null && jsonIndexes.length() > 0) { - columns = new HashSet(); + columns = new HashSet<>(); for (int k = 0; k < jsonIndexes.length(); k++) { JSONArray columnsArrayTemp = jsonIndexes.getJSONObject(k).getJSONArray("fields"); @@ -845,7 +842,7 @@ public String getDataStorePreview(@PathParam("label") String label, String body) JSONObject columnsArray = columnsArrayTemp.getJSONObject(0); if (columnsArray.getString("store").equals(label)) { - columns = new HashSet(columnsArray.length()); + columns = new HashSet<>(columnsArray.length()); columns.add(columnsArray.getString("column")); } } @@ -878,7 +875,7 @@ private boolean isPreparedDAtaset(IDataSet dataSet) { } private Set getQbeDataSetHiddenColumns(IDataSet dataSet) { - Set hiddenColumns = new HashSet(); + Set hiddenColumns = new HashSet<>(); if (dataSet.getDsType().equals("SbiQbeDataSet")) { try { JSONObject dsConfig = new JSONObject(dataSet.getConfiguration()); @@ -886,7 +883,7 @@ private Set getQbeDataSetHiddenColumns(IDataSet dataSet) { JSONArray fields = qbeQuery.getJSONObject("catalogue").getJSONArray("queries").getJSONObject(0).getJSONArray("fields"); for (int i = 0; i < fields.length(); i++) { JSONObject field = fields.getJSONObject(i); - if (field.has("visible") && field.getBoolean("visible") == false) + if (field.has("visible") && !field.getBoolean("visible")) hiddenColumns.add(field.getString("alias")); } } catch (Exception e) { @@ -901,7 +898,7 @@ private Set getQbeDataSetHiddenColumns(IDataSet dataSet) { @Produces(MediaType.APPLICATION_JSON) @UserConstraint(functionalities = { CommunityFunctionalityConstants.SELF_SERVICE_DATASET_MANAGEMENT }) public Response addDatasetInCache(@Context HttpServletRequest req) { - Set columns = new HashSet(); + Set columns = new HashSet<>(); logger.debug("IN"); try { @@ -959,7 +956,7 @@ public String validateFormulaJson(String body) { formulaString = jsonBody.getString("formula"); JSONArray columns = jsonBody.getJSONArray("measuresList"); - List l = new ArrayList(); + List l = new ArrayList<>(); for (int i = 0; i < columns.length(); i++) { SimpleSelectionField a = new SimpleSelectionField(); @@ -998,7 +995,7 @@ public ArrayList> transformRuntimeDrivers(List parameterAsMap = new HashMap(); + HashMap parameterAsMap = new HashMap<>(); parameterAsMap.put("id", objParameter.getBiObjectId()); parameterAsMap.put("label", objParameter.getLabel()); parameterAsMap.put("urlName", objParameter.getId()); @@ -1030,7 +1027,7 @@ public ArrayList> transformRuntimeDrivers(List valuesList = (List) paramValues; List descriptionList = (List) paramDescriptionValues; if (paramDescriptionValues == null || !(paramDescriptionValues instanceof List)) { - descriptionList = new ArrayList(); + descriptionList = new ArrayList<>(); } // String item = null; diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/service/ManageDataSetsForREST.java b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/service/ManageDataSetsForREST.java index b353b9eb6c8..9852c307585 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/service/ManageDataSetsForREST.java +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/service/ManageDataSetsForREST.java @@ -958,12 +958,9 @@ private void getPersistenceInfo(IDataSet ds, JSONObject json) { // This method rename a file and move it from resources\dataset\files\temp // to resources\dataset\files private void renameAndMoveDatasetFile(String originalFileName, String newFileName, String resourcePath, String fileType) { - String filePath = resourcePath + File.separatorChar + "dataset" + File.separatorChar + "files" + File.separatorChar + "temp" + File.separatorChar; - String fileNewPath = resourcePath + File.separatorChar + "dataset" + File.separatorChar + "files" + File.separatorChar; + File originalDatasetFile = PathTraversalChecker.get(resourcePath, "dataset", "files", "temp", originalFileName); + File newDatasetFile = PathTraversalChecker.get(resourcePath, "dataset", "files", newFileName + "." + fileType.toLowerCase()); - File originalDatasetFile = new File(filePath + originalFileName); - File newDatasetFile = new File(fileNewPath + newFileName + "." + fileType.toLowerCase()); - PathTraversalChecker.preventPathTraversalAttack(newDatasetFile, new File(fileNewPath)); String filePathCloning = resourcePath + File.separatorChar + "dataset" + File.separatorChar + "files" + File.separatorChar; File originalDatasetFileCloning = new File(filePathCloning + originalFileName); @@ -1423,7 +1420,7 @@ private FileDataSet manageFileDataSet(boolean savingDataset, JSONObject jsonDsCo File source = new File( SpagoBIUtilities.getResourcePath() + File.separatorChar + "dataset" + File.separatorChar + "files" + File.separatorChar + realName); - if (!source.getCanonicalPath().equals(dest.getCanonicalPath()) && savingDataset && Boolean.TRUE.equals(!newFileUploaded)) { + if (!source.getCanonicalPath().equals(dest.getCanonicalPath()) && savingDataset && !newFileUploaded) { LOGGER.debug("Source and destination are not the same. Copying from source to dest"); FileUtils.copyFile(source, dest); } diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/service/ManageDatasets.java b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/service/ManageDatasets.java index 77bd5539701..fcc80a03b68 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/service/ManageDatasets.java +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/service/ManageDatasets.java @@ -1505,12 +1505,9 @@ private RESTDataSet manageRESTDataSet(boolean savingDataset, JSONObject config) // This method rename a file and move it from resources\dataset\files\temp // to resources\dataset\files private void renameAndMoveDatasetFile(String originalFileName, String newFileName, String resourcePath, String fileType) { - String filePath = resourcePath + File.separatorChar + "dataset" + File.separatorChar + "files" + File.separatorChar + "temp" + File.separatorChar; - String fileNewPath = resourcePath + File.separatorChar + "dataset" + File.separatorChar + "files" + File.separatorChar; + File originalDatasetFile = PathTraversalChecker.get(resourcePath, "dataset", "files", "temp", originalFileName); + File newDatasetFile = PathTraversalChecker.get(resourcePath, "dataset", "files", newFileName + "." + fileType.toLowerCase()); - File originalDatasetFile = new File(filePath + originalFileName); - File newDatasetFile = new File(fileNewPath + newFileName + "." + fileType.toLowerCase()); - PathTraversalChecker.preventPathTraversalAttack(newDatasetFile, new File(fileNewPath)); if (originalDatasetFile.exists()) { /* * This method copies the contents of the specified source file to the specified destination file. The directory holding the destination file is diff --git a/knowagebirtreportengine/src/main/java/it/eng/spagobi/engines/birt/BirtImageServlet.java b/knowagebirtreportengine/src/main/java/it/eng/spagobi/engines/birt/BirtImageServlet.java index 4b1c8251438..713ca351eb5 100644 --- a/knowagebirtreportengine/src/main/java/it/eng/spagobi/engines/birt/BirtImageServlet.java +++ b/knowagebirtreportengine/src/main/java/it/eng/spagobi/engines/birt/BirtImageServlet.java @@ -35,6 +35,7 @@ import org.apache.log4j.Logger; +import it.eng.knowage.commons.security.PathTraversalChecker; import it.eng.spago.security.IEngUserProfile; import it.eng.spagobi.services.proxy.DocumentExecuteServiceProxy; import it.eng.spagobi.utilities.mime.MimeUtils; @@ -56,33 +57,18 @@ public void service(HttpServletRequest request, HttpServletResponse response) { ServletOutputStream ouputStream = null; InputStream fis = null; - File imageTmpDir = null; File imageFile = null; String completeImageFileName = null; String mimeType = null; if (chartLabel == null) { - String tmpDir = System.getProperty("java.io.tmpdir"); - String imageDirectory = tmpDir.endsWith(File.separator) ? tmpDir + "birt" : tmpDir + File.separator + "birt"; - imageTmpDir = new File(imageDirectory); - String imageFileName = request.getParameter("imageID"); if (imageFileName == null) { logger.error("Image directory or image file name missing."); throw new RuntimeException("Image file name missing."); } - // gets complete image file name: - completeImageFileName = imageDirectory + File.separator + imageFileName; - - imageFile = new File(completeImageFileName); - - File parent = imageFile.getParentFile(); - // Prevent directory traversal (path traversal) attacks - if (!imageTmpDir.equals(parent)) { - logger.error("Trying to access the file [" + imageFile.getAbsolutePath() + "] that is not inside ${java.io.tmpdir}/birt!!!"); - throw new SecurityException("Trying to access the file [" + imageFile.getAbsolutePath() + "] that is not inside ${java.io.tmpdir}/birt!!!"); - } + imageFile = PathTraversalChecker.get(System.getProperty("java.io.tmpdir"), "birt", imageFileName); if (!imageFile.exists()) { logger.error("File " + imageFile.getPath() + " not found"); diff --git a/knowagebirtreportengine/src/main/java/it/eng/spagobi/engines/birt/utilities/Utils.java b/knowagebirtreportengine/src/main/java/it/eng/spagobi/engines/birt/utilities/Utils.java index a14706c4a07..20c03235dae 100644 --- a/knowagebirtreportengine/src/main/java/it/eng/spagobi/engines/birt/utilities/Utils.java +++ b/knowagebirtreportengine/src/main/java/it/eng/spagobi/engines/birt/utilities/Utils.java @@ -27,6 +27,7 @@ import org.apache.log4j.Logger; +import it.eng.knowage.commons.security.PathTraversalChecker; import it.eng.spagobi.engines.birt.BirtReportServlet; public class Utils { @@ -36,8 +37,7 @@ public class Utils { /** * Resolve system properties. * - * @param logDir - * the log dir + * @param logDir the log dir * * @return the string */ @@ -54,10 +54,8 @@ public static String resolveSystemProperties(String logDir) { /** * Resolve system properties. * - * @param logDir - * the log dir - * @param startIndex - * the start index + * @param logDir the log dir + * @param startIndex the start index * * @return the string */ @@ -89,14 +87,8 @@ public static void sendPage(HttpServletResponse response, int pageNumber, String String completeImageFileName = null; String mimeType = "text/html"; - htmlFile = new File(BirtReportServlet.OUTPUT_FOLDER + File.separator + reportExecutionId, BirtReportServlet.PAGE_FILE_NAME + pageNumber + ".html"); - - // file path traversal security check - if (!((htmlFile.getParentFile().getParent() + File.separator).equals(BirtReportServlet.OUTPUT_FOLDER))) { - logger.error("Security exception: parent folder " + htmlFile.getParent() + " is not equal to expected folder " + BirtReportServlet.OUTPUT_FOLDER); - throw new RuntimeException( - "Security exception: parent folder " + htmlFile.getParent() + " is not equal to expected folder " + BirtReportServlet.OUTPUT_FOLDER); - } + String fileName = BirtReportServlet.PAGE_FILE_NAME + pageNumber + ".html"; + htmlFile = PathTraversalChecker.get(BirtReportServlet.OUTPUT_FOLDER, reportExecutionId, fileName); try (InputStream fis = new FileInputStream(htmlFile);) { writeToOutput(response, mimeType, fis); diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/export/excel/ExcelExporter.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/export/excel/ExcelExporter.java index 181956e40f2..7f602658bef 100644 --- a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/export/excel/ExcelExporter.java +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/export/excel/ExcelExporter.java @@ -53,6 +53,7 @@ import com.google.gson.Gson; +import it.eng.knowage.commons.security.PathTraversalChecker; import it.eng.knowage.engine.cockpit.api.export.AbstractFormatExporter; import it.eng.knowage.engine.cockpit.api.export.ExporterClient; import it.eng.knowage.engine.cockpit.api.export.excel.exporters.IWidgetExporter; @@ -140,7 +141,7 @@ public byte[] getBinaryData(String documentLabel) throws IOException, Interrupte LOGGER.warn("Exit value: " + exec.exitValue()); // the script creates the resulting xls and saves it to outputFile - Path outputFile = outputDir.resolve(documentLabel + ".xlsx"); + Path outputFile = PathTraversalChecker.get(outputDir.toString(), documentLabel + ".xlsx").toPath(); return getByteArrayFromFile(outputFile, outputDir); } catch (Exception e) { LOGGER.error("Error during scheduled export execution", e); @@ -149,7 +150,9 @@ public byte[] getBinaryData(String documentLabel) throws IOException, Interrupte } private byte[] getByteArrayFromFile(Path excelFile, Path outputDir) { - try (FileInputStream fis = new FileInputStream(excelFile.toString()); ByteArrayOutputStream bos = new ByteArrayOutputStream()) { + String fileName = excelFile.toString(); + + try (FileInputStream fis = new FileInputStream(fileName); ByteArrayOutputStream bos = new ByteArrayOutputStream()) { byte[] buf = new byte[1024]; for (int readNum; (readNum = fis.read(buf)) != -1;) { // Writes len bytes from the specified byte array starting at offset off to this byte array output stream diff --git a/knowagecommonjengine/src/main/java/it/eng/spagobi/engines/commonj/runtime/WorksRepository.java b/knowagecommonjengine/src/main/java/it/eng/spagobi/engines/commonj/runtime/WorksRepository.java index 79463165bd6..d479477220b 100644 --- a/knowagecommonjengine/src/main/java/it/eng/spagobi/engines/commonj/runtime/WorksRepository.java +++ b/knowagecommonjengine/src/main/java/it/eng/spagobi/engines/commonj/runtime/WorksRepository.java @@ -21,6 +21,8 @@ import org.apache.log4j.Logger; +import it.eng.knowage.commons.security.PathTraversalChecker; + public class WorksRepository { private static final Logger LOGGER = Logger.getLogger(WorksRepository.class); @@ -68,7 +70,6 @@ public File getExecutableWorkProjectDir(CommonjWork work) { return worksDir; } - /** * Gets the executable work dir. * @@ -78,12 +79,14 @@ public File getExecutableWorkProjectDir(CommonjWork work) { */ public File getExecutableWorkDir(CommonjWork work) { LOGGER.debug("IN"); - File workDir = new File(rootDir, work.getWorkName()); + + String fileName = work.getWorkName(); + File workDir = PathTraversalChecker.get(rootDir.getName(), fileName); + LOGGER.debug("OUT"); return workDir; } - /** * Gets the executable work file. * @@ -103,9 +106,10 @@ public File getExecutableWorkFile(CommonjWork work) { * @return true, if successful */ public boolean containsWork(CommonjWork work) { + String fileName = work.getWorkName(); + File workFolder = PathTraversalChecker.get(rootDir.getName(), fileName); - File workFolder=new File(rootDir, work.getWorkName()); - return workFolder.exists(); + return workFolder != null && workFolder.exists(); } } diff --git a/knowagejasperreportengine/src/main/java/it/eng/spagobi/engines/jasperreport/JasperReportRunner.java b/knowagejasperreportengine/src/main/java/it/eng/spagobi/engines/jasperreport/JasperReportRunner.java deleted file mode 100644 index 3fd226662df..00000000000 --- a/knowagejasperreportengine/src/main/java/it/eng/spagobi/engines/jasperreport/JasperReportRunner.java +++ /dev/null @@ -1,1119 +0,0 @@ -/* - * Knowage, Open Source Business Intelligence suite - * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * - * Knowage is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Knowage is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package it.eng.spagobi.engines.jasperreport; - -import java.awt.Graphics2D; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FilenameFilter; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URL; -import java.net.URLClassLoader; -import java.sql.Connection; -import java.util.ArrayList; -import java.util.Base64; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Locale.Builder; -import java.util.Map; -import java.util.PropertyResourceBundle; -import java.util.ResourceBundle; -import java.util.jar.JarFile; -import java.util.zip.ZipEntry; - -import javax.imageio.IIOImage; -import javax.imageio.ImageIO; -import javax.imageio.ImageTypeSpecifier; -import javax.imageio.ImageWriteParam; -import javax.imageio.ImageWriter; -import javax.imageio.metadata.IIOMetadata; -import javax.imageio.plugins.jpeg.JPEGImageWriteParam; -import javax.imageio.stream.ImageOutputStream; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - -import org.apache.log4j.Logger; -import org.safehaus.uuid.UUID; -import org.safehaus.uuid.UUIDGenerator; -import org.xml.sax.InputSource; - -import com.jamonapi.Monitor; -import com.jamonapi.MonitorFactory; -//import com.sun.image.codec.jpeg.JPEGCodec; -//import com.sun.image.codec.jpeg.JPEGEncodeParam; -//import com.sun.image.codec.jpeg.JPEGImageEncoder; - -import it.eng.spago.base.SourceBean; -import it.eng.spago.security.IEngUserProfile; -import it.eng.spagobi.commons.bo.UserProfile; -import it.eng.spagobi.commons.constants.SpagoBIConstants; -import it.eng.spagobi.commons.utilities.SpagoBIUtilities; -import it.eng.spagobi.services.common.EnginConf; -import it.eng.spagobi.services.content.bo.Content; -import it.eng.spagobi.services.proxy.ContentServiceProxy; -import it.eng.spagobi.utilities.DynamicClassLoader; -import it.eng.spagobi.utilities.ParametersDecoder; -import it.eng.spagobi.utilities.ResourceClassLoader; -import it.eng.spagobi.utilities.SpagoBIAccessUtils; -import net.sf.jasperreports.engine.JRExporter; -import net.sf.jasperreports.engine.JRExporterParameter; -import net.sf.jasperreports.engine.JRParameter; -import net.sf.jasperreports.engine.JasperCompileManager; -import net.sf.jasperreports.engine.JasperFillManager; -import net.sf.jasperreports.engine.JasperPrint; -import net.sf.jasperreports.engine.JasperReport; -import net.sf.jasperreports.engine.design.JasperDesign; -import net.sf.jasperreports.engine.export.JExcelApiExporter; -import net.sf.jasperreports.engine.export.JRCsvExporter; -import net.sf.jasperreports.engine.export.JRGraphics2DExporter; -import net.sf.jasperreports.engine.export.JRGraphics2DExporterParameter; -import net.sf.jasperreports.engine.export.JRHtmlExporter; -import net.sf.jasperreports.engine.export.JRHtmlExporterParameter; -import net.sf.jasperreports.engine.export.JRPdfExporter; -import net.sf.jasperreports.engine.export.JRRtfExporter; -import net.sf.jasperreports.engine.export.JRTextExporter; -import net.sf.jasperreports.engine.export.JRTextExporterParameter; -import net.sf.jasperreports.engine.export.JRXmlExporter; -import net.sf.jasperreports.engine.fill.JRFileVirtualizer; -import net.sf.jasperreports.engine.fill.JRGzipVirtualizer; -import net.sf.jasperreports.engine.fill.JRSwapFileVirtualizer; -import net.sf.jasperreports.engine.util.JRSwapFile; -import net.sf.jasperreports.engine.xml.JRXmlLoader; - -/** - * Jasper Report implementation built to provide all methods to run a report inside SpagoBI. It is the jasper report Engine implementation for SpagoBI. - * - * @author Gioia * @deprecated - */ -@Deprecated -public class JasperReportRunner { - - private static transient Logger logger = Logger.getLogger(JasperReportRunner.class); - public static final String JS_FILE_ZIP = "JS_File"; - public static final String JS_DIR = "JS_dir"; - public static final String JS_EXT_ZIP = ".zip"; - - private String documentId = null; - private String userId = null; - private String userUniqueIdentifier = null; - - /** - * Class Constructor. - * - * @param session the session - */ - public JasperReportRunner(HttpSession session) { - super(); - } - - /** - * This method, known all input information, runs a report with JasperReport inside SpagoBI. iIt is the Jasper Report Engine's core method. - * - * @param parameters The input parameters map - * @param servletContext The java servlet context object - * @param servletResponse The java http servlet response object - * @param conn the conn - * @param out the out - * @param servletRequest the servlet request - * @throws Exception If any Exception occurred - */ - public void runReport(Connection conn, Map parameters, OutputStream out, ServletContext servletContext, HttpServletResponse servletResponse, - HttpServletRequest servletRequest) throws Exception { - logger.debug("IN"); - Monitor monitor = MonitorFactory.start("JasperReportRunner.service"); - documentId = servletRequest.getParameter("document"); - - HttpSession session = servletRequest.getSession(); - IEngUserProfile profile = (IEngUserProfile) session.getAttribute(IEngUserProfile.ENG_USER_PROFILE); - userId = (String) ((UserProfile) profile).getUserId(); - userUniqueIdentifier = (String) profile.getUserUniqueIdentifier(); - - logger.debug("Read user data from the request. userId=" + userId + ". DocumentId=" + documentId); - - String resourcePath = EnginConf.getInstance().getResourcePath() + "/img/"; - String entity = (String) parameters.get(SpagoBIConstants.SBI_ENTITY); - // IF exist an ENTITY parameter concat to resourcePath - if (entity != null && entity.length() > 0) { - resourcePath = resourcePath.concat(entity + "/"); - } - logger.debug("SetUp resourcePath:" + resourcePath); - - String prefixDirTemplate = (String) parameters.get("prefixName"); - logger.debug("prefixDirTemplate:" + prefixDirTemplate); - - parameters.put("SBI_USERID", userUniqueIdentifier); - parameters.put("SBI_HTTP_SESSION", session); - parameters.put("SBI_RESOURCE_PATH", resourcePath); - - /* - * TODO Since this is the back-end (logic) part of the JasperEngine the direct use of HttpServletResponse, HttpServletRequest and ServletContext objects - * shuold be pushed back to JasperReportServlet that is the front-end (control) part of the engine - */ - File[] compiledSubreports = null; - SpagoBIAccessUtils util = new SpagoBIAccessUtils(); - // identity string for object execution - UUIDGenerator uuidGen = UUIDGenerator.getInstance(); - UUID uuid_local = uuidGen.generateTimeBasedUUID(); - // String executionId = uuid_local.toString(); - // executionId = executionId.replaceAll("-", ""); - String flgTemplateStandard = "true"; - - // ContentServiceProxy contentProxy=new ContentServiceProxy(userId,session); - ContentServiceProxy contentProxy = new ContentServiceProxy(userUniqueIdentifier, session); - - try { - String tmpDirectory = System.getProperty("java.io.tmpdir"); - - // all jar needed by JR to succesfully compile a report should be on this path - // (by default is WEB_INF/lib) - setJRClasspath(getJRLibDir(servletContext)); - - HashMap requestParameters = ParametersDecoder.getDecodedRequestParameters(servletRequest); - Content template = contentProxy.readTemplate(documentId, requestParameters); - if (template == null) { - logger.error("The document haven't the template.documentId=" + documentId + " userUniqueIdentifier=" + userUniqueIdentifier); - return; - } - logger.debug("Read the template." + template.getFileName()); - InputStream is = null; - Base64.Decoder bASE64Decoder = Base64.getDecoder(); - byte[] templateContent = bASE64Decoder.decode(template.getContent()); - is = new java.io.ByteArrayInputStream(templateContent); - - if (template.getFileName().indexOf(".zip") > -1) { - flgTemplateStandard = "false"; - } - - /* - * Dynamic template management: if the template is a zip file it is opened and every class are added to the classpath - */ - boolean propertiesLoaded = false; - if (flgTemplateStandard.equalsIgnoreCase("false")) { - logger.debug("The template is a .ZIP file"); - File fileZip = new File(getJRTempDir(servletContext, prefixDirTemplate), JS_FILE_ZIP + JS_EXT_ZIP); - FileOutputStream foZip = new FileOutputStream(fileZip); - foZip.write(templateContent); - foZip.close(); - util.unzip(fileZip, getJRTempDir(servletContext, prefixDirTemplate)); - JarFile zipFile = new JarFile(fileZip); - Enumeration totalZipEntries = zipFile.entries(); - File jarFile = null; - while (totalZipEntries.hasMoreElements()) { - ZipEntry entry = (ZipEntry) totalZipEntries.nextElement(); - if (entry.getName().endsWith(".jar")) { - jarFile = new File(getJRTempDirName(servletContext, prefixDirTemplate) + entry.getName()); - // set classloader with jar - ClassLoader previous = Thread.currentThread().getContextClassLoader(); - DynamicClassLoader dcl = new DynamicClassLoader(jarFile, previous); - Thread.currentThread().setContextClassLoader(dcl); - } else if (entry.getName().endsWith(".jrxml")) { - // set InputStream with jrxml - File jrxmlFile = new File(getJRTempDirName(servletContext, prefixDirTemplate) + entry.getName()); - InputStream isJrxml = new FileInputStream(jrxmlFile); - byte[] templateJrxml = new byte[0]; - templateJrxml = util.getByteArrayFromInputStream(isJrxml); - is = new java.io.ByteArrayInputStream(templateJrxml); - } - if (entry.getName().endsWith(".properties")) { - - propertiesLoaded = true; - } - } - } - - // Set the temporary location for the files generated on-the-fly by JR - // (by default is the current user tmp-dir) - setJRTempDir(tmpDirectory); - - logger.debug("Compiling template file ..."); - Monitor monitorCompileTemplate = MonitorFactory.start("JasperReportRunner.compileTemplate"); - JasperReport report = JasperCompileManager.compileReport(is); - monitorCompileTemplate.stop(); - logger.debug("Template file compiled succesfully"); - - parameters = adaptReportParams(parameters, report); - - // Add locale - if (parameters.get("SBI_LANGUAGE") != null && parameters.get("SBI_COUNTRY") != null) { - Locale locale = null; - String language = (String) parameters.get("SBI_LANGUAGE"); - String country = (String) parameters.get("SBI_COUNTRY"); - - Builder builder = new Builder().setLanguage(language).setRegion(country); - String script = (String) parameters.get("SBI_SCRIPT"); - if (org.apache.commons.lang.StringUtils.isNotBlank(script)) { - builder.setScript(script); - } - locale = builder.build(); - logger.debug("Internazionalization in " + language); - - parameters.put("REPORT_LOCALE", locale); - - ResourceBundle rs = null; - - if (propertiesLoaded == false) { - - // if properties file are not loaded by template load them from resources - SourceBean config = null; - if (getClass().getResource("/engine-config.xml") != null) { - InputSource source = new InputSource(getClass().getResourceAsStream("/engine-config.xml")); - config = SourceBean.fromXMLStream(source); - } - SourceBean sb = (SourceBean) config.getAttribute("RESOURCE_PATH_JNDI_NAME"); - String path = sb.getCharacters(); - String resPath = SpagoBIUtilities.readJndiResource(path); - resPath += "/jasper_messages/"; - - ClassLoader previous = Thread.currentThread().getContextClassLoader(); - ResourceClassLoader dcl = new ResourceClassLoader(resPath, previous); - // Thread.currentThread().setContextClassLoader(dcl); - try { - // rs=PropertyResourceBundle.getBundle("messages",locale, Thread.currentThread().getContextClassLoader()); - rs = PropertyResourceBundle.getBundle("messages", locale, dcl); - } catch (Exception e) { - logger.error("could not find properties message"); - } - parameters.put("REPORT_RESOURCE_BUNDLE", rs); - } - } - - Monitor monitorSubReport = MonitorFactory.start("JasperReportRunner.compileSubReport"); - // compile subreports - // compiledSubreports = compileSubreports(parameters, getJRCompilationDir(servletContext, executionId),contentProxy, requestParameters); - compiledSubreports = compileSubreports(parameters, servletContext, contentProxy, requestParameters); - monitorSubReport.stop(); - // set classloader - ClassLoader previous = Thread.currentThread().getContextClassLoader(); - ClassLoader current = URLClassLoader.newInstance(new URL[] { getJRCompilationDir(servletContext, prefixDirTemplate).toURI().toURL() }, previous); - Thread.currentThread().setContextClassLoader(current); - - // Create the virtualizer - if (isVirtualizationActive()) { - logger.debug("Virtualization of fill process is active"); - // parameters.put(JRParameter.REPORT_VIRTUALIZER, getVirtualizer(tmpDirectory, servletContext)); - parameters.put(JRParameter.REPORT_VIRTUALIZER, getSwapVirtualizer(tmpDirectory, servletContext)); - // parameters.put(JRParameter.REPORT_VIRTUALIZER, getGzipVirtualizer()); - } - - logger.debug("Filling report ..."); - Monitor monitorFillingReport = MonitorFactory.start("JasperReportRunner.FillingReport"); - JasperPrint jasperPrint = JasperFillManager.fillReport(report, parameters, conn); - monitorFillingReport.stop(); - logger.debug("Report filled succesfully"); - - logger.debug("Exporting report ..."); - String outputType = (String) parameters.get("outputType"); - if (outputType == null) { - logger.debug("Output type is not specified. Default type will be used"); - outputType = "html"; - // outputType = ExporterFactory.getDefaultType(); - } - logger.debug("Output format is [" + outputType + "]"); - Monitor monitorExportReport = MonitorFactory.start("JasperReportRunner.ExportReport"); - JRExporter exporter = ExporterFactory.getExporter(outputType); - String mimeType = ExporterFactory.getMIMEType(outputType); - - if (exporter != null) - logger.debug("Configured exporter class [" + exporter.getClass().getName() + "]"); - else - logger.debug("Exporter class [null]"); - logger.debug("Configured MIME type [" + mimeType + "]"); - - // for base types use default exporter, mimeType and parameters if these - // are not specified by configuration file - if (outputType.equalsIgnoreCase("csv")) { - if (mimeType == null) - mimeType = "text/plain"; - servletResponse.setContentType(mimeType); - if (exporter == null) - exporter = new JRCsvExporter(); - } else if (outputType.equalsIgnoreCase("html")) { - if (mimeType == null) - mimeType = "text/html"; - servletResponse.setContentType(mimeType); - if (exporter == null) - exporter = new JRHtmlExporter(); - exporter.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN, Boolean.FALSE); - exporter.setParameter(JRHtmlExporterParameter.BETWEEN_PAGES_HTML, ""); - // define the map structure for report images - HashMap m_imagesMap = new HashMap(); - String mapName = uuid_local.toString(); - servletRequest.getSession().setAttribute(mapName, m_imagesMap); - exporter.setParameter(JRHtmlExporterParameter.IMAGES_MAP, m_imagesMap); - // exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, "image.jsp?mapname="+mapName+"&image="); - exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, "JRImageServlet?mapname=" + mapName + "&image="); - - /* - * commented by Davide Zerbetto on 12/10/2009: there are problems with MIF (Ext ManagedIFrame library) library // setting HTML header: this is - * necessary in order to inject the document.domain directive String head = getHTMLHeader(); - * exporter.setParameter(JRHtmlExporterParameter.HTML_HEADER, head); - */ - } else if (outputType.equalsIgnoreCase("xls")) { - if (mimeType == null) - mimeType = "application/vnd.ms-excel"; - servletResponse.setContentType(mimeType); - // if(exporter == null) exporter = new JRXlsExporter(); - if (exporter == null) - exporter = new JExcelApiExporter(); - } else if (outputType.equalsIgnoreCase("rtf")) { - if (mimeType == null) - mimeType = "application/rtf"; - servletResponse.setContentType(mimeType); - if (exporter == null) - exporter = new JRRtfExporter(); - } else if (outputType.equalsIgnoreCase("xml")) { - if (mimeType == null) - mimeType = "text/xml"; - servletResponse.setContentType(mimeType); - if (exporter == null) - exporter = new JRXmlExporter(); - } else if (outputType.equalsIgnoreCase("txt")) { - if (mimeType == null) - mimeType = "text/plain"; - servletResponse.setContentType(mimeType); - if (exporter == null) - exporter = new JRTextExporter(); - exporter.setParameter(JRTextExporterParameter.PAGE_HEIGHT, new Integer(100)); - exporter.setParameter(JRTextExporterParameter.PAGE_WIDTH, new Integer(100)); - } else if (outputType.equalsIgnoreCase("pdf")) { - if (mimeType == null) - mimeType = "application/pdf"; - servletResponse.setContentType(mimeType); - if (exporter == null) - exporter = new JRPdfExporter(); - } else if (outputType.equalsIgnoreCase("JPG")) { - byte[] bytes = getImageBytes(report, jasperPrint); - if (mimeType == null) - mimeType = "application/jpeg"; - out.write(bytes); - return; - } else if (outputType.equalsIgnoreCase("JPGBASE64")) { - byte[] bytes = getImagesBase64Bytes(report, jasperPrint); - if (mimeType == null) - mimeType = "text/plain"; - out.write(bytes); - return; - } else { - if (mimeType != null && exporter != null) - servletResponse.setContentType(mimeType); - else { - logger.warn("Impossible to load exporter for type " + outputType); - logger.warn("Pdf exporter will be used"); - servletResponse.setContentType("application/pdf"); - exporter = new JRPdfExporter(); - } - } - - logger.debug("MIME type of response is [" + servletResponse.getContentType() + "]"); - logger.debug("Exporter class used is [" + exporter.getClass().getName() + "]"); - - exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint); - exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out); - exporter.exportReport(); - monitorExportReport.stop(); - logger.debug("Report exported succesfully"); - - } catch (Throwable e) { - logger.error("An exception has occured", e); - throw new Exception(e); - } finally { - // delete tmp dir for dynamic template management only if it's empty (without subreport files) - // File tmpDir = getJRTempDir(servletContext, executionId, prefixDirTemplate).getParentFile(); - File tmpDir = getJRTempDir(servletContext, prefixDirTemplate); - String[] files = tmpDir.list(); - if (files.length == 0) { - util.deleteDirectory(tmpDir); - logger.debug("Delating temporary directory: " + tmpDir); - } - monitor.stop(); - logger.debug("OUT"); - } - - } - - /** - * This method builds the html header string to be injected on report HTML output. This is necessary in order to inject the document.domain javascript - * directive - * - * @return the HTML head tag as a string - */ - /* - * commented by Davide Zerbetto: there are problems with MIF (Ext ManagedIFrame library) library protected String getHTMLHeader() { logger.debug("IN"); - * String header = null; try { SourceBean config = EnginConf.getInstance().getConfig(); SourceBean htmlHeaderSb = (SourceBean) - * config.getAttribute("HTML_HEADER"); header = htmlHeaderSb.getCharacters(); if (header == null || header.trim().equals("")) { throw new - * Exception("HTML_HEADER not configured"); } header = header.replaceAll("\\$\\{SBI_DOMAIN\\}", EnginConf.getInstance().getSpagoBiDomain()); } catch - * (Exception e) { logger.error("Error while retrieving HTML_HEADER from engine configuration.", e); logger.info("Using default HTML header", e); - * StringBuffer buffer = new StringBuffer(); buffer.append(""); buffer.append(""); buffer.append(""); - * buffer.append(" "); buffer.append(" "); buffer.append(" "); buffer.append(""); - * buffer.append(""); - * buffer.append(""); - * buffer.append("
 "); header = buffer.toString(); } logger.debug("OUT"); return header; } - */ - - // /////////////////////////////////////// - // UTILITY METHODS - // /////////////////////////////////////// - - private void setJRClasspath(String jrLibDir) { - logger.debug("JasperReports lib-dir is [" + this.getClass().getName() + "]"); - System.setProperty("jasper.reports.compile.class.path", buildJRClasspathValue(jrLibDir)); - logger.debug("Set [jasper.reports.compile.class.path properties] to value [" + System.getProperty("jasper.reports.compile.class.path") + "]"); - - } - - /** - * Build a classpath variable appending all the jar files founded into the specified directory. - * - * @param libDir JR lib-dir to scan for find jar files to include into the classpath variable - * @return the classpath used by JasperReprorts Engine (by default equals to WEB-INF/lib) - */ - private String buildJRClasspathValue(String libDir) { - logger.debug("IN"); - String getJRClasspathValue = null; - - logger.debug("Reading jar files from lib-dir..."); - StringBuffer jasperReportClassPathStringBuffer = new StringBuffer(); - File f = new File(libDir); - String fileToAppend = null; - if (f.isDirectory()) { - String[] jarFiles = f.list(); - for (int i = 0; i < jarFiles.length; i++) { - String namefile = jarFiles[i]; - if (!namefile.endsWith("jar")) - continue; // the inclusion of txt files causes problems - fileToAppend = libDir + System.getProperty("file.separator") + jarFiles[i]; - logger.debug("Appending jar file [" + fileToAppend + "] to JasperReports classpath"); - jasperReportClassPathStringBuffer.append(fileToAppend); - jasperReportClassPathStringBuffer.append(System.getProperty("path.separator")); - } - } - - getJRClasspathValue = jasperReportClassPathStringBuffer.toString(); - getJRClasspathValue = getJRClasspathValue.substring(0, getJRClasspathValue.length() - 1); - logger.debug("OUT"); - return getJRClasspathValue; - } - - private boolean isVirtualizationActive() { - logger.debug("IN"); - boolean isVirtualizationActive = false; - SourceBean config = EnginConf.getInstance().getConfig(); - String active = (String) config.getAttribute("VIRTUALIZER.active"); - if (active != null) - isVirtualizationActive = active.equalsIgnoreCase("true"); - logger.debug("OUT"); - return isVirtualizationActive; - } - - /** - * Gets the virtualizer. (the slowest) - * - * @param tmpDirectory the tmp directory - * @param servletContext the servlet context - * @return the virtualizer - */ - public JRFileVirtualizer getVirtualizer(String tmpDirectory, ServletContext servletContext) { - logger.debug("IN"); - JRFileVirtualizer virtualizer = null; - - SourceBean config = EnginConf.getInstance().getConfig(); - String maxSizeStr = (String) config.getAttribute("VIRTUALIZER.maxSize"); - int maxSize = 2; - if (maxSizeStr != null) - maxSize = Integer.parseInt(maxSizeStr); - String dir = (String) config.getAttribute("VIRTUALIZER.dir"); - if (dir == null) { - dir = tmpDirectory; - } else { - if (!dir.startsWith("/")) { - String contRealPath = servletContext.getRealPath("/"); - if (contRealPath.endsWith("\\") || contRealPath.endsWith("/")) { - contRealPath = contRealPath.substring(0, contRealPath.length() - 1); - } - dir = contRealPath + "/" + dir; - } - } - dir = dir + System.getProperty("file.separator") + "jrcache"; - File file = new File(dir); - file.mkdirs(); - logger.debug("Max page cached during virtualization process: " + maxSize); - logger.debug("Dir used as storing area during virtualization: " + dir); - virtualizer = new JRFileVirtualizer(maxSize, dir); - virtualizer.setReadOnly(false); - logger.debug("OUT"); - return virtualizer; - } - - /** - * Gets the swap virtualizer. (the fastest) - * - * @param tmpDirectory the tmp directory - * @param servletContext the servlet context - * @return the virtualizer - */ - public JRSwapFileVirtualizer getSwapVirtualizer(String tmpDirectory, ServletContext servletContext) { - logger.debug("IN"); - JRSwapFileVirtualizer virtualizer = null; - - SourceBean config = EnginConf.getInstance().getConfig(); - String maxSizeStr = (String) config.getAttribute("VIRTUALIZER.maxSize"); - int maxSize = 2; - if (maxSizeStr != null) - maxSize = Integer.parseInt(maxSizeStr); - String dir = (String) config.getAttribute("VIRTUALIZER.dir"); - if (dir == null) { - dir = tmpDirectory; - } else { - if (!dir.startsWith("/")) { - String contRealPath = servletContext.getRealPath("/"); - if (contRealPath.endsWith("\\") || contRealPath.endsWith("/")) { - contRealPath = contRealPath.substring(0, contRealPath.length() - 1); - } - dir = contRealPath + "/" + dir; - } - } - - dir = dir + System.getProperty("file.separator") + "jrcache"; - File file = new File(dir); - file.mkdirs(); - logger.debug("Max page cached during virtualization process: " + maxSize); - logger.debug("Dir used as storing area during virtualization: " + dir); - JRSwapFile swapFile = new JRSwapFile(dir, maxSize, maxSize); - virtualizer = new JRSwapFileVirtualizer(maxSize, swapFile); - virtualizer.setReadOnly(false); - logger.debug("OUT"); - return virtualizer; - } - - /** - * Gets the gZip virtualizer (it works in memory: slower). - * - * @param tmpDirectory the tmp directory - * @param servletContext the servlet context - * @return the virtualizer - */ - public JRGzipVirtualizer getGzipVirtualizer() { - logger.debug("IN"); - JRGzipVirtualizer virtualizer = null; - - SourceBean config = EnginConf.getInstance().getConfig(); - String maxSizeStr = (String) config.getAttribute("VIRTUALIZER.maxSize"); - int maxSize = 2; - if (maxSizeStr != null) - maxSize = Integer.parseInt(maxSizeStr); - - logger.debug("Max page cached during virtualization process: " + maxSize); - - virtualizer = new JRGzipVirtualizer(maxSize); - virtualizer.setReadOnly(false); - logger.debug("OUT"); - return virtualizer; - } - - private byte[] getImagesBase64Bytes(JasperReport report, JasperPrint jasperPrint) { - logger.debug("IN"); - byte[] bytes = new byte[0]; - try { - String message = ""; - List bufferedImages = generateReportImages(report, jasperPrint); - Iterator iterImgs = bufferedImages.iterator(); - int count = 1; - while (iterImgs.hasNext()) { - message += ""; - BufferedImage image = (BufferedImage) iterImgs.next(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - ImageWriter imageWriter = ImageIO.getImageWritersBySuffix("jpeg").next(); - ImageOutputStream ios = ImageIO.createImageOutputStream(baos); - imageWriter.setOutput(ios); - IIOMetadata imageMetaData = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(image), null); - ImageWriteParam par = imageWriter.getDefaultWriteParam(); - par.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT); - par.setCompressionQuality(1.0f); - imageWriter.write(imageMetaData, new IIOImage(image, null, null), par); - - // JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(baos); - // JPEGEncodeParam encodeParam = encoder.getDefaultJPEGEncodeParam(image); - // encodeParam.setQuality(1.0f, true); - // encoder.setJPEGEncodeParam(encodeParam); - // encoder.encode(image); - - byte[] byteImg = baos.toByteArray(); - baos.close(); - Base64.Encoder encoder64 = Base64.getEncoder(); - String encodedImage = encoder64.encodeToString(byteImg); - message += encodedImage; - message += ""; - count++; - } - message += ""; - bytes = message.getBytes(); - } catch (Exception e) { - logger.error("Error while producing byte64 encoding of the report images", e); - } - logger.debug("OUT"); - return bytes; - } - - private byte[] getImageBytes(JasperReport report, JasperPrint jasperPrint) { - logger.debug("IN"); - byte[] bytes = new byte[0]; - try { - List bufferedImages = generateReportImages(report, jasperPrint); - // calculate dimension of the final page - Iterator iterImgs = bufferedImages.iterator(); - int totalHeight = 0; - int totalWidth = 0; - while (iterImgs.hasNext()) { - BufferedImage image = (BufferedImage) iterImgs.next(); - int hei = image.getHeight(); - int wid = image.getWidth(); - totalHeight += hei; - totalWidth = wid; - } - // create an unique buffer image - BufferedImage finalImage = new BufferedImage(totalWidth, totalHeight, BufferedImage.TYPE_INT_RGB); - Graphics2D finalGr2 = finalImage.createGraphics(); - // append all images to the final - iterImgs = bufferedImages.iterator(); - int y = 0; - int x = 0; - while (iterImgs.hasNext()) { - BufferedImage image = (BufferedImage) iterImgs.next(); - int hei = image.getHeight(); - finalGr2.drawImage(image, new AffineTransform(1f, 0f, 0f, 1f, x, y), null); - y += hei; - } - // gets byte of the jpeg image - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - ImageWriter imageWriter = ImageIO.getImageWritersBySuffix("jpeg").next(); - ImageOutputStream ios = ImageIO.createImageOutputStream(baos); - imageWriter.setOutput(ios); - IIOMetadata imageMetaData = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(finalImage), null); - ImageWriteParam par = imageWriter.getDefaultWriteParam(); - par.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT); - par.setCompressionQuality(1.0f); - imageWriter.write(imageMetaData, new IIOImage(finalImage, null, null), par); - - // JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(baos); - // JPEGEncodeParam encodeParam = encoder.getDefaultJPEGEncodeParam(finalImage); - // encodeParam.setQuality(1.0f, true); - // encoder.setJPEGEncodeParam(encodeParam); - // encoder.encode(finalImage); - - bytes = baos.toByteArray(); - baos.close(); - - } catch (Exception e) { - logger.error("Error while producing jpg image of the report", e); - } - logger.debug("OUT"); - return bytes; - } - - private List generateReportImages(JasperReport report, JasperPrint jasperPrint) { - logger.debug("IN"); - List bufferedImages = new ArrayList(); - try { - int height = report.getPageHeight(); - int width = report.getPageWidth(); - boolean export = true; - int index = 0; - while (export == true) { - BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); - Graphics2D gr2 = image.createGraphics(); - JRExporter exporter = new JRGraphics2DExporter(); - exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint); - exporter.setParameter(JRGraphics2DExporterParameter.GRAPHICS_2D, gr2); - exporter.setParameter(JRGraphics2DExporterParameter.PAGE_INDEX, new Integer(index)); - try { - exporter.exportReport(); - } catch (Exception e) { - export = false; - continue; - } - index++; - bufferedImages.add(image); - } - } catch (Exception e) { - logger.error("Error while producing jpg images of the report", e); - } - logger.debug("OUT"); - return bufferedImages; - } - - /** - * @return the classpath used by JasperReprorts Engine (by default equals to WEB-INF/lib) TODO convert this to a File returning method - */ - private String getJRLibDir(ServletContext servletContext) { - logger.debug("IN"); - String jrLibDir = null; - jrLibDir = servletContext.getRealPath("WEB-INF") + System.getProperty("file.separator") + "lib"; - logger.debug("OUT"); - return jrLibDir; - } - - private void setJRTempDir(String jrTmpDir) { - System.setProperty("jasper.reports.compile.temp", jrTmpDir); - logger.debug("Set [jasper.reports.compile.temp] to value [" + System.getProperty("jasper.reports.compile.temp") + "]"); - } - - private File getJRCompilationDir(ServletContext servletContext, String prefixTemplate) { - logger.debug("IN"); - File jrCompilationDir = null; - jrCompilationDir = getJRTempDir(servletContext, prefixTemplate); - logger.debug("OUT"); - return jrCompilationDir; - } - - private String getJRTempDirName(ServletContext servletContext, String prefixTemplate) { - logger.debug("IN"); - String jrTempDir = servletContext.getRealPath("tmpdir") + System.getProperty("file.separator") + "reports" + System.getProperty("file.separator") - + JS_DIR + "__" + prefixTemplate + System.getProperty("file.separator"); - logger.debug("OUT"); - return jrTempDir; - } - - private File getJRTempDir(ServletContext servletContext, String prefixTemplate) { - logger.debug("IN"); - File jrTempDir = null; - - String jrTempDirStr = getJRTempDirName(servletContext, prefixTemplate); - jrTempDir = new File(jrTempDirStr.substring(0, jrTempDirStr.length() - 1)); - jrTempDir.mkdirs(); - logger.debug("OUT"); - return jrTempDir; - } - - protected Map adaptReportParams(Map parameters, JasperReport report) { - logger.debug("IN"); - String dateformat = (String) parameters.get("dateformat"); - if (dateformat != null) { - dateformat = dateformat.replaceAll("D", "d"); - dateformat = dateformat.replaceAll("m", "M"); - dateformat = dateformat.replaceAll("Y", "y"); - } - JRParameter[] reportParameters = report.getParameters(); - ParametersDecoder decoder = new ParametersDecoder(); - for (int i = 0; i < reportParameters.length; i++) { - JRParameter aReportParameter = reportParameters[i]; - String paramName = aReportParameter.getName(); - logger.debug("Examining parameter with name [" + paramName + "] ..."); - - String paramValueString = null; - - if (parameters.get(paramName) instanceof String) { - paramValueString = (String) parameters.get(paramName); - } - if (paramValueString == null) { - logger.debug("No value found for parameter with name [" + paramName + "]"); - continue; - } - if (paramValueString != null) { - logger.debug("Value found for parameter with name [" + paramName + "] is [" + paramValueString + "]"); - /* - * The ParameterConverter converts a single value. Multi-value parameters are assumed to contains values that are String type. If they are not - * Strings (list of dates, list of numbers, ...) the converter will not work. - */ - if (decoder.isMultiValues(paramValueString)) { - logger.debug("Value found for parameter with name [" + paramName + "] is [" + paramValueString + "] and it is multivalue. " - + "Cannot adapt parameter nature"); - continue; - } - Class aReportParameterClass = aReportParameter.getValueClass(); - Object newValue = ParameterConverter.convertParameter(aReportParameterClass, paramValueString, dateformat); - if (newValue == null) - newValue = paramValueString; - - if (!(newValue instanceof String)) { - logger.debug("Updating parameter with name [" + paramName + "] to a " + newValue.getClass().getName() + "."); - parameters.put(paramName, newValue); - } - } - } - logger.debug("OUT"); - return parameters; - } - - // ========================================================================================================================= - - private static class SubreportMeta { - private String documentId; // 1, 2, ..., n - private String templateType; // file | archive - private String templateName; - private String templateFingerprint; // documentId + templateId - - public SubreportMeta(String documentId) { - setDocumentId(documentId); - } - - public String getDocumentId() { - return documentId; - } - - public void setDocumentId(String documentId) { - this.documentId = documentId; - } - - public String getTemplateFingerprint() { - return templateFingerprint; - } - - public void setTemplateFingerprint(String templateFingerprint) { - this.templateFingerprint = templateFingerprint; - } - - public String getTemplateType() { - return templateType; - } - - public void setTemplateType(String templateType) { - this.templateType = templateType; - } - - public String getTemplateName() { - return templateName; - } - - public void setTemplateName(String templateName) { - this.templateName = templateName; - } - } - - private Map getSubreportsMeta(Map params) { - Map subreportsMeta; - - logger.debug("IN"); - subreportsMeta = new HashMap(); - - try { - // String subrptnumStr = (params.get("srptnum")==null)?"0":(String)params.get("srptnum"); - // int subrptnum = Integer.parseInt(subrptnumStr); - - /* - * Iterator it = params.keySet().iterator(); while(it.hasNext()){ String parName = (String)it.next(); if(parName.startsWith("subrpt") && - * parName.endsWith("id")) { int start = parName.indexOf('.') + 1; int end = parName.indexOf('.', start); String subreportKey = - * parName.substring(start, end); String subreportId = (String)params.get(parName); SubreportMeta subreportMeta = new SubreportMeta( subreportId ); - * subreportMeta.setTemplateName( (String)params.get("subrpt." + subreportKey + ".tempName") ); subreportMeta.setTemplateFingerprint( - * (String)params.get("subrpt." + subreportKey + ".prefixName") ); subreportMeta.setTemplateType( (String)params.get("subrpt." + subreportKey + - * ".flgTempStd") ); subreportsMeta.put(subreportKey, subreportMeta); logger.debug("JasperReports subreport id : " + params.get(parName)); } } - */ - Iterator it = params.keySet().iterator(); - while (it.hasNext()) { - String parName = (String) it.next(); - if (parName.startsWith("sr") && parName.endsWith("ids")) { - int start = parName.indexOf('.') + 1; - int end = parName.indexOf('.', start); - String subreportKey = parName.substring(start, end); - String subreportIds = (String) params.get(parName); - String[] ids = subreportIds.split("_"); - SubreportMeta subreportMeta = new SubreportMeta(ids[0]); - // subreportMeta.setTemplateName( (String)params.get("subrpt." + subreportKey + ".tempName") ); - subreportMeta.setTemplateFingerprint(subreportIds); - // subreportMeta.setTemplateType( (String)params.get("subrpt." + subreportKey + ".flgTempStd") ); - subreportsMeta.put(subreportKey, subreportMeta); - logger.debug("JasperReports subreport id : " + params.get(parName)); - } - } - - } catch (Throwable t) { - logger.error("Error while extracting subreports meta", t); - } finally { - logger.debug("OUT"); - } - - return subreportsMeta; - - } - - private File[] compileSubreports(Map params, ServletContext servletContext, ContentServiceProxy contentProxy, HashMap requestParameters) { - - File[] files = null; - - logger.debug("IN"); - try { - /* - * String subrptnumStr = (params.get("srptnum")==null)?"0":(String)params.get("srptnum"); int subrptnum = Integer.parseInt(subrptnumStr); String[] - * subreports = new String[subrptnum]; String[] subreportsType = new String[subrptnum]; - */ - - /* - * Iterator it = params.keySet().iterator(); while(it.hasNext()){ String parName = (String)it.next(); if(parName.startsWith("subrpt") && - * parName.endsWith("id")) { int start = parName.indexOf('.') + 1; int end = parName.indexOf('.', start); String numberStr = - * parName.substring(start, end); int number = Integer.parseInt(numberStr) - 1; subreports[number] = (String)params.get(parName); - * logger.debug("JasperReports subreport id : " + params.get(parName)); } else if(parName.startsWith("subrpt") && parName.endsWith("flgTempStd")) { - * int start = parName.indexOf('.') + 1; int end = parName.indexOf('.', start); String numberStr = parName.substring(start, end); int number = - * Integer.parseInt(numberStr) - 1; subreportsType[number] = (String)params.get(parName); } } - */ - Map subreportsMeta = getSubreportsMeta(params); - int subreportNum = subreportsMeta.keySet().size(); - - files = new File[subreportNum]; - logger.debug("Subreports number is equal to [" + subreportNum + "]"); - - Iterator it = subreportsMeta.keySet().iterator(); - int i = 0; - while (it.hasNext()) { - SubreportMeta subreportMeta = subreportsMeta.get(it.next()); - String masterIds = (String) params.get("prefixName"); - - // check if the subreport is cached into file system - String dirTemplate = getJRTempDirName(servletContext, - masterIds + System.getProperty("file.separator") + subreportMeta.getTemplateFingerprint()); - logger.debug("dirTemplate is equal to [" + dirTemplate + "]"); - - // boolean exists = (new File(dirTemplate + subreportMeta.getTemplateName() + ".jasper")).exists(); - File subreportCacheDir = new File(dirTemplate); - if (subreportCacheDir.exists()) { - logger.debug("template [" + subreportMeta.getTemplateFingerprint() + "] alredy exists"); - - // File already exists - File[] compiledJRFiles = subreportCacheDir.listFiles(new FilenameFilter() { - - @Override - public boolean accept(File dir, String name) { - logger.debug("scan dir [" + name + "]"); - return name.endsWith(".jasper"); - } - }); - logger.debug("found [" + compiledJRFiles.length + "] compiled files"); - if (compiledJRFiles.length > 1) { - throw new RuntimeException("More then one compiled file found in directory [" + subreportCacheDir + "]"); - } - // files[i] = new File(dirTemplate, subreportMeta.getTemplateName() + ".jasper"); - files[i] = compiledJRFiles[0]; - } else { - logger.debug("template [" + subreportMeta.getTemplateFingerprint() + "] does not exists yet"); - - File destDir = getJRCompilationDir(servletContext, - masterIds + System.getProperty("file.separator") + subreportMeta.getTemplateFingerprint()); - - logger.debug("destDir number is equal to [" + destDir + "]"); - - // File or directory does not exist, create a new file compiled! - // put "true" to the parameter that not permits the validation on parameters of the subreport. - requestParameters.put("SBI_READ_ONLY_TEMPLATE", "true"); - Content template = contentProxy.readTemplate(subreportMeta.getDocumentId(), requestParameters); - template.getFileName(); - logger.debug("Read the template.(subreport)" + template.getFileName()); - InputStream is = null; - Base64.Decoder bASE64Decoder = Base64.getDecoder(); - byte[] templateContent = bASE64Decoder.decode(template.getContent()); - is = new java.io.ByteArrayInputStream(templateContent); - String str = new String(templateContent); - - SpagoBIAccessUtils util = new SpagoBIAccessUtils(); - - /* - * Dynamic template management: if the template is a zip file it is opened and every class are added to the classpath - */ - String flgTemplateStandard = "true"; // = subreportMeta.getTemplateType(); - if (template.getFileName().indexOf(".zip") > -1) { - flgTemplateStandard = "false"; - } - - if (flgTemplateStandard.equalsIgnoreCase("false")) { - File fileZip = new File(destDir, this.JS_FILE_ZIP + i + JS_EXT_ZIP); - FileOutputStream foZip = new FileOutputStream(fileZip); - foZip.write(templateContent); - foZip.close(); - util.unzip(fileZip, destDir); - JarFile zipFile = new JarFile(fileZip); - Enumeration totalZipEntries = zipFile.entries(); - File jarFile = null; - while (totalZipEntries.hasMoreElements()) { - ZipEntry entry = (ZipEntry) totalZipEntries.nextElement(); - if (entry.getName().endsWith(".jar")) { - // set classloader with jar - jarFile = new File(destDir + entry.getName()); - ClassLoader previous = Thread.currentThread().getContextClassLoader(); - DynamicClassLoader dcl = new DynamicClassLoader(jarFile, previous); - // ClassLoader current = URLClassLoader.newInstance(new URL[]{jarFile.toURI().toURL()}, previous); - Thread.currentThread().setContextClassLoader(dcl); - } - if (entry.getName().endsWith(".jrxml")) { - // set InputStream with jrxml - File jrxmlFile = new File(destDir + System.getProperty("file.separator") + entry.getName()); - InputStream isJrxml = new FileInputStream(jrxmlFile); - templateContent = util.getByteArrayFromInputStream(isJrxml); - is = new java.io.ByteArrayInputStream(templateContent); - } - } - } - - JasperDesign jasperDesign = JRXmlLoader.load(is); - // the following instruction is necessary because the above instruction cleans variable 'is' - is = new java.io.ByteArrayInputStream(templateContent); - - files[i] = new File(destDir, jasperDesign.getName() + ".jasper"); - logger.debug("Compiling template file: " + files[i]); - - FileOutputStream fos = null; - try { - fos = new FileOutputStream(files[i]); - } catch (FileNotFoundException e) { - logger.error("Internal error in compiling subreport method", e); - } - JasperCompileManager.compileReportToStream(is, fos); - logger.debug("Template file compiled succesfully"); - } - - // adds the subreport's folder to the classpath - /* - * ClassLoader previous = Thread.currentThread().getContextClassLoader(); ClassLoader current = URLClassLoader.newInstance( new URL[]{ - * getJRCompilationDir(servletContext, masterIds + System.getProperty("file.separator") + - * subreportMeta.getTemplateFingerprint()).toURI().toURL() }, previous); - */ - // Thread.currentThread().setContextClassLoader(current); - - i++; - } - - URL[] urls = new URL[files.length]; - for (int j = 0; j < files.length; j++) { - // adds the subreport's folder to the classpath - urls[j] = files[j].getParentFile().toURI().toURL(); - logger.debug("Added url [" + files[j].getParentFile().toURI().toURL() + "] to classloader"); - } - ClassLoader previous = Thread.currentThread().getContextClassLoader(); - ClassLoader current = URLClassLoader.newInstance(urls, previous); - Thread.currentThread().setContextClassLoader(current); - } catch (Throwable t) { - logger.error("Error while ccompiling subreports", t); - } finally { - logger.debug("OUT"); - } - - return files; - } - -} diff --git a/knowagemeta/src/main/java/it/eng/knowage/meta/generator/jpamapping/JpaMappingClassesGenerator.java b/knowagemeta/src/main/java/it/eng/knowage/meta/generator/jpamapping/JpaMappingClassesGenerator.java index e5e94686d4a..9c3a9ca0efa 100644 --- a/knowagemeta/src/main/java/it/eng/knowage/meta/generator/jpamapping/JpaMappingClassesGenerator.java +++ b/knowagemeta/src/main/java/it/eng/knowage/meta/generator/jpamapping/JpaMappingClassesGenerator.java @@ -58,7 +58,6 @@ public class JpaMappingClassesGenerator extends JpaMappingCodeGenerator { private String[] libs; public JpaMappingClassesGenerator() { - super(); } @Override @@ -77,6 +76,7 @@ public void generate(ModelObject o, String outputDir, boolean isUpdatableMapping super.generate(o, outputDir, isUpdatableMapping, includeSources, libsDir, null); binDir = (binDir == null) ? new File(outputDir, DEFAULT_BIN_DIR) : binDir; + LOGGER.debug("src dir is equal to [{}]", getSrcDir()); // libDir = (libDir == null) ? new File(outputDir, DEFAULT_LIB_DIR) : libDir; libDir = (libsDir == null) ? new File(outputDir, DEFAULT_LIB_DIR) : libsDir; @@ -93,13 +93,9 @@ public void generate(ModelObject o, String outputDir, boolean isUpdatableMapping Compiler compiler; if (libs == null) { - try(Stream paths = Files.list(libDir.toPath())) { + try (Stream paths = Files.list(libDir.toPath())) { - libs = paths - .map(e -> libDir.toPath().relativize(e)) - .map(Path::toString) - .collect(toList()) - .toArray(new String[0]); + libs = paths.map(e -> libDir.toPath().relativize(e)).map(Path::toString).collect(toList()).toArray(new String[0]); } catch (IOException e) { throw new GenerationException("Impossible to compile mapping code. Please download errors log", e); @@ -181,8 +177,7 @@ public void setLibs(String[] libs) { } /** - * @param errorLog - * the errorLog to set + * @param errorLog the errorLog to set */ public void setErrorLog(PrintWriter errorLog) { this.errorLog = errorLog; diff --git a/knowagetalendengine/src/main/java/it/eng/spagobi/engines/talend/runtime/JobDeploymentDescriptor.java b/knowagetalendengine/src/main/java/it/eng/spagobi/engines/talend/runtime/JobDeploymentDescriptor.java index 6022578ce94..de5d62403ca 100644 --- a/knowagetalendengine/src/main/java/it/eng/spagobi/engines/talend/runtime/JobDeploymentDescriptor.java +++ b/knowagetalendengine/src/main/java/it/eng/spagobi/engines/talend/runtime/JobDeploymentDescriptor.java @@ -5,9 +5,6 @@ * If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package it.eng.spagobi.engines.talend.runtime; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.InputStream; import javax.xml.XMLConstants; @@ -47,18 +44,6 @@ public JobDeploymentDescriptor(String project, String language) { this.language = language; } - /** - * Load. - * - * @param file the file - * - * @throws FileNotFoundException the file not found exception - * @throws DocumentException the document exception - */ - public void load(File file) throws FileNotFoundException, DocumentException { - load(new FileInputStream(file)); - } - /** * Load. * diff --git a/knowagetalendengine/src/main/java/it/eng/spagobi/engines/talend/runtime/RuntimeRepository.java b/knowagetalendengine/src/main/java/it/eng/spagobi/engines/talend/runtime/RuntimeRepository.java index 4c6dc894771..074ad6b4766 100644 --- a/knowagetalendengine/src/main/java/it/eng/spagobi/engines/talend/runtime/RuntimeRepository.java +++ b/knowagetalendengine/src/main/java/it/eng/spagobi/engines/talend/runtime/RuntimeRepository.java @@ -6,11 +6,10 @@ package it.eng.spagobi.engines.talend.runtime; import java.io.File; -import java.io.IOException; import java.util.Map; -import java.util.zip.ZipException; import java.util.zip.ZipFile; +import it.eng.knowage.commons.security.PathTraversalChecker; import it.eng.spagobi.engines.talend.exception.ContextNotFoundException; import it.eng.spagobi.engines.talend.exception.JobExecutionException; import it.eng.spagobi.engines.talend.exception.JobNotFoundException; @@ -27,8 +26,7 @@ public class RuntimeRepository { /** * Instantiates a new runtime repository. * - * @param rootDir - * the root dir + * @param rootDir the root dir */ public RuntimeRepository(File rootDir) { this.rootDir = rootDir; @@ -37,10 +35,8 @@ public RuntimeRepository(File rootDir) { /** * Deploy job. * - * @param jobDeploymentDescriptor - * the job deployment descriptor - * @param executableJobFiles - * the executable job files + * @param jobDeploymentDescriptor the job deployment descriptor + * @param executableJobFiles the executable job files */ public void deployJob(JobDeploymentDescriptor jobDeploymentDescriptor, ZipFile executableJobFiles) { File jobsDir = new File(rootDir, jobDeploymentDescriptor.getLanguage().toLowerCase()); @@ -51,18 +47,13 @@ public void deployJob(JobDeploymentDescriptor jobDeploymentDescriptor, ZipFile e /** * Run job. * - * @param job - * the job - * @param env - * the environment + * @param job the job + * @param env the environment * * - * @throws JobNotFoundException - * the job not found exception - * @throws ContextNotFoundException - * the context not found exception - * @throws JobExecutionException - * the job execution exception + * @throws JobNotFoundException the job not found exception + * @throws ContextNotFoundException the context not found exception + * @throws JobExecutionException the job execution exception */ public void runJob(Job job, Map env) throws JobNotFoundException, ContextNotFoundException, JobExecutionException { IJobRunner jobRunner; @@ -76,8 +67,7 @@ public void runJob(Job job, Map env) throws JobNotFoundException, ContextNotFoun /** * Gets the job runner. * - * @param jobLanguage - * the job language + * @param jobLanguage the job language * * @return the job runner */ @@ -103,8 +93,7 @@ public File getRootDir() { /** * Sets the root dir. * - * @param rootDir - * the new root dir + * @param rootDir the new root dir */ public void setRootDir(File rootDir) { this.rootDir = rootDir; @@ -113,8 +102,7 @@ public void setRootDir(File rootDir) { /** * Gets the executable job project dir. * - * @param job - * the job + * @param job the job * * @return the executable job project dir */ @@ -127,57 +115,38 @@ public File getExecutableJobProjectDir(Job job) { /** * Gets the executable job dir. * - * @param job - * the job + * @param job the job * * @return the executable job dir */ public File getExecutableJobDir(Job job) { - File jobDir = new File(getExecutableJobProjectDir(job), job.getName()); + File projectDir = getExecutableJobProjectDir(job); + File jobDir = PathTraversalChecker.get(projectDir.getAbsolutePath(), job.getName()); + return jobDir; } /** * Gets the executable job file. * - * @param job - * the job + * @param job the job * * @return the executable job file */ public File getExecutableJobFile(Job job) { - File jobExecutableFile = new File(getExecutableJobDir(job), TalendScriptAccessUtils.getExecutableFileName(job)); + File jobExecutableFile = PathTraversalChecker.get(getExecutableJobDir(job).getAbsolutePath(), TalendScriptAccessUtils.getExecutableFileName(job)); + return jobExecutableFile; } /** * Contains job. * - * @param job - * the job + * @param job the job * * @return true, if successful */ public boolean containsJob(Job job) { return getExecutableJobFile(job).exists(); } - - /** - * The main method. - * - * @param args - * the arguments - * - * @throws ZipException - * the zip exception - * @throws IOException - * Signals that an I/O exception has occurred. - */ - public static void main(String[] args) throws ZipException, IOException { - File rootDir = new File("C:\\Prototipi\\SpagoBI-Demo-1.9.2\\webapps\\SpagoBITalendEngine\\RuntimeRepository"); - File zipFile = new File("C:\\Prototipi\\TalendJob2.zip"); - RuntimeRepository runtimeRepository = new RuntimeRepository(rootDir); - JobDeploymentDescriptor jobDeploymentDescriptor = new JobDeploymentDescriptor("PP2", "perl"); - runtimeRepository.deployJob(jobDeploymentDescriptor, new ZipFile(zipFile)); - } } diff --git a/knowageutils/src/main/java/it/eng/knowage/commons/security/PathTraversalChecker.java b/knowageutils/src/main/java/it/eng/knowage/commons/security/PathTraversalChecker.java index 4671b93e907..10f12bec3cf 100644 --- a/knowageutils/src/main/java/it/eng/knowage/commons/security/PathTraversalChecker.java +++ b/knowageutils/src/main/java/it/eng/knowage/commons/security/PathTraversalChecker.java @@ -37,22 +37,45 @@ private PathTraversalChecker() { throw new IllegalStateException("This class provides utility methods. It cannot be instantiated"); } + /** + * Utility method for Path Traversal Attacks prevention. It checks if the sub-directories and files are safe using name and path traversal attack + * validation. The safe directory must be explicitly defined, not dependent on user input, and known to be safe. + * + * @param safeDirectory directory that should be considered safe, it should be defined in configuration + * @param otherFolders folders and files that need to be checked + */ + public static File get(String safeDirectory, String... otherFolders) throws PathTraversalAttackException { + File previousFolderFile = new File(safeDirectory); + + File currentFolderFile = null; + for (String currentFolder : otherFolders) { + isValidFileName(currentFolder); + + currentFolderFile = new File(previousFolderFile, currentFolder); + + preventPathTraversalAttack(previousFolderFile, currentFolderFile); + + previousFolderFile = currentFolderFile; + } + + return currentFolderFile; + } + /** * Utility method for Path Traversal Attacks prevention. It checks that input fine is inside the desired directory or within sub-directory of the desired * directory. In case this is not satisfied, a PathTraversalAttackException is thrown. It is useful when desiredDirectory is known and safe, while file to * be checked is created combining some user inputs. * - * @param fileToBeChecked the file to be checked * @param desiredDirectory the desired directory that is supposed to contain (at any sub-level) the file + * @param fileToBeChecked the file to be checked */ - public static void preventPathTraversalAttack(File fileToBeChecked, File desiredDirectory) { + private static void preventPathTraversalAttack(File desiredDirectory, File fileToBeChecked) { LogMF.debug(logger, "IN : fileToBeChecked = [{0}], desiredDirectory = [{1}]", fileToBeChecked, desiredDirectory); try { Assert.assertNotNull(fileToBeChecked, "File to be checked cannot be null"); Assert.assertNotNull(desiredDirectory, "Desired directory cannot be null"); - Assert.assertTrue(desiredDirectory.exists() && desiredDirectory.isDirectory(), "Desired directory must be an existing folder"); - boolean isInDesiredDirectory = isInDesiredDirectory(fileToBeChecked, desiredDirectory); + boolean isInDesiredDirectory = isDescendentOfDirectory(fileToBeChecked, desiredDirectory); if (!isInDesiredDirectory) { UserProfile profile = UserProfileManager.getProfile(); @@ -66,19 +89,28 @@ public static void preventPathTraversalAttack(File fileToBeChecked, File desired } } - private static boolean isInDesiredDirectory(File fileToBeChecked, File desiredDirectory) { + public static void checkDescendentOfDirectory(File descendentFile, File ancestorDirectory) { + boolean isDescendent = isDescendentOfDirectory(descendentFile, ancestorDirectory); + if (!isDescendent) { + UserProfile profile = UserProfileManager.getProfile(); + throw new PathTraversalAttackException("User [" + profile + "] is trying to access the file [" + descendentFile.getAbsolutePath() + + "] that is not inside [" + ancestorDirectory.getAbsolutePath() + "]!!!"); + } + } + + private static boolean isDescendentOfDirectory(File descendentFile, File ancestorDirectory) { try { - fileToBeChecked = fileToBeChecked.getCanonicalFile(); - desiredDirectory = desiredDirectory.getCanonicalFile(); + descendentFile = descendentFile.getCanonicalFile(); + ancestorDirectory = ancestorDirectory.getCanonicalFile(); } catch (IOException e) { throw new SpagoBIRuntimeException("Error while converting input files into canonical ones", e); } - File parent = fileToBeChecked.getParentFile(); + File parent = descendentFile.getParentFile(); boolean toReturn = false; while (parent != null) { - if (desiredDirectory.equals(parent)) { - LogMF.debug(logger, "Desired directory [{0} matches parent folder of input file]", desiredDirectory); + if (ancestorDirectory.equals(parent)) { + LogMF.debug(logger, "Desired directory [{0} matches parent folder of input file]", ancestorDirectory); toReturn = true; break; } diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/utils/datamart/DefaultEngineDatamartRetriever.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/utils/datamart/DefaultEngineDatamartRetriever.java index 0a21678c821..2328a6c1b89 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/utils/datamart/DefaultEngineDatamartRetriever.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/utils/datamart/DefaultEngineDatamartRetriever.java @@ -29,6 +29,7 @@ import org.apache.log4j.Logger; +import it.eng.knowage.commons.security.PathTraversalChecker; import it.eng.spagobi.commons.utilities.StringUtilities; import it.eng.spagobi.services.common.EnginConf; import it.eng.spagobi.services.proxy.MetamodelServiceProxy; @@ -79,16 +80,17 @@ public File getDataMartDir() { @Override public File retrieveDatamartFile(String metamodelName) { - File metamodelJarFile; + File metamodelJarFile = null; LOGGER.debug("IN"); - metamodelJarFile = null; try { Assert.assertTrue(StringUtilities.isNotEmpty(metamodelName), "Input parameter [metamodelName] cannot be null"); LOGGER.debug("Load metamodel jar file for model [" + metamodelName + "]"); - File targetMetamodelFolder = new File(getDataMartDir(), metamodelName); + File directory = getDataMartDir(); + File targetMetamodelFolder = PathTraversalChecker.get(directory.getAbsolutePath(), metamodelName); + metamodelJarFile = new File(targetMetamodelFolder, "datamart.jar"); if (metamodelJarFile.exists()) { @@ -116,10 +118,8 @@ public File retrieveDatamartFile(String metamodelName) { /** * Download the jarFile from SpagoBI server and store it on the local filesystem in the specified folder * - * @param metamodelName - * the name of the metamodel to download - * @param destinationFolder - * the destination folder on the local filesystem + * @param metamodelName the name of the metamodel to download + * @param destinationFolder the destination folder on the local filesystem */ private void downloadJarFile(String metamodelName, File destinationFolder) { DataHandler handler = null; @@ -141,10 +141,8 @@ private void downloadJarFile(String metamodelName, File destinationFolder) { /** * Store the jarFile on local filesystem * - * @param dataHandler - * the jarFile content - * @param destinationFolder - * the destination folder on the local filesystem + * @param dataHandler the jarFile content + * @param destinationFolder the destination folder on the local filesystem */ private void storeJarFile(DataHandler dataHandler, File destinationFolder) { diff --git a/knowageutils/src/main/java/it/eng/spagobi/utilities/SpagoBIAccessUtils.java b/knowageutils/src/main/java/it/eng/spagobi/utilities/SpagoBIAccessUtils.java index 1d84cf401f6..23568865f69 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/utilities/SpagoBIAccessUtils.java +++ b/knowageutils/src/main/java/it/eng/spagobi/utilities/SpagoBIAccessUtils.java @@ -31,6 +31,8 @@ import org.apache.log4j.Logger; +import it.eng.knowage.commons.security.PathTraversalChecker; + /** * This class has been created to provide SpagoBI Access Utils, in order to customize operations with clients. * @@ -43,15 +45,11 @@ public class SpagoBIAccessUtils { /** * Unzip. * - * @param repositoryZip - * the repository_zip - * @param newDirectory - * the new directory + * @param repositoryZip the repository_zip + * @param newDirectory the new directory * - * @throws ZipException - * the zip exception - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws ZipException the zip exception + * @throws IOException Signals that an I/O exception has occurred. */ public void unzip(File repositoryZip, File newDirectory) throws ZipException, IOException { try (ZipFile zipFile = new ZipFile(repositoryZip)) { @@ -65,6 +63,7 @@ public void unzip(File repositoryZip, File newDirectory) throws ZipException, IO name = entry.getName(); path = newDirectory.getPath() + File.separator + name; file = new File(path); + PathTraversalChecker.checkDescendentOfDirectory(file, newDirectory); // if file already exists, deletes it if (file.exists() && file.isFile()) @@ -73,7 +72,10 @@ public void unzip(File repositoryZip, File newDirectory) throws ZipException, IO if (!entry.isDirectory()) { file = file.getParentFile(); file.mkdirs(); - try (FileOutputStream fileout = new FileOutputStream(newDirectory.getPath() + File.separator + entry.getName()); + + String fileName = newDirectory.getPath() + File.separator + entry.getName(); + + try (FileOutputStream fileout = new FileOutputStream(fileName); BufferedOutputStream bufout = new BufferedOutputStream(fileout); InputStream in = zipFile.getInputStream(entry)) { copyInputStream(in, bufout); @@ -97,8 +99,7 @@ private void copyInputStream(InputStream in, OutputStream out) throws IOExceptio /** * Delete directory. * - * @param pathdest - * the pathdest + * @param pathdest the pathdest * * @return true, if successful */ @@ -110,8 +111,7 @@ public boolean deleteDirectory(String pathdest) { /** * Delete directory. * - * @param directory - * the directory + * @param directory the directory * * @return true, if successful */ @@ -139,10 +139,8 @@ public boolean deleteDirectory(File directory) { /** * Delete file. * - * @param fileName - * the file name - * @param path - * the path + * @param fileName the file name + * @param path the path * * @return true, if successful */ @@ -160,8 +158,7 @@ public boolean deleteFile(String fileName, String path) { /** * Given an InputStream as input, gets the correspondent bytes array. * - * @param is - * The input straeam + * @param is The input straeam * * @return An array of bytes obtained from the input stream. */ @@ -194,12 +191,9 @@ public byte[] getByteArrayFromInputStream(InputStream is) { /** * Given an InputStream as input flushs the content into an OutputStream and then close the input and output stream. * - * @param is - * The input stream - * @param os - * The output stream - * @param closeStreams - * the close streams + * @param is The input stream + * @param os The output stream + * @param closeStreams the close streams */ public void flushFromInputStreamToOutputStream(InputStream is, OutputStream os, boolean closeStreams) { try {