diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java index 24aaf70d2e..4f25030fd3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java @@ -29,6 +29,8 @@ import org.netbeans.swing.outline.Outline; import org.openide.nodes.Node; import java.awt.EventQueue; import java.io.File; +import java.io.IOException; +import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; @@ -207,28 +209,34 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider 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' files. - */ - File[] fileArray = caseFolder.listFiles(); - if (fileArray == null) { - continue; - } - String autFilePath = null; - for (File file : fileArray) { - String name = file.getName().toLowerCase(); - if (autFilePath == null && name.endsWith(".aut")) { - try { - caseList.add(new CaseMetadata(Paths.get(file.getAbsolutePath()))); - } catch (CaseMetadata.CaseMetadataException ex) { - LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFilePath), ex); + Path casePath; + try { + casePath = Paths.get(node).toRealPath(LinkOption.NOFOLLOW_LINKS); + + File caseFolder = casePath.toFile(); + if (caseFolder.exists()) { + /* + * Search for '*.aut' files. + */ + File[] fileArray = caseFolder.listFiles(); + if (fileArray == null) { + continue; + } + String autFilePath = null; + for (File file : fileArray) { + String name = file.getName().toLowerCase(); + if (autFilePath == null && name.endsWith(".aut")) { + try { + caseList.add(new CaseMetadata(Paths.get(file.getAbsolutePath()))); + } catch (CaseMetadata.CaseMetadataException ex) { + LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFilePath), ex); + } + break; } - break; } } + } catch (IOException ignore) { + //if a path could not be resolved to a real path do add it to the caseList } } return caseList; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java index b03a17920e..2a460d5c46 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.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"); @@ -61,6 +61,11 @@ class CaseInformationPanel extends javax.swing.JPanel { @Override public void stateChanged(ChangeEvent e) { tabbedPane.getSelectedComponent().setSize(tabbedPane.getSelectedComponent().getPreferredSize()); + if (tabbedPane.getSelectedComponent() instanceof CasePropertiesPanel) { + editDetailsButton.setVisible(true); + } else { + editDetailsButton.setVisible(false); + } } }); } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index 2cac9b4927..87478529f7 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -2172,7 +2172,7 @@ public abstract class AbstractSqlEamDb implements EamDb { } CorrelationAttributeInstance eamArtifactInstance = new CorrelationAttributeInstance( new CorrelationCase(resultSet.getInt("case_id"), resultSet.getString("case_uid"), resultSet.getString("case_name")), - new CorrelationDataSource(-1, resultSet.getInt("case_id"), resultSet.getString("device_id"), resultSet.getString("name")), + new CorrelationDataSource(resultSet.getInt("case_id"), -1, resultSet.getString("device_id"), resultSet.getString("name")), resultSet.getString("file_path"), resultSet.getString("comment"), TskData.FileKnown.valueOf(resultSet.getByte("known_status")) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java index a7a97e4b75..7a4df69e9d 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java @@ -453,7 +453,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont return; } - Content content = (selectedNode).getLookup().lookup(Content.class); + Content content = DataContentViewerUtility.getDefaultContent(selectedNode); if (content == null) { resetComponent(); return; diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java index 14cb2eb2c1..936ff3c46b 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java @@ -452,8 +452,7 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC return; } - Lookup lookup = selectedNode.getLookup(); - Content content = lookup.lookup(Content.class); + Content content = DataContentViewerUtility.getDefaultContent(selectedNode); if (content != null) { this.setDataView(content, 0); return; diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerUtility.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerUtility.java new file mode 100755 index 0000000000..53491b407e --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerUtility.java @@ -0,0 +1,54 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 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.corecomponents; + +import org.sleuthkit.datamodel.Content; +import org.openide.nodes.Node; +import org.sleuthkit.datamodel.BlackboardArtifact; + +/** + * Utility classes for content viewers. + * In theory, this would live in the contentviewer package, + * but the initial method was needed only be viewers in + * corecomponents and therefore can stay out of public API. + */ +class DataContentViewerUtility { + /** + * Returns the first non-Blackboard Artifact from a Node. + * Needed for (at least) Hex and Strings that want to view + * all types of content (not just AbstractFile), but don't want + * to display an artifact unless that's the only thing there. + * Scenario is hash hit or interesting item hit. + * + * @param node Node passed into content viewer + * @return highest priority content or null if there is no content + */ + static Content getDefaultContent(Node node) { + Content bbContentSeen = null; + for (Content content : (node).getLookup().lookupAll(Content.class)) { + if (content instanceof BlackboardArtifact) { + bbContentSeen = content; + } + else { + return content; + } + } + return bbContentSeen; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java index 19526a0a19..9158790ad6 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java @@ -34,6 +34,7 @@ class ReportExcel implements TableReportModule { private static final Logger logger = Logger.getLogger(ReportExcel.class.getName()); private static ReportExcel instance; + private static final int EXCEL_CELL_MAXIMUM_SIZE = 36767; //Specified at:https://poi.apache.org/apidocs/org/apache/poi/ss/SpreadsheetVersion.html private Workbook wb; private Sheet sheet; @@ -236,10 +237,24 @@ class ReportExcel implements TableReportModule { * @param row cells to add */ @Override + @NbBundle.Messages({ + "ReportExcel.exceptionMessage.dataTooLarge=Value is too long to fit into an Excel cell. ", + "ReportExcel.exceptionMessage.errorText=Error showing data into an Excel cell." + }) + public void addRow(List rowData) { Row row = sheet.createRow(rowIndex); for (int i = 0; i < rowData.size(); ++i) { - row.createCell(i).setCellValue(rowData.get(i)); + Cell excelCell = row.createCell(i); + try { + excelCell.setCellValue(rowData.get(i)); + } catch (Exception e) { + if (e instanceof java.lang.IllegalArgumentException && rowData.get(i).length() > EXCEL_CELL_MAXIMUM_SIZE) { + excelCell.setCellValue(Bundle.ReportExcel_exceptionMessage_dataTooLarge() + e.getMessage()); + } else { + excelCell.setCellValue(Bundle.ReportExcel_exceptionMessage_errorText()); + } + } } ++rowIndex; } diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java index 88d9fe44b1..01a179a370 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java @@ -51,6 +51,7 @@ import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.Services; import org.sleuthkit.autopsy.casemodule.services.TagsManager; +import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor; @@ -554,7 +555,8 @@ class ReportHTML implements TableReportModule { StringBuilder builder = new StringBuilder(); builder.append("\t\n"); //NON-NLS for (String cell : row) { - builder.append("\t\t").append(cell).append("\n"); //NON-NLS + String escapeHTMLCell = EscapeUtil.escapeHtml(cell); + builder.append("\t\t").append(escapeHTMLCell).append("\n"); //NON-NLS } builder.append("\t\n"); //NON-NLS rowCount++; diff --git a/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java index 93894022b3..499f848d54 100644 --- a/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-16 Basis Technology Corp. + * Copyright 2013-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,7 +40,6 @@ import java.util.logging.Level; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.TagsManager; -import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.ContentUtils; @@ -666,8 +665,7 @@ class TableReportGenerator { tableModule.startTable(columnHeaderNames); } - String previewreplace = EscapeUtil.escapeHtml(preview); - tableModule.addRow(Arrays.asList(new String[]{previewreplace.replaceAll(" toImport = reader.getListsL(); - List toImportConfirmed = new ArrayList<>(); - - final XmlKeywordSearchList writer = XmlKeywordSearchList.getCurrent(); - - for (KeywordList list : toImport) { - //check name collisions - listName = list.getName(); - if (writer.listExists(listName)) { - String[] options; - if (toImport.size() == 1) { //only give them cancel and yes buttons for single list imports - options = new String[]{NbBundle.getMessage(this.getClass(), "KeywordSearch.yesOwMsg"), - NbBundle.getMessage(this.getClass(), "KeywordSearch.cancelImportMsg")}; - } else { - options = new String[]{NbBundle.getMessage(this.getClass(), "KeywordSearch.yesOwMsg"), - NbBundle.getMessage(this.getClass(), "KeywordSearch.noSkipMsg"), - NbBundle.getMessage(this.getClass(), "KeywordSearch.cancelImportMsg")}; - } - int choice = JOptionPane.showOptionDialog(this, - NbBundle.getMessage(this.getClass(), "KeywordSearch.overwriteListPrompt", listName), - NbBundle.getMessage(this.getClass(), "KeywordSearch.importOwConflict"), - JOptionPane.YES_NO_CANCEL_OPTION, - JOptionPane.QUESTION_MESSAGE, - null, - options, - options[0]); - if (choice == JOptionPane.OK_OPTION) { - toImportConfirmed.add(list); - } else if (choice == JOptionPane.CANCEL_OPTION) { - break; - } + for (File file : selFiles) { + if (file == null) { + continue; + } + + //force append extension if not given + String fileAbs = file.getAbsolutePath(); + final KeywordSearchList reader; + if (KeywordSearchUtil.isXMLList(fileAbs)) { + reader = new XmlKeywordSearchList(fileAbs); } else { - //no conflict - toImportConfirmed.add(list); + reader = new EnCaseKeywordSearchList(fileAbs); } - } + if (!reader.load()) { + KeywordSearchUtil.displayDialog( + NbBundle.getMessage(this.getClass(), "KeywordSearch.listImportFeatureTitle"), NbBundle.getMessage(this.getClass(), "KeywordSearch.importListFileDialogMsg", fileAbs), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR); + return; + } - if (toImportConfirmed.isEmpty()) { - return; - } + List toImport = reader.getListsL(); + List toImportConfirmed = new ArrayList<>(); - if (!writer.writeLists(toImportConfirmed)) { - KeywordSearchUtil.displayDialog( - NbBundle.getMessage(this.getClass(), "KeywordSearch.listImportFeatureTitle"), NbBundle.getMessage(this.getClass(), "KeywordSearch.kwListFailImportMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO); + final XmlKeywordSearchList writer = XmlKeywordSearchList.getCurrent(); + + for (KeywordList list : toImport) { + //check name collisions + listName = list.getName(); + if (writer.listExists(listName)) { + String[] options; + if (toImport.size() == 1) { //only give them cancel and yes buttons for single list imports + options = new String[]{NbBundle.getMessage(this.getClass(), "KeywordSearch.yesOwMsg"), + NbBundle.getMessage(this.getClass(), "KeywordSearch.cancelImportMsg")}; + } else { + options = new String[]{NbBundle.getMessage(this.getClass(), "KeywordSearch.yesOwMsg"), + NbBundle.getMessage(this.getClass(), "KeywordSearch.noSkipMsg"), + NbBundle.getMessage(this.getClass(), "KeywordSearch.cancelImportMsg")}; + } + int choice = JOptionPane.showOptionDialog(this, + NbBundle.getMessage(this.getClass(), "KeywordSearch.overwriteListPrompt", listName), + NbBundle.getMessage(this.getClass(), "KeywordSearch.importOwConflict"), + JOptionPane.YES_NO_CANCEL_OPTION, + JOptionPane.QUESTION_MESSAGE, + null, + options, + options[0]); + if (choice == JOptionPane.OK_OPTION) { + toImportConfirmed.add(list); + } else if (choice == JOptionPane.CANCEL_OPTION) { + break; + } + + } else { + //no conflict + toImportConfirmed.add(list); + } + + } + + if (toImportConfirmed.isEmpty()) { + return; + } + + if (!writer.writeLists(toImportConfirmed)) { + KeywordSearchUtil.displayDialog( + NbBundle.getMessage(this.getClass(), "KeywordSearch.listImportFeatureTitle"), NbBundle.getMessage(this.getClass(), "KeywordSearch.kwListFailImportMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO); + } + ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_KEYWORD_LIST_PATH_KEY, file.getParent()); } - ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_KEYWORD_LIST_PATH_KEY, selFile.getParent()); } tableModel.resync(); diff --git a/docs/doxygen-user/images/case-properties-history-tab.PNG b/docs/doxygen-user/images/case-properties-history-tab.PNG index fc0a4da441..0a5d8f25b7 100644 Binary files a/docs/doxygen-user/images/case-properties-history-tab.PNG and b/docs/doxygen-user/images/case-properties-history-tab.PNG differ