From cb9a967c4b89b3465722e6b57c4ac40aae1871a4 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Thu, 21 Dec 2017 17:07:54 -0500 Subject: [PATCH 01/28] 3412: rename index.html to report.html and move html report files to a subdirectory --- .../autopsy/report/Bundle.properties | 6 +-- .../sleuthkit/autopsy/report/ReportHTML.java | 50 +++++++++++-------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties index 09c6fa8906..49eb13d806 100755 --- a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties @@ -181,8 +181,8 @@ ReportHTML.getName.text=Results - HTML ReportHTML.getDesc.text=A report about results and tagged items in HTML format. ReportHTML.writeIndex.title=for case {0} ReportHTML.writeIndex.noFrames.msg=Your browser is not compatible with our frame setup. -ReportHTML.writeIndex.noFrames.seeNav=Please see the navigation page for artifact links, -ReportHTML.writeIndex.seeSum=and the summary page for a case summary. +ReportHTML.writeIndex.noFrames.seeNav=Please see the navigation page for artifact links, +ReportHTML.writeIndex.seeSum=and the summary page for a case summary. ReportHTML.writeNav.title=Report Navigation ReportHTML.writeNav.h1=Report Navigation ReportHTML.writeNav.summary=Case Summary @@ -190,7 +190,7 @@ ReportHTML.writeSum.title=Case Summary ReportHTML.writeSum.warningMsg=Warning, this report was run before ingest services completed\! # # autopsy/test/scripts/regression.py._html_report_diff() uses reportGenOn.text, caseName, caseNum, -# examiner as a regex signature to skip index.html and summary.html +# examiner as a regex signature to skip report.html and summary.html # ReportHTML.writeSum.reportGenOn.text=HTML Report Generated on {0} ReportHTML.writeSum.caseName=Case\: diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java index 834fb69710..83163054d8 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java @@ -72,6 +72,8 @@ class ReportHTML implements TableReportModule { private static final String THUMBS_REL_PATH = "thumbs" + File.separator; //NON-NLS private static ReportHTML instance; private static final int MAX_THUMBS_PER_PAGE = 1000; + private static final String HTML_REPORT = "HTML Report"; + private static final String HTML_SUBDIR = "reports"; private Case currentCase; private SleuthkitCase skCase; static Integer THUMBNAIL_COLUMNS = 5; @@ -79,6 +81,7 @@ class ReportHTML implements TableReportModule { private Map dataTypes; private String path; private String thumbsPath; + private String subPath; private String currentDataType; // name of current data type private Integer rowCount; // number of rows (aka artifacts or tags) for the current data type private Writer out; @@ -107,6 +110,7 @@ class ReportHTML implements TableReportModule { path = ""; thumbsPath = ""; + subPath = ""; currentDataType = ""; rowCount = 0; @@ -157,7 +161,7 @@ class ReportHTML implements TableReportModule { if (null != artifactType) { // set the icon file name iconFileName = dataTypeToFileName(artifactType.getDisplayName()) + ".png"; //NON-NLS - iconFilePath = path + File.separator + iconFileName; + iconFilePath = subPath + iconFileName; // determine the source image to use switch (artifactType) { @@ -268,7 +272,7 @@ class ReportHTML implements TableReportModule { logger.log(Level.WARNING, "useDataTypeIcon: unhandled artifact type = " + dataType); //NON-NLS in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/star.png"); //NON-NLS iconFileName = "star.png"; //NON-NLS - iconFilePath = path + File.separator + iconFileName; + iconFilePath = subPath + iconFileName; break; } } else if (dataType.startsWith(ARTIFACT_TYPE.TSK_ACCOUNT.getDisplayName())) { @@ -281,11 +285,11 @@ class ReportHTML implements TableReportModule { */ in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/accounts.png"); //NON-NLS iconFileName = "accounts.png"; //NON-NLS - iconFilePath = path + File.separator + iconFileName; + iconFilePath = subPath + iconFileName; } else { // no defined artifact found for this dataType in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/star.png"); //NON-NLS iconFileName = "star.png"; //NON-NLS - iconFilePath = path + File.separator + iconFileName; + iconFilePath = subPath + iconFileName; } try { @@ -325,10 +329,12 @@ class ReportHTML implements TableReportModule { // Refresh the HTML report refresh(); // Setup the path for the HTML report - this.path = baseReportDir + "HTML Report" + File.separator; //NON-NLS - this.thumbsPath = this.path + "thumbs" + File.separator; //NON-NLS + this.path = baseReportDir + HTML_REPORT + File.separator; //NON-NLS + this.subPath = this.path + HTML_SUBDIR + File.separator; + this.thumbsPath = this.subPath + THUMBS_REL_PATH; //NON-NLS try { FileUtil.createFolder(new File(this.path)); + FileUtil.createFolder(new File(this.subPath)); FileUtil.createFolder(new File(this.thumbsPath)); } catch (IOException ex) { logger.log(Level.SEVERE, "Unable to make HTML report folder."); //NON-NLS @@ -367,7 +373,7 @@ class ReportHTML implements TableReportModule { public void startDataType(String name, String description) { String title = dataTypeToFileName(name); try { - out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path + title + ".html"), "UTF-8")); //NON-NLS + out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(subPath + title + ".html"), "UTF-8")); //NON-NLS } catch (FileNotFoundException ex) { logger.log(Level.SEVERE, "File not found: {0}", ex); //NON-NLS } catch (UnsupportedEncodingException ex) { @@ -747,7 +753,7 @@ class ReportHTML implements TableReportModule { // Make a folder for the local file with the same tagName as the tag. StringBuilder localFilePath = new StringBuilder(); // full path - localFilePath.append(path); + localFilePath.append(subPath); localFilePath.append(dirName2); File localFileFolder = new File(localFilePath.toString()); if (!localFileFolder.exists()) { @@ -777,7 +783,7 @@ class ReportHTML implements TableReportModule { } // get the relative path - return localFilePath.toString().substring(path.length()); + return localFilePath.toString().substring(subPath.length()); } /** @@ -795,7 +801,7 @@ class ReportHTML implements TableReportModule { @Override public String getRelativeFilePath() { - return "HTML Report" + File.separator + "index.html"; //NON-NLS + return HTML_REPORT + File.separator + "report.html"; //NON-NLS } @Override @@ -814,7 +820,7 @@ class ReportHTML implements TableReportModule { private void writeCss() { Writer cssOut = null; try { - cssOut = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path + "index.css"), "UTF-8")); //NON-NLS NON-NLS + cssOut = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(subPath + "index.css"), "UTF-8")); //NON-NLS NON-NLS String css = "body {margin: 0px; padding: 0px; background: #FFFFFF; font: 13px/20px Arial, Helvetica, sans-serif; color: #535353;}\n" + //NON-NLS "#content {padding: 30px;}\n" @@ -875,7 +881,7 @@ class ReportHTML implements TableReportModule { */ private void writeIndex() { Writer indexOut = null; - String indexFilePath = path + "index.html"; //NON-NLS + String indexFilePath = path + "report.html"; //NON-NLS try { indexOut = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(indexFilePath), "UTF-8")); //NON-NLS StringBuilder index = new StringBuilder(); @@ -883,7 +889,7 @@ class ReportHTML implements TableReportModule { String iconPath = reportBranding.getAgencyLogoPath(); if (iconPath == null) { // use default Autopsy icon if custom icon is not set - iconPath = "favicon.ico"; + iconPath = HTML_SUBDIR + "favicon.ico"; } else { iconPath = Paths.get(reportBranding.getAgencyLogoPath()).getFileName().toString(); //ref to writeNav() for agency_logo } @@ -895,8 +901,8 @@ class ReportHTML implements TableReportModule { index.append("\n"); //NON-NLS index.append("\n"); //NON-NLS index.append("\n"); //NON-NLS - index.append("\n"); //NON-NLS - index.append("\n"); //NON-NLS + index.append("\n"); //NON-NLS + index.append("\n"); //NON-NLS index.append("").append(NbBundle.getMessage(this.getClass(), "ReportHTML.writeIndex.noFrames.msg")).append("<br />\n"); //NON-NLS index.append(NbBundle.getMessage(this.getClass(), "ReportHTML.writeIndex.noFrames.seeNav")).append("<br />\n"); //NON-NLS index.append(NbBundle.getMessage(this.getClass(), "ReportHTML.writeIndex.seeSum")).append("\n"); //NON-NLS @@ -906,7 +912,7 @@ class ReportHTML implements TableReportModule { Case.getCurrentCase().addReport(indexFilePath, NbBundle.getMessage(this.getClass(), "ReportHTML.writeIndex.srcModuleName.text"), ""); } catch (IOException ex) { - logger.log(Level.SEVERE, "Error creating Writer for index.html: {0}", ex); //NON-NLS + logger.log(Level.SEVERE, "Error creating Writer for report.html: {0}", ex); //NON-NLS } catch (TskCoreException ex) { String errorMessage = String.format("Error adding %s to case as a report", indexFilePath); //NON-NLS logger.log(Level.SEVERE, errorMessage, ex); @@ -927,7 +933,7 @@ class ReportHTML implements TableReportModule { private void writeNav() { Writer navOut = null; try { - navOut = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path + "nav.html"), "UTF-8")); //NON-NLS + navOut = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(subPath + "nav.html"), "UTF-8")); //NON-NLS StringBuilder nav = new StringBuilder(); nav.append("\n\n\t").append( //NON-NLS NbBundle.getMessage(this.getClass(), "ReportHTML.writeNav.title")) @@ -972,24 +978,24 @@ class ReportHTML implements TableReportModule { String generatorLogoPath = reportBranding.getGeneratorLogoPath(); if (generatorLogoPath != null && !generatorLogoPath.isEmpty()) { File from = new File(generatorLogoPath); - File to = new File(path); + File to = new File(subPath); FileUtil.copyFile(FileUtil.toFileObject(from), FileUtil.toFileObject(to), "generator_logo"); //NON-NLS } String agencyLogoPath = reportBranding.getAgencyLogoPath(); if (agencyLogoPath != null && !agencyLogoPath.isEmpty()) { - Path destinationPath = Paths.get(path); + Path destinationPath = Paths.get(subPath); Files.copy(Files.newInputStream(Paths.get(agencyLogoPath)), destinationPath.resolve(Paths.get(agencyLogoPath).getFileName())); //NON-NLS } in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/favicon.ico"); //NON-NLS - output = new FileOutputStream(new File(path + File.separator + "favicon.ico")); + output = new FileOutputStream(new File(subPath + "favicon.ico")); FileUtil.copy(in, output); in.close(); output.close(); in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/summary.png"); //NON-NLS - output = new FileOutputStream(new File(path + File.separator + "summary.png")); + output = new FileOutputStream(new File(subPath + "summary.png")); FileUtil.copy(in, output); in.close(); output.close(); @@ -1019,7 +1025,7 @@ class ReportHTML implements TableReportModule { private void writeSummary() { Writer out = null; try { - out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path + "summary.html"), "UTF-8")); //NON-NLS + out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(subPath + "summary.html"), "UTF-8")); //NON-NLS StringBuilder head = new StringBuilder(); head.append("<html>\n<head>\n<title>").append( //NON-NLS NbBundle.getMessage(this.getClass(), "ReportHTML.writeSum.title")).append("\n"); //NON-NLS From ee06b813e46a630badbba7c4aabee5cd59fa6ee5 Mon Sep 17 00:00:00 2001 From: esaunders Date: Wed, 3 Jan 2018 14:46:23 -0500 Subject: [PATCH 02/28] Upgrade to Tika 1.17 --- Core/ivy.xml | 4 +- Core/nbproject/project.properties | 12 +- Core/nbproject/project.xml | 40 +-- CoreLibs/ivy.xml | 4 +- CoreLibs/nbproject/project.properties | 10 +- CoreLibs/nbproject/project.xml | 98 +++++--- Experimental/ivy.xml | 2 +- Experimental/nbproject/project.properties | 2 +- Experimental/nbproject/project.xml | 8 +- KeywordSearch/ivy.xml | 2 +- KeywordSearch/nbproject/project.properties | 79 +++--- KeywordSearch/nbproject/project.xml | 272 ++++++++------------- 12 files changed, 228 insertions(+), 305 deletions(-) diff --git a/Core/ivy.xml b/Core/ivy.xml index 35cb8de904..6d67fb0992 100755 --- a/Core/ivy.xml +++ b/Core/ivy.xml @@ -15,8 +15,8 @@ - - + + diff --git a/Core/nbproject/project.properties b/Core/nbproject/project.properties index d98228ef4e..ec299345a1 100755 --- a/Core/nbproject/project.properties +++ b/Core/nbproject/project.properties @@ -1,6 +1,6 @@ file.reference.activemq-all-5.11.1.jar=release/modules/ext/activemq-all-5.11.1.jar file.reference.c3p0-0.9.5.jar=release/modules/ext/c3p0-0.9.5.jar -file.reference.commons-compress-1.12.jar=release/modules/ext/commons-compress-1.12.jar +file.reference.commons-compress-1.14.jar=release/modules/ext/commons-compress-1.14.jar file.reference.commons-dbcp2-2.1.1.jar=release\\modules\\ext\\commons-dbcp2-2.1.1.jar file.reference.commons-pool2-2.4.2.jar=release\\modules\\ext\\commons-pool2-2.4.2.jar file.reference.jdom-2.0.5-contrib.jar=release/modules/ext/jdom-2.0.5-contrib.jar @@ -8,7 +8,7 @@ file.reference.jdom-2.0.5.jar=release/modules/ext/jdom-2.0.5.jar file.reference.jsoup-1.10.3.jar=release/modules/ext/jsoup-1.10.3.jar file.reference.jython-standalone-2.7.0.jar=release/modules/ext/jython-standalone-2.7.0.jar file.reference.mchange-commons-java-0.2.9.jar=release/modules/ext/mchange-commons-java-0.2.9.jar -file.reference.metadata-extractor-2.9.1.jar=release/modules/ext/metadata-extractor-2.9.1.jar +file.reference.metadata-extractor-2.10.1.jar=release/modules/ext/metadata-extractor-2.10.1.jar file.reference.postgresql-9.4.1211.jre7.jar=release/modules/ext/postgresql-9.4.1211.jre7.jar file.reference.opencv-248.jar=release/modules/ext/opencv-248.jar file.reference.Rejistry-1.0-SNAPSHOT.jar=release/modules/ext/Rejistry-1.0-SNAPSHOT.jar @@ -16,14 +16,14 @@ file.reference.sevenzipjbinding-AllPlatforms.jar=release/modules/ext/sevenzipjbi file.reference.sevenzipjbinding.jar=release/modules/ext/sevenzipjbinding.jar file.reference.sqlite-jdbc-3.8.11.jar=release/modules/ext/sqlite-jdbc-3.8.11.jar file.reference.StixLib.jar=release/modules/ext/StixLib.jar -file.reference.tika-core-1.14.jar=release/modules/ext/tika-core-1.14.jar -file.reference.tika-parsers-1.14.jar=release/modules/ext/tika-parsers-1.14.jar +file.reference.tika-core-1.17.jar=release/modules/ext/tika-core-1.17.jar +file.reference.tika-parsers-1.17.jar=release/modules/ext/tika-parsers-1.17.jar file.reference.Tsk_DataModel_PostgreSQL.jar=release/modules/ext/Tsk_DataModel_PostgreSQL.jar -file.reference.xmpcore-5.1.2.jar=release/modules/ext/xmpcore-5.1.2.jar file.reference.curator-client-2.8.0.jar=release/modules/ext/curator-client-2.8.0.jar file.reference.curator-framework-2.8.0.jar=release/modules/ext/curator-framework-2.8.0.jar file.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0.jar -file.reference.xz-1.5.jar=release/modules/ext/xz-1.5.jar +file.reference.xmpcore-5.1.3.jar=release/modules/ext/xmpcore-5.1.3.jar +file.reference.xz-1.6.jar=release/modules/ext/xz-1.6.jar file.reference.zookeeper-3.4.6.jar=release/modules/ext/zookeeper-3.4.6.jar javac.source=1.8 javac.compilerargs=-Xlint -Xlint:-serial diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index 1663abca2b..1407b88da9 100755 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -328,10 +328,6 @@ ext/jdom-2.0.5.jar release/modules/ext/jdom-2.0.5.jar - - ext/tika-core-1.14.jar - release/modules/ext/tika-core-1.14.jar - ext/Tsk_DataModel_PostgreSQL.jar release/modules/ext/Tsk_DataModel_PostgreSQL.jar @@ -345,12 +341,12 @@ release/modules/ext/curator-framework-2.8.0.jar - ext/commons-dbcp2-2.1.1.jar - release\modules\ext\commons-dbcp2-2.1.1.jar + ext/commons-compress-1.14.jar + release/modules/ext/commons-compress-1.14.jar - ext/tika-parsers-1.14.jar - release/modules/ext/tika-parsers-1.14.jar + ext/commons-dbcp2-2.1.1.jar + release\modules\ext\commons-dbcp2-2.1.1.jar ext/jython-standalone-2.7.0.jar @@ -373,12 +369,12 @@ release/modules/ext/curator-recipes-2.8.0.jar - ext/xz-1.5.jar - release/modules/ext/xz-1.5.jar + ext/metadata-extractor-2.10.1.jar + release/modules/ext/metadata-extractor-2.10.1.jar - ext/xmpcore-5.1.2.jar - release/modules/ext/xmpcore-5.1.2.jar + ext/tika-core-1.17.jar + release/modules/ext/tika-core-1.17.jar ext/StixLib.jar @@ -388,6 +384,10 @@ ext/curator-client-2.8.0.jar release/modules/ext/curator-client-2.8.0.jar + + ext/tika-parsers-1.17.jar + release/modules/ext/tika-parsers-1.17.jar + ext/sqlite-jdbc-3.8.11.jar release/modules/ext/sqlite-jdbc-3.8.11.jar @@ -396,6 +396,10 @@ ext/activemq-all-5.11.1.jar release/modules/ext/activemq-all-5.11.1.jar + + ext/xz-1.6.jar + release/modules/ext/xz-1.6.jar + ext/Rejistry-1.0-SNAPSHOT.jar release/modules/ext/Rejistry-1.0-SNAPSHOT.jar @@ -408,14 +412,6 @@ ext/commons-pool2-2.4.2.jar release\modules\ext\commons-pool2-2.4.2.jar - - ext/metadata-extractor-2.9.1.jar - release/modules/ext/metadata-extractor-2.9.1.jar - - - ext/commons-compress-1.12.jar - release/modules/ext/commons-compress-1.12.jar - ext/jsoup-1.10.3.jar release/modules/ext/jsoup-1.10.3.jar @@ -428,6 +424,10 @@ ext/c3p0-0.9.5.jar release/modules/ext/c3p0-0.9.5.jar + + ext/xmpcore-5.1.3.jar + release/modules/ext/xmpcore-5.1.3.jar + diff --git a/CoreLibs/ivy.xml b/CoreLibs/ivy.xml index b5de9e9ac2..a5f7aab768 100755 --- a/CoreLibs/ivy.xml +++ b/CoreLibs/ivy.xml @@ -28,8 +28,8 @@ - - + + diff --git a/CoreLibs/nbproject/project.properties b/CoreLibs/nbproject/project.properties index 09225d0115..4031d14fc3 100755 --- a/CoreLibs/nbproject/project.properties +++ b/CoreLibs/nbproject/project.properties @@ -58,11 +58,11 @@ file.reference.logkit-1.0.1.jar=release/modules/ext/logkit-1.0.1.jar file.reference.mail-1.4.3.jar=release/modules/ext/mail-1.4.3.jar file.reference.openjfx-dialogs-1.0.2.jar=release/modules/ext/openjfx-dialogs-1.0.3.jar file.reference.platform-3.4.0.jar=release/modules/ext/platform-3.4.0.jar -file.reference.poi-3.15.jar=release/modules/ext/poi-3.15.jar -file.reference.poi-excelant-3.15.jar=release/modules/ext/poi-excelant-3.15.jar -file.reference.poi-ooxml-3.15.jar=release/modules/ext/poi-ooxml-3.15.jar -file.reference.poi-ooxml-schemas-3.15.jar=release/modules/ext/poi-ooxml-schemas-3.15.jar -file.reference.poi-scratchpad-3.15.jar=release/modules/ext/poi-scratchpad-3.15.jar +file.reference.poi-3.17.jar=release/modules/ext/poi-3.17.jar +file.reference.poi-excelant-3.17.jar=release/modules/ext/poi-excelant-3.17.jar +file.reference.poi-ooxml-3.17.jar=release/modules/ext/poi-ooxml-3.17.jar +file.reference.poi-ooxml-schemas-3.17.jar=release/modules/ext/poi-ooxml-schemas-3.17.jar +file.reference.poi-scratchpad-3.17.jar=release/modules/ext/poi-scratchpad-3.17.jar file.reference.reflections-0.9.8.jar=release/modules/ext/reflections-0.9.8.jar file.reference.servlet-api-2.5.jar=release/modules/ext/servlet-api-2.5.jar file.reference.sigar-1.6.4-sources.jar=release/modules/ext/sigar-1.6.4-sources.jar diff --git a/CoreLibs/nbproject/project.xml b/CoreLibs/nbproject/project.xml index 5b4cb9fd83..ca89b8c1c2 100755 --- a/CoreLibs/nbproject/project.xml +++ b/CoreLibs/nbproject/project.xml @@ -295,17 +295,10 @@ org.apache.log4j.xml org.apache.poi org.apache.poi.common.usermodel + org.apache.poi.common.usermodel.fonts org.apache.poi.ddf org.apache.poi.dev org.apache.poi.extractor - org.apache.poi.hdf.event - org.apache.poi.hdf.extractor - org.apache.poi.hdf.extractor.data - org.apache.poi.hdf.extractor.util - org.apache.poi.hdf.model - org.apache.poi.hdf.model.hdftypes - org.apache.poi.hdf.model.hdftypes.definitions - org.apache.poi.hdf.model.util org.apache.poi.hdgf org.apache.poi.hdgf.chunks org.apache.poi.hdgf.dev @@ -313,6 +306,9 @@ org.apache.poi.hdgf.extractor org.apache.poi.hdgf.pointers org.apache.poi.hdgf.streams + org.apache.poi.hemf.extractor + org.apache.poi.hemf.hemfplus.record + org.apache.poi.hemf.record org.apache.poi.hmef org.apache.poi.hmef.attribute org.apache.poi.hmef.dev @@ -325,7 +321,6 @@ org.apache.poi.hpsf org.apache.poi.hpsf.extractor org.apache.poi.hpsf.wellknown - org.apache.poi.hslf org.apache.poi.hslf.blip org.apache.poi.hslf.dev org.apache.poi.hslf.exceptions @@ -358,7 +353,11 @@ org.apache.poi.hssf.record.crypto org.apache.poi.hssf.record.pivottable org.apache.poi.hssf.usermodel + org.apache.poi.hssf.usermodel.helpers org.apache.poi.hssf.util + org.apache.poi.hwmf.draw + org.apache.poi.hwmf.record + org.apache.poi.hwmf.usermodel org.apache.poi.hwpf org.apache.poi.hwpf.converter org.apache.poi.hwpf.dev @@ -372,18 +371,30 @@ org.apache.poi.openxml4j.opc org.apache.poi.openxml4j.opc.internal org.apache.poi.openxml4j.opc.internal.marshallers - org.apache.poi.openxml4j.opc.internal.signature org.apache.poi.openxml4j.opc.internal.unmarshallers - org.apache.poi.openxml4j.opc.signature org.apache.poi.openxml4j.util org.apache.poi.poifs.common org.apache.poi.poifs.crypt + org.apache.poi.poifs.crypt.agile + org.apache.poi.poifs.crypt.binaryrc4 + org.apache.poi.poifs.crypt.cryptoapi + org.apache.poi.poifs.crypt.dsig + org.apache.poi.poifs.crypt.dsig.facets + org.apache.poi.poifs.crypt.dsig.services + org.apache.poi.poifs.crypt.standard + org.apache.poi.poifs.crypt.temp + org.apache.poi.poifs.crypt.xor org.apache.poi.poifs.dev org.apache.poi.poifs.eventfilesystem org.apache.poi.poifs.filesystem + org.apache.poi.poifs.macros org.apache.poi.poifs.nio org.apache.poi.poifs.property org.apache.poi.poifs.storage + org.apache.poi.sl.draw + org.apache.poi.sl.draw.binding + org.apache.poi.sl.draw.geom + org.apache.poi.sl.image org.apache.poi.sl.usermodel org.apache.poi.ss org.apache.poi.ss.excelant @@ -401,15 +412,27 @@ org.apache.poi.ss.formula.udf org.apache.poi.ss.usermodel org.apache.poi.ss.usermodel.charts + org.apache.poi.ss.usermodel.helpers org.apache.poi.ss.util org.apache.poi.ss.util.cellwalk org.apache.poi.util - org.apache.poi.xslf + org.apache.poi.wp.usermodel + org.apache.poi.xdgf.exceptions + org.apache.poi.xdgf.extractor + org.apache.poi.xdgf.geom + org.apache.poi.xdgf.usermodel + org.apache.poi.xdgf.usermodel.section + org.apache.poi.xdgf.usermodel.section.geometry + org.apache.poi.xdgf.usermodel.shape + org.apache.poi.xdgf.usermodel.shape.exceptions + org.apache.poi.xdgf.util + org.apache.poi.xdgf.xml org.apache.poi.xslf.extractor org.apache.poi.xslf.model - org.apache.poi.xslf.model.geom org.apache.poi.xslf.usermodel org.apache.poi.xslf.util + org.apache.poi.xssf + org.apache.poi.xssf.binary org.apache.poi.xssf.dev org.apache.poi.xssf.eventusermodel org.apache.poi.xssf.extractor @@ -620,6 +643,8 @@ org.openxmlformats.schemas.spreadsheetml.x2006.main.impl org.openxmlformats.schemas.wordprocessingml.x2006.main org.openxmlformats.schemas.wordprocessingml.x2006.main.impl + org.openxmlformats.schemas.xpackage.x2006.digitalSignature + org.openxmlformats.schemas.xpackage.x2006.digitalSignature.impl org.reflections org.reflections.adapters org.reflections.scanners @@ -643,17 +668,10 @@ org.xml.sax.ext org.xml.sax.helpers repackage - schemaorg_apache_xmlbeans.system.sE130CAA0A01A7CDE5A2B4FEB8B311707 schemaorg_apache_xmlbeans.system.sXMLCONFIG schemaorg_apache_xmlbeans.system.sXMLLANG schemaorg_apache_xmlbeans.system.sXMLSCHEMA schemaorg_apache_xmlbeans.system.sXMLTOOLS - schemasMicrosoftComOfficeExcel - schemasMicrosoftComOfficeExcel.impl - schemasMicrosoftComOfficeOffice - schemasMicrosoftComOfficeOffice.impl - schemasMicrosoftComVml - schemasMicrosoftComVml.impl ext/commons-logging-1.1.2-sources.jar @@ -763,10 +781,6 @@ ext/joda-time-2.4-javadoc.jar release/modules/ext/joda-time-2.4-javadoc.jar - - ext/poi-excelant-3.15.jar - release/modules/ext/poi-excelant-3.15.jar - ext/imageio-psd-3.2.jar release/modules/ext/imageio-psd-3.2.jar @@ -823,10 +837,6 @@ ext/jfxtras-fxml-8.0-r4.jar release/modules/ext/jfxtras-fxml-8.0-r4.jar - - ext/poi-ooxml-3.15.jar - release/modules/ext/poi-ooxml-3.15.jar - ext/joda-time-2.4.jar release/modules/ext/joda-time-2.4.jar @@ -851,18 +861,22 @@ ext/guava-19.0.jar release/modules/ext/guava-19.0.jar + + ext/poi-3.17.jar + release/modules/ext/poi-3.17.jar + + + ext/poi-ooxml-schemas-3.17.jar + release/modules/ext/poi-ooxml-schemas-3.17.jar + + + ext/poi-scratchpad-3.17.jar + release/modules/ext/poi-scratchpad-3.17.jar + ext/commons-io-2.5.jar release/modules/ext/commons-io-2.5.jar - - ext/poi-ooxml-schemas-3.15.jar - release/modules/ext/poi-ooxml-schemas-3.15.jar - - - ext/poi-scratchpad-3.15.jar - release/modules/ext/poi-scratchpad-3.15.jar - ext/imageio-bmp-3.2.jar release/modules/ext/imageio-bmp-3.2.jar @@ -887,6 +901,10 @@ ext/ant-1.8.2.jar release/modules/ext/ant-1.8.2.jar + + ext/poi-excelant-3.17.jar + release/modules/ext/poi-excelant-3.17.jar + ext/javassist-3.12.1.GA.jar release/modules/ext/javassist-3.12.1.GA.jar @@ -899,6 +917,10 @@ ext/commons-logging-1.1.2.jar release/modules/ext/commons-logging-1.1.2.jar + + ext/poi-ooxml-3.17.jar + release/modules/ext/poi-ooxml-3.17.jar + ext/controlsfx-8.40.11.jar release/modules/ext/controlsfx-8.40.11.jar @@ -911,10 +933,6 @@ ext/javaee-api-5.0-2.jar release/modules/ext/javaee-api-5.0-2.jar - - ext/poi-3.15.jar - release/modules/ext/poi-3.15.jar - ext/common-image-3.2.jar release/modules/ext/common-image-3.2.jar diff --git a/Experimental/ivy.xml b/Experimental/ivy.xml index 93d6dafa8d..965af1bc12 100755 --- a/Experimental/ivy.xml +++ b/Experimental/ivy.xml @@ -6,7 +6,7 @@ - + diff --git a/Experimental/nbproject/project.properties b/Experimental/nbproject/project.properties index 1bd0e2fc90..2db8202ab7 100755 --- a/Experimental/nbproject/project.properties +++ b/Experimental/nbproject/project.properties @@ -3,7 +3,7 @@ file.reference.jackson-core-2.7.0.jar=release/modules/ext/jackson-core-2.7.0.jar file.reference.LGoodDatePicker-10.3.1.jar=release/modules/ext/LGoodDatePicker-10.3.1.jar file.reference.mchange-commons-java-0.2.9.jar=release/modules/ext/mchange-commons-java-0.2.9.jar file.reference.postgresql-9.4-1201-jdbc41.jar=release/modules/ext/postgresql-9.4-1201-jdbc41.jar -file.reference.tika-core-1.14.jar=release/modules/ext/tika-core-1.14.jar +file.reference.tika-core-1.17.jar=release/modules/ext/tika-core-1.17.jar javac.source=1.8 javac.compilerargs=-Xlint -Xlint:-serial javadoc.reference.LGoodDatePicker-10.3.1.jar=release/modules/ext/LGoodDatePicker-10.3.1-javadoc.jar diff --git a/Experimental/nbproject/project.xml b/Experimental/nbproject/project.xml index 8293608102..f2bf6d1996 100755 --- a/Experimental/nbproject/project.xml +++ b/Experimental/nbproject/project.xml @@ -146,12 +146,12 @@ org.sleuthkit.autopsy.experimental.configuration - ext/tika-core-1.14.jar - release/modules/ext/tika-core-1.14.jar + ext/LGoodDatePicker-10.3.1.jar + release/modules/ext/LGoodDatePicker-10.3.1.jar - ext/LGoodDatePicker-10.3.1.jar - release/modules/ext/LGoodDatePicker-10.3.1.jar + ext/tika-core-1.17.jar + release/modules/ext/tika-core-1.17.jar ext/mchange-commons-java-0.2.9.jar diff --git a/KeywordSearch/ivy.xml b/KeywordSearch/ivy.xml index 3ceb4e6378..fc6aa00269 100755 --- a/KeywordSearch/ivy.xml +++ b/KeywordSearch/ivy.xml @@ -22,7 +22,7 @@ - + diff --git a/KeywordSearch/nbproject/project.properties b/KeywordSearch/nbproject/project.properties index 5aa1b716e0..ddc825b4d4 100755 --- a/KeywordSearch/nbproject/project.properties +++ b/KeywordSearch/nbproject/project.properties @@ -1,6 +1,5 @@ -file.reference.aopalliance-1.0.jar=release/modules/ext/aopalliance-1.0.jar -file.reference.apache-mime4j-core-0.7.2.jar=release/modules/ext/apache-mime4j-core-0.7.2.jar -file.reference.apache-mime4j-dom-0.7.2.jar=release/modules/ext/apache-mime4j-dom-0.7.2.jar +file.reference.apache-mime4j-core-0.8.1.jar=release/modules/ext/apache-mime4j-core-0.8.1.jar +file.reference.apache-mime4j-dom-0.8.1.jar=release/modules/ext/apache-mime4j-dom-0.8.1.jar file.reference.asm-5.0.4.jar=release/modules/ext/asm-5.0.4.jar file.reference.asm-all-3.1.jar=release/modules/ext/asm-all-3.1.jar file.reference.bcmail-jdk15on-1.54.jar=release/modules/ext/bcmail-jdk15on-1.54.jar @@ -15,7 +14,7 @@ file.reference.commons-beanutils-1.9.2.jar=release/modules/ext/commons-beanutils file.reference.commons-codec-1.10.jar=release/modules/ext/commons-codec-1.10.jar file.reference.commons-collections-3.2.2.jar=release/modules/ext/commons-collections-3.2.2.jar file.reference.commons-collections4-4.1.jar=release/modules/ext/commons-collections4-4.1.jar -file.reference.commons-compress-1.12.jar=release/modules/ext/commons-compress-1.12.jar +file.reference.commons-compress-1.14.jar=release/modules/ext/commons-compress-1.14.jar file.reference.commons-csv-1.0.jar=release/modules/ext/commons-csv-1.0.jar file.reference.commons-digester-1.8.1.jar=release/modules/ext/commons-digester-1.8.1.jar file.reference.commons-exec-1.3.jar=release/modules/ext/commons-exec-1.3.jar @@ -26,35 +25,34 @@ file.reference.commons-logging-api-1.1.jar=release/modules/ext/commons-logging-a file.reference.commons-validator-1.5.1-javadoc.jar=release/modules/ext/commons-validator-1.5.1-javadoc.jar file.reference.commons-validator-1.5.1-sources.jar=release/modules/ext/commons-validator-1.5.1-sources.jar file.reference.commons-validator-1.5.1.jar=release/modules/ext/commons-validator-1.5.1.jar -file.reference.commons-vfs2-2.0.jar=release/modules/ext/commons-vfs2-2.0.jar file.reference.ctakes-core-3.2.2.jar=release/modules/ext/ctakes-core-3.2.2.jar file.reference.ctakes-core-res-3.2.2.jar=release/modules/ext/ctakes-core-res-3.2.2.jar file.reference.ctakes-type-system-3.2.2.jar=release/modules/ext/ctakes-type-system-3.2.2.jar file.reference.ctakes-utils-3.2.2.jar=release/modules/ext/ctakes-utils-3.2.2.jar file.reference.curvesapi-1.04.jar=release/modules/ext/curvesapi-1.04.jar -file.reference.cxf-core-3.0.3.jar=release/modules/ext/cxf-core-3.0.3.jar -file.reference.cxf-rt-frontend-jaxrs-3.0.3.jar=release/modules/ext/cxf-rt-frontend-jaxrs-3.0.3.jar -file.reference.cxf-rt-rs-client-3.0.3.jar=release/modules/ext/cxf-rt-rs-client-3.0.3.jar -file.reference.cxf-rt-transports-http-3.0.3.jar=release/modules/ext/cxf-rt-transports-http-3.0.3.jar +file.reference.cxf-core-3.0.16.jar=release/modules/ext/cxf-core-3.0.16.jar +file.reference.cxf-rt-frontend-jaxrs-3.0.16.jar=release/modules/ext/cxf-rt-frontend-jaxrs-3.0.16.jar +file.reference.cxf-rt-rs-client-3.0.16.jar=release/modules/ext/cxf-rt-rs-client-3.0.16.jar +file.reference.cxf-rt-transports-http-3.0.16.jar=release/modules/ext/cxf-rt-transports-http-3.0.16.jar file.reference.ehcache-core-2.6.2.jar=release/modules/ext/ehcache-core-2.6.2.jar file.reference.findstructapi-0.0.1.jar=release/modules/ext/findstructapi-0.0.1.jar -file.reference.fontbox-2.0.3.jar=release/modules/ext/fontbox-2.0.3.jar +file.reference.fontbox-2.0.8.jar=release/modules/ext/fontbox-2.0.8.jar file.reference.geoapi-3.0.0.jar=release/modules/ext/geoapi-3.0.0.jar file.reference.grib-4.5.5.jar=release/modules/ext/grib-4.5.5.jar -file.reference.gson-2.2.4.jar=release/modules/ext/gson-2.2.4.jar +file.reference.gson-2.8.1.jar=release/modules/ext/gson-2.8.1.jar file.reference.guava-17.0.jar=release/modules/ext/guava-17.0.jar file.reference.hamcrest-core-1.3.jar=release/modules/ext/hamcrest-core-1.3.jar -file.reference.httpclient-4.3.1.jar=release/modules/ext/httpclient-4.3.1.jar -file.reference.httpcore-4.3.jar=release/modules/ext/httpcore-4.3.jar +file.reference.httpclient-4.5.4.jar=release/modules/ext/httpclient-4.5.4.jar file.reference.httpcore-4.4.1.jar=release/modules/ext/httpcore-4.4.1.jar -file.reference.httpmime-4.3.1.jar=release/modules/ext/httpmime-4.3.1.jar +file.reference.httpcore-4.4.7.jar=release/modules/ext/httpcore-4.4.7.jar file.reference.httpmime-4.4.1.jar=release/modules/ext/httpmime-4.4.1.jar +file.reference.httpmime-4.5.4.jar=release/modules/ext/httpmime-4.5.4.jar file.reference.httpservices-4.5.5.jar=release/modules/ext/httpservices-4.5.5.jar file.reference.icu4j-3.8.jar=release/modules/ext/icu4j-3.8.jar file.reference.isoparser-1.1.18.jar=release/modules/ext/isoparser-1.1.18.jar -file.reference.jackcess-2.1.4.jar=release/modules/ext/jackcess-2.1.4.jar -file.reference.jackcess-encrypt-2.1.1.jar=release/modules/ext/jackcess-encrypt-2.1.1.jar -file.reference.jackson-core-2.8.1.jar=release/modules/ext/jackson-core-2.8.1.jar +file.reference.jackcess-2.1.8.jar=release/modules/ext/jackcess-2.1.8.jar +file.reference.jackcess-encrypt-2.1.2.jar=release/modules/ext/jackcess-encrypt-2.1.2.jar +file.reference.jackson-core-2.9.2.jar=release/modules/ext/jackson-core-2.9.2.jar file.reference.jakarta-regexp-1.4.jar=release/modules/ext/jakarta-regexp-1.4.jar file.reference.java-libpst-0.8.1.jar=release/modules/ext/java-libpst-0.8.1.jar file.reference.javax.annotation-api-1.2.jar=release/modules/ext/javax.annotation-api-1.2.jar @@ -63,20 +61,17 @@ file.reference.jcip-annotations-1.0.jar=release/modules/ext/jcip-annotations-1.0 file.reference.jcommander-1.35.jar=release/modules/ext/jcommander-1.35.jar file.reference.jdom-1.0.jar=release/modules/ext/jdom-1.0.jar file.reference.jdom2-2.0.4.jar=release/modules/ext/jdom2-2.0.4.jar -file.reference.jempbox-1.8.12.jar=release/modules/ext/jempbox-1.8.12.jar +file.reference.jempbox-1.8.13.jar=release/modules/ext/jempbox-1.8.13.jar file.reference.jericho-html-3.3-javadoc.jar=release/modules/ext/jericho-html-3.3-javadoc.jar file.reference.jericho-html-3.3-sources.jar=release/modules/ext/jericho-html-3.3-sources.jar file.reference.jericho-html-3.3.jar=release/modules/ext/jericho-html-3.3.jar file.reference.jhighlight-1.0.2.jar=release/modules/ext/jhighlight-1.0.2.jar -file.reference.jj2000-5.2.jar=release/modules/ext/jj2000-5.2.jar file.reference.jmatio-1.2.jar=release/modules/ext/jmatio-1.2.jar file.reference.jna-4.1.0.jar=release/modules/ext/jna-4.1.0.jar file.reference.joda-time-2.2.jar=release/modules/ext/joda-time-2.2.jar -file.reference.json-20140107.jar=release/modules/ext/json-20140107.jar file.reference.json-simple-1.1.1.jar=release/modules/ext/json-simple-1.1.1.jar file.reference.jsoup-1.7.2.jar=release/modules/ext/jsoup-1.7.2.jar file.reference.jsr-275-0.9.3.jar=release/modules/ext/jsr-275-0.9.3.jar -file.reference.junit-4.11.jar=release/modules/ext/junit-4.11.jar file.reference.juniversalchardet-1.0.3.jar=release/modules/ext/juniversalchardet-1.0.3.jar file.reference.junrar-0.7.jar=release/modules/ext/junrar-0.7.jar file.reference.jVinci-2.6.0.jar=release/modules/ext/jVinci-2.6.0.jar @@ -88,10 +83,7 @@ file.reference.lucene-core-4.0.0.jar=release/modules/ext/lucene-core-4.0.0.jar file.reference.lucene-queries-4.0.0.jar=release/modules/ext/lucene-queries-4.0.0.jar file.reference.lucene-queryparser-4.0.0.jar=release/modules/ext/lucene-queryparser-4.0.0.jar file.reference.lucene-sandbox-4.0.0.jar=release/modules/ext/lucene-sandbox-4.0.0.jar -file.reference.maven-scm-api-1.4.jar=release/modules/ext/maven-scm-api-1.4.jar -file.reference.maven-scm-provider-svn-commons-1.4.jar=release/modules/ext/maven-scm-provider-svn-commons-1.4.jar -file.reference.maven-scm-provider-svnexe-1.4.jar=release/modules/ext/maven-scm-provider-svnexe-1.4.jar -file.reference.metadata-extractor-2.9.1.jar=release/modules/ext/metadata-extractor-2.9.1.jar +file.reference.metadata-extractor-2.10.1.jar=release/modules/ext/metadata-extractor-2.10.1.jar file.reference.netcdf4-4.5.5.jar=release/modules/ext/netcdf4-4.5.5.jar file.reference.noggit-0.5.jar=release/modules/ext/noggit-0.5.jar file.reference.openaifsm-0.0.1.jar=release/modules/ext/openaifsm-0.0.1.jar @@ -101,18 +93,15 @@ file.reference.org.apache.felix.scr.annotations-1.6.0.jar=release/modules/ext/or file.reference.org.apache.felix.scr.generator-1.1.2.jar=release/modules/ext/org.apache.felix.scr.generator-1.1.2.jar file.reference.org.osgi.compendium-4.0.0.jar=release/modules/ext/org.osgi.compendium-4.0.0.jar file.reference.org.osgi.core-4.0.0.jar=release/modules/ext/org.osgi.core-4.0.0.jar -file.reference.pdfbox-2.0.3.jar=release/modules/ext/pdfbox-2.0.3.jar -file.reference.pdfbox-debugger-2.0.3.jar=release/modules/ext/pdfbox-debugger-2.0.3.jar -file.reference.pdfbox-tools-2.0.3.jar=release/modules/ext/pdfbox-tools-2.0.3.jar -file.reference.plexus-utils-1.5.6.jar=release/modules/ext/plexus-utils-1.5.6.jar -file.reference.poi-3.15.jar=release/modules/ext/poi-3.15.jar -file.reference.poi-ooxml-3.15.jar=release/modules/ext/poi-ooxml-3.15.jar -file.reference.poi-ooxml-schemas-3.15.jar=release/modules/ext/poi-ooxml-schemas-3.15.jar -file.reference.poi-scratchpad-3.15.jar=release/modules/ext/poi-scratchpad-3.15.jar +file.reference.pdfbox-2.0.8.jar=release/modules/ext/pdfbox-2.0.8.jar +file.reference.pdfbox-tools-2.0.8.jar=release/modules/ext/pdfbox-tools-2.0.8.jar +file.reference.poi-3.17.jar=release/modules/ext/poi-3.17.jar +file.reference.poi-ooxml-3.17.jar=release/modules/ext/poi-ooxml-3.17.jar +file.reference.poi-ooxml-schemas-3.17.jar=release/modules/ext/poi-ooxml-schemas-3.17.jar +file.reference.poi-scratchpad-3.17.jar=release/modules/ext/poi-scratchpad-3.17.jar file.reference.protobuf-java-2.5.0.jar=release/modules/ext/protobuf-java-2.5.0.jar file.reference.qdox-1.12.jar=release/modules/ext/qdox-1.12.jar file.reference.quartz-2.2.0.jar=release/modules/ext/quartz-2.2.0.jar -file.reference.regexp-1.3.jar=release/modules/ext/regexp-1.3.jar file.reference.rome-1.5.1.jar=release/modules/ext/rome-1.5.1.jar file.reference.rome-utils-1.5.1.jar=release/modules/ext/rome-utils-1.5.1.jar file.reference.sis-metadata-0.6.jar=release/modules/ext/sis-metadata-0.6.jar @@ -120,24 +109,18 @@ file.reference.sis-netcdf-0.6.jar=release/modules/ext/sis-netcdf-0.6.jar file.reference.sis-referencing-0.6.jar=release/modules/ext/sis-referencing-0.6.jar file.reference.sis-storage-0.6.jar=release/modules/ext/sis-storage-0.6.jar file.reference.sis-utility-0.6.jar=release/modules/ext/sis-utility-0.6.jar -file.reference.slf4j-api-1.7.12.jar=release/modules/ext/slf4j-api-1.7.12.jar +file.reference.slf4j-api-1.7.24.jar=release/modules/ext/slf4j-api-1.7.24.jar file.reference.solr-solrj-4.9.1-javadoc.jar=release/modules/ext/solr-solrj-4.9.1-javadoc.jar file.reference.solr-solrj-4.9.1-sources.jar=release/modules/ext/solr-solrj-4.9.1-sources.jar file.reference.solr-solrj-4.9.1.jar=release/modules/ext/solr-solrj-4.9.1.jar -file.reference.spring-aop-3.1.2.RELEASE.jar=release/modules/ext/spring-aop-3.1.2.RELEASE.jar -file.reference.spring-asm-3.1.2.RELEASE.jar=release/modules/ext/spring-asm-3.1.2.RELEASE.jar -file.reference.spring-beans-3.1.2.RELEASE.jar=release/modules/ext/spring-beans-3.1.2.RELEASE.jar -file.reference.spring-context-3.1.2.RELEASE.jar=release/modules/ext/spring-context-3.1.2.RELEASE.jar -file.reference.spring-core-3.1.2.RELEASE.jar=release/modules/ext/spring-core-3.1.2.RELEASE.jar -file.reference.spring-expression-3.1.2.RELEASE.jar=release/modules/ext/spring-expression-3.1.2.RELEASE.jar -file.reference.sqlite-jdbc-3.8.11.2.jar=release/modules/ext/sqlite-jdbc-3.8.11.2.jar +file.reference.sqlite-jdbc-3.19.3.jar=release/modules/ext/sqlite-jdbc-3.19.3.jar file.reference.sqlwrapper-0.0.1.jar=release/modules/ext/sqlwrapper-0.0.1.jar file.reference.stax2-api-3.1.4.jar=release/modules/ext/stax2-api-3.1.4.jar file.reference.tagsoup-1.2.1.jar=release/modules/ext/tagsoup-1.2.1.jar -file.reference.tika-core-1.14.jar=release/modules/ext/tika-core-1.14.jar -file.reference.tika-parsers-1.14-javadoc.jar=release/modules/ext/tika-parsers-1.14-javadoc.jar -file.reference.tika-parsers-1.14-sources.jar=release/modules/ext/tika-parsers-1.14-sources.jar -file.reference.tika-parsers-1.14.jar=release/modules/ext/tika-parsers-1.14.jar +file.reference.tika-core-1.17.jar=release/modules/ext/tika-core-1.17.jar +file.reference.tika-parsers-1.17-javadoc.jar=release/modules/ext/tika-parsers-1.17-javadoc.jar +file.reference.tika-parsers-1.17-sources.jar=release/modules/ext/tika-parsers-1.17-sources.jar +file.reference.tika-parsers-1.17.jar=release/modules/ext/tika-parsers-1.17.jar file.reference.udunits-4.5.5.jar=release/modules/ext/udunits-4.5.5.jar file.reference.uimafit-core-2.1.0.jar=release/modules/ext/uimafit-core-2.1.0.jar file.reference.uimaj-adapter-vinci-2.6.0.jar=release/modules/ext/uimaj-adapter-vinci-2.6.0.jar @@ -150,9 +133,7 @@ file.reference.vorbis-java-core-0.8.jar=release/modules/ext/vorbis-java-core-0.8 file.reference.vorbis-java-tika-0.8.jar=release/modules/ext/vorbis-java-tika-0.8.jar file.reference.woodstox-core-asl-4.4.1.jar=release/modules/ext/woodstox-core-asl-4.4.1.jar file.reference.xmlbeans-2.6.0.jar=release/modules/ext/xmlbeans-2.6.0.jar -file.reference.xmlschema-core-2.1.0.jar=release/modules/ext/xmlschema-core-2.1.0.jar -file.reference.xmpcore-5.1.2.jar=release/modules/ext/xmpcore-5.1.2.jar -file.reference.xz-1.5.jar=release/modules/ext/xz-1.5.jar +file.reference.xmpcore-5.1.3.jar=release/modules/ext/xmpcore-5.1.3.jar file.reference.zookeeper-3.4.6.jar=release/modules/ext/zookeeper-3.4.6.jar javac.source=1.8 javac.compilerargs=-Xlint -Xlint:-serial diff --git a/KeywordSearch/nbproject/project.xml b/KeywordSearch/nbproject/project.xml index 357c2178e2..db9ada1b1b 100755 --- a/KeywordSearch/nbproject/project.xml +++ b/KeywordSearch/nbproject/project.xml @@ -141,6 +141,10 @@ ext/commons-validator-1.5.1-sources.jar release/modules/ext/commons-validator-1.5.1-sources.jar + + ext/apache-mime4j-dom-0.8.1.jar + release/modules/ext/apache-mime4j-dom-0.8.1.jar + ext/commons-digester-1.8.1.jar release/modules/ext/commons-digester-1.8.1.jar @@ -149,14 +153,14 @@ ext/jwnl-1.3.3.jar release/modules/ext/jwnl-1.3.3.jar - - ext/tika-core-1.14.jar - release/modules/ext/tika-core-1.14.jar - ext/lucene-queryparser-4.0.0.jar release/modules/ext/lucene-queryparser-4.0.0.jar + + ext/httpclient-4.5.4.jar + release/modules/ext/httpclient-4.5.4.jar + ext/uimaj-examples-2.4.0.jar release/modules/ext/uimaj-examples-2.4.0.jar @@ -165,10 +169,6 @@ ext/cdm-4.5.5.jar release/modules/ext/cdm-4.5.5.jar - - ext/gson-2.2.4.jar - release/modules/ext/gson-2.2.4.jar - ext/org.osgi.compendium-4.0.0.jar release/modules/ext/org.osgi.compendium-4.0.0.jar @@ -177,6 +177,10 @@ ext/geoapi-3.0.0.jar release/modules/ext/geoapi-3.0.0.jar + + ext/commons-compress-1.14.jar + release/modules/ext/commons-compress-1.14.jar + ext/hamcrest-core-1.3.jar release/modules/ext/hamcrest-core-1.3.jar @@ -197,30 +201,34 @@ ext/xmlbeans-2.6.0.jar release/modules/ext/xmlbeans-2.6.0.jar - - ext/maven-scm-api-1.4.jar - release/modules/ext/maven-scm-api-1.4.jar - ext/quartz-2.2.0.jar release/modules/ext/quartz-2.2.0.jar - ext/jackcess-2.1.4.jar - release/modules/ext/jackcess-2.1.4.jar - - - ext/slf4j-api-1.7.12.jar - release/modules/ext/slf4j-api-1.7.12.jar + ext/sqlite-jdbc-3.19.3.jar + release/modules/ext/sqlite-jdbc-3.19.3.jar ext/guava-17.0.jar release/modules/ext/guava-17.0.jar + + ext/metadata-extractor-2.10.1.jar + release/modules/ext/metadata-extractor-2.10.1.jar + + + ext/apache-mime4j-core-0.8.1.jar + release/modules/ext/apache-mime4j-core-0.8.1.jar + ext/opennlp-maxent-3.0.3.jar release/modules/ext/opennlp-maxent-3.0.3.jar + + ext/pdfbox-tools-2.0.8.jar + release/modules/ext/pdfbox-tools-2.0.8.jar + ext/jVinci-2.6.0.jar release/modules/ext/jVinci-2.6.0.jar @@ -229,18 +237,14 @@ ext/json-simple-1.1.1.jar release/modules/ext/json-simple-1.1.1.jar + + ext/tika-parsers-1.17.jar + release/modules/ext/tika-parsers-1.17.jar + ext/sis-utility-0.6.jar release/modules/ext/sis-utility-0.6.jar - - ext/jj2000-5.2.jar - release/modules/ext/jj2000-5.2.jar - - - ext/httpclient-4.3.1.jar - release/modules/ext/httpclient-4.3.1.jar - ext/jhighlight-1.0.2.jar release/modules/ext/jhighlight-1.0.2.jar @@ -258,12 +262,12 @@ release/modules/ext/ctakes-utils-3.2.2.jar - ext/apache-mime4j-dom-0.7.2.jar - release/modules/ext/apache-mime4j-dom-0.7.2.jar + ext/cxf-rt-rs-client-3.0.16.jar + release/modules/ext/cxf-rt-rs-client-3.0.16.jar - ext/commons-compress-1.12.jar - release/modules/ext/commons-compress-1.12.jar + ext/jempbox-1.8.13.jar + release/modules/ext/jempbox-1.8.13.jar ext/openaifsm-0.0.1.jar @@ -277,14 +281,18 @@ ext/commons-collections4-4.1.jar release/modules/ext/commons-collections4-4.1.jar - - ext/cxf-rt-rs-client-3.0.3.jar - release/modules/ext/cxf-rt-rs-client-3.0.3.jar - ext/solr-solrj-4.9.1.jar release/modules/ext/solr-solrj-4.9.1.jar + + ext/xmpcore-5.1.3.jar + release/modules/ext/xmpcore-5.1.3.jar + + + ext/jackcess-2.1.8.jar + release/modules/ext/jackcess-2.1.8.jar + ext/findstructapi-0.0.1.jar release/modules/ext/findstructapi-0.0.1.jar @@ -317,6 +325,22 @@ ext/commons-codec-1.10.jar release/modules/ext/commons-codec-1.10.jar + + ext/gson-2.8.1.jar + release/modules/ext/gson-2.8.1.jar + + + ext/poi-ooxml-schemas-3.17.jar + release/modules/ext/poi-ooxml-schemas-3.17.jar + + + ext/poi-scratchpad-3.17.jar + release/modules/ext/poi-scratchpad-3.17.jar + + + ext/poi-3.17.jar + release/modules/ext/poi-3.17.jar + ext/lucene-queries-4.0.0.jar release/modules/ext/lucene-queries-4.0.0.jar @@ -326,45 +350,25 @@ release/modules/ext/bcprov-jdk15on-1.54.jar - ext/poi-ooxml-schemas-3.15.jar - release/modules/ext/poi-ooxml-schemas-3.15.jar - - - ext/poi-scratchpad-3.15.jar - release/modules/ext/poi-scratchpad-3.15.jar + ext/fontbox-2.0.8.jar + release/modules/ext/fontbox-2.0.8.jar ext/solr-solrj-4.9.1-sources.jar release/modules/ext/solr-solrj-4.9.1-sources.jar - - ext/commons-vfs2-2.0.jar - release/modules/ext/commons-vfs2-2.0.jar - - - ext/tika-parsers-1.14.jar - release/modules/ext/tika-parsers-1.14.jar - - - ext/jackcess-encrypt-2.1.1.jar - release/modules/ext/jackcess-encrypt-2.1.1.jar - - - ext/spring-expression-3.1.2.RELEASE.jar - release/modules/ext/spring-expression-3.1.2.RELEASE.jar - ext/lucene-analyzers-common-4.0.0.jar release/modules/ext/lucene-analyzers-common-4.0.0.jar - - ext/tika-parsers-1.14-sources.jar - release/modules/ext/tika-parsers-1.14-sources.jar - ext/javax.ws.rs-api-2.0.1.jar release/modules/ext/javax.ws.rs-api-2.0.1.jar + + ext/httpmime-4.5.4.jar + release/modules/ext/httpmime-4.5.4.jar + ext/junrar-0.7.jar release/modules/ext/junrar-0.7.jar @@ -378,21 +382,13 @@ release/modules/ext/noggit-0.5.jar - ext/xmlschema-core-2.1.0.jar - release/modules/ext/xmlschema-core-2.1.0.jar - - - ext/httpmime-4.3.1.jar - release/modules/ext/httpmime-4.3.1.jar + ext/poi-ooxml-3.17.jar + release/modules/ext/poi-ooxml-3.17.jar ext/jna-4.1.0.jar release/modules/ext/jna-4.1.0.jar - - ext/xz-1.5.jar - release/modules/ext/xz-1.5.jar - ext/qdox-1.12.jar release/modules/ext/qdox-1.12.jar @@ -410,37 +406,17 @@ release/modules/ext/grib-4.5.5.jar - ext/maven-scm-provider-svn-commons-1.4.jar - release/modules/ext/maven-scm-provider-svn-commons-1.4.jar - - - ext/poi-3.15.jar - release/modules/ext/poi-3.15.jar - - - ext/spring-aop-3.1.2.RELEASE.jar - release/modules/ext/spring-aop-3.1.2.RELEASE.jar - - - ext/json-20140107.jar - release/modules/ext/json-20140107.jar + ext/jackson-core-2.9.2.jar + release/modules/ext/jackson-core-2.9.2.jar ext/uimaj-core-2.5.0.jar release/modules/ext/uimaj-core-2.5.0.jar - - ext/pdfbox-2.0.3.jar - release/modules/ext/pdfbox-2.0.3.jar - ext/jmatio-1.2.jar release/modules/ext/jmatio-1.2.jar - - ext/metadata-extractor-2.9.1.jar - release/modules/ext/metadata-extractor-2.9.1.jar - ext/commons-csv-1.0.jar release/modules/ext/commons-csv-1.0.jar @@ -466,21 +442,13 @@ release/modules/ext/httpservices-4.5.5.jar - ext/plexus-utils-1.5.6.jar - release/modules/ext/plexus-utils-1.5.6.jar - - - ext/fontbox-2.0.3.jar - release/modules/ext/fontbox-2.0.3.jar + ext/httpcore-4.4.7.jar + release/modules/ext/httpcore-4.4.7.jar ext/bcmail-jdk15on-1.54.jar release/modules/ext/bcmail-jdk15on-1.54.jar - - ext/spring-beans-3.1.2.RELEASE.jar - release/modules/ext/spring-beans-3.1.2.RELEASE.jar - ext/solr-solrj-4.9.1-javadoc.jar release/modules/ext/solr-solrj-4.9.1-javadoc.jar @@ -490,8 +458,8 @@ release/modules/ext/asm-all-3.1.jar - ext/tika-parsers-1.14-javadoc.jar - release/modules/ext/tika-parsers-1.14-javadoc.jar + ext/tika-parsers-1.17-javadoc.jar + release/modules/ext/tika-parsers-1.17-javadoc.jar ext/icu4j-3.8.jar @@ -501,10 +469,6 @@ ext/curvesapi-1.04.jar release/modules/ext/curvesapi-1.04.jar - - ext/xmpcore-5.1.2.jar - release/modules/ext/xmpcore-5.1.2.jar - ext/sis-referencing-0.6.jar release/modules/ext/sis-referencing-0.6.jar @@ -521,6 +485,10 @@ ext/tagsoup-1.2.1.jar release/modules/ext/tagsoup-1.2.1.jar + + ext/tika-core-1.17.jar + release/modules/ext/tika-core-1.17.jar + ext/lucene-core-4.0.0.jar release/modules/ext/lucene-core-4.0.0.jar @@ -533,10 +501,6 @@ ext/commons-logging-1.2.jar release/modules/ext/commons-logging-1.2.jar - - ext/jackson-core-2.8.1.jar - release/modules/ext/jackson-core-2.8.1.jar - ext/org.osgi.core-4.0.0.jar release/modules/ext/org.osgi.core-4.0.0.jar @@ -545,10 +509,18 @@ ext/c3p0-0.9.1.1.jar release/modules/ext/c3p0-0.9.1.1.jar + + ext/tika-parsers-1.17-sources.jar + release/modules/ext/tika-parsers-1.17-sources.jar + ext/sqlwrapper-0.0.1.jar release/modules/ext/sqlwrapper-0.0.1.jar + + ext/jackcess-encrypt-2.1.2.jar + release/modules/ext/jackcess-encrypt-2.1.2.jar + ext/jericho-html-3.3-javadoc.jar release/modules/ext/jericho-html-3.3-javadoc.jar @@ -557,18 +529,10 @@ ext/udunits-4.5.5.jar release/modules/ext/udunits-4.5.5.jar - - ext/aopalliance-1.0.jar - release/modules/ext/aopalliance-1.0.jar - ext/commons-collections-3.2.2.jar release/modules/ext/commons-collections-3.2.2.jar - - ext/cxf-rt-frontend-jaxrs-3.0.3.jar - release/modules/ext/cxf-rt-frontend-jaxrs-3.0.3.jar - ext/uimaj-document-annotation-2.5.0.jar release/modules/ext/uimaj-document-annotation-2.5.0.jar @@ -577,41 +541,29 @@ ext/woodstox-core-asl-4.4.1.jar release/modules/ext/woodstox-core-asl-4.4.1.jar - - ext/poi-ooxml-3.15.jar - release/modules/ext/poi-ooxml-3.15.jar - ext/org.apache.felix.scr.generator-1.1.2.jar release/modules/ext/org.apache.felix.scr.generator-1.1.2.jar + + ext/pdfbox-2.0.8.jar + release/modules/ext/pdfbox-2.0.8.jar + ext/zookeeper-3.4.6.jar release/modules/ext/zookeeper-3.4.6.jar - ext/cxf-rt-transports-http-3.0.3.jar - release/modules/ext/cxf-rt-transports-http-3.0.3.jar - - - ext/pdfbox-debugger-2.0.3.jar - release/modules/ext/pdfbox-debugger-2.0.3.jar - - - ext/spring-core-3.1.2.RELEASE.jar - release/modules/ext/spring-core-3.1.2.RELEASE.jar + ext/cxf-rt-transports-http-3.0.16.jar + release/modules/ext/cxf-rt-transports-http-3.0.16.jar ext/netcdf4-4.5.5.jar release/modules/ext/netcdf4-4.5.5.jar - ext/spring-asm-3.1.2.RELEASE.jar - release/modules/ext/spring-asm-3.1.2.RELEASE.jar - - - ext/junit-4.11.jar - release/modules/ext/junit-4.11.jar + ext/slf4j-api-1.7.24.jar + release/modules/ext/slf4j-api-1.7.24.jar ext/protobuf-java-2.5.0.jar @@ -642,37 +594,17 @@ release/modules/ext/commons-lang-2.6.jar - ext/sqlite-jdbc-3.8.11.2.jar - release/modules/ext/sqlite-jdbc-3.8.11.2.jar - - - ext/jempbox-1.8.12.jar - release/modules/ext/jempbox-1.8.12.jar - - - ext/maven-scm-provider-svnexe-1.4.jar - release/modules/ext/maven-scm-provider-svnexe-1.4.jar + ext/cxf-core-3.0.16.jar + release/modules/ext/cxf-core-3.0.16.jar ext/opennlp-tools-1.5.3.jar release/modules/ext/opennlp-tools-1.5.3.jar - - ext/apache-mime4j-core-0.7.2.jar - release/modules/ext/apache-mime4j-core-0.7.2.jar - ext/rome-utils-1.5.1.jar release/modules/ext/rome-utils-1.5.1.jar - - ext/httpcore-4.3.jar - release/modules/ext/httpcore-4.3.jar - - - ext/pdfbox-tools-2.0.3.jar - release/modules/ext/pdfbox-tools-2.0.3.jar - ext/sis-storage-0.6.jar release/modules/ext/sis-storage-0.6.jar @@ -689,6 +621,10 @@ ext/uimafit-core-2.1.0.jar release/modules/ext/uimafit-core-2.1.0.jar + + ext/cxf-rt-frontend-jaxrs-3.0.16.jar + release/modules/ext/cxf-rt-frontend-jaxrs-3.0.16.jar + ext/cleartk-util-2.0.0.jar release/modules/ext/cleartk-util-2.0.0.jar @@ -697,14 +633,6 @@ ext/jdom-1.0.jar release/modules/ext/jdom-1.0.jar - - ext/cxf-core-3.0.3.jar - release/modules/ext/cxf-core-3.0.3.jar - - - ext/regexp-1.3.jar - release/modules/ext/regexp-1.3.jar - ext/commons-beanutils-1.9.2.jar release/modules/ext/commons-beanutils-1.9.2.jar @@ -713,10 +641,6 @@ ext/ehcache-core-2.6.2.jar release/modules/ext/ehcache-core-2.6.2.jar - - ext/spring-context-3.1.2.RELEASE.jar - release/modules/ext/spring-context-3.1.2.RELEASE.jar - ext/ctakes-type-system-3.2.2.jar release/modules/ext/ctakes-type-system-3.2.2.jar From f1e6d8ff72b674798c81c1c8a792d4350bb2df0e Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Wed, 3 Jan 2018 14:56:47 -0500 Subject: [PATCH 03/28] 3412: update the reports directory name from 'case timestamp' to 'case timestamp reportType' --- .../autopsy/modules/stix/STIXReportModule.java | 17 +++++++++++++---- .../autopsy/report/FileReportText.java | 14 ++++++++++++-- .../autopsy/report/ReportBodyFile.java | 11 +++++++++-- .../sleuthkit/autopsy/report/ReportExcel.java | 14 +++++++++++--- .../autopsy/report/ReportGenerator.java | 10 +--------- .../sleuthkit/autopsy/report/ReportHTML.java | 14 +++++++------- .../org/sleuthkit/autopsy/report/ReportKML.java | 10 +++++++++- 7 files changed, 62 insertions(+), 28 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java b/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java index 899de3630c..c4e15656c1 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java @@ -49,6 +49,7 @@ import org.mitre.cybox.objects.WindowsRegistryKey; import org.mitre.stix.common_1.IndicatorBaseType; import org.mitre.stix.indicator_2.Indicator; import org.mitre.stix.stix_1.STIXPackage; +import org.openide.filesystems.FileUtil; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; @@ -66,6 +67,7 @@ import org.sleuthkit.datamodel.TskCoreException; public class STIXReportModule implements GeneralReportModule { private static final Logger logger = Logger.getLogger(STIXReportModule.class.getName()); + private static final String STIX_REPORT = "STIX Report"; private STIXReportModuleConfigPanel configPanel; private static STIXReportModule instance = null; private String reportPath; @@ -101,6 +103,13 @@ public class STIXReportModule implements GeneralReportModule { progressPanel.setIndeterminate(false); progressPanel.start(); progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.readSTIX")); + String stixReportDir = baseReportDir + " " + STIX_REPORT; + try { + FileUtil.createFolder(new File(stixReportDir)); + } catch (IOException ex) { + logger.log(Level.SEVERE, "Unable to make STIX report folder."); //NON-NLS + } + reportPath = baseReportDir + getRelativeFilePath(); File reportFile = new File(reportPath); // Check if the user wants to display all output or just hits @@ -119,7 +128,7 @@ public class STIXReportModule implements GeneralReportModule { progressPanel.complete(ReportStatus.ERROR); progressPanel.updateStatusLabel( NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.noFildDirProvided")); - new File(baseReportDir).delete(); + new File(stixReportDir).delete(); return; } if (stixFileName.isEmpty()) { @@ -129,7 +138,7 @@ public class STIXReportModule implements GeneralReportModule { progressPanel.complete(ReportStatus.ERROR); progressPanel.updateStatusLabel( NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.noFildDirProvided")); - new File(baseReportDir).delete(); + new File(stixReportDir).delete(); return; } File stixFile = new File(stixFileName); @@ -142,7 +151,7 @@ public class STIXReportModule implements GeneralReportModule { progressPanel.complete(ReportStatus.ERROR); progressPanel.updateStatusLabel( NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.couldNotOpenFileDir", stixFileName)); - new File(baseReportDir).delete(); + new File(stixReportDir).delete(); return; } @@ -649,7 +658,7 @@ public class STIXReportModule implements GeneralReportModule { @Override public String getRelativeFilePath() { - return "stix.txt"; //NON-NLS + return " " + STIX_REPORT + File.separator + "stix.txt"; //NON-NLS } @Override diff --git a/Core/src/org/sleuthkit/autopsy/report/FileReportText.java b/Core/src/org/sleuthkit/autopsy/report/FileReportText.java index 6b22e4a962..94e3aa9b0a 100755 --- a/Core/src/org/sleuthkit/autopsy/report/FileReportText.java +++ b/Core/src/org/sleuthkit/autopsy/report/FileReportText.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.report; import java.io.BufferedWriter; +import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; @@ -27,6 +28,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.logging.Level; +import org.openide.filesystems.FileUtil; import org.sleuthkit.autopsy.coreutils.Logger; import org.openide.util.NbBundle; @@ -45,6 +47,7 @@ class FileReportText implements FileReportModule { private String reportPath; private Writer out; private static final String FILE_NAME = "file-report.txt"; //NON-NLS + private static final String FILE_REPORT = "Text Report"; private static FileReportText instance; @@ -58,7 +61,14 @@ class FileReportText implements FileReportModule { @Override public void startReport(String baseReportDir) { - this.reportPath = baseReportDir + FILE_NAME; + String fileReportDir = baseReportDir + " " + FILE_REPORT; + try { + FileUtil.createFolder(new File(fileReportDir)); + } catch (IOException ex) { + logger.log(Level.SEVERE, "Unable to make File report folder."); //NON-NLS + } + + this.reportPath = baseReportDir + getRelativeFilePath(); try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(this.reportPath))); } catch (IOException ex) { @@ -138,6 +148,6 @@ class FileReportText implements FileReportModule { @Override public String getRelativeFilePath() { - return FILE_NAME; + return " " + FILE_REPORT + File.separator + FILE_NAME; } } diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportBodyFile.java b/Core/src/org/sleuthkit/autopsy/report/ReportBodyFile.java index c495ac2c72..378948f73c 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportBodyFile.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportBodyFile.java @@ -28,6 +28,7 @@ import java.io.IOException; import java.util.List; import java.util.logging.Level; import javax.swing.JPanel; +import org.openide.filesystems.FileUtil; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; @@ -44,6 +45,7 @@ import org.sleuthkit.datamodel.*; class ReportBodyFile implements GeneralReportModule { private static final Logger logger = Logger.getLogger(ReportBodyFile.class.getName()); + private static final String TSK_BODY_REPORT = "TSK Body File Report"; private static ReportBodyFile instance = null; private Case currentCase; @@ -76,7 +78,12 @@ class ReportBodyFile implements GeneralReportModule { progressPanel.setIndeterminate(false); progressPanel.start(); progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "ReportBodyFile.progress.querying")); - reportPath = baseReportDir + "BodyFile.txt"; //NON-NLS + try { + FileUtil.createFolder(new java.io.File(baseReportDir + " " + TSK_BODY_REPORT)); + } catch (IOException ex) { + logger.log(Level.SEVERE, "Unable to make TSK Body File report folder."); //NON-NLS + } + reportPath = baseReportDir + getRelativeFilePath(); //NON-NLS currentCase = Case.getCurrentCase(); skCase = currentCase.getSleuthkitCase(); @@ -180,7 +187,7 @@ class ReportBodyFile implements GeneralReportModule { @Override public String getRelativeFilePath() { - return NbBundle.getMessage(this.getClass(), "ReportBodyFile.getFilePath.text"); + return " " + TSK_BODY_REPORT + java.io.File.separator + NbBundle.getMessage(this.getClass(), "ReportBodyFile.getFilePath.text"); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java index 56de46f04d..a4c8d36ce1 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.report; +import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; @@ -25,6 +26,7 @@ import java.util.List; import java.util.logging.Level; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.openide.filesystems.FileUtil; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; @@ -33,6 +35,7 @@ import org.sleuthkit.datamodel.TskCoreException; class ReportExcel implements TableReportModule { private static final Logger logger = Logger.getLogger(ReportExcel.class.getName()); + private static final String EXCEL_REPORT = "Excel Report"; private static ReportExcel instance; private Workbook wb; @@ -65,8 +68,13 @@ class ReportExcel implements TableReportModule { @Override public void startReport(String baseReportDir) { // Set the path and save it for when the report is written to disk. - this.reportPath = baseReportDir + getRelativeFilePath(); - + try { + FileUtil.createFolder(new File(baseReportDir + " " + EXCEL_REPORT)); + } catch (IOException ex) { + logger.log(Level.SEVERE, "Unable to make Excel report folder."); //NON-NLS + } + this.reportPath = baseReportDir + getRelativeFilePath(); + // Make a workbook. wb = new XSSFWorkbook(); @@ -269,7 +277,7 @@ class ReportExcel implements TableReportModule { @Override public String getRelativeFilePath() { - return "Excel.xlsx"; //NON-NLS + return " " + EXCEL_REPORT + File.separator + "Excel.xlsx"; //NON-NLS } /** diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index afad0d5746..9713215d99 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -93,17 +93,9 @@ class ReportGenerator { DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss"); Date date = new Date(); String dateNoTime = dateFormat.format(date); - this.reportPath = currentCase.getReportDirectory() + File.separator + currentCase.getDisplayName() + " " + dateNoTime + File.separator; + this.reportPath = currentCase.getReportDirectory() + File.separator + currentCase.getDisplayName() + " " + dateNoTime + " "; this.errorList = new ArrayList<>(); - - // Create the root reports directory. - try { - FileUtil.createFolder(new File(this.reportPath)); - } catch (IOException ex) { - errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedMakeRptFolder")); - logger.log(Level.SEVERE, "Failed to make report folder, may be unable to generate reports.", ex); //NON-NLS - } } /** diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java index 83163054d8..a1c9914a2c 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java @@ -73,7 +73,7 @@ class ReportHTML implements TableReportModule { private static ReportHTML instance; private static final int MAX_THUMBS_PER_PAGE = 1000; private static final String HTML_REPORT = "HTML Report"; - private static final String HTML_SUBDIR = "reports"; + private static final String HTML_SUBDIR = "content"; private Case currentCase; private SleuthkitCase skCase; static Integer THUMBNAIL_COLUMNS = 5; @@ -161,7 +161,7 @@ class ReportHTML implements TableReportModule { if (null != artifactType) { // set the icon file name iconFileName = dataTypeToFileName(artifactType.getDisplayName()) + ".png"; //NON-NLS - iconFilePath = subPath + iconFileName; + iconFilePath = subPath + File.separator + iconFileName; // determine the source image to use switch (artifactType) { @@ -272,7 +272,7 @@ class ReportHTML implements TableReportModule { logger.log(Level.WARNING, "useDataTypeIcon: unhandled artifact type = " + dataType); //NON-NLS in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/star.png"); //NON-NLS iconFileName = "star.png"; //NON-NLS - iconFilePath = subPath + iconFileName; + iconFilePath = subPath + File.separator + iconFileName; break; } } else if (dataType.startsWith(ARTIFACT_TYPE.TSK_ACCOUNT.getDisplayName())) { @@ -285,11 +285,11 @@ class ReportHTML implements TableReportModule { */ in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/accounts.png"); //NON-NLS iconFileName = "accounts.png"; //NON-NLS - iconFilePath = subPath + iconFileName; + iconFilePath = subPath + File.separator + iconFileName; } else { // no defined artifact found for this dataType in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/star.png"); //NON-NLS iconFileName = "star.png"; //NON-NLS - iconFilePath = subPath + iconFileName; + iconFilePath = subPath + File.separator + iconFileName; } try { @@ -329,7 +329,7 @@ class ReportHTML implements TableReportModule { // Refresh the HTML report refresh(); // Setup the path for the HTML report - this.path = baseReportDir + HTML_REPORT + File.separator; //NON-NLS + this.path = baseReportDir + " " + HTML_REPORT + File.separator; //NON-NLS this.subPath = this.path + HTML_SUBDIR + File.separator; this.thumbsPath = this.subPath + THUMBS_REL_PATH; //NON-NLS try { @@ -801,7 +801,7 @@ class ReportHTML implements TableReportModule { @Override public String getRelativeFilePath() { - return HTML_REPORT + File.separator + "report.html"; //NON-NLS + return " " + HTML_REPORT + File.separator + "report.html"; //NON-NLS } @Override diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportKML.java b/Core/src/org/sleuthkit/autopsy/report/ReportKML.java index a24850c514..f0cfff46e6 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportKML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportKML.java @@ -53,6 +53,7 @@ class ReportKML implements GeneralReportModule { private static final String KML_STYLE_FILE = "style.kml"; private static final String REPORT_KML = "ReportKML.kml"; private static final String STYLESHEETS_PATH = "/org/sleuthkit/autopsy/report/stylesheets/"; + private static final String KML_REPORT = "Google Earth KML Report"; private static ReportKML instance = null; private Case currentCase; private SleuthkitCase skCase; @@ -103,7 +104,14 @@ class ReportKML implements GeneralReportModule { progressPanel.setIndeterminate(true); progressPanel.start(); progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "ReportKML.progress.querying")); + baseReportDir += " " + KML_REPORT + File.separator; String kmlFileFullPath = baseReportDir + REPORT_KML; //NON-NLS + try { + FileUtil.createFolder(new File(baseReportDir)); + } catch (IOException ex) { + logger.log(Level.SEVERE, "Unable to make KML report folder."); //NON-NLS + } + currentCase = Case.getCurrentCase(); skCase = currentCase.getSleuthkitCase(); @@ -832,7 +840,7 @@ class ReportKML implements GeneralReportModule { @Override public String getRelativeFilePath() { - return "ReportKML.kml"; //NON-NLS + return " " + KML_REPORT + File.separator + "ReportKML.kml"; //NON-NLS } @Override From 316edff6f9f35b6de1b9b35fdceed9518ef42ecf Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Mon, 8 Jan 2018 14:15:51 -0500 Subject: [PATCH 04/28] 3412: Updates to let base directory not be touched by the modules and stay with ReportGenerator --- .../modules/stix/STIXReportModule.java | 19 +++------- .../autopsy/report/Bundle.properties | 10 ++--- .../autopsy/report/FileReportText.java | 12 +----- .../autopsy/report/ReportBodyFile.java | 8 +--- .../sleuthkit/autopsy/report/ReportExcel.java | 10 +---- .../autopsy/report/ReportGenerator.java | 37 ++++++++++++++++--- .../sleuthkit/autopsy/report/ReportHTML.java | 5 +-- .../sleuthkit/autopsy/report/ReportKML.java | 11 +----- 8 files changed, 50 insertions(+), 62 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java b/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java index c4e15656c1..24c1dae6dc 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java @@ -49,7 +49,6 @@ import org.mitre.cybox.objects.WindowsRegistryKey; import org.mitre.stix.common_1.IndicatorBaseType; import org.mitre.stix.indicator_2.Indicator; import org.mitre.stix.stix_1.STIXPackage; -import org.openide.filesystems.FileUtil; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; @@ -67,7 +66,6 @@ import org.sleuthkit.datamodel.TskCoreException; public class STIXReportModule implements GeneralReportModule { private static final Logger logger = Logger.getLogger(STIXReportModule.class.getName()); - private static final String STIX_REPORT = "STIX Report"; private STIXReportModuleConfigPanel configPanel; private static STIXReportModule instance = null; private String reportPath; @@ -102,14 +100,7 @@ public class STIXReportModule implements GeneralReportModule { // Start the progress bar and setup the report progressPanel.setIndeterminate(false); progressPanel.start(); - progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.readSTIX")); - String stixReportDir = baseReportDir + " " + STIX_REPORT; - try { - FileUtil.createFolder(new File(stixReportDir)); - } catch (IOException ex) { - logger.log(Level.SEVERE, "Unable to make STIX report folder."); //NON-NLS - } - + progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.readSTIX")); reportPath = baseReportDir + getRelativeFilePath(); File reportFile = new File(reportPath); // Check if the user wants to display all output or just hits @@ -128,7 +119,7 @@ public class STIXReportModule implements GeneralReportModule { progressPanel.complete(ReportStatus.ERROR); progressPanel.updateStatusLabel( NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.noFildDirProvided")); - new File(stixReportDir).delete(); + new File(baseReportDir).delete(); return; } if (stixFileName.isEmpty()) { @@ -138,7 +129,7 @@ public class STIXReportModule implements GeneralReportModule { progressPanel.complete(ReportStatus.ERROR); progressPanel.updateStatusLabel( NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.noFildDirProvided")); - new File(stixReportDir).delete(); + new File(baseReportDir).delete(); return; } File stixFile = new File(stixFileName); @@ -151,7 +142,7 @@ public class STIXReportModule implements GeneralReportModule { progressPanel.complete(ReportStatus.ERROR); progressPanel.updateStatusLabel( NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.couldNotOpenFileDir", stixFileName)); - new File(stixReportDir).delete(); + new File(baseReportDir).delete(); return; } @@ -658,7 +649,7 @@ public class STIXReportModule implements GeneralReportModule { @Override public String getRelativeFilePath() { - return " " + STIX_REPORT + File.separator + "stix.txt"; //NON-NLS + return "stix.txt"; //NON-NLS } @Override diff --git a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties index 49eb13d806..2da0862826 100755 --- a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties @@ -47,13 +47,13 @@ ReportBodyFile.getDesc.text=Body file format report with MAC times for every fil ReportBodyFile.getFilePath.text=BodyFile.txt ReportKML.progress.querying=Querying files... ReportKML.progress.loading=Loading files... -ReportKML.getName.text=Google Earth/KML +ReportKML.getName.text=Google Earth KML ReportKML.getDesc.text=KML format report with coordinates for relevant files. This format can be used for google earth views. ReportKML.getFilePath.text=ReportKML.kml ReportBranding.defaultReportTitle.text=Autopsy Forensic Report ReportBranding.defaultReportFooter.text=Powered by Autopsy Open Source Digital Forensics Platform - www.sleuthkit.org ReportExcel.numAartifacts.text=Number of artifacts\: -ReportExcel.getName.text=Results - Excel +ReportExcel.getName.text=Excel Report ReportExcel.getDesc.text=A report about results and tagged items in Excel (XLS) format. ReportExcel.sheetName.text=Summary ReportExcel.cellVal.summary=Summary @@ -177,12 +177,12 @@ ReportGenerator.errors.reportErrorText=Error generating report: ReportHTML.addThumbRows.dataType.title=Tagged Images - {0} ReportHTML.addThumbRows.dataType.msg=Tagged Results and Contents that contain images. ReportHTML.thumbLink.tags=Tags\: -ReportHTML.getName.text=Results - HTML +ReportHTML.getName.text=HTML Report ReportHTML.getDesc.text=A report about results and tagged items in HTML format. ReportHTML.writeIndex.title=for case {0} ReportHTML.writeIndex.noFrames.msg=Your browser is not compatible with our frame setup. -ReportHTML.writeIndex.noFrames.seeNav=Please see the navigation page for artifact links, -ReportHTML.writeIndex.seeSum=and the summary page for a case summary. +ReportHTML.writeIndex.noFrames.seeNav=Please see the navigation page for artifact links, +ReportHTML.writeIndex.seeSum=and the summary page for a case summary. ReportHTML.writeNav.title=Report Navigation ReportHTML.writeNav.h1=Report Navigation ReportHTML.writeNav.summary=Case Summary diff --git a/Core/src/org/sleuthkit/autopsy/report/FileReportText.java b/Core/src/org/sleuthkit/autopsy/report/FileReportText.java index 94e3aa9b0a..426f0dd2a7 100755 --- a/Core/src/org/sleuthkit/autopsy/report/FileReportText.java +++ b/Core/src/org/sleuthkit/autopsy/report/FileReportText.java @@ -47,7 +47,6 @@ class FileReportText implements FileReportModule { private String reportPath; private Writer out; private static final String FILE_NAME = "file-report.txt"; //NON-NLS - private static final String FILE_REPORT = "Text Report"; private static FileReportText instance; @@ -61,14 +60,7 @@ class FileReportText implements FileReportModule { @Override public void startReport(String baseReportDir) { - String fileReportDir = baseReportDir + " " + FILE_REPORT; - try { - FileUtil.createFolder(new File(fileReportDir)); - } catch (IOException ex) { - logger.log(Level.SEVERE, "Unable to make File report folder."); //NON-NLS - } - - this.reportPath = baseReportDir + getRelativeFilePath(); + this.reportPath = baseReportDir + FILE_NAME; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(this.reportPath))); } catch (IOException ex) { @@ -148,6 +140,6 @@ class FileReportText implements FileReportModule { @Override public String getRelativeFilePath() { - return " " + FILE_REPORT + File.separator + FILE_NAME; + return FILE_NAME; } } diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportBodyFile.java b/Core/src/org/sleuthkit/autopsy/report/ReportBodyFile.java index 378948f73c..bddbcd4778 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportBodyFile.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportBodyFile.java @@ -45,7 +45,6 @@ import org.sleuthkit.datamodel.*; class ReportBodyFile implements GeneralReportModule { private static final Logger logger = Logger.getLogger(ReportBodyFile.class.getName()); - private static final String TSK_BODY_REPORT = "TSK Body File Report"; private static ReportBodyFile instance = null; private Case currentCase; @@ -78,11 +77,6 @@ class ReportBodyFile implements GeneralReportModule { progressPanel.setIndeterminate(false); progressPanel.start(); progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "ReportBodyFile.progress.querying")); - try { - FileUtil.createFolder(new java.io.File(baseReportDir + " " + TSK_BODY_REPORT)); - } catch (IOException ex) { - logger.log(Level.SEVERE, "Unable to make TSK Body File report folder."); //NON-NLS - } reportPath = baseReportDir + getRelativeFilePath(); //NON-NLS currentCase = Case.getCurrentCase(); skCase = currentCase.getSleuthkitCase(); @@ -187,7 +181,7 @@ class ReportBodyFile implements GeneralReportModule { @Override public String getRelativeFilePath() { - return " " + TSK_BODY_REPORT + java.io.File.separator + NbBundle.getMessage(this.getClass(), "ReportBodyFile.getFilePath.text"); + return NbBundle.getMessage(this.getClass(), "ReportBodyFile.getFilePath.text"); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java index a4c8d36ce1..07c02c81c7 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java @@ -35,7 +35,6 @@ import org.sleuthkit.datamodel.TskCoreException; class ReportExcel implements TableReportModule { private static final Logger logger = Logger.getLogger(ReportExcel.class.getName()); - private static final String EXCEL_REPORT = "Excel Report"; private static ReportExcel instance; private Workbook wb; @@ -68,12 +67,7 @@ class ReportExcel implements TableReportModule { @Override public void startReport(String baseReportDir) { // Set the path and save it for when the report is written to disk. - try { - FileUtil.createFolder(new File(baseReportDir + " " + EXCEL_REPORT)); - } catch (IOException ex) { - logger.log(Level.SEVERE, "Unable to make Excel report folder."); //NON-NLS - } - this.reportPath = baseReportDir + getRelativeFilePath(); + this.reportPath = baseReportDir + getRelativeFilePath(); // Make a workbook. wb = new XSSFWorkbook(); @@ -277,7 +271,7 @@ class ReportExcel implements TableReportModule { @Override public String getRelativeFilePath() { - return " " + EXCEL_REPORT + File.separator + "Excel.xlsx"; //NON-NLS + return "Excel.xlsx"; //NON-NLS } /** diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index 9713215d99..7fcc124fab 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -63,7 +63,7 @@ class ReportGenerator { */ private ReportProgressPanel progressPanel; - private final String reportPath; + private String reportPathFormatString; private final ReportGenerationPanel reportGenerationPanel = new ReportGenerationPanel(); static final String REPORTS_DIR = "Reports"; //NON-NLS @@ -93,11 +93,12 @@ class ReportGenerator { DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss"); Date date = new Date(); String dateNoTime = dateFormat.format(date); - this.reportPath = currentCase.getReportDirectory() + File.separator + currentCase.getDisplayName() + " " + dateNoTime + " "; + this.reportPathFormatString = currentCase.getReportDirectory() + File.separator + currentCase.getDisplayName() + " %s " + dateNoTime + File.separator; this.errorList = new ArrayList<>(); } + /** * Display the progress panels to the user, and add actions to close the * parent dialog. @@ -137,9 +138,17 @@ class ReportGenerator { */ void generateGeneralReport(GeneralReportModule generalReportModule) { if (generalReportModule != null) { + reportPathFormatString = String.format(reportPathFormatString, generalReportModule.getName()); + // Create the root reports directory. + try { + FileUtil.createFolder(new File(reportPathFormatString)); + } catch (IOException ex) { + errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedMakeRptFolder")); + logger.log(Level.SEVERE, "Failed to make report folder, may be unable to generate reports.", ex); //NON-NLS + } setupProgressPanel(generalReportModule); ReportWorker worker = new ReportWorker(() -> { - generalReportModule.generateReport(reportPath, progressPanel); + generalReportModule.generateReport(reportPathFormatString, progressPanel); }); worker.execute(); displayProgressPanel(); @@ -156,9 +165,17 @@ class ReportGenerator { */ void generateTableReport(TableReportModule tableReport, Map artifactTypeSelections, Map tagNameSelections) { if (tableReport != null && null != artifactTypeSelections) { + reportPathFormatString = String.format(reportPathFormatString, tableReport.getName()); + // Create the root reports directory. + try { + FileUtil.createFolder(new File(reportPathFormatString)); + } catch (IOException ex) { + errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedMakeRptFolder")); + logger.log(Level.SEVERE, "Failed to make report folder, may be unable to generate reports.", ex); //NON-NLS + } setupProgressPanel(tableReport); ReportWorker worker = new ReportWorker(() -> { - tableReport.startReport(reportPath); + tableReport.startReport(reportPathFormatString); TableReportGenerator generator = new TableReportGenerator(artifactTypeSelections, tagNameSelections, progressPanel, tableReport); generator.execute(); tableReport.endReport(); @@ -179,6 +196,14 @@ class ReportGenerator { */ void generateFileListReport(FileReportModule fileReportModule, Map enabledInfo) { if (fileReportModule != null && null != enabledInfo) { + reportPathFormatString = String.format(reportPathFormatString, fileReportModule.getName()); + // Create the root reports directory. + try { + FileUtil.createFolder(new File(reportPathFormatString)); + } catch (IOException ex) { + errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedMakeRptFolder")); + logger.log(Level.SEVERE, "Failed to make report folder, may be unable to generate reports.", ex); //NON-NLS + } List enabled = new ArrayList<>(); for (Entry e : enabledInfo.entrySet()) { if (e.getValue()) { @@ -196,7 +221,7 @@ class ReportGenerator { List files = getFiles(); int numFiles = files.size(); if (progressPanel.getStatus() != ReportStatus.CANCELED) { - fileReportModule.startReport(reportPath); + fileReportModule.startReport(reportPathFormatString); fileReportModule.startTable(enabled); } progressPanel.setIndeterminate(false); @@ -254,7 +279,7 @@ class ReportGenerator { private void setupProgressPanel(ReportModule module) { String reportFilePath = module.getRelativeFilePath(); if (!reportFilePath.isEmpty()) { - this.progressPanel = reportGenerationPanel.addReport(module.getName(), reportPath + reportFilePath); + this.progressPanel = reportGenerationPanel.addReport(module.getName(), String.format(reportPathFormatString, module.getName()) + reportFilePath); } else { this.progressPanel = reportGenerationPanel.addReport(module.getName(), null); } diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java index a1c9914a2c..4f6f2f4671 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java @@ -329,11 +329,10 @@ class ReportHTML implements TableReportModule { // Refresh the HTML report refresh(); // Setup the path for the HTML report - this.path = baseReportDir + " " + HTML_REPORT + File.separator; //NON-NLS + this.path = baseReportDir; //NON-NLS this.subPath = this.path + HTML_SUBDIR + File.separator; this.thumbsPath = this.subPath + THUMBS_REL_PATH; //NON-NLS try { - FileUtil.createFolder(new File(this.path)); FileUtil.createFolder(new File(this.subPath)); FileUtil.createFolder(new File(this.thumbsPath)); } catch (IOException ex) { @@ -801,7 +800,7 @@ class ReportHTML implements TableReportModule { @Override public String getRelativeFilePath() { - return " " + HTML_REPORT + File.separator + "report.html"; //NON-NLS + return "report.html"; //NON-NLS } @Override diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportKML.java b/Core/src/org/sleuthkit/autopsy/report/ReportKML.java index f0cfff46e6..b55a25ef84 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportKML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportKML.java @@ -53,7 +53,6 @@ class ReportKML implements GeneralReportModule { private static final String KML_STYLE_FILE = "style.kml"; private static final String REPORT_KML = "ReportKML.kml"; private static final String STYLESHEETS_PATH = "/org/sleuthkit/autopsy/report/stylesheets/"; - private static final String KML_REPORT = "Google Earth KML Report"; private static ReportKML instance = null; private Case currentCase; private SleuthkitCase skCase; @@ -104,14 +103,8 @@ class ReportKML implements GeneralReportModule { progressPanel.setIndeterminate(true); progressPanel.start(); progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "ReportKML.progress.querying")); - baseReportDir += " " + KML_REPORT + File.separator; String kmlFileFullPath = baseReportDir + REPORT_KML; //NON-NLS - try { - FileUtil.createFolder(new File(baseReportDir)); - } catch (IOException ex) { - logger.log(Level.SEVERE, "Unable to make KML report folder."); //NON-NLS - } - + currentCase = Case.getCurrentCase(); skCase = currentCase.getSleuthkitCase(); @@ -840,7 +833,7 @@ class ReportKML implements GeneralReportModule { @Override public String getRelativeFilePath() { - return " " + KML_REPORT + File.separator + "ReportKML.kml"; //NON-NLS + return "ReportKML.kml"; //NON-NLS } @Override From f82956e353831d0a3bd41d68a63e6cc6f93c2831 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Mon, 8 Jan 2018 15:53:19 -0500 Subject: [PATCH 05/28] 3412: Update the copyright date --- .../org/sleuthkit/autopsy/modules/stix/STIXReportModule.java | 2 +- Core/src/org/sleuthkit/autopsy/report/FileReportText.java | 4 +--- Core/src/org/sleuthkit/autopsy/report/ReportBodyFile.java | 3 +-- Core/src/org/sleuthkit/autopsy/report/ReportExcel.java | 4 +--- Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java | 2 +- Core/src/org/sleuthkit/autopsy/report/ReportHTML.java | 2 +- Core/src/org/sleuthkit/autopsy/report/ReportKML.java | 2 +- 7 files changed, 7 insertions(+), 12 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java b/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java index 24c1dae6dc..5909b26d9a 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013 Basis Technology Corp. + * Copyright 2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Core/src/org/sleuthkit/autopsy/report/FileReportText.java b/Core/src/org/sleuthkit/autopsy/report/FileReportText.java index 426f0dd2a7..8ad3625eb4 100755 --- a/Core/src/org/sleuthkit/autopsy/report/FileReportText.java +++ b/Core/src/org/sleuthkit/autopsy/report/FileReportText.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013 Basis Technology Corp. + * Copyright 2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.report; import java.io.BufferedWriter; -import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; @@ -28,7 +27,6 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.logging.Level; -import org.openide.filesystems.FileUtil; import org.sleuthkit.autopsy.coreutils.Logger; import org.openide.util.NbBundle; diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportBodyFile.java b/Core/src/org/sleuthkit/autopsy/report/ReportBodyFile.java index bddbcd4778..33609f7333 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportBodyFile.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportBodyFile.java @@ -2,7 +2,7 @@ * * Autopsy Forensic Browser * - * Copyright 2012-2014 Basis Technology Corp. + * Copyright 2012-2018 Basis Technology Corp. * * Copyright 2012 42six Solutions. * Contact: aebadirad 42six com @@ -28,7 +28,6 @@ import java.io.IOException; import java.util.List; import java.util.logging.Level; import javax.swing.JPanel; -import org.openide.filesystems.FileUtil; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java index 07c02c81c7..19526a0a19 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2017 Basis Technology Corp. + * Copyright 2013-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.report; -import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; @@ -26,7 +25,6 @@ import java.util.List; import java.util.logging.Level; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.openide.filesystems.FileUtil; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index 7fcc124fab..d34e5426f7 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013 Basis Technology Corp. + * Copyright 2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java index 4f6f2f4671..dcbc8dc88c 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java @@ -2,7 +2,7 @@ * * Autopsy Forensic Browser * - * Copyright 2012-2014 Basis Technology Corp. + * Copyright 2012-2018 Basis Technology Corp. * * Copyright 2012 42six Solutions. * Contact: aebadirad 42six com diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportKML.java b/Core/src/org/sleuthkit/autopsy/report/ReportKML.java index b55a25ef84..f089855e0c 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportKML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportKML.java @@ -2,7 +2,7 @@ * * Autopsy Forensic Browser * - * Copyright 2014-2016 Basis Technology Corp. + * Copyright 2014-2018 Basis Technology Corp. * contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); From 9c02f119bf54737500ae5a5d2a95d612417829aa Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Mon, 8 Jan 2018 16:14:39 -0500 Subject: [PATCH 06/28] 3412: cleanup unused memeber --- Core/src/org/sleuthkit/autopsy/report/ReportHTML.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java index dcbc8dc88c..88d9fe44b1 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java @@ -72,7 +72,6 @@ class ReportHTML implements TableReportModule { private static final String THUMBS_REL_PATH = "thumbs" + File.separator; //NON-NLS private static ReportHTML instance; private static final int MAX_THUMBS_PER_PAGE = 1000; - private static final String HTML_REPORT = "HTML Report"; private static final String HTML_SUBDIR = "content"; private Case currentCase; private SleuthkitCase skCase; From d10714fdb45f937680d76d02ee3ea7dfe44e8793 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Tue, 9 Jan 2018 10:28:00 -0500 Subject: [PATCH 07/28] 3412: Update regression.py to take care of the new HTML report path --- test/script/regression.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/script/regression.py b/test/script/regression.py index be6515f054..afe1ea4976 100755 --- a/test/script/regression.py +++ b/test/script/regression.py @@ -652,10 +652,10 @@ class TestData(object): # we are looking for is the only one in the self.reports_dir folder html_path = "" for fs in os.listdir(self.reports_dir): - html_path = make_path(self.reports_dir, fs) - if os.path.isdir(html_path): + if "HTML Report" in fs: + html_path = make_path(self.reports_dir, fs) break - return make_path(html_path, os.listdir(html_path)[0]) + return html_path def get_sorted_data_path(self, file_type): """Get the path to the BlackboardDump file that corresponds to the given DBType. From 26554731ed1f1f8b1493591f2dcf7aae196aaf87 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Tue, 9 Jan 2018 14:54:00 -0500 Subject: [PATCH 08/28] 3412: Keey the copyright date record --- .../org/sleuthkit/autopsy/modules/stix/STIXReportModule.java | 4 ++-- Core/src/org/sleuthkit/autopsy/report/FileReportText.java | 2 +- Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java b/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java index 5909b26d9a..9d08bf7115 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/stix/STIXReportModule.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018 Basis Technology Corp. + * Copyright 2013 - 2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,7 +29,7 @@ import java.util.Map; import java.util.logging.Level; import javax.swing.JPanel; import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; +import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import javax.xml.namespace.QName; import org.mitre.cybox.cybox_2.ObjectType; diff --git a/Core/src/org/sleuthkit/autopsy/report/FileReportText.java b/Core/src/org/sleuthkit/autopsy/report/FileReportText.java index 8ad3625eb4..c9a239cf0a 100755 --- a/Core/src/org/sleuthkit/autopsy/report/FileReportText.java +++ b/Core/src/org/sleuthkit/autopsy/report/FileReportText.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018 Basis Technology Corp. + * Copyright 2013 - 2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index d34e5426f7..0c8aa263c3 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018 Basis Technology Corp. + * Copyright 2013 - 2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); From c9240668130381012cb7454f4f0b52b97c99219a Mon Sep 17 00:00:00 2001 From: esaunders Date: Tue, 9 Jan 2018 17:49:24 -0500 Subject: [PATCH 09/28] Update file extractor and Tika text extractor to use new Tika SAX parsers in order to reduce the amount of memory required to process DOCX and PPTX files. --- .../MSOfficeEmbeddedContentExtractor.java | 13 ++++++++----- .../keywordsearch/TikaTextExtractor.java | 18 +++++++++++++++++- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/MSOfficeEmbeddedContentExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/MSOfficeEmbeddedContentExtractor.java index 4a3a20da07..7fca6a896c 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/MSOfficeEmbeddedContentExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/MSOfficeEmbeddedContentExtractor.java @@ -51,6 +51,7 @@ import org.apache.tika.mime.MimeTypeException; import org.apache.tika.parser.AutoDetectParser; import org.apache.tika.parser.ParseContext; import org.apache.tika.parser.Parser; +import org.apache.tika.parser.microsoft.OfficeParserConfig; import org.apache.tika.sax.BodyContentHandler; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; @@ -231,11 +232,13 @@ class MSOfficeEmbeddedContentExtractor { // write limit (which defaults to 100,000 characters. ContentHandler contentHandler = new BodyContentHandler(-1); - // TODO: this will be needed once we upgrade to Tika 1.16 or later. - // OfficeParserConfig officeParserConfig = new OfficeParserConfig(); - // officeParserConfig.setUseSAXPptxExtractor(true); - // officeParserConfig.setUseSAXDocxExtractor(true); - // parseContext.set(OfficeParserConfig.class, officeParserConfig); + // Use the more memory efficient Tika SAX parsers for DOCX and + // PPTX files (it already uses SAX for XLSX). + OfficeParserConfig officeParserConfig = new OfficeParserConfig(); + officeParserConfig.setUseSAXPptxExtractor(true); + officeParserConfig.setUseSAXDocxExtractor(true); + parseContext.set(OfficeParserConfig.class, officeParserConfig); + EmbeddedDocumentExtractor extractor = new EmbeddedContentExtractor(parseContext); parseContext.set(EmbeddedDocumentExtractor.class, extractor); ReadContentInputStream stream = new ReadContentInputStream(abstractFile); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TikaTextExtractor.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TikaTextExtractor.java index fcbace158d..4b9c3b17cb 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TikaTextExtractor.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TikaTextExtractor.java @@ -33,7 +33,11 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.tika.Tika; import org.apache.tika.metadata.Metadata; +import org.apache.tika.parser.AutoDetectParser; import org.apache.tika.parser.ParseContext; +import org.apache.tika.parser.Parser; +import org.apache.tika.parser.ParsingReader; +import org.apache.tika.parser.microsoft.OfficeParserConfig; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AbstractFile; @@ -48,6 +52,8 @@ class TikaTextExtractor extends FileTextExtractor { static final private Logger logger = Logger.getLogger(TikaTextExtractor.class.getName()); private final ExecutorService tikaParseExecutor = Executors.newSingleThreadExecutor(); + private final AutoDetectParser parser = new AutoDetectParser(); + private static final List TIKA_SUPPORTED_TYPES = new Tika().getParser().getSupportedTypes(new ParseContext()) .stream() @@ -64,8 +70,18 @@ class TikaTextExtractor extends FileTextExtractor { ReadContentInputStream stream = new ReadContentInputStream(sourceFile); Metadata metadata = new Metadata(); + ParseContext parseContext = new ParseContext(); + parseContext.set(Parser.class, parser); + + // Use the more memory efficient Tika SAX parsers for DOCX and + // PPTX files (it already uses SAX for XLSX). + OfficeParserConfig officeParserConfig = new OfficeParserConfig(); + officeParserConfig.setUseSAXPptxExtractor(true); + officeParserConfig.setUseSAXDocxExtractor(true); + parseContext.set(OfficeParserConfig.class, officeParserConfig); + //Parse the file in a task, a convenient way to have a timeout... - final Future future = tikaParseExecutor.submit(() -> new Tika().parse(stream, metadata)); + final Future future = tikaParseExecutor.submit(() -> new ParsingReader(parser, stream, metadata, parseContext)); try { final Reader tikaReader = future.get(getTimeout(sourceFile.getSize()), TimeUnit.SECONDS); From ef87e9a7b6c41918a8d4b954b95c78097133ba43 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 9 Jan 2018 16:15:08 -0500 Subject: [PATCH 10/28] 3408 initial working changes for multi user case explorer --- .../autopsy/casemodule/Bundle.properties | 10 +- .../autopsy/casemodule/CaseBrowser.form | 47 ++ .../autopsy/casemodule/CaseBrowser.java | 226 +++++++ .../autopsy/casemodule/CaseNode.java | 203 ++++++ .../casemodule/MultiUserCaseManager.java | 442 ------------- .../casemodule/MultiUserCasesPanel.form | 207 +----- .../casemodule/MultiUserCasesPanel.java | 619 ++++++------------ .../datamodel/DisplayableItemNodeVisitor.java | 10 +- 8 files changed, 709 insertions(+), 1055 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.form create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/CaseNode.java delete mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 1cc822fea5..ab2b5c12dc 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -223,17 +223,11 @@ ReviewModeCasePanel.MetadataFileHeaderText=Metadata File OpenMultiUserCasePanel.jLabel1.text=Recent Cases OpenMultiUserCasePanel.openButton.text=Open OpenMultiUserCasePanel.cancelButton.text=Cancel -MultiUserCasesPanel.rbWeeks.text=Weeks -MultiUserCasesPanel.rbDays.text=Days -MultiUserCasesPanel.bnShowLog.toolTipText=Display case log file for selected case -MultiUserCasesPanel.bnShowLog.text=&Show Auto Ingest Case Log -MultiUserCasesPanel.rbAllCases.text=Everything -MultiUserCasesPanel.bnRefresh.text=&Refresh MultiUserCasesPanel.bnOpen.text=&Open -MultiUserCasesPanel.rbGroupLabel.text=Show cases created in the last 10: -MultiUserCasesPanel.rbMonths.text=Months CueBannerPanel.newCaseLabel.text=New Case CueBannerPanel.openCaseButton.text= CueBannerPanel.openCaseLabel.text=Open Case MultiUserCasesPanel.bnOpenSingleUserCase.text=Open Single-User Case... CueBannerPanel.newCaseButton.text= +MultiUserCasesPanel.searchLabel.text=Start typing to search by case name +MultiUserCasesPanel.cancelButton.text=Cancel diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.form b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.form new file mode 100644 index 0000000000..cdb5a13686 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.form @@ -0,0 +1,47 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java new file mode 100644 index 0000000000..901f646717 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java @@ -0,0 +1,226 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2017-2018 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.casemodule; + +import java.awt.Component; +import java.awt.Cursor; +import java.lang.reflect.InvocationTargetException; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionListener; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import org.netbeans.swing.outline.DefaultOutlineModel; +import org.netbeans.swing.outline.Outline; +import org.openide.explorer.ExplorerManager; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.util.Exceptions; +import org.sleuthkit.autopsy.coreutils.ThreadConfined; +import org.sleuthkit.autopsy.datamodel.NodeProperty; + +/** + * A Swing JPanel with a JTabbedPane child component. The tabbed pane contains + * result viewers. + * + * The "main" DataResultPanel for the desktop application has a table viewer + * (DataResultViewerTable) and a thumbnail viewer (DataResultViewerThumbnail), + * plus zero to many additional DataResultViewers, since the DataResultViewer + * interface is an extension point. + * + * The "main" DataResultPanel resides in the "main" results view + * (DataResultTopComponent) that is normally docked into the upper right hand + * side of the main window of the desktop application. + * + * The result viewers in the "main panel" are used to view the child nodes of a + * node selected in the tree view (DirectoryTreeTopComponent) that is normally + * docked into the left hand side of the main window of the desktop application. + * + * Nodes selected in the child results viewers of a DataResultPanel are + * displayed in a content view (implementation of the DataContent interface) + * supplied the panel. The default content view is (DataContentTopComponent) is + * normally docked into the lower right hand side of the main window, underneath + * the results view. A custom content view may be specified instead. + */ +class CaseBrowser extends javax.swing.JPanel { + + private static final long serialVersionUID = 1L; + + private Outline outline; + private ExplorerManager em; + private org.openide.explorer.view.OutlineView outlineView; + + /** + * Creates new form CaseBrowser + */ + CaseBrowser() { + outlineView = new org.openide.explorer.view.OutlineView(); + initComponents(); + + outline = outlineView.getOutline(); + outlineView.setPropertyColumns( + Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), + Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), + Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath() + ); + outline.setRootVisible(false); + ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.CaseNode_column_name()); + outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + outline.setColumnSorted(1, false, 1); //it would be nice if the column index wasn't hardcoded + + } + + /** + * Initializes this panel. Intended to be called by a parent top component + * when the top component is opened. + */ + void open() { + if (null == em) { + /* + * Get an explorer manager to pass to the child result viewers. If + * the application components are put together as expected, this + * will be an explorer manager owned by a parent top component, and + * placed by the top component in the look up that is proxied as the + * action global context when the top component has focus. The + * sharing of this explorer manager enables the same child node + * selections to be made in all of the result viewers. + */ + em = ExplorerManager.find(this); + } + jScrollPane1.setViewportView(outlineView); + setColumnWidths(); + this.setVisible(true); + } + + @ThreadConfined(type = ThreadConfined.ThreadType.AWT) + public void setNode(Node selectedNode) { + + /* + * The quick filter must be reset because when determining column width, + * ETable.getRowCount is called, and the documentation states that quick + * filters must be unset for the method to work "If the quick-filter is + * applied the number of rows do not match the number of rows in the + * model." + */ + outline.unsetQuickFilter(); + // change the cursor to "waiting cursor" for this operation + this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + try { + boolean hasChildren = false; + if (selectedNode != null) { + // @@@ This just did a DB round trip to get the count and the results were not saved... + hasChildren = selectedNode.getChildren().getNodesCount() > 0; + } + + if (hasChildren) { + em.setRootContext(selectedNode);; + outline = outlineView.getOutline(); + } else { + Node emptyNode = new AbstractNode(Children.LEAF); + em.setRootContext(emptyNode); // make empty node + outlineView.setPropertyColumns(); // set the empty property header + } + } finally { + this.setCursor(null); + } + } + + public void addListSelectionListener(ListSelectionListener listener) { + outline.getSelectionModel().addListSelectionListener(listener); + } + + String getCasePath() { + int[] selectedRows = outline.getSelectedRows(); + System.out.println("Explored Context: " + em.getExploredContext()); + System.out.println("EM ROOT NODe: " + em.getRootContext().getDisplayName()); + if (selectedRows.length == 1) { + System.out.println("Selected Row: " + selectedRows[0]); + for (int colIndex = 0; colIndex < outline.getColumnCount(); colIndex++) { + TableColumn col = outline.getColumnModel().getColumn(colIndex); + System.out.println("COL: " + col.getHeaderValue().toString()); + if (col.getHeaderValue().toString().equals(Bundle.CaseNode_column_metadataFilePath())) { + try { + return ((NodeProperty)outline.getValueAt(selectedRows[0], colIndex)).getValue().toString(); + } catch (IllegalAccessException ex) { + + } catch (InvocationTargetException ex) { + + } + } + } + + } + return null; + } + + boolean isRowSelected() { + System.out.println("SELECTED ROWS: " + outline.getSelectedRows().length); + return outline.getSelectedRows().length > 0; + } + + private void setColumnWidths() { + int margin = 4; + int padding = 8; + + final int rows = Math.min(100, outline.getRowCount()); + + for (int column = 0; column < outline.getModel().getColumnCount(); column++) { + int columnWidthLimit = 500; + int columnWidth = 0; + + // find the maximum width needed to fit the values for the first 100 rows, at most + for (int row = 0; row < rows; row++) { + TableCellRenderer renderer = outline.getCellRenderer(row, column); + Component comp = outline.prepareRenderer(renderer, row, column); + columnWidth = Math.max(comp.getPreferredSize().width, columnWidth); + } + + columnWidth += 2 * margin + padding; // add margin and regular padding + columnWidth = Math.min(columnWidth, columnWidthLimit); + + outline.getColumnModel().getColumn(column).setPreferredWidth(columnWidth); + } + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jScrollPane1 = new javax.swing.JScrollPane(); + + setMinimumSize(new java.awt.Dimension(0, 5)); + setPreferredSize(new java.awt.Dimension(5, 5)); + setLayout(new java.awt.BorderLayout()); + + jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPane1.setMinimumSize(new java.awt.Dimension(0, 5)); + jScrollPane1.setOpaque(false); + jScrollPane1.setPreferredSize(new java.awt.Dimension(5, 5)); + add(jScrollPane1, java.awt.BorderLayout.CENTER); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JScrollPane jScrollPane1; + // End of variables declaration//GEN-END:variables + +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseNode.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseNode.java new file mode 100644 index 0000000000..abd6b965d8 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseNode.java @@ -0,0 +1,203 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2016 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.casemodule; + +import java.awt.event.ActionEvent; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.SwingUtilities; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.ChildFactory; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.nodes.Sheet; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; +import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; +import org.sleuthkit.autopsy.datamodel.NodeProperty; +/** + * Provides a root node for the results views with a single child node that + * displays a message as the sole item in its property sheet, useful for + * displaying explanatory text in the result views when there is a node with no + * children in the tree view. + */ +public final class CaseNode extends AbstractNode { + + @Messages({"CaseNode.column.name=Name", + "CaseNode.column.createdTime=Created Time", + "CaseNode.column.status=Status", + "CaseNode.column.metadataFilePath=Path"}) + + /** + * Provides a root node for the results views with a single child node that + * displays a message as the sole item in its property sheet, useful for + * displaying explanatory text in the result views when there is a node with + * no children in the tree view. + * + * @param displayedMessage The text for the property sheet of the child + * node. + */ + CaseNode(Map caseList) { + super(Children.create(new CaseNodeChildren(caseList), true)); + } + + static class CaseNodeChildren extends ChildFactory> { + + Map caseList; + + public CaseNodeChildren(Map caseList) { + this.caseList = caseList; + } + + @Override + protected boolean createKeys(List> list) { + if (caseList != null && caseList.size() > 0) { + list.addAll(caseList.entrySet()); + } + System.out.println("NUM OF KEYS: " + list.size()); + return true; + } + + @Override + protected Node createNodeForKey(Entry key) { + return new CaseNameNode(key); + } + + } + + /** + * The single child node of an EmptyNode, responsible for displaying a + * message as the sole item in its property sheet. + */ + public static final class CaseNameNode extends DisplayableItemNode { + + CaseMetadata multiUserCase; + String caseMetadataFilePath; + boolean caseHasAlert; + + CaseNameNode(Entry userCase) { + super(Children.LEAF); + multiUserCase = userCase.getKey(); + caseHasAlert = userCase.getValue(); + super.setName(multiUserCase.getCaseDisplayName()); + setName(multiUserCase.getCaseDisplayName()); + setDisplayName(multiUserCase.getCaseDisplayName()); + caseMetadataFilePath = multiUserCase.getFilePath().toString(); + } + + @Override + public boolean isLeafTypeNode() { + return true; + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + public String getItemType() { + return getClass().getName(); + } + + public String getMetadataFilePath() { + return caseMetadataFilePath; + } + + @Override + protected Sheet createSheet() { + Sheet s = super.createSheet(); + Sheet.Set ss = s.get(Sheet.PROPERTIES); + if (ss == null) { + ss = Sheet.createPropertiesSet(); + s.put(ss); + } + ss.put(new NodeProperty<>(Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(), + multiUserCase.getCaseDisplayName())); + ss.put(new NodeProperty<>(Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), + multiUserCase.getCreatedDate())); + ss.put(new NodeProperty<>(Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), + (caseHasAlert == true ? "Alert" : ""))); + ss.put(new NodeProperty<>(Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), + caseMetadataFilePath)); + return s; + } + + @Override + public Action[] getActions(boolean context) { + List actions = new ArrayList<>(); + actions.addAll(Arrays.asList(super.getActions(context))); + actions.add(new OpenMultiUserCaseAction(multiUserCase.getFilePath())); + return actions.toArray(new Action[actions.size()]); + } + } + + /** + * An action that opens the case node which it was generated off of + */ + private static final class OpenMultiUserCaseAction extends AbstractAction { + + private static final long serialVersionUID = 1L; + + private final Path caseMetadataFilePath; + + public OpenMultiUserCaseAction(Path path) { + super("Open Case"); + caseMetadataFilePath = path; + } + + @Override + public void actionPerformed(ActionEvent e) { + StartupWindowProvider.getInstance().close(); + openCaseThread(caseMetadataFilePath); + } + } + + private static void openCaseThread(Path caseMetadataFilePath) { + + new Thread( + () -> { + try { + Case.openAsCurrentCase(caseMetadataFilePath.toString()); + } catch (CaseActionException ex) { + if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) { + // LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS + MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage()); + } + SwingUtilities.invokeLater(() -> { + //GUI changes done back on the EDT + StartupWindowProvider.getInstance().open(); + }); + } finally { + SwingUtilities.invokeLater(() -> { + //GUI changes done back on the EDT + }); + } + } + ).start(); + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java deleted file mode 100644 index bedc09d799..0000000000 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java +++ /dev/null @@ -1,442 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011-2017 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.casemodule; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.Date; -import java.util.List; -import java.util.Objects; -import java.util.logging.Level; -import org.sleuthkit.autopsy.coordinationservice.CaseNodeData; -import org.sleuthkit.autopsy.coordinationservice.CoordinationService; -import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; -import org.sleuthkit.autopsy.coreutils.Logger; - -/** - * Handles locating and opening multi-user cases. - */ -final class MultiUserCaseManager { - - private static final Logger LOGGER = Logger.getLogger(MultiUserCaseManager.class.getName()); - private static final String ALERT_FILE_NAME = "autoingest.alert"; - private static MultiUserCaseManager instance; - private CoordinationService coordinationService; - - /** - * Gets the multi-user case manager. - * - * @return The multi-user case manager singleton. - * - * @throws MultiUserCaseManagerException - */ - synchronized static MultiUserCaseManager getInstance() throws MultiUserCaseManager.MultiUserCaseManagerException { - if (null == instance) { - instance = new MultiUserCaseManager(); - } - return instance; - } - - /** - * Constructs an object that handles locating and opening multi-user cases. - * - * @throws MultiUserCaseManagerException - */ - private MultiUserCaseManager() throws MultiUserCaseManagerException { - try { - coordinationService = CoordinationService.getInstance(); - } catch (CoordinationServiceException ex) { - throw new MultiUserCaseManager.MultiUserCaseManagerException("Failed to get the coordination service.", ex); - } - } - - /** - * Gets a list of the cases in the top level case folder - * - * @return List of cases. - * - * @throws CoordinationServiceException - */ - List getCases() throws CoordinationServiceException { - List cases = new ArrayList<>(); - List nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.CASES); - for (String node : nodeList) { - Path casePath = Paths.get(node); - File caseFolder = casePath.toFile(); - if (caseFolder.exists()) { - /* - * Search for '*.aut' and 'autoingest.alert' files. - */ - File[] fileArray = caseFolder.listFiles(); - if (fileArray == null) { - continue; - } - String autFilePath = null; - boolean alertFileFound = false; - for (File file : fileArray) { - String name = file.getName().toLowerCase(); - if (autFilePath == null && name.endsWith(".aut")) { - autFilePath = file.getAbsolutePath(); - if (!alertFileFound) { - continue; - } - } - if (!alertFileFound && name.endsWith(ALERT_FILE_NAME)) { - alertFileFound = true; - } - if (autFilePath != null && alertFileFound) { - break; - } - } - - if (autFilePath != null) { - try { - CaseStatus caseStatus; - if (alertFileFound) { - /* - * When an alert file exists, ignore the node data - * and use the ALERT status. - */ - caseStatus = CaseStatus.ALERT; - } else { - byte[] rawData = coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, node); - if (rawData != null && rawData.length > 0) { - /* - * When node data exists, use the status stored - * in the node data. - */ - CaseNodeData caseNodeData = new CaseNodeData(rawData); - if (caseNodeData.getErrorsOccurred()) { - caseStatus = CaseStatus.ALERT; - } else { - caseStatus = CaseStatus.OK; - } - } else { - /* - * When no node data is available, use the 'OK' - * status to avoid confusing the end-user. - */ - caseStatus = CaseStatus.OK; - } - } - - CaseMetadata caseMetadata = new CaseMetadata(Paths.get(autFilePath)); - cases.add(new MultiUserCase(casePath, caseMetadata, caseStatus)); - } catch (CaseMetadata.CaseMetadataException | MultiUserCase.MultiUserCaseException ex) { - LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFilePath), ex); - } catch (InterruptedException | CaseNodeData.InvalidDataException ex) { - LOGGER.log(Level.SEVERE, String.format("Error reading case node data for '%s'.", node), ex); - } - } - } - } - return cases; - } - - /** - * Opens a multi-user case. - * - * @param caseMetadataFilePath Path to the case metadata file. - * - * @throws CaseActionException - */ - synchronized void openCase(Path caseMetadataFilePath) throws CaseActionException { - /* - * Open the case. - */ - Case.openAsCurrentCase(caseMetadataFilePath.toString()); - } - - /** - * Exception type thrown when there is an error completing a multi-user case - * manager operation. - */ - static final class MultiUserCaseManagerException extends Exception { - - private static final long serialVersionUID = 1L; - - /** - * Constructs an instance of the exception type thrown when there is an - * error completing a multi-user case manager operation. - * - * @param message The exception message. - */ - private MultiUserCaseManagerException(String message) { - super(message); - } - - /** - * Constructs an instance of the exception type thrown when there is an - * error completing a multi-user case manager operation. - * - * @param message The exception message. - * @param cause A Throwable cause for the error. - */ - private MultiUserCaseManagerException(String message, Throwable cause) { - super(message, cause); - } - - } - - /** - * A representation of a multi-user case. - */ - static class MultiUserCase implements Comparable { - - private final Path caseDirectoryPath; - private final String caseDisplayName; - private final String metadataFileName; - private final Date createDate; - private final Date lastAccessedDate; - private CaseStatus status; - - /** - * Constructs a representation of a multi-user case - * - * @param caseDirectoryPath The case directory path. - * @param caseMetadata The case metadata. - * - * @throws MultiUserCaseException If no case metadata (.aut) file is - * found in the case directory. - */ - MultiUserCase(Path caseDirectoryPath, CaseMetadata caseMetadata, CaseStatus status) throws MultiUserCaseException { - this.caseDirectoryPath = caseDirectoryPath; - caseDisplayName = caseMetadata.getCaseDisplayName(); - metadataFileName = caseMetadata.getFilePath().getFileName().toString(); - this.status = status; - BasicFileAttributes fileAttrs = null; - try { - fileAttrs = Files.readAttributes(Paths.get(caseDirectoryPath.toString(), metadataFileName), BasicFileAttributes.class); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, String.format("Error reading file attributes of case metadata file in %s, will use current time for case createDate/lastModfiedDate", caseDirectoryPath), ex); - } - if (null != fileAttrs) { - createDate = new Date(fileAttrs.creationTime().toMillis()); - lastAccessedDate = new Date(fileAttrs.lastAccessTime().toMillis()); - } else { - createDate = new Date(); - lastAccessedDate = new Date(); - } - } - - /** - * Gets the case directory path. - * - * @return The case directory path. - */ - Path getCaseDirectoryPath() { - return this.caseDirectoryPath; - } - - /** - * Gets the case display name. This may differ from the name supplied to - * the directory or metadata file names if a case has been renamed. - * - * @return The case display name. - */ - String getCaseDisplayName() { - return this.caseDisplayName; - } - - /** - * Gets the creation date for the case, defined as the create time of - * the case metadata file. - * - * @return The case creation date. - */ - Date getCreationDate() { - return this.createDate; - } - - /** - * Gets the last accessed date for the case, defined as the last - * accessed time of the case metadata file. - * - * @return The last accessed date. - */ - Date getLastAccessedDate() { - return this.lastAccessedDate; - } - - /** - * Gets metadata (.aut) file name. - * - * @return The metadata file name. - */ - String getMetadataFileName() { - return this.metadataFileName; - } - - /** - * Gets the status of this case. - * - * @return See CaseStatus enum definition. - */ - CaseStatus getStatus() { - return status; - } - - /** - * Gets the case metadata from a case directory path. - * - * @param caseDirectoryPath The case directory path. - * - * @return Case metadata. - * - * @throws CaseMetadata.CaseMetadataException If the CaseMetadata object - * cannot be constructed. - * @throws MultiUserCaseException If no case metadata (.aut) - * file is found in the case - * directory. - */ - private CaseMetadata getCaseMetadataFromCaseDirectoryPath(Path caseDirectoryPath) throws CaseMetadata.CaseMetadataException, MultiUserCaseException { - CaseMetadata caseMetadata = null; - - File directory = new File(caseDirectoryPath.toString()); - if (directory.isDirectory()) { - File autFile = null; - - /* - * Attempt to find an AUT file via a directory scan. - */ - for (File file : directory.listFiles()) { - if (file.getName().toLowerCase().endsWith(CaseMetadata.getFileExtension()) && file.isFile()) { - autFile = file; - break; - } - } - - if (autFile == null || !autFile.isFile()) { - throw new MultiUserCaseException(String.format("No case metadata (.aut) file found in the case directory '%s'.", caseDirectoryPath.toString())); - } - - caseMetadata = new CaseMetadata(Paths.get(autFile.getAbsolutePath())); - } - - return caseMetadata; - } - - /** - * Indicates whether or not some other object is "equal to" this - * MultiUserCase object. - * - * @param other The other object. - * - * @return True or false. - */ - @Override - public boolean equals(Object other) { - if (!(other instanceof MultiUserCase)) { - return false; - } - if (other == this) { - return true; - } - return this.caseDirectoryPath.toString().equals(((MultiUserCase) other).caseDirectoryPath.toString()); - } - - /** - * Returns a hash code value for this MultiUserCase object. - * - * @return The has code. - */ - @Override - public int hashCode() { - int hash = 7; - hash = 71 * hash + Objects.hashCode(this.caseDirectoryPath); - hash = 71 * hash + Objects.hashCode(this.createDate); - hash = 71 * hash + Objects.hashCode(this.caseDisplayName); - return hash; - } - - /** - * Compares this MultiUserCase object with another MultiUserCase object - * for order. - */ - @Override - public int compareTo(MultiUserCase other) { - return -this.lastAccessedDate.compareTo(other.getLastAccessedDate()); - } - - /** - * Comparator for a descending order sort on date created. - */ - static class LastAccessedDateDescendingComparator implements Comparator { - - /** - * Compares two MultiUserCase objects for order based on last - * accessed date (descending). - * - * @param object The first MultiUserCase object - * @param otherObject The second MultiUserCase object. - * - * @return A negative integer, zero, or a positive integer as the - * first argument is less than, equal to, or greater than - * the second. - */ - @Override - public int compare(MultiUserCase object, MultiUserCase otherObject) { - return -object.getLastAccessedDate().compareTo(otherObject.getLastAccessedDate()); - } - } - - /** - * Exception thrown when there is a problem creating a multi-user case. - */ - final class MultiUserCaseException extends Exception { - - private static final long serialVersionUID = 1L; - - /** - * Constructs an exception to throw when there is a problem creating - * a multi-user case. - * - * @param message The exception message. - */ - private MultiUserCaseException(String message) { - super(message); - } - - /** - * Constructs an exception to throw when there is a problem creating - * a multi-user case. - * - * @param message The exception message. - * @param cause The cause of the exception, if it was an - * exception. - */ - private MultiUserCaseException(String message, Throwable cause) { - super(message, cause); - } - } - - } - - static enum CaseStatus { - OK, - ALERT - } - -} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form index 58ef6f79fb..3f897d70c0 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form @@ -1,10 +1,6 @@
- - - - @@ -26,30 +22,19 @@ - + - + + - + + - - - - - - - - - - - - - + - @@ -59,26 +44,15 @@ - + - - - - - - - - - - - - - - - - + + + + + - + @@ -95,140 +69,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -239,5 +79,26 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java index e0d63f07d7..e17faab27e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java @@ -19,79 +19,47 @@ package org.sleuthkit.autopsy.casemodule; import java.awt.Cursor; -import java.awt.Desktop; -import java.io.IOException; +import java.awt.EventQueue; +import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.logging.Level; import javax.swing.JDialog; -import javax.swing.JOptionPane; import javax.swing.SortOrder; import javax.swing.SwingWorker; import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.table.DefaultTableModel; -import javax.swing.table.TableColumn; import javax.swing.table.TableRowSorter; +import org.openide.explorer.ExplorerManager; +import org.openide.explorer.ExplorerUtils; import org.openide.util.Lookup; import org.openide.util.NbBundle; -import org.sleuthkit.autopsy.casemodule.MultiUserCaseManager.MultiUserCase; +import org.openide.windows.TopComponent; +import org.sleuthkit.autopsy.coordinationservice.CaseNodeData; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.guiutils.LongDateCellRenderer; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.guiutils.GrayableCellRenderer; -import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.TskCoreException; /** * A panel that allows a user to open cases created by auto ingest. */ @NbBundle.Messages({"MultiUSerCasesPanel.caseListLoading.message=Retrieving list of cases, please wait..."}) -final class MultiUserCasesPanel extends javax.swing.JPanel { +final class MultiUserCasesPanel extends TopComponent implements ExplorerManager.Provider { private static final long serialVersionUID = 1L; private static final Logger LOGGER = Logger.getLogger(MultiUserCasesPanel.class.getName()); - private static final String LOG_FILE_NAME = "auto_ingest_log.txt"; - private static final int CASE_COL_MIN_WIDTH = 30; - private static final int CASE_COL_MAX_WIDTH = 2000; - private static final int CASE_COL_PREFERRED_WIDTH = 300; - private static final int TIME_COL_MIN_WIDTH = 40; - private static final int TIME_COL_MAX_WIDTH = 250; - private static final int TIME_COL_PREFERRED_WIDTH = 160; - private static final int STATUS_COL_MIN_WIDTH = 55; - private static final int STATUS_COL_MAX_WIDTH = 250; - private static final int STATUS_COL_PREFERRED_WIDTH = 60; - private static final String CASES_POPULATING_MESSAGE = NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUSerCasesPanel.caseListLoading.message"); - - /* - * The JTable table model for the cases table presented by this view is - * defined by the following string, enum, and array. - * - * TODO (RC): Consider unifying this stuff in an enum as in - * AutoIngestDashboard to make it less error prone. - */ - private static final String CASE_HEADER = NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.CaseHeaderText"); - private static final String CREATEDTIME_HEADER = NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.CreatedTimeHeaderText"); - private static final String STATUS_ICON_HEADER = NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.StatusIconHeaderText"); - private static final String OUTPUT_FOLDER_HEADER = NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.OutputFolderHeaderText"); - private static final String METADATA_FILE_HEADER = NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.MetadataFileHeaderText"); - - enum COLUMN_HEADERS { - - CASE, - CREATEDTIME, - STATUS_ICON, - OUTPUTFOLDER, - METADATA_FILE - } - private final String[] columnNames = {CASE_HEADER, CREATEDTIME_HEADER, STATUS_ICON_HEADER, OUTPUT_FOLDER_HEADER, METADATA_FILE_HEADER}; - private DefaultTableModel caseTableModel; - private JDialog parentDialog; - private LoadTableWorker tableWorker; - private Path currentlySelectedCase; + private final JDialog parentDialog; + private LoadCaseListWorker tableWorker; + private final CaseBrowser caseListPanel; + private final ExplorerManager explorerManager; /** * Constructs a panel that allows a user to open cases created by automated @@ -99,66 +67,23 @@ final class MultiUserCasesPanel extends javax.swing.JPanel { */ MultiUserCasesPanel(JDialog parentDialog) { this.parentDialog = parentDialog; - caseTableModel = new DefaultTableModel(columnNames, 0) { - private static final long serialVersionUID = 1L; - - @Override - public boolean isCellEditable(int row, int column) { - return false; - } - - @Override - public Class getColumnClass(int col) { - if (this.getColumnName(col).equals(CREATEDTIME_HEADER)) { - return Date.class; - } else { - return super.getColumnClass(col); - } - } - }; - + explorerManager = new ExplorerManager(); + associateLookup(ExplorerUtils.createLookup(explorerManager, getActionMap())); initComponents(); - /* - * Configure the columns of the cases table. - */ - TableColumn theColumn; - theColumn = casesTable.getColumn(CASE_HEADER); - theColumn.setCellRenderer(new GrayableCellRenderer()); - theColumn.setMinWidth(CASE_COL_MIN_WIDTH); - theColumn.setMaxWidth(CASE_COL_MAX_WIDTH); - theColumn.setPreferredWidth(CASE_COL_PREFERRED_WIDTH); - theColumn.setWidth(CASE_COL_PREFERRED_WIDTH); + caseListPanel = new CaseBrowser(); + caseListPanel.open(); - theColumn = casesTable.getColumn(CREATEDTIME_HEADER); - theColumn.setCellRenderer(new LongDateCellRenderer()); - theColumn.setMinWidth(TIME_COL_MIN_WIDTH); - theColumn.setMaxWidth(TIME_COL_MAX_WIDTH); - theColumn.setPreferredWidth(TIME_COL_PREFERRED_WIDTH); - theColumn.setWidth(TIME_COL_PREFERRED_WIDTH); - - theColumn = casesTable.getColumn(STATUS_ICON_HEADER); - theColumn.setCellRenderer(new StatusIconCellRenderer()); - theColumn.setMinWidth(STATUS_COL_MIN_WIDTH); - theColumn.setMaxWidth(STATUS_COL_MAX_WIDTH); - theColumn.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH); - theColumn.setWidth(STATUS_COL_PREFERRED_WIDTH); - - casesTable.removeColumn(casesTable.getColumn(OUTPUT_FOLDER_HEADER)); - casesTable.removeColumn(casesTable.getColumn(METADATA_FILE_HEADER)); - casesTable.setRowSorter(new RowSorter<>(caseTableModel)); - casesTable.getRowSorter().toggleSortOrder(casesTable.getColumn(CREATEDTIME_HEADER).getModelIndex()); + caseExplorerScrollPane.add(caseListPanel); + caseExplorerScrollPane.setViewportView(caseListPanel); /* * Listen for row selection changes and set button state for the current * selection. */ - casesTable.getSelectionModel().addListSelectionListener((ListSelectionEvent e) -> { - //Ignore extra messages. - if (e.getValueIsAdjusting()) { - return; - } + caseListPanel.addListSelectionListener((ListSelectionEvent e) -> { setButtons(); }); + } /** @@ -168,54 +93,12 @@ final class MultiUserCasesPanel extends javax.swing.JPanel { void refresh() { if (tableWorker == null || tableWorker.isDone()) { //create a new TableWorker to and execute it in a background thread if one is not currently working - currentlySelectedCase = getSelectedCase(); //set the table to display text informing the user that the list is being retreived and disable case selection - caseTableModel.setRowCount(0); - casesTable.setRowSelectionAllowed(false); - caseTableModel.addRow(new Object[]{CASES_POPULATING_MESSAGE, null, null, "", ""}); - tableWorker = new LoadTableWorker(); + tableWorker = new LoadCaseListWorker(); tableWorker.execute(); - } - } - /** - * Gets the current selection in the cases table. - * - * @return A path representing the current selected case, null if there is - * no selection. - */ - private Path getSelectedCase() { - try { - int selectedRow = casesTable.getSelectedRow(); - if (selectedRow >= 0 && selectedRow < casesTable.getRowCount()) { - return Paths.get(caseTableModel.getValueAt(casesTable.convertRowIndexToModel(selectedRow), COLUMN_HEADERS.CASE.ordinal()).toString()); - } - } catch (Exception ignored) { - return null; } - return null; - } - /** - * Sets the current selection in the cases table. - * - * @param path The case folder path of the case to select. - */ - private void setSelectedCase(Path path) { - if (path != null) { - try { - for (int row = 0; row < casesTable.getRowCount(); ++row) { - Path temp = Paths.get(caseTableModel.getValueAt(casesTable.convertRowIndexToModel(row), COLUMN_HEADERS.CASE.ordinal()).toString()); - if (temp.compareTo(path) == 0) { // found it - casesTable.setRowSelectionInterval(row, row); - return; - } - } - } catch (Exception ignored) { - casesTable.clearSelection(); - } - } - casesTable.clearSelection(); } /** @@ -223,30 +106,8 @@ final class MultiUserCasesPanel extends javax.swing.JPanel { * in the cases table. */ private void setButtons() { - boolean openEnabled = casesTable.getRowSelectionAllowed() && casesTable.getSelectedRow() >= 0 && casesTable.getSelectedRow() < casesTable.getRowCount(); + boolean openEnabled = caseListPanel.isRowSelected(); bnOpen.setEnabled(openEnabled); - - Path pathToLog = getSelectedCaseLogFilePath(); - boolean showLogEnabled = openEnabled && pathToLog != null && pathToLog.toFile().exists(); - bnShowLog.setEnabled(showLogEnabled); - } - - /** - * Retrieves the log file path for the selected case in the cases table. - * - * @return The case log path. - */ - private Path getSelectedCaseLogFilePath() { - Path retValue = null; - - int selectedRow = casesTable.getSelectedRow(); - int rowCount = casesTable.getRowCount(); - if (selectedRow >= 0 && selectedRow < rowCount) { - String caseDirectory = (String) caseTableModel.getValueAt(casesTable.convertRowIndexToModel(selectedRow), COLUMN_HEADERS.OUTPUTFOLDER.ordinal()); - retValue = Paths.get(caseDirectory, LOG_FILE_NAME); - } - - return retValue; } /** @@ -254,56 +115,40 @@ final class MultiUserCasesPanel extends javax.swing.JPanel { * * @param caseMetadataFilePath The path to the case metadata file. */ - private void openCase(Path caseMetadataFilePath) { - setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + private void openCase(String caseMetadataFilePath) { + if (caseMetadataFilePath != null) { + System.out.println("OPENENING CASE: " + caseMetadataFilePath); + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - StartupWindowProvider.getInstance().close(); - if (parentDialog != null) { - parentDialog.setVisible(false); - } - new Thread(() -> { - try { - MultiUserCaseManager.getInstance().openCase(caseMetadataFilePath); - } catch (CaseActionException | MultiUserCaseManager.MultiUserCaseManagerException ex) { - if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) { - LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS - MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage()); - } - SwingUtilities.invokeLater(() -> { - //GUI changes done back on the EDT - StartupWindowProvider.getInstance().open(); - }); - } finally { - SwingUtilities.invokeLater(() -> { - //GUI changes done back on the EDT - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - }); + StartupWindowProvider.getInstance().close(); + if (parentDialog != null) { + parentDialog.setVisible(false); } - }).start(); + new Thread(() -> { + try { + Case.openAsCurrentCase(caseMetadataFilePath); + } catch (CaseActionException ex) { + if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) { + LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS + MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage()); + } + SwingUtilities.invokeLater(() -> { + //GUI changes done back on the EDT + StartupWindowProvider.getInstance().open(); + }); + } finally { + SwingUtilities.invokeLater(() -> { + //GUI changes done back on the EDT + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + }); + } + }).start(); + } } - /** - * Indicates whether or not a time satisfies a time filter defined by this - * panel's time filter radio buttons. - * - * @param currentTime The current date and time in milliseconds from the - * Unix epoch. - * @param inputTime The date and time to be tested as milliseconds from - * the Unix epoch. - */ - private boolean passesTimeFilter(long currentTime, long inputTime) { - long numberOfUnits = 10; - long multiplier = 1; - if (rbAllCases.isSelected()) { - return true; - } else if (rbMonths.isSelected()) { - multiplier = 31; - } else if (rbWeeks.isSelected()) { - multiplier = 7; - } else if (rbDays.isSelected()) { - multiplier = 1; - } - return ((currentTime - inputTime) / (1000 * 60 * 60 * 24)) < (numberOfUnits * multiplier); + @Override + public ExplorerManager getExplorerManager() { + return explorerManager; } /** @@ -345,19 +190,11 @@ final class MultiUserCasesPanel extends javax.swing.JPanel { // //GEN-BEGIN:initComponents private void initComponents() { - rbGroupHistoryLength = new javax.swing.ButtonGroup(); bnOpen = new javax.swing.JButton(); - scrollPaneTable = new javax.swing.JScrollPane(); - casesTable = new javax.swing.JTable(); - bnRefresh = new javax.swing.JButton(); - panelFilter = new javax.swing.JPanel(); - rbAllCases = new javax.swing.JRadioButton(); - bnShowLog = new javax.swing.JButton(); - rbDays = new javax.swing.JRadioButton(); - rbWeeks = new javax.swing.JRadioButton(); - rbMonths = new javax.swing.JRadioButton(); - rbGroupLabel = new javax.swing.JLabel(); bnOpenSingleUserCase = new javax.swing.JButton(); + cancelButton = new javax.swing.JButton(); + searchLabel = new javax.swing.JLabel(); + caseExplorerScrollPane = new javax.swing.JScrollPane(); setName("Completed Cases"); // NOI18N setPreferredSize(new java.awt.Dimension(960, 485)); @@ -370,84 +207,6 @@ final class MultiUserCasesPanel extends javax.swing.JPanel { } }); - casesTable.setModel(caseTableModel); - casesTable.setRowHeight(20); - casesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); - casesTable.addMouseListener(new java.awt.event.MouseAdapter() { - public void mouseClicked(java.awt.event.MouseEvent evt) { - casesTableMouseClicked(evt); - } - }); - scrollPaneTable.setViewportView(casesTable); - - org.openide.awt.Mnemonics.setLocalizedText(bnRefresh, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnRefresh.text")); // NOI18N - bnRefresh.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - bnRefreshActionPerformed(evt); - } - }); - - rbGroupHistoryLength.add(rbAllCases); - rbAllCases.setSelected(true); - org.openide.awt.Mnemonics.setLocalizedText(rbAllCases, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbAllCases.text")); // NOI18N - rbAllCases.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - rbAllCasesItemStateChanged(evt); - } - }); - - javax.swing.GroupLayout panelFilterLayout = new javax.swing.GroupLayout(panelFilter); - panelFilter.setLayout(panelFilterLayout); - panelFilterLayout.setHorizontalGroup( - panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelFilterLayout.createSequentialGroup() - .addComponent(rbAllCases) - .addGap(0, 0, Short.MAX_VALUE)) - ); - panelFilterLayout.setVerticalGroup( - panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelFilterLayout.createSequentialGroup() - .addGap(0, 0, 0) - .addComponent(rbAllCases)) - ); - - org.openide.awt.Mnemonics.setLocalizedText(bnShowLog, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnShowLog.text")); // NOI18N - bnShowLog.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnShowLog.toolTipText")); // NOI18N - bnShowLog.setEnabled(false); - bnShowLog.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - bnShowLogActionPerformed(evt); - } - }); - - rbGroupHistoryLength.add(rbDays); - org.openide.awt.Mnemonics.setLocalizedText(rbDays, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbDays.text")); // NOI18N - rbDays.setName(""); // NOI18N - rbDays.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - rbDaysItemStateChanged(evt); - } - }); - - rbGroupHistoryLength.add(rbWeeks); - org.openide.awt.Mnemonics.setLocalizedText(rbWeeks, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbWeeks.text")); // NOI18N - rbWeeks.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - rbWeeksItemStateChanged(evt); - } - }); - - rbGroupHistoryLength.add(rbMonths); - org.openide.awt.Mnemonics.setLocalizedText(rbMonths, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbMonths.text")); // NOI18N - rbMonths.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - rbMonthsItemStateChanged(evt); - } - }); - - rbGroupLabel.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(rbGroupLabel, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbGroupLabel.text")); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(bnOpenSingleUserCase, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnOpenSingleUserCase.text")); // NOI18N bnOpenSingleUserCase.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -455,55 +214,45 @@ final class MultiUserCasesPanel extends javax.swing.JPanel { } }); + org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.cancelButton.text")); // NOI18N + cancelButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cancelButtonActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(searchLabel, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.searchLabel.text")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(caseExplorerScrollPane) .addGroup(layout.createSequentialGroup() - .addGap(4, 4, 4) + .addComponent(searchLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 555, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 175, Short.MAX_VALUE) .addComponent(bnOpen, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(bnOpenSingleUserCase) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(bnShowLog) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 13, Short.MAX_VALUE) - .addComponent(rbGroupLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(rbDays) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(rbWeeks) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(rbMonths) - .addGap(0, 0, 0) - .addComponent(panelFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(14, 14, 14) - .addComponent(bnRefresh)) - .addComponent(scrollPaneTable)) + .addComponent(cancelButton))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGap(6, 6, 6) - .addComponent(scrollPaneTable, javax.swing.GroupLayout.PREFERRED_SIZE, 450, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(caseExplorerScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 450, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(bnOpen) - .addComponent(bnOpenSingleUserCase) - .addComponent(bnShowLog)) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(rbDays) - .addComponent(rbWeeks) - .addComponent(rbMonths) - .addComponent(rbGroupLabel)) - .addComponent(panelFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(bnRefresh, javax.swing.GroupLayout.Alignment.TRAILING)) - .addGap(0, 0, 0)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cancelButton) + .addComponent(bnOpen) + .addComponent(bnOpenSingleUserCase) + .addComponent(searchLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); }// //GEN-END:initComponents @@ -513,129 +262,139 @@ final class MultiUserCasesPanel extends javax.swing.JPanel { * @param evt -- The event that caused this to be called */ private void bnOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOpenActionPerformed - int modelRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow()); - String caseDirectory = (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.OUTPUTFOLDER.ordinal()); - Path caseMetadataFilePath = Paths.get(caseDirectory, (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.METADATA_FILE.ordinal())); - openCase(caseMetadataFilePath); + openCase(caseListPanel.getCasePath()); }//GEN-LAST:event_bnOpenActionPerformed - /** - * Refresh button action - * - * @param evt -- The event that caused this to be called - */ - private void bnRefreshActionPerformed(java.awt.event.ActionEvent evt) { - refresh(); - } - - private void rbDaysItemStateChanged(java.awt.event.ItemEvent evt) { - if (rbDays.isSelected()) { - refresh(); - } - } - - private void rbAllCasesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbAllCasesItemStateChanged - if (rbAllCases.isSelected()) { - refresh(); - } - }//GEN-LAST:event_rbAllCasesItemStateChanged - - private void rbMonthsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbMonthsItemStateChanged - if (rbMonths.isSelected()) { - refresh(); - } - }//GEN-LAST:event_rbMonthsItemStateChanged - - private void rbWeeksItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbWeeksItemStateChanged - if (rbWeeks.isSelected()) { - refresh(); - } - }//GEN-LAST:event_rbWeeksItemStateChanged - - private void bnShowLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowLogActionPerformed - Path pathToLog = getSelectedCaseLogFilePath(); - if (pathToLog != null) { - try { - if (pathToLog.toFile().exists()) { - Desktop.getDesktop().edit(pathToLog.toFile()); - - } else { - JOptionPane.showMessageDialog(this, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotFindLog"), - org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.ERROR_MESSAGE); - } - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, String.format("Error attempting to open case auto ingest log file %s", pathToLog), ex); - JOptionPane.showMessageDialog(this, - org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotOpenLog"), - org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"), - JOptionPane.PLAIN_MESSAGE); - } - } - }//GEN-LAST:event_bnShowLogActionPerformed - - private void casesTableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_casesTableMouseClicked - if (evt.getClickCount() == 2 && casesTable.getRowSelectionAllowed() && casesTable.getSelectedRow() >= 0 && casesTable.getSelectedRow() < casesTable.getRowCount()) { - int modelRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow()); - String caseDirectory = (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.OUTPUTFOLDER.ordinal()); - Path caseMetadataFilePath = Paths.get(caseDirectory, (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.METADATA_FILE.ordinal())); - openCase(caseMetadataFilePath); - } - }//GEN-LAST:event_casesTableMouseClicked - private void bnOpenSingleUserCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOpenSingleUserCaseActionPerformed Lookup.getDefault().lookup(CaseOpenAction.class).openCaseSelectionWindow(); }//GEN-LAST:event_bnOpenSingleUserCaseActionPerformed + private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed + if (parentDialog != null) { + parentDialog.setVisible(false); + } + }//GEN-LAST:event_cancelButtonActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton bnOpen; private javax.swing.JButton bnOpenSingleUserCase; - private javax.swing.JButton bnRefresh; - private javax.swing.JButton bnShowLog; - private javax.swing.JTable casesTable; - private javax.swing.JPanel panelFilter; - private javax.swing.JRadioButton rbAllCases; - private javax.swing.JRadioButton rbDays; - private javax.swing.ButtonGroup rbGroupHistoryLength; - private javax.swing.JLabel rbGroupLabel; - private javax.swing.JRadioButton rbMonths; - private javax.swing.JRadioButton rbWeeks; - private javax.swing.JScrollPane scrollPaneTable; + private javax.swing.JButton cancelButton; + private javax.swing.JScrollPane caseExplorerScrollPane; + private javax.swing.JLabel searchLabel; // End of variables declaration//GEN-END:variables - private class LoadTableWorker extends SwingWorker { + private class LoadCaseListWorker extends SwingWorker { - private List cases; + private static final String ALERT_FILE_NAME = "autoingest.alert"; + private Map cases; + + /** + * Gets a list of the cases in the top level case folder + * + * @return List of cases. + * + * @throws CoordinationServiceException + */ + private Map getCases() throws CoordinationService.CoordinationServiceException { + Map cases = new HashMap<>(); + List nodeList = CoordinationService.getInstance().getNodeList(CoordinationService.CategoryNode.CASES); + + for (String node : nodeList) { + Path casePath = Paths.get(node); + File caseFolder = casePath.toFile(); + if (caseFolder.exists()) { + /* + * Search for '*.aut' and 'autoingest.alert' files. + */ + File[] fileArray = caseFolder.listFiles(); + if (fileArray == null) { + continue; + } + String autFilePath = null; + boolean alertFileFound = false; + for (File file : fileArray) { + String name = file.getName().toLowerCase(); + if (autFilePath == null && name.endsWith(".aut")) { + autFilePath = file.getAbsolutePath(); + if (!alertFileFound) { + continue; + } + } + if (!alertFileFound && name.endsWith(ALERT_FILE_NAME)) { + alertFileFound = true; + } + if (autFilePath != null && alertFileFound) { + break; + } + } + + if (autFilePath != null) { + try { + boolean hasAlertStatus = false; + if (alertFileFound) { + /* + * When an alert file exists, ignore the node + * data and use the ALERT status. + */ + hasAlertStatus = true; + } else { + byte[] rawData = CoordinationService.getInstance().getNodeData(CoordinationService.CategoryNode.CASES, node); + if (rawData != null && rawData.length > 0) { + /* + * When node data exists, use the status + * stored in the node data. + */ + CaseNodeData caseNodeData = new CaseNodeData(rawData); + if (caseNodeData.getErrorsOccurred()) { + hasAlertStatus = true; + } + } + } + + CaseMetadata caseMetadata = new CaseMetadata(Paths.get(autFilePath)); + cases.put(caseMetadata, hasAlertStatus); + } catch (CaseMetadata.CaseMetadataException ex) { + LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFilePath), ex); + } catch (InterruptedException | CaseNodeData.InvalidDataException ex) { + LOGGER.log(Level.SEVERE, String.format("Error reading case node data for '%s'.", node), ex); + } + } + } + } + return cases; + } @Override protected Void doInBackground() throws Exception { try { - MultiUserCaseManager manager = MultiUserCaseManager.getInstance(); - cases = manager.getCases(); - } catch (MultiUserCaseManager.MultiUserCaseManagerException | CoordinationService.CoordinationServiceException ex) { + cases = getCases(); + } catch (CoordinationService.CoordinationServiceException ex) { LOGGER.log(Level.SEVERE, "Unexpected exception while refreshing the table.", ex); //NON-NLS - } + } return null; } @Override protected void done() { - caseTableModel.setRowCount(0); - long now = new Date().getTime(); - for (MultiUserCase autoIngestCase : cases) { - if (autoIngestCase.getCreationDate() != null && passesTimeFilter(now, autoIngestCase.getCreationDate().getTime())) { - caseTableModel.addRow(new Object[]{ - autoIngestCase.getCaseDisplayName(), - autoIngestCase.getCreationDate(), - (MultiUserCaseManager.CaseStatus.OK != autoIngestCase.getStatus()) ? StatusIconCellRenderer.Status.WARNING : StatusIconCellRenderer.Status.OK, - autoIngestCase.getCaseDirectoryPath().toString(), - autoIngestCase.getMetadataFileName()}); + + EventQueue.invokeLater(() -> { + CaseNode caseListNode = new CaseNode(cases); + explorerManager.setRootContext(caseListNode); + String displayName = ""; + Content content = caseListNode.getLookup().lookup(Content.class); + if (content != null) { + try { + displayName = content.getUniquePath(); + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Exception while calling Content.getUniquePath() for node: {0}", caseListNode); //NON-NLS + } + } else if (caseListNode.getLookup().lookup(String.class) != null) { + displayName = caseListNode.getLookup().lookup(String.class); } - } - //ensure the cases are able to be selected - casesTable.setRowSelectionAllowed(true); - setSelectedCase(currentlySelectedCase); - setButtons(); + System.out.println("GET CASES DONE"); + setButtons(); + }); } } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index e6e8afed52..d95c8f099e 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.datamodel; +import org.sleuthkit.autopsy.casemodule.CaseNode; import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.DeletedContentNode; import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode; import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode; @@ -41,7 +42,7 @@ public interface DisplayableItemNodeVisitor { T visit(LocalFileNode dfn); T visit(VirtualDirectoryNode ldn); - + T visit(LocalDirectoryNode ldn); T visit(DirectoryNode dn); @@ -158,6 +159,8 @@ public interface DisplayableItemNodeVisitor { T visit(EmptyNode.MessageNode emptyNode); + T visit(CaseNode.CaseNameNode caseNode); + T visit(InterestingHits.InterestingItemTypeNode aThis); /** @@ -241,7 +244,10 @@ public interface DisplayableItemNodeVisitor { public T visit(EmptyNode.MessageNode ftByMimeTypeEmptyNode) { return defaultVisit(ftByMimeTypeEmptyNode); } - + @Override + public T visit(CaseNode.CaseNameNode caseNameNode) { + return defaultVisit(caseNameNode); + } @Override public T visit(InterestingHits.InterestingItemTypeNode interestingItemTypeNode) { return defaultVisit(interestingItemTypeNode); From 978f37620ba65d4d6652b4e48077ce32872e07e5 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 9 Jan 2018 16:22:37 -0500 Subject: [PATCH 11/28] 3408 remove unused method in CaseBrowser --- .../autopsy/casemodule/CaseBrowser.java | 39 ------------------- 1 file changed, 39 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java index 901f646717..bbf43746f3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.casemodule; import java.awt.Component; -import java.awt.Cursor; import java.lang.reflect.InvocationTargetException; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionListener; @@ -28,11 +27,6 @@ import javax.swing.table.TableColumn; import org.netbeans.swing.outline.DefaultOutlineModel; import org.netbeans.swing.outline.Outline; import org.openide.explorer.ExplorerManager; -import org.openide.nodes.AbstractNode; -import org.openide.nodes.Children; -import org.openide.nodes.Node; -import org.openide.util.Exceptions; -import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.datamodel.NodeProperty; /** @@ -108,39 +102,6 @@ class CaseBrowser extends javax.swing.JPanel { this.setVisible(true); } - @ThreadConfined(type = ThreadConfined.ThreadType.AWT) - public void setNode(Node selectedNode) { - - /* - * The quick filter must be reset because when determining column width, - * ETable.getRowCount is called, and the documentation states that quick - * filters must be unset for the method to work "If the quick-filter is - * applied the number of rows do not match the number of rows in the - * model." - */ - outline.unsetQuickFilter(); - // change the cursor to "waiting cursor" for this operation - this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - try { - boolean hasChildren = false; - if (selectedNode != null) { - // @@@ This just did a DB round trip to get the count and the results were not saved... - hasChildren = selectedNode.getChildren().getNodesCount() > 0; - } - - if (hasChildren) { - em.setRootContext(selectedNode);; - outline = outlineView.getOutline(); - } else { - Node emptyNode = new AbstractNode(Children.LEAF); - em.setRootContext(emptyNode); // make empty node - outlineView.setPropertyColumns(); // set the empty property header - } - } finally { - this.setCursor(null); - } - } - public void addListSelectionListener(ListSelectionListener listener) { outline.getSelectionModel().addListSelectionListener(listener); } From b2915ef4f85ff3108c545d0953de683c8e765194 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 9 Jan 2018 18:50:11 -0500 Subject: [PATCH 12/28] 3408 clean up and bug fixes for MultiUserCasePanel --- .../autopsy/casemodule/CaseBrowser.java | 70 +++++++------- .../autopsy/casemodule/CaseNode.java | 93 ++++++++++--------- .../casemodule/MultiUserCasesPanel.java | 31 ++----- 3 files changed, 96 insertions(+), 98 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java index bbf43746f3..3af48d6000 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java @@ -23,11 +23,13 @@ import java.lang.reflect.InvocationTargetException; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionListener; import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; +import org.netbeans.swing.etable.ETableColumn; +import org.netbeans.swing.etable.ETableColumnModel; import org.netbeans.swing.outline.DefaultOutlineModel; import org.netbeans.swing.outline.Outline; import org.openide.explorer.ExplorerManager; -import org.sleuthkit.autopsy.datamodel.NodeProperty; +import org.openide.nodes.Node; /** * A Swing JPanel with a JTabbedPane child component. The tabbed pane contains @@ -56,10 +58,10 @@ class CaseBrowser extends javax.swing.JPanel { private static final long serialVersionUID = 1L; - private Outline outline; + private final Outline outline; private ExplorerManager em; - private org.openide.explorer.view.OutlineView outlineView; - + private final org.openide.explorer.view.OutlineView outlineView; + private int originalPathColumnIndex = 0; /** * Creates new form CaseBrowser */ @@ -71,13 +73,28 @@ class CaseBrowser extends javax.swing.JPanel { outlineView.setPropertyColumns( Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), - Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath() - ); + Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath()); + customize(); + + } + + private void customize() { + TableColumnModel columnModel = outline.getColumnModel(); + int dateColumnIndex = 0; + for (int index = 0; index < columnModel.getColumnCount(); index++) { //get indexes for hidden column and default sorting column + if (columnModel.getColumn(index).getHeaderValue().toString().equals(Bundle.CaseNode_column_metadataFilePath())) { + originalPathColumnIndex = index; + } else if (columnModel.getColumn(index).getHeaderValue().toString().equals(Bundle.CaseNode_column_createdTime())) { + dateColumnIndex = index; + } + } + ETableColumn column = (ETableColumn) columnModel.getColumn(originalPathColumnIndex); + ((ETableColumnModel) columnModel).setColumnHidden(column, true); outline.setRootVisible(false); + ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.CaseNode_column_name()); outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - outline.setColumnSorted(1, false, 1); //it would be nice if the column index wasn't hardcoded - + outline.setColumnSorted(dateColumnIndex, false, 1); //it would be nice if the column index wasn't hardcoded } /** @@ -102,37 +119,28 @@ class CaseBrowser extends javax.swing.JPanel { this.setVisible(true); } - public void addListSelectionListener(ListSelectionListener listener) { + void setRowSelectionAllowed(boolean allowed) { + outline.setRowSelectionAllowed(allowed); + } + + void addListSelectionListener(ListSelectionListener listener) { outline.getSelectionModel().addListSelectionListener(listener); } String getCasePath() { int[] selectedRows = outline.getSelectedRows(); - System.out.println("Explored Context: " + em.getExploredContext()); - System.out.println("EM ROOT NODe: " + em.getRootContext().getDisplayName()); if (selectedRows.length == 1) { - System.out.println("Selected Row: " + selectedRows[0]); - for (int colIndex = 0; colIndex < outline.getColumnCount(); colIndex++) { - TableColumn col = outline.getColumnModel().getColumn(colIndex); - System.out.println("COL: " + col.getHeaderValue().toString()); - if (col.getHeaderValue().toString().equals(Bundle.CaseNode_column_metadataFilePath())) { - try { - return ((NodeProperty)outline.getValueAt(selectedRows[0], colIndex)).getValue().toString(); - } catch (IllegalAccessException ex) { - - } catch (InvocationTargetException ex) { - - } - } + try { + return ((Node.Property) outline.getModel().getValueAt(outline.convertRowIndexToModel(selectedRows[0]), originalPathColumnIndex)).getValue().toString(); + } catch (IllegalAccessException | InvocationTargetException ex) { + System.out.println("THROW"); } - } return null; } - + boolean isRowSelected() { - System.out.println("SELECTED ROWS: " + outline.getSelectedRows().length); - return outline.getSelectedRows().length > 0; + return outline.getRowSelectionAllowed() && outline.getSelectedRows().length > 0; } private void setColumnWidths() { @@ -141,8 +149,8 @@ class CaseBrowser extends javax.swing.JPanel { final int rows = Math.min(100, outline.getRowCount()); - for (int column = 0; column < outline.getModel().getColumnCount(); column++) { - int columnWidthLimit = 500; + for (int column = 0; column < outline.getColumnModel().getColumnCount(); column++) { + int columnWidthLimit = 800; int columnWidth = 0; // find the maximum width needed to fit the values for the first 100 rows, at most diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseNode.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseNode.java index abd6b965d8..bde2cb0b73 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseNode.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseNode.java @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.casemodule; import java.awt.event.ActionEvent; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -38,6 +37,7 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.NodeProperty; + /** * Provides a root node for the results views with a single child node that * displays a message as the sole item in its property sheet, useful for @@ -66,18 +66,17 @@ public final class CaseNode extends AbstractNode { static class CaseNodeChildren extends ChildFactory> { - Map caseList; + private final Map caseMap; - public CaseNodeChildren(Map caseList) { - this.caseList = caseList; + CaseNodeChildren(Map caseMap) { + this.caseMap = caseMap; } @Override protected boolean createKeys(List> list) { - if (caseList != null && caseList.size() > 0) { - list.addAll(caseList.entrySet()); + if (caseMap != null && caseMap.size() > 0) { + list.addAll(caseMap.entrySet()); } - System.out.println("NUM OF KEYS: " + list.size()); return true; } @@ -94,18 +93,20 @@ public final class CaseNode extends AbstractNode { */ public static final class CaseNameNode extends DisplayableItemNode { - CaseMetadata multiUserCase; - String caseMetadataFilePath; - boolean caseHasAlert; + private final String caseName; + private final String caseCreatedDate; + private final String caseMetadataFilePath; + private final boolean caseHasAlert; CaseNameNode(Entry userCase) { super(Children.LEAF); - multiUserCase = userCase.getKey(); + caseName = userCase.getKey().getCaseDisplayName(); + caseCreatedDate = userCase.getKey().getCreatedDate(); caseHasAlert = userCase.getValue(); - super.setName(multiUserCase.getCaseDisplayName()); - setName(multiUserCase.getCaseDisplayName()); - setDisplayName(multiUserCase.getCaseDisplayName()); - caseMetadataFilePath = multiUserCase.getFilePath().toString(); + super.setName(caseName); + setName(caseName); + setDisplayName(caseName); + caseMetadataFilePath = userCase.getKey().getFilePath().toString(); } @Override @@ -122,7 +123,7 @@ public final class CaseNode extends AbstractNode { public String getItemType() { return getClass().getName(); } - + public String getMetadataFilePath() { return caseMetadataFilePath; } @@ -136,9 +137,9 @@ public final class CaseNode extends AbstractNode { s.put(ss); } ss.put(new NodeProperty<>(Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(), - multiUserCase.getCaseDisplayName())); + caseName)); ss.put(new NodeProperty<>(Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), - multiUserCase.getCreatedDate())); + caseCreatedDate)); ss.put(new NodeProperty<>(Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), (caseHasAlert == true ? "Alert" : ""))); ss.put(new NodeProperty<>(Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), @@ -150,7 +151,7 @@ public final class CaseNode extends AbstractNode { public Action[] getActions(boolean context) { List actions = new ArrayList<>(); actions.addAll(Arrays.asList(super.getActions(context))); - actions.add(new OpenMultiUserCaseAction(multiUserCase.getFilePath())); + actions.add(new OpenMultiUserCaseAction(caseMetadataFilePath)); return actions.toArray(new Action[actions.size()]); } } @@ -162,9 +163,9 @@ public final class CaseNode extends AbstractNode { private static final long serialVersionUID = 1L; - private final Path caseMetadataFilePath; + private final String caseMetadataFilePath; - public OpenMultiUserCaseAction(Path path) { + OpenMultiUserCaseAction(String path) { super("Open Case"); caseMetadataFilePath = path; } @@ -172,32 +173,32 @@ public final class CaseNode extends AbstractNode { @Override public void actionPerformed(ActionEvent e) { StartupWindowProvider.getInstance().close(); - openCaseThread(caseMetadataFilePath); + new Thread( + () -> { + try { + Case.openAsCurrentCase(caseMetadataFilePath); + } catch (CaseActionException ex) { + if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) { + // LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS + MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage()); + } + SwingUtilities.invokeLater(() -> { + //GUI changes done back on the EDT + StartupWindowProvider.getInstance().open(); + }); + } finally { + SwingUtilities.invokeLater(() -> { + //GUI changes done back on the EDT + }); + } + } + ).start(); + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); //To change body of generated methods, choose Tools | Templates. } } - private static void openCaseThread(Path caseMetadataFilePath) { - - new Thread( - () -> { - try { - Case.openAsCurrentCase(caseMetadataFilePath.toString()); - } catch (CaseActionException ex) { - if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) { - // LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS - MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage()); - } - SwingUtilities.invokeLater(() -> { - //GUI changes done back on the EDT - StartupWindowProvider.getInstance().open(); - }); - } finally { - SwingUtilities.invokeLater(() -> { - //GUI changes done back on the EDT - }); - } - } - ).start(); - } - } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java index e17faab27e..b4e16bfa91 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java @@ -45,13 +45,12 @@ import org.sleuthkit.autopsy.coordinationservice.CaseNodeData; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.autopsy.datamodel.EmptyNode; /** * A panel that allows a user to open cases created by auto ingest. */ -@NbBundle.Messages({"MultiUSerCasesPanel.caseListLoading.message=Retrieving list of cases, please wait..."}) +@NbBundle.Messages({"MultiUserCasesPanel.caseListLoading.message=Please wait..."}) final class MultiUserCasesPanel extends TopComponent implements ExplorerManager.Provider { private static final long serialVersionUID = 1L; @@ -73,7 +72,7 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager. caseListPanel = new CaseBrowser(); caseListPanel.open(); - + caseListPanel.setRowSelectionAllowed(false); caseExplorerScrollPane.add(caseListPanel); caseExplorerScrollPane.setViewportView(caseListPanel); /* @@ -92,11 +91,13 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager. */ void refresh() { if (tableWorker == null || tableWorker.isDone()) { + caseListPanel.setRowSelectionAllowed(false); //create a new TableWorker to and execute it in a background thread if one is not currently working //set the table to display text informing the user that the list is being retreived and disable case selection + EmptyNode emptyNode = new EmptyNode(Bundle.MultiUserCasesPanel_caseListLoading_message()); + explorerManager.setRootContext(emptyNode); tableWorker = new LoadCaseListWorker(); tableWorker.execute(); - } } @@ -117,7 +118,6 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager. */ private void openCase(String caseMetadataFilePath) { if (caseMetadataFilePath != null) { - System.out.println("OPENENING CASE: " + caseMetadataFilePath); setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); StartupWindowProvider.getInstance().close(); @@ -296,7 +296,7 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager. * @throws CoordinationServiceException */ private Map getCases() throws CoordinationService.CoordinationServiceException { - Map cases = new HashMap<>(); + Map casesMap = new HashMap<>(); List nodeList = CoordinationService.getInstance().getNodeList(CoordinationService.CategoryNode.CASES); for (String node : nodeList) { @@ -352,7 +352,7 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager. } CaseMetadata caseMetadata = new CaseMetadata(Paths.get(autFilePath)); - cases.put(caseMetadata, hasAlertStatus); + casesMap.put(caseMetadata, hasAlertStatus); } catch (CaseMetadata.CaseMetadataException ex) { LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFilePath), ex); } catch (InterruptedException | CaseNodeData.InvalidDataException ex) { @@ -361,7 +361,7 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager. } } } - return cases; + return casesMap; } @Override @@ -381,18 +381,7 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager. EventQueue.invokeLater(() -> { CaseNode caseListNode = new CaseNode(cases); explorerManager.setRootContext(caseListNode); - String displayName = ""; - Content content = caseListNode.getLookup().lookup(Content.class); - if (content != null) { - try { - displayName = content.getUniquePath(); - } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Exception while calling Content.getUniquePath() for node: {0}", caseListNode); //NON-NLS - } - } else if (caseListNode.getLookup().lookup(String.class) != null) { - displayName = caseListNode.getLookup().lookup(String.class); - } - System.out.println("GET CASES DONE"); + caseListPanel.setRowSelectionAllowed(true); setButtons(); }); } From 96d9bdb0229fbf30ec30b50c2e29ed1ecfae34d2 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 10 Jan 2018 10:55:09 -0500 Subject: [PATCH 13/28] 3408 adjust context menu options for open multi user case panel --- Core/src/org/sleuthkit/autopsy/casemodule/CaseNode.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseNode.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseNode.java index bde2cb0b73..87862d4d01 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseNode.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseNode.java @@ -20,10 +20,10 @@ package org.sleuthkit.autopsy.casemodule; import java.awt.event.ActionEvent; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.logging.Level; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.SwingUtilities; @@ -33,6 +33,7 @@ import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; @@ -50,6 +51,7 @@ public final class CaseNode extends AbstractNode { "CaseNode.column.createdTime=Created Time", "CaseNode.column.status=Status", "CaseNode.column.metadataFilePath=Path"}) + private static final Logger LOGGER = Logger.getLogger(CaseNode.class.getName()); /** * Provides a root node for the results views with a single child node that @@ -150,7 +152,7 @@ public final class CaseNode extends AbstractNode { @Override public Action[] getActions(boolean context) { List actions = new ArrayList<>(); - actions.addAll(Arrays.asList(super.getActions(context))); + // actions.addAll(Arrays.asList(super.getActions(context))); actions.add(new OpenMultiUserCaseAction(caseMetadataFilePath)); return actions.toArray(new Action[actions.size()]); } @@ -173,13 +175,14 @@ public final class CaseNode extends AbstractNode { @Override public void actionPerformed(ActionEvent e) { StartupWindowProvider.getInstance().close(); + MultiUserCasesDialog.getInstance().setVisible(false); new Thread( () -> { try { Case.openAsCurrentCase(caseMetadataFilePath); } catch (CaseActionException ex) { if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) { - // LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS + LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage()); } SwingUtilities.invokeLater(() -> { From 84d113f965863246080db7bc937c76cae512b7d2 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 10 Jan 2018 11:36:05 -0500 Subject: [PATCH 14/28] 3408 move explorer provider manager down to CaseBrowser level and eliminate TopComponent --- .../autopsy/casemodule/CaseBrowser.java | 154 ++++++++++++++++-- .../casemodule/MultiUserCasesPanel.java | 144 +--------------- 2 files changed, 146 insertions(+), 152 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java index 3af48d6000..1eaef654eb 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java @@ -28,8 +28,21 @@ import org.netbeans.swing.etable.ETableColumn; import org.netbeans.swing.etable.ETableColumnModel; import org.netbeans.swing.outline.DefaultOutlineModel; import org.netbeans.swing.outline.Outline; -import org.openide.explorer.ExplorerManager; import org.openide.nodes.Node; +import java.awt.EventQueue; +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import javax.swing.SwingWorker; +import org.openide.explorer.ExplorerManager; +import org.sleuthkit.autopsy.coordinationservice.CaseNodeData; +import org.sleuthkit.autopsy.coordinationservice.CoordinationService; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datamodel.EmptyNode; /** * A Swing JPanel with a JTabbedPane child component. The tabbed pane contains @@ -54,7 +67,7 @@ import org.openide.nodes.Node; * normally docked into the lower right hand side of the main window, underneath * the results view. A custom content view may be specified instead. */ -class CaseBrowser extends javax.swing.JPanel { +class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider { private static final long serialVersionUID = 1L; @@ -62,6 +75,14 @@ class CaseBrowser extends javax.swing.JPanel { private ExplorerManager em; private final org.openide.explorer.view.OutlineView outlineView; private int originalPathColumnIndex = 0; + private static final Logger LOGGER = Logger.getLogger(CaseBrowser.class.getName()); + private LoadCaseListWorker tableWorker; + + @Override + public ExplorerManager getExplorerManager() { + return em; + } + /** * Creates new form CaseBrowser */ @@ -103,16 +124,7 @@ class CaseBrowser extends javax.swing.JPanel { */ void open() { if (null == em) { - /* - * Get an explorer manager to pass to the child result viewers. If - * the application components are put together as expected, this - * will be an explorer manager owned by a parent top component, and - * placed by the top component in the look up that is proxied as the - * action global context when the top component has focus. The - * sharing of this explorer manager enables the same child node - * selections to be made in all of the result viewers. - */ - em = ExplorerManager.find(this); + em = new ExplorerManager(); } jScrollPane1.setViewportView(outlineView); setColumnWidths(); @@ -167,6 +179,23 @@ class CaseBrowser extends javax.swing.JPanel { } } + /** + * Gets the list of cases known to the review mode cases manager and + * refreshes the cases table. + */ + void refresh() { + if (tableWorker == null || tableWorker.isDone()) { + setRowSelectionAllowed(false); + //create a new TableWorker to and execute it in a background thread if one is not currently working + //set the table to display text informing the user that the list is being retreived and disable case selection + EmptyNode emptyNode = new EmptyNode(Bundle.MultiUserCasesPanel_caseListLoading_message()); + em.setRootContext(emptyNode); + tableWorker = new LoadCaseListWorker(); + tableWorker.execute(); + } + + } + /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -191,5 +220,106 @@ class CaseBrowser extends javax.swing.JPanel { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JScrollPane jScrollPane1; // End of variables declaration//GEN-END:variables + private class LoadCaseListWorker extends SwingWorker { + private static final String ALERT_FILE_NAME = "autoingest.alert"; + private Map cases; + + /** + * Gets a list of the cases in the top level case folder + * + * @return List of cases. + * + * @throws CoordinationServiceException + */ + private Map getCases() throws CoordinationService.CoordinationServiceException { + Map casesMap = new HashMap<>(); + List nodeList = CoordinationService.getInstance().getNodeList(CoordinationService.CategoryNode.CASES); + + for (String node : nodeList) { + Path casePath = Paths.get(node); + File caseFolder = casePath.toFile(); + if (caseFolder.exists()) { + /* + * Search for '*.aut' and 'autoingest.alert' files. + */ + File[] fileArray = caseFolder.listFiles(); + if (fileArray == null) { + continue; + } + String autFilePath = null; + boolean alertFileFound = false; + for (File file : fileArray) { + String name = file.getName().toLowerCase(); + if (autFilePath == null && name.endsWith(".aut")) { + autFilePath = file.getAbsolutePath(); + if (!alertFileFound) { + continue; + } + } + if (!alertFileFound && name.endsWith(ALERT_FILE_NAME)) { + alertFileFound = true; + } + if (autFilePath != null && alertFileFound) { + break; + } + } + + if (autFilePath != null) { + try { + boolean hasAlertStatus = false; + if (alertFileFound) { + /* + * When an alert file exists, ignore the node + * data and use the ALERT status. + */ + hasAlertStatus = true; + } else { + byte[] rawData = CoordinationService.getInstance().getNodeData(CoordinationService.CategoryNode.CASES, node); + if (rawData != null && rawData.length > 0) { + /* + * When node data exists, use the status + * stored in the node data. + */ + CaseNodeData caseNodeData = new CaseNodeData(rawData); + if (caseNodeData.getErrorsOccurred()) { + hasAlertStatus = true; + } + } + } + + CaseMetadata caseMetadata = new CaseMetadata(Paths.get(autFilePath)); + casesMap.put(caseMetadata, hasAlertStatus); + } catch (CaseMetadata.CaseMetadataException ex) { + LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFilePath), ex); + } catch (InterruptedException | CaseNodeData.InvalidDataException ex) { + LOGGER.log(Level.SEVERE, String.format("Error reading case node data for '%s'.", node), ex); + } + } + } + } + return casesMap; + } + + @Override + protected Void doInBackground() throws Exception { + + try { + cases = getCases(); + } catch (CoordinationService.CoordinationServiceException ex) { + LOGGER.log(Level.SEVERE, "Unexpected exception while refreshing the table.", ex); //NON-NLS + } + return null; + } + + @Override + protected void done() { + + EventQueue.invokeLater(() -> { + CaseNode caseListNode = new CaseNode(cases); + em.setRootContext(caseListNode); + setRowSelectionAllowed(true); + }); + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java index b4e16bfa91..d012107e1f 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java @@ -19,46 +19,30 @@ package org.sleuthkit.autopsy.casemodule; import java.awt.Cursor; -import java.awt.EventQueue; -import java.io.File; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import java.util.logging.Level; import javax.swing.JDialog; +import javax.swing.JPanel; import javax.swing.SortOrder; -import javax.swing.SwingWorker; import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableRowSorter; -import org.openide.explorer.ExplorerManager; -import org.openide.explorer.ExplorerUtils; import org.openide.util.Lookup; import org.openide.util.NbBundle; -import org.openide.windows.TopComponent; -import org.sleuthkit.autopsy.coordinationservice.CaseNodeData; -import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.datamodel.EmptyNode; /** * A panel that allows a user to open cases created by auto ingest. */ @NbBundle.Messages({"MultiUserCasesPanel.caseListLoading.message=Please wait..."}) -final class MultiUserCasesPanel extends TopComponent implements ExplorerManager.Provider { +final class MultiUserCasesPanel extends JPanel{ - private static final long serialVersionUID = 1L; private static final Logger LOGGER = Logger.getLogger(MultiUserCasesPanel.class.getName()); private final JDialog parentDialog; - private LoadCaseListWorker tableWorker; private final CaseBrowser caseListPanel; - private final ExplorerManager explorerManager; /** * Constructs a panel that allows a user to open cases created by automated @@ -66,8 +50,6 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager. */ MultiUserCasesPanel(JDialog parentDialog) { this.parentDialog = parentDialog; - explorerManager = new ExplorerManager(); - associateLookup(ExplorerUtils.createLookup(explorerManager, getActionMap())); initComponents(); caseListPanel = new CaseBrowser(); @@ -90,23 +72,14 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager. * refreshes the cases table. */ void refresh() { - if (tableWorker == null || tableWorker.isDone()) { - caseListPanel.setRowSelectionAllowed(false); - //create a new TableWorker to and execute it in a background thread if one is not currently working - //set the table to display text informing the user that the list is being retreived and disable case selection - EmptyNode emptyNode = new EmptyNode(Bundle.MultiUserCasesPanel_caseListLoading_message()); - explorerManager.setRootContext(emptyNode); - tableWorker = new LoadCaseListWorker(); - tableWorker.execute(); - } - + caseListPanel.refresh(); } /** * Enables/disables the Open and Show Log buttons based on the case selected * in the cases table. */ - private void setButtons() { + void setButtons() { boolean openEnabled = caseListPanel.isRowSelected(); bnOpen.setEnabled(openEnabled); } @@ -146,11 +119,6 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager. } } - @Override - public ExplorerManager getExplorerManager() { - return explorerManager; - } - /** * RowSorter which makes columns whose type is Date to be sorted first in * Descending order then in Ascending order @@ -282,108 +250,4 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager. private javax.swing.JScrollPane caseExplorerScrollPane; private javax.swing.JLabel searchLabel; // End of variables declaration//GEN-END:variables - - private class LoadCaseListWorker extends SwingWorker { - - private static final String ALERT_FILE_NAME = "autoingest.alert"; - private Map cases; - - /** - * Gets a list of the cases in the top level case folder - * - * @return List of cases. - * - * @throws CoordinationServiceException - */ - private Map getCases() throws CoordinationService.CoordinationServiceException { - Map casesMap = new HashMap<>(); - List nodeList = CoordinationService.getInstance().getNodeList(CoordinationService.CategoryNode.CASES); - - for (String node : nodeList) { - Path casePath = Paths.get(node); - File caseFolder = casePath.toFile(); - if (caseFolder.exists()) { - /* - * Search for '*.aut' and 'autoingest.alert' files. - */ - File[] fileArray = caseFolder.listFiles(); - if (fileArray == null) { - continue; - } - String autFilePath = null; - boolean alertFileFound = false; - for (File file : fileArray) { - String name = file.getName().toLowerCase(); - if (autFilePath == null && name.endsWith(".aut")) { - autFilePath = file.getAbsolutePath(); - if (!alertFileFound) { - continue; - } - } - if (!alertFileFound && name.endsWith(ALERT_FILE_NAME)) { - alertFileFound = true; - } - if (autFilePath != null && alertFileFound) { - break; - } - } - - if (autFilePath != null) { - try { - boolean hasAlertStatus = false; - if (alertFileFound) { - /* - * When an alert file exists, ignore the node - * data and use the ALERT status. - */ - hasAlertStatus = true; - } else { - byte[] rawData = CoordinationService.getInstance().getNodeData(CoordinationService.CategoryNode.CASES, node); - if (rawData != null && rawData.length > 0) { - /* - * When node data exists, use the status - * stored in the node data. - */ - CaseNodeData caseNodeData = new CaseNodeData(rawData); - if (caseNodeData.getErrorsOccurred()) { - hasAlertStatus = true; - } - } - } - - CaseMetadata caseMetadata = new CaseMetadata(Paths.get(autFilePath)); - casesMap.put(caseMetadata, hasAlertStatus); - } catch (CaseMetadata.CaseMetadataException ex) { - LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFilePath), ex); - } catch (InterruptedException | CaseNodeData.InvalidDataException ex) { - LOGGER.log(Level.SEVERE, String.format("Error reading case node data for '%s'.", node), ex); - } - } - } - } - return casesMap; - } - - @Override - protected Void doInBackground() throws Exception { - - try { - cases = getCases(); - } catch (CoordinationService.CoordinationServiceException ex) { - LOGGER.log(Level.SEVERE, "Unexpected exception while refreshing the table.", ex); //NON-NLS - } - return null; - } - - @Override - protected void done() { - - EventQueue.invokeLater(() -> { - CaseNode caseListNode = new CaseNode(cases); - explorerManager.setRootContext(caseListNode); - caseListPanel.setRowSelectionAllowed(true); - setButtons(); - }); - } - } } From f3bdf7d84e455b431e4f8359f4a1806786d5ef6a Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 10 Jan 2018 11:40:40 -0500 Subject: [PATCH 15/28] 3408 fix capilization and inline enabling of button --- .../sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java index d012107e1f..5eaa5bed6d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java @@ -37,7 +37,7 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; /** * A panel that allows a user to open cases created by auto ingest. */ -@NbBundle.Messages({"MultiUserCasesPanel.caseListLoading.message=Please wait..."}) +@NbBundle.Messages({"MultiUserCasesPanel.caseListLoading.message=Please Wait..."}) final class MultiUserCasesPanel extends JPanel{ private static final Logger LOGGER = Logger.getLogger(MultiUserCasesPanel.class.getName()); @@ -80,8 +80,7 @@ final class MultiUserCasesPanel extends JPanel{ * in the cases table. */ void setButtons() { - boolean openEnabled = caseListPanel.isRowSelected(); - bnOpen.setEnabled(openEnabled); + bnOpen.setEnabled(caseListPanel.isRowSelected()); } /** From 80b77a0739f19ae577d1638c390ad994b4a6a06b Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 10 Jan 2018 12:29:59 -0500 Subject: [PATCH 16/28] 3408 clean up comments and names for multi user case explorer changes --- .../autopsy/casemodule/{CaseNode.java => MultiUserNode.java} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Core/src/org/sleuthkit/autopsy/casemodule/{CaseNode.java => MultiUserNode.java} (100%) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseNode.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java similarity index 100% rename from Core/src/org/sleuthkit/autopsy/casemodule/CaseNode.java rename to Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java From 9d4f6bb146c53cb226bd025a48fcfb121e801c1c Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 10 Jan 2018 12:30:07 -0500 Subject: [PATCH 17/28] 3408 clean up comments and names for multi user case explorer changes --- .../autopsy/casemodule/CaseBrowser.form | 2 +- .../autopsy/casemodule/CaseBrowser.java | 96 +++++++++---------- .../casemodule/MultiUserCasesPanel.java | 21 ++-- .../autopsy/casemodule/MultiUserNode.java | 56 +++++------ .../datamodel/DisplayableItemNodeVisitor.java | 6 +- 5 files changed, 81 insertions(+), 100 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.form b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.form index cdb5a13686..edda7a749c 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.form @@ -24,7 +24,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java index 1eaef654eb..4c7980fe32 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java @@ -39,44 +39,29 @@ import java.util.Map; import java.util.logging.Level; import javax.swing.SwingWorker; import org.openide.explorer.ExplorerManager; +import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coordinationservice.CaseNodeData; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.EmptyNode; /** - * A Swing JPanel with a JTabbedPane child component. The tabbed pane contains - * result viewers. + * A Swing JPanel with a scroll pane child component. The scroll pane contain + * the table of cases. * - * The "main" DataResultPanel for the desktop application has a table viewer - * (DataResultViewerTable) and a thumbnail viewer (DataResultViewerThumbnail), - * plus zero to many additional DataResultViewers, since the DataResultViewer - * interface is an extension point. + * Used to display a list of multi user cases and allow the user to open one of + * them. * - * The "main" DataResultPanel resides in the "main" results view - * (DataResultTopComponent) that is normally docked into the upper right hand - * side of the main window of the desktop application. - * - * The result viewers in the "main panel" are used to view the child nodes of a - * node selected in the tree view (DirectoryTreeTopComponent) that is normally - * docked into the left hand side of the main window of the desktop application. - * - * Nodes selected in the child results viewers of a DataResultPanel are - * displayed in a content view (implementation of the DataContent interface) - * supplied the panel. The default content view is (DataContentTopComponent) is - * normally docked into the lower right hand side of the main window, underneath - * the results view. A custom content view may be specified instead. */ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider { private static final long serialVersionUID = 1L; - private final Outline outline; private ExplorerManager em; private final org.openide.explorer.view.OutlineView outlineView; private int originalPathColumnIndex = 0; private static final Logger LOGGER = Logger.getLogger(CaseBrowser.class.getName()); - private LoadCaseListWorker tableWorker; + private LoadCaseMapWorker tableWorker; @Override public ExplorerManager getExplorerManager() { @@ -84,7 +69,7 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider } /** - * Creates new form CaseBrowser + * Creates a new CaseBrowser */ CaseBrowser() { outlineView = new org.openide.explorer.view.OutlineView(); @@ -99,6 +84,9 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider } + /** + * Configures the the table of cases and its columns. + */ private void customize() { TableColumnModel columnModel = outline.getColumnModel(); int dateColumnIndex = 0; @@ -116,25 +104,20 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.CaseNode_column_name()); outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); outline.setColumnSorted(dateColumnIndex, false, 1); //it would be nice if the column index wasn't hardcoded - } - - /** - * Initializes this panel. Intended to be called by a parent top component - * when the top component is opened. - */ - void open() { if (null == em) { em = new ExplorerManager(); } - jScrollPane1.setViewportView(outlineView); + caseTableScrollPane.setViewportView(outlineView); setColumnWidths(); this.setVisible(true); + outline.setRowSelectionAllowed(false); } - void setRowSelectionAllowed(boolean allowed) { - outline.setRowSelectionAllowed(allowed); - } - + /** + * Add a listener to changes in case selections in the table + * + * @param listener the ListSelectionListener to add + */ void addListSelectionListener(ListSelectionListener listener) { outline.getSelectionModel().addListSelectionListener(listener); } @@ -145,12 +128,17 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider try { return ((Node.Property) outline.getModel().getValueAt(outline.convertRowIndexToModel(selectedRows[0]), originalPathColumnIndex)).getValue().toString(); } catch (IllegalAccessException | InvocationTargetException ex) { - System.out.println("THROW"); + //WJS-TODO THROW SOMETHING } } return null; } + /** + * Check if a row could be and is selected. + * + * @return true if a row is selected, false if no row is selected + */ boolean isRowSelected() { return outline.getRowSelectionAllowed() && outline.getSelectedRows().length > 0; } @@ -162,8 +150,8 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider final int rows = Math.min(100, outline.getRowCount()); for (int column = 0; column < outline.getColumnModel().getColumnCount(); column++) { - int columnWidthLimit = 800; - int columnWidth = 0; + int columnWidthLimit = 2000; + int columnWidth = 200; // find the maximum width needed to fit the values for the first 100 rows, at most for (int row = 0; row < rows; row++) { @@ -179,18 +167,19 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider } } + @NbBundle.Messages({"CaseBrowser.caseListLoading.message=Please Wait..."}) /** * Gets the list of cases known to the review mode cases manager and * refreshes the cases table. */ void refresh() { if (tableWorker == null || tableWorker.isDone()) { - setRowSelectionAllowed(false); + outline.setRowSelectionAllowed(false); //create a new TableWorker to and execute it in a background thread if one is not currently working //set the table to display text informing the user that the list is being retreived and disable case selection - EmptyNode emptyNode = new EmptyNode(Bundle.MultiUserCasesPanel_caseListLoading_message()); + EmptyNode emptyNode = new EmptyNode(Bundle.CaseBrowser_caseListLoading_message()); em.setRootContext(emptyNode); - tableWorker = new LoadCaseListWorker(); + tableWorker = new LoadCaseMapWorker(); tableWorker.execute(); } @@ -205,22 +194,27 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider // //GEN-BEGIN:initComponents private void initComponents() { - jScrollPane1 = new javax.swing.JScrollPane(); + caseTableScrollPane = new javax.swing.JScrollPane(); setMinimumSize(new java.awt.Dimension(0, 5)); setPreferredSize(new java.awt.Dimension(5, 5)); setLayout(new java.awt.BorderLayout()); - jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - jScrollPane1.setMinimumSize(new java.awt.Dimension(0, 5)); - jScrollPane1.setOpaque(false); - jScrollPane1.setPreferredSize(new java.awt.Dimension(5, 5)); - add(jScrollPane1, java.awt.BorderLayout.CENTER); + caseTableScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + caseTableScrollPane.setMinimumSize(new java.awt.Dimension(0, 5)); + caseTableScrollPane.setOpaque(false); + caseTableScrollPane.setPreferredSize(new java.awt.Dimension(5, 5)); + add(caseTableScrollPane, java.awt.BorderLayout.CENTER); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane caseTableScrollPane; // End of variables declaration//GEN-END:variables - private class LoadCaseListWorker extends SwingWorker { + + /** + * Swingworker to fetch the updated map of cases and their status in a + * background thread + */ + private class LoadCaseMapWorker extends SwingWorker { private static final String ALERT_FILE_NAME = "autoingest.alert"; private Map cases; @@ -314,11 +308,11 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider @Override protected void done() { - EventQueue.invokeLater(() -> { - CaseNode caseListNode = new CaseNode(cases); + MultiUserNode caseListNode = new MultiUserNode(cases); em.setRootContext(caseListNode); - setRowSelectionAllowed(true); + setColumnWidths(); + outline.setRowSelectionAllowed(true); }); } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java index 5eaa5bed6d..a2a2ec13ad 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java @@ -30,19 +30,18 @@ import javax.swing.event.ListSelectionEvent; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableRowSorter; import org.openide.util.Lookup; -import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; /** * A panel that allows a user to open cases created by auto ingest. */ -@NbBundle.Messages({"MultiUserCasesPanel.caseListLoading.message=Please Wait..."}) final class MultiUserCasesPanel extends JPanel{ private static final Logger LOGGER = Logger.getLogger(MultiUserCasesPanel.class.getName()); + private static final long serialVersionUID = 1L; private final JDialog parentDialog; - private final CaseBrowser caseListPanel; + private final CaseBrowser caseBrowserPanel; /** * Constructs a panel that allows a user to open cases created by automated @@ -52,16 +51,14 @@ final class MultiUserCasesPanel extends JPanel{ this.parentDialog = parentDialog; initComponents(); - caseListPanel = new CaseBrowser(); - caseListPanel.open(); - caseListPanel.setRowSelectionAllowed(false); - caseExplorerScrollPane.add(caseListPanel); - caseExplorerScrollPane.setViewportView(caseListPanel); + caseBrowserPanel = new CaseBrowser(); + caseExplorerScrollPane.add(caseBrowserPanel); + caseExplorerScrollPane.setViewportView(caseBrowserPanel); /* * Listen for row selection changes and set button state for the current * selection. */ - caseListPanel.addListSelectionListener((ListSelectionEvent e) -> { + caseBrowserPanel.addListSelectionListener((ListSelectionEvent e) -> { setButtons(); }); @@ -72,7 +69,7 @@ final class MultiUserCasesPanel extends JPanel{ * refreshes the cases table. */ void refresh() { - caseListPanel.refresh(); + caseBrowserPanel.refresh(); } /** @@ -80,7 +77,7 @@ final class MultiUserCasesPanel extends JPanel{ * in the cases table. */ void setButtons() { - bnOpen.setEnabled(caseListPanel.isRowSelected()); + bnOpen.setEnabled(caseBrowserPanel.isRowSelected()); } /** @@ -229,7 +226,7 @@ final class MultiUserCasesPanel extends JPanel{ * @param evt -- The event that caused this to be called */ private void bnOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOpenActionPerformed - openCase(caseListPanel.getCasePath()); + openCase(caseBrowserPanel.getCasePath()); }//GEN-LAST:event_bnOpenActionPerformed private void bnOpenSingleUserCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOpenSingleUserCaseActionPerformed diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java index 87862d4d01..c410afb71b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2016 Basis Technology Corp. + * Copyright 2017-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,37 +40,31 @@ import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.NodeProperty; /** - * Provides a root node for the results views with a single child node that - * displays a message as the sole item in its property sheet, useful for - * displaying explanatory text in the result views when there is a node with no - * children in the tree view. + * A root node containing child nodes of the multi user cases */ -public final class CaseNode extends AbstractNode { +public final class MultiUserNode extends AbstractNode { @Messages({"CaseNode.column.name=Name", "CaseNode.column.createdTime=Created Time", "CaseNode.column.status=Status", "CaseNode.column.metadataFilePath=Path"}) - private static final Logger LOGGER = Logger.getLogger(CaseNode.class.getName()); + private static final Logger LOGGER = Logger.getLogger(MultiUserNode.class.getName()); /** - * Provides a root node for the results views with a single child node that - * displays a message as the sole item in its property sheet, useful for - * displaying explanatory text in the result views when there is a node with - * no children in the tree view. + * Provides a root node with children which each represent a case. * - * @param displayedMessage The text for the property sheet of the child - * node. + * @param caseMap the map of cases and a boolean indicating if they have an + * alert */ - CaseNode(Map caseList) { - super(Children.create(new CaseNodeChildren(caseList), true)); + MultiUserNode(Map caseMap) { + super(Children.create(new MultiUserNodeChildren(caseMap), true)); } - static class CaseNodeChildren extends ChildFactory> { + static class MultiUserNodeChildren extends ChildFactory> { private final Map caseMap; - CaseNodeChildren(Map caseMap) { + MultiUserNodeChildren(Map caseMap) { this.caseMap = caseMap; } @@ -84,31 +78,30 @@ public final class CaseNode extends AbstractNode { @Override protected Node createNodeForKey(Entry key) { - return new CaseNameNode(key); + return new MultiUserCaseNode(key); } } /** - * The single child node of an EmptyNode, responsible for displaying a - * message as the sole item in its property sheet. + * A node which represents a single multi user case. */ - public static final class CaseNameNode extends DisplayableItemNode { + public static final class MultiUserCaseNode extends DisplayableItemNode { private final String caseName; private final String caseCreatedDate; private final String caseMetadataFilePath; private final boolean caseHasAlert; - CaseNameNode(Entry userCase) { + MultiUserCaseNode(Entry multiUserCase) { super(Children.LEAF); - caseName = userCase.getKey().getCaseDisplayName(); - caseCreatedDate = userCase.getKey().getCreatedDate(); - caseHasAlert = userCase.getValue(); + caseName = multiUserCase.getKey().getCaseDisplayName(); + caseCreatedDate = multiUserCase.getKey().getCreatedDate(); + caseHasAlert = multiUserCase.getValue(); super.setName(caseName); setName(caseName); setDisplayName(caseName); - caseMetadataFilePath = userCase.getKey().getFilePath().toString(); + caseMetadataFilePath = multiUserCase.getKey().getFilePath().toString(); } @Override @@ -152,14 +145,14 @@ public final class CaseNode extends AbstractNode { @Override public Action[] getActions(boolean context) { List actions = new ArrayList<>(); - // actions.addAll(Arrays.asList(super.getActions(context))); - actions.add(new OpenMultiUserCaseAction(caseMetadataFilePath)); + actions.add(new OpenMultiUserCaseAction(caseMetadataFilePath)); //open case context menu option return actions.toArray(new Action[actions.size()]); } } /** - * An action that opens the case node which it was generated off of + * An action that opens the specified case and hides the multi user case + * panel. */ private static final class OpenMultiUserCaseAction extends AbstractAction { @@ -188,10 +181,7 @@ public final class CaseNode extends AbstractNode { SwingUtilities.invokeLater(() -> { //GUI changes done back on the EDT StartupWindowProvider.getInstance().open(); - }); - } finally { - SwingUtilities.invokeLater(() -> { - //GUI changes done back on the EDT + MultiUserCasesDialog.getInstance().setVisible(true); }); } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index d95c8f099e..f6d461e578 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -18,7 +18,7 @@ */ package org.sleuthkit.autopsy.datamodel; -import org.sleuthkit.autopsy.casemodule.CaseNode; +import org.sleuthkit.autopsy.casemodule.MultiUserNode; import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.DeletedContentNode; import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode; import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode; @@ -159,7 +159,7 @@ public interface DisplayableItemNodeVisitor { T visit(EmptyNode.MessageNode emptyNode); - T visit(CaseNode.CaseNameNode caseNode); + T visit(MultiUserNode.MultiUserCaseNode caseNode); T visit(InterestingHits.InterestingItemTypeNode aThis); @@ -245,7 +245,7 @@ public interface DisplayableItemNodeVisitor { return defaultVisit(ftByMimeTypeEmptyNode); } @Override - public T visit(CaseNode.CaseNameNode caseNameNode) { + public T visit(MultiUserNode.MultiUserCaseNode caseNameNode) { return defaultVisit(caseNameNode); } @Override From bde7c89f8fa759db677912a7b40829f5d5bb7b90 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 10 Jan 2018 12:44:38 -0500 Subject: [PATCH 18/28] 3408 remove unnecessary method, add coments --- .../autopsy/casemodule/CaseBrowser.java | 39 ++++--------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java index 4c7980fe32..6ecb0e849d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java @@ -80,6 +80,7 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath()); + ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.CaseNode_column_name()); customize(); } @@ -88,27 +89,28 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider * Configures the the table of cases and its columns. */ private void customize() { + outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); TableColumnModel columnModel = outline.getColumnModel(); int dateColumnIndex = 0; - for (int index = 0; index < columnModel.getColumnCount(); index++) { //get indexes for hidden column and default sorting column + for (int index = 0; index < columnModel.getColumnCount(); index++) { + //get indexes for created date column and path column if (columnModel.getColumn(index).getHeaderValue().toString().equals(Bundle.CaseNode_column_metadataFilePath())) { originalPathColumnIndex = index; } else if (columnModel.getColumn(index).getHeaderValue().toString().equals(Bundle.CaseNode_column_createdTime())) { dateColumnIndex = index; } } + //Hide path column by default will need to ETableColumn column = (ETableColumn) columnModel.getColumn(originalPathColumnIndex); ((ETableColumnModel) columnModel).setColumnHidden(column, true); outline.setRootVisible(false); - ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.CaseNode_column_name()); - outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - outline.setColumnSorted(dateColumnIndex, false, 1); //it would be nice if the column index wasn't hardcoded + //Sort on Created date column in descending order by default + outline.setColumnSorted(dateColumnIndex, false, 1); if (null == em) { em = new ExplorerManager(); } caseTableScrollPane.setViewportView(outlineView); - setColumnWidths(); this.setVisible(true); outline.setRowSelectionAllowed(false); } @@ -136,37 +138,13 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider /** * Check if a row could be and is selected. - * + * * @return true if a row is selected, false if no row is selected */ boolean isRowSelected() { return outline.getRowSelectionAllowed() && outline.getSelectedRows().length > 0; } - private void setColumnWidths() { - int margin = 4; - int padding = 8; - - final int rows = Math.min(100, outline.getRowCount()); - - for (int column = 0; column < outline.getColumnModel().getColumnCount(); column++) { - int columnWidthLimit = 2000; - int columnWidth = 200; - - // find the maximum width needed to fit the values for the first 100 rows, at most - for (int row = 0; row < rows; row++) { - TableCellRenderer renderer = outline.getCellRenderer(row, column); - Component comp = outline.prepareRenderer(renderer, row, column); - columnWidth = Math.max(comp.getPreferredSize().width, columnWidth); - } - - columnWidth += 2 * margin + padding; // add margin and regular padding - columnWidth = Math.min(columnWidth, columnWidthLimit); - - outline.getColumnModel().getColumn(column).setPreferredWidth(columnWidth); - } - } - @NbBundle.Messages({"CaseBrowser.caseListLoading.message=Please Wait..."}) /** * Gets the list of cases known to the review mode cases manager and @@ -311,7 +289,6 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider EventQueue.invokeLater(() -> { MultiUserNode caseListNode = new MultiUserNode(cases); em.setRootContext(caseListNode); - setColumnWidths(); outline.setRowSelectionAllowed(true); }); } From d88aabf9a2daefc3a72b6dfd155e9b91c1ba87e5 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 10 Jan 2018 13:56:09 -0500 Subject: [PATCH 19/28] 3408 basic context menu action for opening log file --- .../autopsy/casemodule/MultiUserNode.java | 60 ++++++++++++++++++- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java index c410afb71b..8723212801 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java @@ -18,7 +18,11 @@ */ package org.sleuthkit.autopsy.casemodule; +import java.awt.Desktop; import java.awt.event.ActionEvent; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -26,6 +30,7 @@ import java.util.Map.Entry; import java.util.logging.Level; import javax.swing.AbstractAction; import javax.swing.Action; +import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import org.openide.nodes.AbstractNode; import org.openide.nodes.ChildFactory; @@ -49,6 +54,7 @@ public final class MultiUserNode extends AbstractNode { "CaseNode.column.status=Status", "CaseNode.column.metadataFilePath=Path"}) private static final Logger LOGGER = Logger.getLogger(MultiUserNode.class.getName()); + private static final String LOG_FILE_NAME = "auto_ingest_log.txt"; /** * Provides a root node with children which each represent a case. @@ -92,6 +98,7 @@ public final class MultiUserNode extends AbstractNode { private final String caseCreatedDate; private final String caseMetadataFilePath; private final boolean caseHasAlert; + private final Path caseLogFilePath; MultiUserCaseNode(Entry multiUserCase) { super(Children.LEAF); @@ -102,6 +109,7 @@ public final class MultiUserNode extends AbstractNode { setName(caseName); setDisplayName(caseName); caseMetadataFilePath = multiUserCase.getKey().getFilePath().toString(); + caseLogFilePath = Paths.get(multiUserCase.getKey().getCaseDirectory(), LOG_FILE_NAME); } @Override @@ -123,6 +131,7 @@ public final class MultiUserNode extends AbstractNode { return caseMetadataFilePath; } + @Messages({"MultiUserNode.AlertColumn.text=Alert"}) //text to display when there is an alert present @Override protected Sheet createSheet() { Sheet s = super.createSheet(); @@ -136,7 +145,7 @@ public final class MultiUserNode extends AbstractNode { ss.put(new NodeProperty<>(Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), caseCreatedDate)); ss.put(new NodeProperty<>(Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), - (caseHasAlert == true ? "Alert" : ""))); + (caseHasAlert == true ? Bundle.MultiUserNode_AlertColumn_text() : ""))); ss.put(new NodeProperty<>(Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), caseMetadataFilePath)); return s; @@ -146,10 +155,14 @@ public final class MultiUserNode extends AbstractNode { public Action[] getActions(boolean context) { List actions = new ArrayList<>(); actions.add(new OpenMultiUserCaseAction(caseMetadataFilePath)); //open case context menu option + if (caseLogFilePath != null && caseLogFilePath.toFile().exists()) { + actions.add(new OpenCaseLogAction(caseLogFilePath)); + } return actions.toArray(new Action[actions.size()]); } } + @Messages({"MultiUserNode.OpenMultiUserCaseAction.text=Open Case"}) /** * An action that opens the specified case and hides the multi user case * panel. @@ -161,7 +174,7 @@ public final class MultiUserNode extends AbstractNode { private final String caseMetadataFilePath; OpenMultiUserCaseAction(String path) { - super("Open Case"); + super(Bundle.MultiUserNode_OpenMultiUserCaseAction_text()); caseMetadataFilePath = path; } @@ -193,5 +206,48 @@ public final class MultiUserNode extends AbstractNode { return super.clone(); //To change body of generated methods, choose Tools | Templates. } } + @Messages({"MultiUserNode.OpenCaseLogAction.text=Open Log File"}) + /** + * An action that opens the specified case and hides the multi user case + * panel. + */ + private static final class OpenCaseLogAction extends AbstractAction { + + private static final long serialVersionUID = 1L; + + private final Path pathToLog; + + OpenCaseLogAction(Path caseLogFilePath) { + super(Bundle.MultiUserNode_OpenCaseLogAction_text()); + pathToLog = caseLogFilePath; + } + + @Override + public void actionPerformed(ActionEvent e) { + + if (pathToLog != null) { + try { + if (pathToLog.toFile().exists()) { + Desktop.getDesktop().edit(pathToLog.toFile()); + + } else { + JOptionPane.showMessageDialog(MultiUserCasesDialog.getInstance(), org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotFindLog"), + org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.ERROR_MESSAGE); + } + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, String.format("Error attempting to open case auto ingest log file %s", pathToLog), ex); + JOptionPane.showMessageDialog(MultiUserCasesDialog.getInstance(), + org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotOpenLog"), + org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"), + JOptionPane.PLAIN_MESSAGE); + } + } + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); //To change body of generated methods, choose Tools | Templates. + } + } } From d171f89ffd1ac9c51d8144589f98b93b5ef353db Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 10 Jan 2018 14:16:36 -0500 Subject: [PATCH 20/28] 3408 disable open log file option instead of hide it when not available --- .../autopsy/casemodule/MultiUserNode.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java index 8723212801..d6fb271dd6 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java @@ -155,9 +155,7 @@ public final class MultiUserNode extends AbstractNode { public Action[] getActions(boolean context) { List actions = new ArrayList<>(); actions.add(new OpenMultiUserCaseAction(caseMetadataFilePath)); //open case context menu option - if (caseLogFilePath != null && caseLogFilePath.toFile().exists()) { - actions.add(new OpenCaseLogAction(caseLogFilePath)); - } + actions.add(new OpenCaseLogAction(caseLogFilePath)); return actions.toArray(new Action[actions.size()]); } } @@ -206,6 +204,7 @@ public final class MultiUserNode extends AbstractNode { return super.clone(); //To change body of generated methods, choose Tools | Templates. } } + @Messages({"MultiUserNode.OpenCaseLogAction.text=Open Log File"}) /** * An action that opens the specified case and hides the multi user case @@ -220,6 +219,7 @@ public final class MultiUserNode extends AbstractNode { OpenCaseLogAction(Path caseLogFilePath) { super(Bundle.MultiUserNode_OpenCaseLogAction_text()); pathToLog = caseLogFilePath; + this.setEnabled(caseLogFilePath != null && caseLogFilePath.toFile().exists()); } @Override @@ -231,14 +231,14 @@ public final class MultiUserNode extends AbstractNode { Desktop.getDesktop().edit(pathToLog.toFile()); } else { - JOptionPane.showMessageDialog(MultiUserCasesDialog.getInstance(), org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotFindLog"), - org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(MultiUserCasesDialog.getInstance(), org.openide.util.NbBundle.getMessage(MultiUserNode.class, "DisplayLogDialog.cannotFindLog"), + org.openide.util.NbBundle.getMessage(MultiUserNode.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.ERROR_MESSAGE); } } catch (IOException ex) { LOGGER.log(Level.SEVERE, String.format("Error attempting to open case auto ingest log file %s", pathToLog), ex); JOptionPane.showMessageDialog(MultiUserCasesDialog.getInstance(), - org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotOpenLog"), - org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"), + org.openide.util.NbBundle.getMessage(MultiUserNode.class, "DisplayLogDialog.cannotOpenLog"), + org.openide.util.NbBundle.getMessage(MultiUserNode.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.PLAIN_MESSAGE); } } From b82d5b5c5b23c95336e3070cb3fd8881910e1b53 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 10 Jan 2018 15:49:37 -0500 Subject: [PATCH 21/28] 3408 remove unnecessary use of DisplayableItemNode --- .../autopsy/casemodule/MultiUserNode.java | 25 ++----------------- .../datamodel/DisplayableItemNodeVisitor.java | 8 +----- 2 files changed, 3 insertions(+), 30 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java index d6fb271dd6..39f7059c42 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java @@ -40,14 +40,12 @@ import org.openide.nodes.Sheet; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; -import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.NodeProperty; /** * A root node containing child nodes of the multi user cases */ -public final class MultiUserNode extends AbstractNode { +final class MultiUserNode extends AbstractNode { @Messages({"CaseNode.column.name=Name", "CaseNode.column.createdTime=Created Time", @@ -92,7 +90,7 @@ public final class MultiUserNode extends AbstractNode { /** * A node which represents a single multi user case. */ - public static final class MultiUserCaseNode extends DisplayableItemNode { + static final class MultiUserCaseNode extends AbstractNode { private final String caseName; private final String caseCreatedDate; @@ -112,25 +110,6 @@ public final class MultiUserNode extends AbstractNode { caseLogFilePath = Paths.get(multiUserCase.getKey().getCaseDirectory(), LOG_FILE_NAME); } - @Override - public boolean isLeafTypeNode() { - return true; - } - - @Override - public T accept(DisplayableItemNodeVisitor v) { - return v.visit(this); - } - - @Override - public String getItemType() { - return getClass().getName(); - } - - public String getMetadataFilePath() { - return caseMetadataFilePath; - } - @Messages({"MultiUserNode.AlertColumn.text=Alert"}) //text to display when there is an alert present @Override protected Sheet createSheet() { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index f6d461e578..2713992139 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.datamodel; -import org.sleuthkit.autopsy.casemodule.MultiUserNode; import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.DeletedContentNode; import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode; import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode; @@ -159,8 +158,6 @@ public interface DisplayableItemNodeVisitor { T visit(EmptyNode.MessageNode emptyNode); - T visit(MultiUserNode.MultiUserCaseNode caseNode); - T visit(InterestingHits.InterestingItemTypeNode aThis); /** @@ -244,10 +241,7 @@ public interface DisplayableItemNodeVisitor { public T visit(EmptyNode.MessageNode ftByMimeTypeEmptyNode) { return defaultVisit(ftByMimeTypeEmptyNode); } - @Override - public T visit(MultiUserNode.MultiUserCaseNode caseNameNode) { - return defaultVisit(caseNameNode); - } + @Override public T visit(InterestingHits.InterestingItemTypeNode interestingItemTypeNode) { return defaultVisit(interestingItemTypeNode); From 8f7491eb9baa775c9df702c94558b090eca6582a Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 10 Jan 2018 15:58:49 -0500 Subject: [PATCH 22/28] 3408 allow support for opening cases with double click again --- .../org/sleuthkit/autopsy/casemodule/MultiUserNode.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java index 39f7059c42..9443ae35e9 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java @@ -109,6 +109,15 @@ final class MultiUserNode extends AbstractNode { caseMetadataFilePath = multiUserCase.getKey().getFilePath().toString(); caseLogFilePath = Paths.get(multiUserCase.getKey().getCaseDirectory(), LOG_FILE_NAME); } + + /** + * Returns action to open the Case represented by this node + * @return an action which will open the current case + */ + @Override + public Action getPreferredAction() { + return new OpenMultiUserCaseAction(caseMetadataFilePath); + } @Messages({"MultiUserNode.AlertColumn.text=Alert"}) //text to display when there is an alert present @Override From b3c98ab2c0b818c3e8690f28a04c772d508f6ceb Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 10 Jan 2018 17:29:10 -0500 Subject: [PATCH 23/28] 3408 log exception which was being ignored when path not in case table --- Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java index 6ecb0e849d..9440ca1356 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java @@ -130,7 +130,7 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider try { return ((Node.Property) outline.getModel().getValueAt(outline.convertRowIndexToModel(selectedRows[0]), originalPathColumnIndex)).getValue().toString(); } catch (IllegalAccessException | InvocationTargetException ex) { - //WJS-TODO THROW SOMETHING + LOGGER.log(Level.SEVERE, "Unable to get case path from table.", ex); } } return null; From 44496e611aca92e01f38e37ccb5b837ffbe3439b Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Thu, 11 Jan 2018 02:49:16 -0500 Subject: [PATCH 24/28] Added node for displaying no results message. --- .../KeywordSearchResultFactory.java | 84 +++++++++++-------- 1 file changed, 50 insertions(+), 34 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java index a48b40e756..4c36ce9b78 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2011-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,11 +39,13 @@ import org.openide.nodes.Node; import org.openide.util.NbBundle; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.corecomponents.TableFilterNode; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode; import static org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType.LOCATION; import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode; +import org.sleuthkit.autopsy.datamodel.EmptyNode; import org.sleuthkit.autopsy.datamodel.KeyValue; import org.sleuthkit.autopsy.datamodel.KeyValueNode; import org.sleuthkit.autopsy.keywordsearch.KeywordSearchResultFactory.KeyValueQueryContent; @@ -63,21 +65,21 @@ import org.sleuthkit.datamodel.TskCoreException; * Responsible for assembling nodes and columns in the right way and performing * lazy queries as needed. */ -class KeywordSearchResultFactory extends ChildFactory { +class KeywordSearchResultFactory extends ChildFactory { - private static final Logger logger = Logger.getLogger(KeywordSearchResultFactory.class.getName()); + private static final Logger LOGGER = Logger.getLogger(KeywordSearchResultFactory.class.getName()); //common properties (superset of all Node properties) to be displayed as columns - static final List COMMON_PROPERTIES = - Stream.concat( + static final List COMMON_PROPERTIES + = Stream.concat( Stream.of( TSK_KEYWORD, TSK_KEYWORD_REGEXP, TSK_KEYWORD_PREVIEW) - .map(BlackboardAttribute.ATTRIBUTE_TYPE::getDisplayName), + .map(BlackboardAttribute.ATTRIBUTE_TYPE::getDisplayName), Arrays.stream(AbstractAbstractFileNode.AbstractFilePropertyType.values()) - .map(Object::toString)) - .collect(Collectors.toList()); + .map(Object::toString)) + .collect(Collectors.toList()); private final Collection queryRequests; @@ -93,7 +95,7 @@ class KeywordSearchResultFactory extends ChildFactory { * @param toPopulate property set map for a Node */ @Override - protected boolean createKeys(List toPopulate) { + protected boolean createKeys(List toPopulate) { for (QueryRequest queryRequest : queryRequests) { /** @@ -130,7 +132,7 @@ class KeywordSearchResultFactory extends ChildFactory { * @return */ @NbBundle.Messages({"KeywordSearchResultFactory.query.exception.msg=Could not perform the query "}) - private boolean createFlatKeys(KeywordSearchQuery queryRequest, List toPopulate) { + private boolean createFlatKeys(KeywordSearchQuery queryRequest, List toPopulate) { /** * Execute the requested query. @@ -139,15 +141,15 @@ class KeywordSearchResultFactory extends ChildFactory { try { queryResults = queryRequest.performQuery(); } catch (KeywordSearchModuleException | NoOpenCoreException ex) { - logger.log(Level.SEVERE, "Could not perform the query " + queryRequest.getQueryString(), ex); //NON-NLS + LOGGER.log(Level.SEVERE, "Could not perform the query " + queryRequest.getQueryString(), ex); //NON-NLS MessageNotifyUtil.Notify.error(Bundle.KeywordSearchResultFactory_query_exception_msg() + queryRequest.getQueryString(), ex.getCause().getMessage()); return false; } - SleuthkitCase tskCase = null; + SleuthkitCase tskCase; try { tskCase = Case.getCurrentCase().getSleuthkitCase(); } catch (IllegalStateException ex) { - logger.log(Level.SEVERE, "There was no case open.", ex); //NON-NLS + LOGGER.log(Level.SEVERE, "There was no case open.", ex); //NON-NLS return false; } @@ -159,16 +161,16 @@ class KeywordSearchResultFactory extends ChildFactory { * Get file properties. */ Map properties = new LinkedHashMap<>(); - Content content = null; - String contentName = ""; + Content content; + String contentName; try { content = tskCase.getContentById(hit.getContentID()); if (content == null) { - logger.log(Level.SEVERE, "There was a error getting content by id."); //NON-NLS + LOGGER.log(Level.SEVERE, "There was a error getting content by id."); //NON-NLS return false; } } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "There was a error getting content by id.", ex); //NON-NLS + LOGGER.log(Level.SEVERE, "There was a error getting content by id.", ex); //NON-NLS return false; } @@ -191,7 +193,7 @@ class KeywordSearchResultFactory extends ChildFactory { try { hitName = tskCase.getBlackboardArtifact(hit.getArtifactID().get()).getDisplayName() + " Artifact"; //NON-NLS } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error getting blckboard artifact by id", ex); + LOGGER.log(Level.SEVERE, "Error getting blckboard artifact by id", ex); return false; } } else { @@ -202,9 +204,13 @@ class KeywordSearchResultFactory extends ChildFactory { } - // Add all the nodes to toPopulate at once. Minimizes node creation - // EDT threads, which can slow and/or hang the UI on large queries. - toPopulate.addAll(tempList); + if (hitNumber == 0) { + toPopulate.add(new KeyValue("This KeyValue Is Empty", 0)); + } else { + // Add all the nodes to toPopulate at once. Minimizes node creation + // EDT threads, which can slow and/or hang the UI on large queries. + toPopulate.addAll(tempList); + } //write to bb //cannot reuse snippet in BlackboardResultWriter @@ -239,15 +245,25 @@ class KeywordSearchResultFactory extends ChildFactory { return hits.values(); } + @NbBundle.Messages({"KeywordSearchResultFactory.createNodeForKey.noMatchessFound.text=No matches found."}) @Override - protected Node createNodeForKey(KeyValueQueryContent key) { - final Content content = key.getContent(); - QueryResults hits = key.getHits(); + protected Node createNodeForKey(KeyValue key) { + Node resultNode; - Node kvNode = new KeyValueNode(key, Children.LEAF, Lookups.singleton(content)); + if (key instanceof KeyValueQueryContent) { + final Content content = ((KeyValueQueryContent) key).getContent(); + QueryResults hits = ((KeyValueQueryContent) key).getHits(); - //wrap in KeywordSearchFilterNode for the markup content, might need to override FilterNode for more customization - return new KeywordSearchFilterNode(hits, kvNode); + Node kvNode = new KeyValueNode(key, Children.LEAF, Lookups.singleton(content)); + + //wrap in KeywordSearchFilterNode for the markup content, might need to override FilterNode for more customization + resultNode = new KeywordSearchFilterNode(hits, kvNode); + } else { + resultNode = new EmptyNode("This Node Is Empty"); + resultNode.setDisplayName(NbBundle.getMessage(this.getClass(), "KeywordSearchResultFactory.createNodeForKey.noMatchessFound.text")); + } + + return resultNode; } @@ -308,7 +324,7 @@ class KeywordSearchResultFactory extends ChildFactory { */ static class BlackboardResultWriter extends SwingWorker { - private static final List writers = new ArrayList<>(); + private static final List WRITERS = new ArrayList<>(); private ProgressHandle progress; private final KeywordSearchQuery query; private final QueryResults hits; @@ -343,24 +359,24 @@ class KeywordSearchResultFactory extends ChildFactory { try { get(); } catch (InterruptedException | CancellationException ex) { - logger.log(Level.WARNING, "User cancelled writing of ad hoc search query results for '{0}' to the blackboard", query.getQueryString()); //NON-NLS + LOGGER.log(Level.WARNING, "User cancelled writing of ad hoc search query results for '{0}' to the blackboard", query.getQueryString()); //NON-NLS } catch (ExecutionException ex) { - logger.log(Level.SEVERE, "Error writing of ad hoc search query results for " + query.getQueryString() + " to the blackboard", ex); //NON-NLS + LOGGER.log(Level.SEVERE, "Error writing of ad hoc search query results for " + query.getQueryString() + " to the blackboard", ex); //NON-NLS } } private static synchronized void registerWriter(BlackboardResultWriter writer) { - writers.add(writer); + WRITERS.add(writer); } private static synchronized void deregisterWriter(BlackboardResultWriter writer) { - writers.remove(writer); + WRITERS.remove(writer); } static synchronized void stopAllWriters() { - for (BlackboardResultWriter w : writers) { + for (BlackboardResultWriter w : WRITERS) { w.cancel(true); - writers.remove(w); + WRITERS.remove(w); } } } From 3cce43e95d9820a4adde842bde2b0c3490972d9a Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Thu, 11 Jan 2018 03:20:14 -0500 Subject: [PATCH 25/28] Fixed message. --- .../autopsy/keywordsearch/KeywordSearchResultFactory.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java index 4c36ce9b78..d0ea6b8fff 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java @@ -245,7 +245,7 @@ class KeywordSearchResultFactory extends ChildFactory { return hits.values(); } - @NbBundle.Messages({"KeywordSearchResultFactory.createNodeForKey.noMatchessFound.text=No matches found."}) + @NbBundle.Messages({"KeywordSearchResultFactory.createNodeForKey.noResultsFound.text=No results found."}) @Override protected Node createNodeForKey(KeyValue key) { Node resultNode; @@ -260,7 +260,7 @@ class KeywordSearchResultFactory extends ChildFactory { resultNode = new KeywordSearchFilterNode(hits, kvNode); } else { resultNode = new EmptyNode("This Node Is Empty"); - resultNode.setDisplayName(NbBundle.getMessage(this.getClass(), "KeywordSearchResultFactory.createNodeForKey.noMatchessFound.text")); + resultNode.setDisplayName(NbBundle.getMessage(this.getClass(), "KeywordSearchResultFactory.createNodeForKey.noResultsFound.text")); } return resultNode; From 3ec32ec4cfeab757f8c11f33cd1ad27ec2071d08 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Thu, 11 Jan 2018 10:25:53 -0500 Subject: [PATCH 26/28] Cleanup. --- .../autopsy/keywordsearch/KeywordSearchResultFactory.java | 1 - 1 file changed, 1 deletion(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java index d0ea6b8fff..a8bc995eae 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java @@ -39,7 +39,6 @@ import org.openide.nodes.Node; import org.openide.util.NbBundle; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.corecomponents.TableFilterNode; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode; From 6a976324ee9a8b22d9536e93289d5c26fb57575f Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 12 Jan 2018 14:15:43 -0500 Subject: [PATCH 27/28] Fix releaseing of correct lock for processing Raw data image --- .../sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java index 14a3dc9e2f..3d576eebf0 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java @@ -178,7 +178,7 @@ final class AddRawImageTask implements Runnable { logger.log(Level.SEVERE, errorMessage, ex); criticalErrorOccurred = true; } finally { - caseDatabase.releaseSingleUserCaseReadLock(); + caseDatabase.releaseSingleUserCaseWriteLock(); } } From b0e8e83fb9ccc87440b01b78d6385af07ef09aca Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 12 Jan 2018 14:15:43 -0500 Subject: [PATCH 28/28] Fix releaseing of correct lock for processing Raw data image --- .../sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java index 14a3dc9e2f..3d576eebf0 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java @@ -178,7 +178,7 @@ final class AddRawImageTask implements Runnable { logger.log(Level.SEVERE, errorMessage, ex); criticalErrorOccurred = true; } finally { - caseDatabase.releaseSingleUserCaseReadLock(); + caseDatabase.releaseSingleUserCaseWriteLock(); } }