diff --git a/Core/ivy.xml b/Core/ivy.xml index 9dfd0fcf85..54ed532feb 100644 --- a/Core/ivy.xml +++ b/Core/ivy.xml @@ -45,6 +45,9 @@ + + + diff --git a/Core/nbproject/project.properties b/Core/nbproject/project.properties index 955079d04a..8209da0221 100644 --- a/Core/nbproject/project.properties +++ b/Core/nbproject/project.properties @@ -111,6 +111,10 @@ file.reference.grpc-context-1.19.0.jar=release/modules/ext/grpc-context-1.19.0.j file.reference.opencensus-api-0.19.2.jar=release/modules/ext/opencensus-api-0.19.2.jar file.reference.opencensus-contrib-http-util-0.19.2.jar=release/modules/ext/opencensus-contrib-http-util-0.19.2.jar file.reference.threetenbp-1.3.3.jar=release/modules/ext/threetenbp-1.3.3.jar +file.reference.okhttp-2.7.5-javadoc.jar=release/modules/ext/okhttp-2.7.5-javadoc.jar +file.reference.okhttp-2.7.5-sources.jar=release/modules/ext/okhttp-2.7.5-sources.jar +file.reference.okhttp-2.7.5.jar=release/modules/ext/okhttp-2.7.5.jar +file.reference.okio-1.6.0.jar=release/modules/ext/okio-1.6.0.jar javac.source=1.8 javac.compilerargs=-Xlint -Xlint:-serial license.file=../LICENSE-2.0.txt diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index 1ac3c9d2fd..3dbc3069e3 100644 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -773,6 +773,14 @@ ext/google-api-services-translate-v2-rev20170525-1.27.0.jar release/modules/ext/google-api-services-translate-v2-rev20170525-1.27.0.jar + + ext/okhttp-2.7.5.jar + release/modules/ext/okhttp-2.7.5.jar + + + ext/okio-1.6.0.jar + release/modules/ext/okio-1.6.0.jar + diff --git a/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties-MERGED index 506786c42d..bb34c94363 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties-MERGED @@ -1,35 +1,25 @@ AddBlackboardArtifactTagAction.pluralTagResult=Add Result Tags AddBlackboardArtifactTagAction.singularTagResult=Add Result Tag AddBlackboardArtifactTagAction.taggingErr=Tagging Error -# {0} - artifactName AddBlackboardArtifactTagAction.unableToTag.msg=Unable to tag {0}. AddContentTagAction.cannotApplyTagErr=Cannot Apply Tag AddContentTagAction.pluralTagFile=Add File Tags AddContentTagAction.singularTagFile=Add File Tag -# {0} - fileName -# {1} - tagName AddContentTagAction.tagExists={0} has been tagged as {1}. Cannot reapply the same tag. AddContentTagAction.taggingErr=Tagging Error -# {0} - fileName AddContentTagAction.unableToTag.msg=Unable to tag {0}, not a regular file. -# {0} - fileName AddContentTagAction.unableToTag.msg2=Unable to tag {0}. CTL_ShowIngestProgressSnapshotAction=Ingest Status Details DeleteBlackboardArtifactTagAction.deleteTag=Remove Selected Tag(s) DeleteBlackboardArtifactTagAction.tagDelErr=Tag Deletion Error -# {0} - tagName DeleteBlackboardArtifactTagAction.unableToDelTag.msg=Unable to delete tag {0}. DeleteContentTagAction.deleteTag=Remove Selected Tag(s) DeleteContentTagAction.tagDelErr=Tag Deletion Error -# {0} - tagName DeleteContentTagAction.unableToDelTag.msg=Unable to delete tag {0}. DeleteFileBlackboardArtifactTagAction.deleteTag=Remove Result Tag -# {0} - artifactID DeleteFileBlackboardArtifactTagAction.deleteTag.alert=Unable to untag artifact {0}. -# {0} - artifactID DeleteFileBlackboardArtifactTagAction.deleteTags.alert=Unable to untag artifact {0}. DeleteFileContentTagAction.deleteTag=Remove File Tag -# {0} - fileID DeleteFileContentTagAction.deleteTag.alert=Unable to untag file {0}. ExitAction.confirmationDialog.message=Ingest is running, are you sure you want to exit? ExitAction.confirmationDialog.title=Ingest is Running @@ -83,11 +73,7 @@ CTL_OpenOutputFolder=Open Output Folder OpenOutputFolder.error1=Output Folder Not Found: {0} OpenOutputFolder.noCaseOpen=No open case, therefore no current output folder available. OpenOutputFolder.CouldNotOpenOutputFolder=Could not open output folder -# {0} - old tag name -# {1} - artifactID ReplaceBlackboardArtifactTagAction.replaceTag.alert=Unable to replace tag {0} for artifact {1}. -# {0} - old tag name -# {1} - content obj id ReplaceContentTagAction.replaceTag.alert=Unable to replace tag {0} for {1}. ReplaceTagAction.replaceTag=Replace Selected Tag(s) With ShowIngestProgressSnapshotAction.actionName.text=Get Ingest Progress Snapshot diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED index 5ad9042e9f..bcaa9d1d28 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED @@ -1,18 +1,10 @@ AddImageWizardIngestConfigPanel.name.text=Configure Ingest Modules AddImageWizardSelectDspVisual.multiUserWarning.text=This type of Data Source Processor is not available in multi-user mode -# {0} - file AddLogicalImageTask.addingToReport=Adding {0} to report -# {0} - src -# {1} - dest AddLogicalImageTask.copyingImageFromTo=Copying image from {0} to {1} -# {0} - file AddLogicalImageTask.doneAddingToReport=Done adding {0} to report AddLogicalImageTask.doneCopying=Done copying -# {0} - file -# {1} - exception message AddLogicalImageTask.failedToAddReport=Failed to add report {0}. Reason= {1} -# {0} - src -# {1} - dest AddLogicalImageTask.failedToCopyDirectory=Failed to copy directory {0} to {1} # {0} - exception message Case.closeException.couldNotCloseCase=Error closing case: {0} @@ -20,7 +12,6 @@ Case.creationException.couldNotAcquireDirLock=Failed to get lock on case directo Case.creationException.couldNotAcquireResourcesLock=Failed to get lock on case resources Case.deleteCaseConfirmationDialog.message=Are you sure you want to close and delete the current case? Case.deleteCaseConfirmationDialog.title=Delete Current Case? -# {0} - exception message Case.deleteCaseFailureMessageBox.message=Error deleting case: {0} Case.deleteCaseFailureMessageBox.title=Failed to Delete Case Case.exceptionMessage.cancelledByUser=Cancelled by user. @@ -183,19 +174,13 @@ LogicalEvidenceFilePanel.validatePanel.nonL01Error.text=Only files with the .l01 LogicalFilesDspPanel.subTypeComboBox.l01FileOption.text=Logical evidence file (L01) LogicalFilesDspPanel.subTypeComboBox.localFilesOption.text=Local files and folders LogicalImagerDSProcessor.dataSourceType=Autopsy Imager -# {0} - directory LogicalImagerDSProcessor.directoryAlreadyExists=Directory {0} already exists -# {0} - directory LogicalImagerDSProcessor.failToCreateDirectory=Failed to create directory {0} -# {0} - imageDirPath LogicalImagerDSProcessor.imageDirPathNotFound={0} not found.\nUSB drive has been ejected. LogicalImagerPanel.imageTable.columnModel.title0=Hostname LogicalImagerPanel.imageTable.columnModel.title1=Extracted Date LogicalImagerPanel.messageLabel.clickScanOrBrowse=Click SCAN or BROWSE button to find images -# {0} - sparseImageDirectory -# {1} - image LogicalImagerPanel.messageLabel.directoryDoesNotContainSparseImage=Directory {0} does not contain {1} -# {0} - invalidFormatDirectory LogicalImagerPanel.messageLabel.directoryFormatInvalid=Directory {0} does not match format Logical_Imager_HOSTNAME_yyyymmdd_HH_MM_SS LogicalImagerPanel.messageLabel.driveHasNoImages=Drive has no images LogicalImagerPanel.messageLabel.noExternalDriveFound=No drive found @@ -266,15 +251,10 @@ AddImageWizardIngestConfigPanel.dsProcDone.errs.text=*Errors encountered in addi AddImageWizardIngestConfigVisual.getName.text=Configure Ingest Modules AddImageWizardIterator.stepXofN=Step {0} of {1} AddLocalFilesTask.localFileAdd.progress.text=Adding: {0}/{1} -Case.getCurCase.exception.noneOpen=Cannot get the current case; there is no case open\! +Case.getCurCase.exception.noneOpen=Cannot get the current case; there is no case open! Case.open.msgDlg.updated.msg=Updated case database schema.\nA backup copy of the database with the following path has been made:\n {0} Case.open.msgDlg.updated.title=Case Database Schema Update -Case.checkImgExist.confDlg.doesntExist.msg=One of the images associated with \n\ -this case are missing. Would you like to search for them now?\n\ -Previously, the image was located at:\n\ -{0}\n\ -Please note that you will still be able to browse directories and generate reports\n\ -if you choose No, but you will not be able to view file content or run the ingest process. +Case.checkImgExist.confDlg.doesntExist.msg=One of the images associated with \nthis case are missing. Would you like to search for them now?\nPreviously, the image was located at:\n{0}\nPlease note that you will still be able to browse directories and generate reports\nif you choose No, but you will not be able to view file content or run the ingest process. Case.checkImgExist.confDlg.doesntExist.title=Missing Image Case.addImg.exception.msg=Error adding image to the case Case.updateCaseName.exception.msg=Error while trying to update the case name. @@ -293,12 +273,9 @@ Case.GetCaseTypeGivenPath.Failure=Unable to get case type Case.metaDataFileCorrupt.exception.msg=The case metadata file (.aut) is corrupted. Case.deleteReports.deleteFromDiskException.log.msg=Unable to delete the report from the disk. Case.deleteReports.deleteFromDiskException.msg=Unable to delete the report {0} from the disk.\nYou may manually delete it from {1} -CaseDeleteAction.closeConfMsg.text=Are you sure want to close and delete this case? \n\ - Case Name: {0}\n\ - Case Directory: {1} +CaseDeleteAction.closeConfMsg.text=Are you sure want to close and delete this case? \nCase Name: {0}\nCase Directory: {1} CaseDeleteAction.closeConfMsg.title=Warning: Closing the Current Case -CaseDeleteAction.msgDlg.fileInUse.msg=The delete action cannot be fully completed because the folder or file in it is open by another program.\n\n\ -Close the folder and file and try again or you can delete the case manually. +CaseDeleteAction.msgDlg.fileInUse.msg=The delete action cannot be fully completed because the folder or file in it is open by another program.\n\nClose the folder and file and try again or you can delete the case manually. CaseDeleteAction.msgDlg.fileInUse.title=Error: Folder In Use CaseDeleteAction.msgDlg.caseDelete.msg=Case {0} has been deleted. CaseOpenAction.autFilter.title={0} Case File ( {1}) @@ -330,8 +307,7 @@ NewCaseWizardAction.databaseProblem1.text=Cannot open database. Cancelling case NewCaseWizardAction.databaseProblem2.text=Error NewCaseWizardPanel1.validate.errMsg.invalidSymbols=The Case Name cannot contain any of the following symbols: \\ / : * ? " < > | NewCaseWizardPanel1.validate.errMsg.dirExists=Case directory ''{0}'' already exists. -NewCaseWizardPanel1.validate.confMsg.createDir.msg=The base directory "{0}" does not exist. \n\n\ - Do you want to create that directory? +NewCaseWizardPanel1.validate.confMsg.createDir.msg=The base directory "{0}" does not exist. \n\nDo you want to create that directory? NewCaseWizardPanel1.validate.confMsg.createDir.title=Create directory NewCaseWizardPanel1.validate.errMsg.cantCreateParDir.msg=Error: Could not create case parent directory {0} NewCaseWizardPanel1.validate.errMsg.prevCreateBaseDir.msg=Prevented from creating base directory {0} @@ -360,14 +336,12 @@ OptionalCasePropertiesPanel.lbPointOfContactPhoneLabel.text=Phone: OptionalCasePropertiesPanel.orgainizationPanel.border.title=Organization RecentCases.exception.caseIdxOutOfRange.msg=Recent case index {0} is out of range. RecentCases.getName.text=Clear Recent Cases -# {0} - case name RecentItems.openRecentCase.msgDlg.text=Case {0} no longer exists. SelectDataSourceProcessorPanel.name.text=Select Type of Data Source To Add StartupWindow.title.text=Welcome UnpackagePortableCaseDialog.title.text=Unpackage Portable Case UnpackagePortableCaseDialog.UnpackagePortableCaseDialog.extensions=Portable case package (.zip, .zip.001) UnpackagePortableCaseDialog.validatePaths.badExtension=File extension must be .zip or .zip.001 -# {0} - case folder UnpackagePortableCaseDialog.validatePaths.caseFolderExists=Folder {0} already exists UnpackagePortableCaseDialog.validatePaths.caseIsNotFile=Selected path is not a file UnpackagePortableCaseDialog.validatePaths.caseNotFound=File does not exist @@ -381,15 +355,15 @@ UnpackageWorker.doInBackground.errorFinding7zip=Could not locate 7-Zip executabl UpdateRecentCases.menuItem.clearRecentCases.text=Clear Recent Cases UpdateRecentCases.menuItem.empty=-Empty- AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text=Cancel -NewCaseVisualPanel1.CaseFolderOnCDriveError.text=Warning: Path to multi-user case folder is on \"C:\" drive -NewCaseVisualPanel1.CaseFolderOnInternalDriveWindowsError.text=Warning: Path to case folder is on \"C:\" drive. Case folder is created on the target system +NewCaseVisualPanel1.CaseFolderOnCDriveError.text=Warning: Path to multi-user case folder is on "C:" drive +NewCaseVisualPanel1.CaseFolderOnInternalDriveWindowsError.text=Warning: Path to case folder is on "C:" drive. Case folder is created on the target system NewCaseVisualPanel1.CaseFolderOnInternalDriveLinuxError.text=Warning: Path to case folder is on the target system. Create case folder in mounted drive. CollaborationMonitor.addingDataSourceStatus.msg={0} adding data source CollaborationMonitor.analyzingDataSourceStatus.msg={0} analyzing {1} MissingImageDialog.lbWarning.text= MissingImageDialog.lbWarning.toolTipText= NewCaseVisualPanel1.caseParentDirWarningLabel.text= -NewCaseVisualPanel1.multiUserCaseRadioButton.text=Multi-user +NewCaseVisualPanel1.multiUserCaseRadioButton.text=Multi-user\t\t NewCaseVisualPanel1.singleUserCaseRadioButton.text=Single-user NewCaseVisualPanel1.caseTypeLabel.text=Case Type: SingleUserCaseConverter.BadDatabaseFileName=Database file does not exist! diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED index 508e04b76a..fe998b0e57 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties-MERGED @@ -66,6 +66,7 @@ DataSourceSummaryDialog.window.title=Data Sources Summary DataSourceSummaryNode.column.dataSourceName.header=Data Source Name DataSourceSummaryNode.column.files.header=Files DataSourceSummaryNode.column.results.header=Results +DataSourceSummaryNode.column.status.header=Ingest Status DataSourceSummaryNode.column.tags.header=Tags DataSourceSummaryNode.column.type.header=Type DataSourceSummaryNode.viewDataSourceAction.text=Go to Data Source diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceBrowser.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceBrowser.java index e3b9fa0e93..ac09010de1 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceBrowser.java @@ -37,8 +37,10 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.datasourcesummary.DataSourceSummaryNode.DataSourceSummaryEntryNode; import static javax.swing.SwingConstants.RIGHT; +import javax.swing.SwingUtilities; import javax.swing.table.TableColumn; import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.IngestJobInfo; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; @@ -50,9 +52,10 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(DataSourceBrowser.class.getName()); - private static final int COUNT_COLUMN_WIDTH = 25; - private static final int USAGE_COLUMN_WIDTH = 120; - private static final int DATA_SOURCE_COLUMN_WIDTH = 325; + private static final int COUNT_COLUMN_WIDTH = 20; + private static final int INGEST_STATUS_WIDTH = 50; + private static final int USAGE_COLUMN_WIDTH = 110; + private static final int DATA_SOURCE_COLUMN_WIDTH = 280; private final Outline outline; private final org.openide.explorer.view.OutlineView outlineView; private final ExplorerManager explorerManager; @@ -69,6 +72,7 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana outlineView = new org.openide.explorer.view.OutlineView(); this.setVisible(true); outlineView.setPropertyColumns( + Bundle.DataSourceSummaryNode_column_status_header(), Bundle.DataSourceSummaryNode_column_status_header(), Bundle.DataSourceSummaryNode_column_type_header(), Bundle.DataSourceSummaryNode_column_type_header(), Bundle.DataSourceSummaryNode_column_files_header(), Bundle.DataSourceSummaryNode_column_files_header(), Bundle.DataSourceSummaryNode_column_results_header(), Bundle.DataSourceSummaryNode_column_results_header(), @@ -90,6 +94,8 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana column.setPreferredWidth(COUNT_COLUMN_WIDTH); } else if (column.getHeaderValue().toString().equals(Bundle.DataSourceSummaryNode_column_type_header())) { column.setPreferredWidth(USAGE_COLUMN_WIDTH); + } else if (column.getHeaderValue().toString().equals(Bundle.DataSourceSummaryNode_column_status_header())) { + column.setPreferredWidth(INGEST_STATUS_WIDTH); } else { column.setPreferredWidth(DATA_SOURCE_COLUMN_WIDTH); } @@ -182,6 +188,47 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana return null; } + /** + * Update the DataSourceBrowser to display up to date status information for + * the data sources. + * + * @param dataSourceId the ID of the data source which should be updated + * @param newStatus the new status which the data source should have + */ + void refresh(long dataSourceId, IngestJobInfo.IngestJobStatusType newStatus) { + + //attempt to update the status of any datasources that had status which was STARTED + for (DataSourceSummary summary : dataSourceSummaryList) { + if (summary.getDataSource().getId() == dataSourceId) { + summary.setIngestStatus(newStatus); + } + } + //figure out which nodes were previously selected + Node[] selectedNodes = explorerManager.getSelectedNodes(); + SwingUtilities.invokeLater(() -> { + explorerManager.setRootContext(new DataSourceSummaryNode(dataSourceSummaryList)); + List nodesToSelect = new ArrayList<>(); + for (Node node : explorerManager.getRootContext().getChildren().getNodes()) { + if (node instanceof DataSourceSummaryEntryNode) { + //there should only be one selected node as multi-select is disabled + for (Node selectedNode : selectedNodes) { + if (((DataSourceSummaryEntryNode) node).getDataSource().equals(((DataSourceSummaryEntryNode) selectedNode).getDataSource())) { + nodesToSelect.add(node); + } + } + } + } + //reselect the previously selected Nodes + try { + explorerManager.setSelectedNodes(nodesToSelect.toArray(new Node[nodesToSelect.size()])); + } catch (PropertyVetoException ex) { + logger.log(Level.WARNING, "Error selecting previously selected nodes", ex); + } + + }); + + } + /** * 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 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummary.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummary.java index 1aa55d95b5..390dce1afe 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummary.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummary.java @@ -18,15 +18,27 @@ */ package org.sleuthkit.autopsy.casemodule.datasourcesummary; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.datamodel.CaseDbAccessManager; import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.IngestJobInfo.IngestJobStatusType; +import org.sleuthkit.datamodel.TskCoreException; /** * Wrapper object for a DataSource and the information associated with it. * */ class DataSourceSummary { - + + private static final Logger logger = Logger.getLogger(DataSourceSummary.class.getName()); + private static final String INGEST_JOB_STATUS_QUERY = "status_id FROM ingest_jobs WHERE obj_id="; private final DataSource dataSource; + private IngestJobStatusType status = null; private final String type; private final long filesCount; private final long resultsCount; @@ -45,12 +57,26 @@ class DataSourceSummary { */ DataSourceSummary(DataSource dSource, String typeValue, Long numberOfFiles, Long numberOfResults, Long numberOfTags) { dataSource = dSource; + getStatusFromDatabase(); type = typeValue == null ? "" : typeValue; filesCount = numberOfFiles == null ? 0 : numberOfFiles; resultsCount = numberOfResults == null ? 0 : numberOfResults; tagsCount = numberOfTags == null ? 0 : numberOfTags; } + /** + * Get the status of the ingest job from the case database + */ + private void getStatusFromDatabase() { + try { + IngestJobQueryCallback callback = new IngestJobQueryCallback(); + Case.getCurrentCaseThrows().getSleuthkitCase().getCaseDbAccessManager().select(INGEST_JOB_STATUS_QUERY + dataSource.getId(), callback); + status = callback.getStatus(); + } catch (NoCurrentCaseException | TskCoreException ex) { + logger.log(Level.WARNING, "Error getting status for data source from case database", ex); + } + } + /** * Get the DataSource * @@ -60,6 +86,16 @@ class DataSourceSummary { return dataSource; } + /** + * Manually set the ingest job status + * + * @param ingestStatus the status which the ingest job should have + * currently, null to display empty string + */ + void setIngestStatus(IngestJobStatusType ingestStatus) { + status = ingestStatus; + } + /** * Get the type of this DataSource * @@ -87,6 +123,16 @@ class DataSourceSummary { return resultsCount; } + /** + * Get the IngestJobStatusType associated with this data source. + * + * @return the IngestJobStatusType associated with this data source. Can be + * null if the IngestJobStatusType is not STARTED or COMPLETED. + */ + IngestJobStatusType getIngestStatus() { + return status; + } + /** * Get the number of tagged content objects in this DataSource * @@ -95,4 +141,40 @@ class DataSourceSummary { long getTagsCount() { return tagsCount; } + + /** + * Callback to parse result set, getting the status to be associated with + * this data source + */ + class IngestJobQueryCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback { + + private IngestJobStatusType jobStatus = null; + + @Override + public void process(ResultSet rs) { + try { + while (rs.next()) { + IngestJobStatusType currentStatus = IngestJobStatusType.fromID(rs.getInt("status_id")); + if (currentStatus == IngestJobStatusType.COMPLETED) { + jobStatus = currentStatus; + } else if (currentStatus == IngestJobStatusType.STARTED) { + jobStatus = currentStatus; + return; + } + } + } catch (SQLException ex) { + logger.log(Level.WARNING, "Error getting status for ingest job", ex); + } + } + + /** + * Get the status which was determined for this callback + * + * @return the status of the data source which was queried for + */ + IngestJobStatusType getStatus() { + return jobStatus; + } + + } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.java index 3fd86c8de8..1535cbefe0 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryDialog.java @@ -19,14 +19,18 @@ package org.sleuthkit.autopsy.casemodule.datasourcesummary; import java.awt.Frame; +import java.beans.PropertyChangeEvent; import java.util.Map; import java.util.Observable; import java.util.Observer; -import java.util.logging.Logger; import javax.swing.event.ListSelectionEvent; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel; +import org.sleuthkit.autopsy.ingest.IngestManager; +import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent; +import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent.Reason; import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.IngestJobInfo; /** * Dialog for displaying the Data Sources Summary information @@ -38,7 +42,6 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser private final DataSourceSummaryDetailsPanel detailsPanel; private final DataSourceBrowser dataSourcesPanel; private final IngestJobInfoPanel ingestHistoryPanel; - private static final Logger logger = Logger.getLogger(DataSourceSummaryDialog.class.getName()); /** * Creates new form DataSourceSummaryDialog for displaying a summary of the @@ -73,6 +76,17 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser this.repaint(); } }); + //add listener to refresh jobs with Started status when they complete + IngestManager.getInstance().addIngestJobEventListener((PropertyChangeEvent evt) -> { + if (evt instanceof DataSourceAnalysisCompletedEvent) { + DataSourceAnalysisCompletedEvent dsEvent = (DataSourceAnalysisCompletedEvent) evt; + if (dsEvent.getResult() == Reason.ANALYSIS_COMPLETED) { + dataSourcesPanel.refresh(dsEvent.getDataSource().getId(), IngestJobInfo.IngestJobStatusType.COMPLETED); + } else if (dsEvent.getResult() == Reason.ANALYSIS_CANCELLED) { + dataSourcesPanel.refresh(dsEvent.getDataSource().getId(), null); + } + } + }); this.pack(); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryNode.java b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryNode.java index 8323061a66..0411d94bb2 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryNode.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/datasourcesummary/DataSourceSummaryNode.java @@ -109,6 +109,7 @@ final class DataSourceSummaryNode extends AbstractNode { static final class DataSourceSummaryEntryNode extends AbstractNode { private final DataSource dataSource; + private final String status; private final String type; private final long filesCount; private final long resultsCount; @@ -124,6 +125,7 @@ final class DataSourceSummaryNode extends AbstractNode { DataSourceSummaryEntryNode(DataSourceSummary dataSourceSummary) { super(Children.LEAF); dataSource = dataSourceSummary.getDataSource(); + status = dataSourceSummary.getIngestStatus() == null ? "" : dataSourceSummary.getIngestStatus().getDisplayName(); type = dataSourceSummary.getType(); filesCount = dataSourceSummary.getFilesCount(); resultsCount = dataSourceSummary.getResultsCount(); @@ -143,6 +145,7 @@ final class DataSourceSummaryNode extends AbstractNode { } @Messages({"DataSourceSummaryNode.column.dataSourceName.header=Data Source Name", + "DataSourceSummaryNode.column.status.header=Ingest Status", "DataSourceSummaryNode.column.type.header=Type", "DataSourceSummaryNode.column.files.header=Files", "DataSourceSummaryNode.column.results.header=Results", @@ -157,6 +160,7 @@ final class DataSourceSummaryNode extends AbstractNode { } sheetSet.put(new NodeProperty<>(Bundle.DataSourceSummaryNode_column_dataSourceName_header(), Bundle.DataSourceSummaryNode_column_dataSourceName_header(), Bundle.DataSourceSummaryNode_column_dataSourceName_header(), dataSource)); + sheetSet.put(new NodeProperty<>(Bundle.DataSourceSummaryNode_column_status_header(), Bundle.DataSourceSummaryNode_column_status_header(), Bundle.DataSourceSummaryNode_column_status_header(), status)); sheetSet.put(new NodeProperty<>(Bundle.DataSourceSummaryNode_column_type_header(), Bundle.DataSourceSummaryNode_column_type_header(), Bundle.DataSourceSummaryNode_column_type_header(), type)); sheetSet.put(new NodeProperty<>(Bundle.DataSourceSummaryNode_column_files_header(), Bundle.DataSourceSummaryNode_column_files_header(), Bundle.DataSourceSummaryNode_column_files_header(), diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index 896298c2bd..40597e9af3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.casemodule.services; import java.io.Closeable; import java.io.IOException; import java.util.ArrayList; +import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -30,15 +31,18 @@ import java.util.logging.Level; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewerTagManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifactTag; +import org.sleuthkit.datamodel.CaseDbAccessManager; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; +import org.sleuthkit.datamodel.TskData.DbType; /** * A per case Autopsy service that manages the addition of content and artifact @@ -48,6 +52,32 @@ public class TagsManager implements Closeable { private static final Logger LOGGER = Logger.getLogger(TagsManager.class.getName()); private final SleuthkitCase caseDb; + + static { + //Create the contentviewer tags table (beta) if the current case does not + //have the table present + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), evt -> { + if (evt.getNewValue() != null) { + Case currentCase = (Case) evt.getNewValue(); + try { + CaseDbAccessManager caseDb = currentCase.getSleuthkitCase().getCaseDbAccessManager(); + if (caseDb.tableExists(ContentViewerTagManager.TABLE_NAME)) { + return; + } + + if (currentCase.getSleuthkitCase().getDatabaseType().equals(DbType.SQLITE)) { + caseDb.createTable(ContentViewerTagManager.TABLE_NAME, ContentViewerTagManager.TABLE_SCHEMA_SQLITE); + } else if (currentCase.getSleuthkitCase().getDatabaseType().equals(DbType.POSTGRESQL)) { + caseDb.createTable(ContentViewerTagManager.TABLE_NAME, ContentViewerTagManager.TABLE_SCHEMA_POSTGRESQL); + } + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, + String.format("Unable to create the %s table for image tag storage.", + ContentViewerTagManager.TABLE_NAME), ex); + } + } + }); + } /** * Tests whether or not a given tag display name contains an illegal diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/contentviewertags/ContentViewerTagManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/contentviewertags/ContentViewerTagManager.java new file mode 100755 index 0000000000..8d117e908b --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/contentviewertags/ContentViewerTagManager.java @@ -0,0 +1,276 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2019 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.services.contentviewertags; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.sql.ResultSet; +import java.sql.SQLException; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.datamodel.ContentTag; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * A per case Autopsy service that manages the addition of content viewer tags + * to the case database. This manager is also responsible for serializing and + * deserializing instances of your tag data objects for persistence and + * retrieval. + */ +public class ContentViewerTagManager { + + //Used to convert Java beans into the physical representation that will be stored + //in the database. + private static final ObjectMapper SERIALIZER = new ObjectMapper(); + + public static final String TABLE_NAME = "beta_tag_app_data"; + public static final String TABLE_SCHEMA_SQLITE = "(app_data_id INTEGER PRIMARY KEY, " + + "content_tag_id INTEGER NOT NULL, app_data TEXT NOT NULL, " + + "FOREIGN KEY(content_tag_id) REFERENCES content_tags(tag_id))"; + public static final String TABLE_SCHEMA_POSTGRESQL = "(app_data_id BIGSERIAL PRIMARY KEY, " + + "content_tag_id INTEGER NOT NULL, app_data TEXT NOT NULL, " + + "FOREIGN KEY(content_tag_id) REFERENCES content_tags(tag_id))"; + + private static final String INSERT_TAG_DATA = "(content_tag_id, app_data) VALUES (%d, '%s')"; + private static final String UPDATE_TAG_DATA = "SET content_tag_id = %d, app_data = '%s' WHERE app_data_id = %d"; + private static final String SELECT_TAG_DATA = "* FROM " + TABLE_NAME + " WHERE content_tag_id = %d"; + private static final String DELETE_TAG_DATA = "WHERE app_data_id = %d"; + + /** + * Creates and saves a new ContentViewerTag in the case database. The + * generic tag data instance T will be automatically serialized into a + * storable format. + * + * @param Generic class type that will be serialized into a storable + * format for persistence. + * @param contentTag ContentTag that this ContentViewerTag is associated + * with (1:1). + * @param tagDataBean Data instance that contains the tag information to be + * persisted. + * @return An instance of a ContentViewerTag of type T, which contains all + * the stored information. + * + * @throws SerializationException Thrown if the tag data instance T could + * not be serialized into a storable format. + * @throws TskCoreException Thrown if this operation did not successfully + * persist in the case database. + * @throws NoCurrentCaseException Thrown if invocation of this method occurs + * when no case is open. + */ + public static ContentViewerTag saveTag(ContentTag contentTag, T tagDataBean) + throws SerializationException, TskCoreException, NoCurrentCaseException { + try { + long contentTagId = contentTag.getId(); + String serialAppData = SERIALIZER.writeValueAsString(tagDataBean); + String insertTemplateInstance = String.format(INSERT_TAG_DATA, + contentTagId, serialAppData); + long insertId = Case.getCurrentCaseThrows() + .getSleuthkitCase() + .getCaseDbAccessManager() + .insert(TABLE_NAME, insertTemplateInstance); + return new ContentViewerTag<>(insertId, contentTag, tagDataBean); + } catch (JsonProcessingException ex) { + throw new SerializationException("Unable to convert object instance into a storable format", ex); + } + } + + /** + * Updates the ContentViewerTag instance with the new tag data T and + * persists the changes to the case database. + * + * @param Generic class type that will be serialized into a storable + * format. + * @param oldTag ContentViewerTag instance to be updated + * @param tagDataBean Data instance that contains the updated information to + * be persisted. + * + * @throws SerializationException Thrown if the tag data instance T could + * not be serialized into a storable format. + * @throws TskCoreException Thrown if this operation did not successfully + * persist in the case database. + * @throws NoCurrentCaseException Thrown if invocation of this method occurs + * when no case is open. + */ + public static ContentViewerTag updateTag(ContentViewerTag oldTag, T tagDataBean) + throws SerializationException, TskCoreException, NoCurrentCaseException { + try { + String serialAppData = SERIALIZER.writeValueAsString(tagDataBean); + String updateTemplateInstance = String.format(UPDATE_TAG_DATA, + oldTag.getContentTag().getId(), serialAppData, oldTag.getId()); + Case.getCurrentCaseThrows() + .getSleuthkitCase() + .getCaseDbAccessManager() + .update(TABLE_NAME, updateTemplateInstance); + return new ContentViewerTag<>(oldTag.getId(), oldTag.getContentTag(), tagDataBean); + } catch (JsonProcessingException ex) { + throw new SerializationException("Unable to convert object instance into a storable format", ex); + } + } + + /** + * Retrieves a ContentViewerTag instance that is associated with the + * specified ContentTag. The Java class T that represents the technical + * details of the tag should be passed so that automatic binding can take + * place. + * + * @param Generic class type that will be instantiated and filled in + * with data. + * @param contentTag ContentTag that this ContentViewerTag is associated + * with (1:1) + * @param clazz Generic class that will be instantiated and filled in with + * data. + * @return ContentViewerTag with an instance of T as a member variable or + * null if the content tag does not have an associated ContentViewerTag of + * type T. + * + * @throws TskCoreException Thrown if this operation did not successfully + * persist in the case database. + * @throws NoCurrentCaseException Thrown if invocation of this method occurs + * when no case is open. + */ + public static ContentViewerTag getTag(ContentTag contentTag, Class clazz) throws TskCoreException, NoCurrentCaseException { + String selectTemplateInstance = String.format(SELECT_TAG_DATA, contentTag.getId()); + final ResultWrapper> result = new ResultWrapper<>(); + Case.getCurrentCaseThrows() + .getSleuthkitCase() + .getCaseDbAccessManager() + .select(selectTemplateInstance, (ResultSet rs) -> { + try { + if (rs.next()) { + long tagId = rs.getLong(1); + String appDetails = rs.getString(3); + try { + T instance = SERIALIZER.readValue(appDetails, clazz); + result.setResult(new ContentViewerTag<>(tagId, contentTag, instance)); + } catch (IOException ex) { + //Databind for type T failed. Not a system error + //but rather a logic error on the part of the caller. + result.setResult(null); + } + } + } catch (SQLException ex) { + result.setException(ex); + } + }); + + if (result.hasException()) { + throw new TskCoreException("Unable to select tag from case db", result.getException()); + } + + return result.getResult(); + } + + /** + * Wrapper for holding state in the CaseDbAccessQueryCallback. + * CaseDbAccessQueryCallback has no support for exception handling. + * + * @param + */ + private static class ResultWrapper { + + private T result; + private SQLException ex = null; + + public void setResult(T result) { + this.result = result; + } + + public void setException(SQLException ex) { + this.ex = ex; + } + + public boolean hasException() { + return this.ex != null; + } + + public SQLException getException() { + return ex; + } + + public T getResult() { + return result; + } + } + + /** + * Deletes the content viewer tag with the specified id. + * + * @param contentViewerTag ContentViewerTag to delete + * @throws TskCoreException Thrown if this operation did not successfully + * persist in the case database. + * @throws NoCurrentCaseException Thrown if invocation of this method occurs + * when no case is open. + */ + public static void deleteTag(ContentViewerTag contentViewerTag) throws TskCoreException, NoCurrentCaseException { + String deleteTemplateInstance = String.format(DELETE_TAG_DATA, contentViewerTag.getId()); + Case.getCurrentCaseThrows() + .getSleuthkitCase() + .getCaseDbAccessManager() + .delete(TABLE_NAME, deleteTemplateInstance); + } + + /** + * This class represents a stored tag in the case database. It is a wrapper + * for the tag id, the attached Content tag object, and the Java bean + * instance that describes the technical details for reconstructing the tag. + * + * @param Generic class type that will be instantiated and filled in + * with data. + */ + public static class ContentViewerTag { + + private final long id; + private final ContentTag contentTag; + private final T details; + + private ContentViewerTag(long id, ContentTag contentTag, T details) { + this.id = id; + this.contentTag = contentTag; + this.details = details; + } + + public long getId() { + return id; + } + + public ContentTag getContentTag() { + return contentTag; + } + + public T getDetails() { + return details; + } + } + + /** + * System exception thrown in the event that class instance T could not be + * properly serialized. + */ + public static class SerializationException extends Exception { + + public SerializationException(String message, Exception source) { + super(message, source); + } + } + + //Prevent this class from being instantiated. + private ContentViewerTagManager() { + } +} diff --git a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/Bundle.properties-MERGED index d164529639..9cd17f566f 100755 --- a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/Bundle.properties-MERGED @@ -1,13 +1,8 @@ AbstractCommonFilesMetadataBuilder.buildCategorySelectionString.all=All File Categories AbstractCommonFilesMetadataBuilder.buildCategorySelectionString.doc=Documents AbstractCommonFilesMetadataBuilder.buildCategorySelectionString.media=Media -# {0} - threshold percent AbstractCommonFilesMetadataBuilder.getPercentFilter.thresholdPercent=, Threshold {0}% -# {0} - attr type -# {1} - threshold string AllInterCaseCommonAttributeSearcher.buildTabTitle.titleInterAll=Common Properties (All Central Repository Cases, {0}{1}) -# {0} - build category -# {1} - threshold string AllIntraCaseCommonAttributeSearcher.buildTabTitle.titleIntraAll=Common Properties (All Data Sources, {0}{1}) # {0} - number of datasources CommonAttributePanel.dataSourcesLabel.text=The current Central Repository contains {0} data source(s). @@ -103,13 +98,7 @@ CommonAttributePanel.organizeByCountRadio.text=Number of occurrences CommonAttributePanel.caseResultsRadioButton.text=Case CommonAttributePanel.countResultsRadioButton.text=Number of data sources CommonAttributePanel.displayResultsLabel.text_2=Display results organized by: -# {0} - case name -# {1} - attr type -# {2} - threshold string SingleInterCaseCommonAttributeSearcher.buildTabTitle.titleInterSingle=Common Properties (Central Repository Case: {0}, {1}{2}) -# {0} - data source name -# {1} - build category -# {2} - threshold string SingleIntraCaseCommonAttributeSearcher.buildTabTitle.titleIntraSingle=Common Properties (Data Source: {0}, {1}{2}) UserInputErrorManager.categories=No file categories are included in the search. UserInputErrorManager.frequency=Invalid Frequency Percentage: 0 < % < 100. diff --git a/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java index fcf64182a3..54ab3fba23 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/AccountsBrowser.java @@ -75,6 +75,10 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro public AccountsBrowser() { initComponents(); + + jSplitPane1.setResizeWeight(0.5); + jSplitPane1.setDividerLocation(0.75); + outline = outlineView.getOutline(); outlineView.setPropertyColumns( "device", Bundle.AccountNode_device(), diff --git a/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.form b/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.form index 055719c488..77fc276f83 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.form +++ b/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.form @@ -13,32 +13,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -51,6 +26,11 @@ + + + + + @@ -90,6 +70,11 @@ + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java b/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java index 16c3208ff8..8e8365436c 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java @@ -22,12 +22,13 @@ import com.google.common.eventbus.Subscribe; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; import java.util.List; import java.util.stream.Collectors; -import javax.swing.GroupLayout; import javax.swing.ImageIcon; import javax.swing.JTabbedPane; -import javax.swing.LayoutStyle; import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.windows.Mode; @@ -93,39 +94,39 @@ public final class CVTTopComponent extends TopComponent { */ // //GEN-BEGIN:initComponents private void initComponents() { + GridBagConstraints gridBagConstraints; browseVisualizeTabPane = new JTabbedPane(); accountsBrowser = new AccountsBrowser(); vizPanel = new VisualizationPanel(); filtersPane = new FiltersPanel(); + setLayout(new GridBagLayout()); + browseVisualizeTabPane.setFont(new Font("Tahoma", 0, 18)); // NOI18N browseVisualizeTabPane.addTab(NbBundle.getMessage(CVTTopComponent.class, "CVTTopComponent.accountsBrowser.TabConstraints.tabTitle_1"), new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/table.png")), accountsBrowser); // NOI18N browseVisualizeTabPane.addTab(NbBundle.getMessage(CVTTopComponent.class, "CVTTopComponent.vizPanel.TabConstraints.tabTitle_1"), new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/emblem-web.png")), vizPanel); // NOI18N - filtersPane.setMinimumSize(new Dimension(256, 495)); - - GroupLayout layout = new GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(6, 6, 6) - .addComponent(filtersPane, GroupLayout.PREFERRED_SIZE, 265, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(browseVisualizeTabPane, GroupLayout.PREFERRED_SIZE, 786, Short.MAX_VALUE) - .addContainerGap()) - ); - layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(6, 6, 6) - .addComponent(filtersPane, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGap(5, 5, 5)) - .addGroup(GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addComponent(browseVisualizeTabPane) - .addContainerGap()) - ); - + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = GridBagConstraints.BOTH; + gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new Insets(15, 0, 15, 15); + add(browseVisualizeTabPane, gridBagConstraints); browseVisualizeTabPane.getAccessibleContext().setAccessibleName(NbBundle.getMessage(CVTTopComponent.class, "CVTTopComponent.browseVisualizeTabPane.AccessibleContext.accessibleName")); // NOI18N + + filtersPane.setMinimumSize(new Dimension(256, 495)); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = GridBagConstraints.BOTH; + gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new Insets(15, 15, 15, 5); + add(filtersPane, gridBagConstraints); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED index b31598dbc6..162cf1982f 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties-MERGED @@ -44,3 +44,4 @@ SummaryViewer_CentralRepository_Message= diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.form b/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.form index 83cb8057d0..308eec1a42 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.form +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.form @@ -11,29 +11,38 @@ + - - - - - - - - - - - - - - - - - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.java index 2fec1406c0..4fdb400c87 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.java @@ -23,7 +23,6 @@ import java.awt.KeyboardFocusManager; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JPanel; -import javax.swing.SwingUtilities; import static javax.swing.SwingUtilities.isDescendingFrom; import org.netbeans.swing.outline.DefaultOutlineModel; import org.netbeans.swing.outline.Outline; @@ -126,6 +125,9 @@ public final class ContactsViewer extends JPanel implements RelationshipsViewer{ updateOutlineViewPanel(); } }); + + splitPane.setResizeWeight(0.5); + splitPane.setDividerLocation(0.5); } @Override @@ -183,29 +185,32 @@ public final class ContactsViewer extends JPanel implements RelationshipsViewer{ @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + splitPane = new javax.swing.JSplitPane(); contactPane = new org.sleuthkit.autopsy.communications.relationships.ContactDetailsPane(); outlineViewPanel = new org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel(); - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(contactPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(outlineViewPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(outlineViewPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(contactPane, javax.swing.GroupLayout.DEFAULT_SIZE, 332, Short.MAX_VALUE)) - ); + setLayout(new java.awt.GridBagLayout()); + + splitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); + splitPane.setRightComponent(contactPane); + splitPane.setLeftComponent(outlineViewPanel); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + add(splitPane, gridBagConstraints); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private org.sleuthkit.autopsy.communications.relationships.ContactDetailsPane contactPane; private org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel outlineViewPanel; + private javax.swing.JSplitPane splitPane; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.form b/Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.form index 8f311d3dd4..cd109eaea8 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.form +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.form @@ -11,58 +11,57 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.java index 95405b0887..cbb71263e2 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.java @@ -65,6 +65,11 @@ final class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerM * Creates new form ThumbnailViewer */ public MediaViewer() { + initComponents(); + + splitPane.setResizeWeight(0.5); + splitPane.setDividerLocation(0.5); + proxyLookup = new ModifiableProxyLookup(createLookup(tableEM, getActionMap())); // See org.sleuthkit.autopsy.timeline.TimeLineTopComponent for a detailed @@ -87,8 +92,6 @@ final class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerM } }; - initComponents(); - tableEM.addPropertyChangeListener((PropertyChangeEvent evt) -> { if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) { handleNodeSelectionChange(); @@ -190,43 +193,37 @@ final class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerM @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + splitPane = new javax.swing.JSplitPane(); thumbnailViewer = new org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail(tableEM); contentViewer = new MessageDataContent(); - separator = new javax.swing.JSeparator(); + + setLayout(new java.awt.GridBagLayout()); + + splitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); thumbnailViewer.setMinimumSize(new java.awt.Dimension(350, 102)); thumbnailViewer.setPreferredSize(new java.awt.Dimension(450, 400)); + splitPane.setLeftComponent(thumbnailViewer); contentViewer.setPreferredSize(new java.awt.Dimension(450, 400)); + splitPane.setRightComponent(contentViewer); - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(thumbnailViewer, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(contentViewer, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(separator) - .addContainerGap()) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(thumbnailViewer, javax.swing.GroupLayout.DEFAULT_SIZE, 350, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(separator, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(contentViewer, javax.swing.GroupLayout.PREFERRED_SIZE, 450, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(3, 3, 3)) - ); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + add(splitPane, gridBagConstraints); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private org.sleuthkit.autopsy.contentviewers.MessageContentViewer contentViewer; - private javax.swing.JSeparator separator; + private javax.swing.JSplitPane splitPane; private org.sleuthkit.autopsy.corecomponents.DataResultViewerThumbnail thumbnailViewer; // End of variables declaration//GEN-END:variables diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/MessageNode.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/MessageNode.java index e6ac3f507f..d1cdcbabf2 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/MessageNode.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/MessageNode.java @@ -18,13 +18,10 @@ */ package org.sleuthkit.autopsy.communications.relationships; -import java.util.List; import java.util.TimeZone; import java.util.logging.Level; import org.apache.commons.lang3.StringUtils; import org.openide.nodes.Sheet; -import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; -import org.sleuthkit.autopsy.core.UserPreferences; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; @@ -40,7 +37,6 @@ import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHO import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT; import static org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME; -import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TimeUtilities; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.communications.Utils; @@ -72,7 +68,6 @@ final class MessageNode extends BlackboardArtifactNode { @Override protected Sheet createSheet() { Sheet sheet = super.createSheet(); - List tags = getAllTagsFromDatabase(); Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES); if (sheetSet == null) { sheetSet = Sheet.createPropertiesSet(); @@ -81,17 +76,6 @@ final class MessageNode extends BlackboardArtifactNode { sheetSet.put(new NodeProperty<>("Type", Bundle.MessageNode_Node_Property_Type(), "", getDisplayName())); //NON-NLS - addScoreProperty(sheetSet, tags); - - CorrelationAttributeInstance correlationAttribute = null; - if (UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) { - correlationAttribute = getCorrelationAttributeInstance(); - } - addCommentProperty(sheetSet, tags, correlationAttribute); - - if (UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) { - addCountProperty(sheetSet, correlationAttribute); - } final BlackboardArtifact artifact = getArtifact(); BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID()); diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/MessagesViewer.form b/Core/src/org/sleuthkit/autopsy/communications/relationships/MessagesViewer.form index 34126bbf8c..780c55aa04 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/MessagesViewer.form +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/MessagesViewer.form @@ -11,32 +11,41 @@ + - - - - - - - - - - - - - - - - - + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/MessagesViewer.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/MessagesViewer.java index 8bda078161..f258e2c7a3 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/MessagesViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/MessagesViewer.java @@ -23,7 +23,6 @@ import java.awt.KeyboardFocusManager; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JPanel; -import javax.swing.SwingUtilities; import static javax.swing.SwingUtilities.isDescendingFrom; import org.netbeans.swing.outline.DefaultOutlineModel; import org.netbeans.swing.outline.Outline; @@ -68,6 +67,8 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer public MessagesViewer() { initComponents(); + splitPane.setResizeWeight(0.5); + outlineViewPanel.hideOutlineView(Bundle.MessageViewer_no_messages()); proxyLookup = new ModifiableProxyLookup(createLookup(outlineViewPanel.getExplorerManager(), getActionMap())); @@ -138,6 +139,8 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer updateOutlineViewPanel(); } }); + + outlineViewPanel.setTableColumnsWidth(5,10,10,15,50,10); } @Override @@ -192,29 +195,32 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + splitPane = new javax.swing.JSplitPane(); contentViewer = new MessageDataContent(); outlineViewPanel = new org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel(); - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(contentViewer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(outlineViewPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(outlineViewPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(contentViewer, javax.swing.GroupLayout.DEFAULT_SIZE, 390, Short.MAX_VALUE)) - ); + setLayout(new java.awt.GridBagLayout()); + + splitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); + splitPane.setBottomComponent(contentViewer); + splitPane.setLeftComponent(outlineViewPanel); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + add(splitPane, gridBagConstraints); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private org.sleuthkit.autopsy.contentviewers.MessageContentViewer contentViewer; private org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel outlineViewPanel; + private javax.swing.JSplitPane splitPane; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/OutlineViewPanel.form b/Core/src/org/sleuthkit/autopsy/communications/relationships/OutlineViewPanel.form index 5efb16c2b1..159fd3d554 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/OutlineViewPanel.form +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/OutlineViewPanel.form @@ -1,6 +1,9 @@
+ + + @@ -21,6 +24,7 @@ + diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/OutlineViewPanel.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/OutlineViewPanel.java index 4e04db4f53..ff229960c3 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/OutlineViewPanel.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/OutlineViewPanel.java @@ -19,7 +19,9 @@ package org.sleuthkit.autopsy.communications.relationships; import java.awt.CardLayout; +import javax.swing.JTable; import javax.swing.SwingUtilities; +import javax.swing.table.TableColumn; import org.openide.explorer.ExplorerManager; import static org.openide.explorer.ExplorerUtils.createLookup; import org.openide.explorer.view.OutlineView; @@ -98,7 +100,20 @@ public class OutlineViewPanel extends javax.swing.JPanel implements ExplorerMana super.setEnabled(enabled); outlineView.setEnabled(enabled); } + + public void setTableColumnsWidth(double... percentages) { + JTable table = outlineView.getOutline(); + double total = 0; + for (int i = 0; i < table.getColumnModel().getColumnCount(); i++) { + total += percentages[i]; + } + for (int i = 0; i < table.getColumnModel().getColumnCount(); i++) { + TableColumn column = table.getColumnModel().getColumn(i); + column.setPreferredWidth((int) (table.getPreferredSize().width * (percentages[i] / total))); + } + } + /** * 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 @@ -112,8 +127,10 @@ public class OutlineViewPanel extends javax.swing.JPanel implements ExplorerMana messagePanel = new javax.swing.JPanel(); messageLabel = new javax.swing.JLabel(); + setEnabled(false); setLayout(new java.awt.CardLayout(5, 5)); + outlineView.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); outlineView.setPreferredSize(new java.awt.Dimension(300, 400)); add(outlineView, "outlineCard"); diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.form b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.form index ac40867a25..fefdd4dc19 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.form +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.form @@ -11,42 +11,22 @@ + - - - - - - - - - - - - - - - - - - + - - - - + + + + + + + + + - - - - - - - - - - + diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java index b8c19f518e..29ec349b82 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java @@ -54,9 +54,7 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider tabPane.add(summaryViewer.getDisplayName(), summaryViewer); tabPane.add(messagesViewer.getDisplayName(), messagesViewer); tabPane.add(contactsViewer.getDisplayName(), contactsViewer); - tabPane.add(mediaViewer.getDisplayName(), mediaViewer); - - + tabPane.add(mediaViewer.getDisplayName(), mediaViewer); } /** @@ -78,33 +76,26 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; - scrollPane = new javax.swing.JScrollPane(); tabPane = new javax.swing.JTabbedPane(); - scrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); + setLayout(new java.awt.GridBagLayout()); tabPane.addChangeListener(new javax.swing.event.ChangeListener() { public void stateChanged(javax.swing.event.ChangeEvent evt) { tabPaneStateChanged(evt); } }); - scrollPane.setViewportView(tabPane); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 400, Short.MAX_VALUE) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(scrollPane, javax.swing.GroupLayout.Alignment.TRAILING)) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 300, Short.MAX_VALUE) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(scrollPane)) - ); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(1, 1, 1, 1); + add(tabPane, gridBagConstraints); }// //GEN-END:initComponents private void tabPaneStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabPaneStateChanged @@ -121,7 +112,6 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JScrollPane scrollPane; private javax.swing.JTabbedPane tabPane; // End of variables declaration//GEN-END:variables diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.form b/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.form index af02a7dee7..c789e2c0cd 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.form +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.form @@ -11,36 +11,10 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -52,6 +26,11 @@ + + + + + @@ -183,7 +162,7 @@ - + @@ -192,12 +171,14 @@ - - - + + + + + - + @@ -206,10 +187,12 @@ - - - + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.java index d31e7c902f..464fb137f8 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.java @@ -46,7 +46,8 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi "SummaryViewer_FileRefNameColumn_Title=Path", "SummaryViewer_CaseRefNameColumn_Title=Case Name", "SummaryViewer_CentralRepository_Message=", - "SummaryViewer_Creation_Date_Title=Creation Date" + "SummaryViewer_Creation_Date_Title=Creation Date", + "SummeryViewer_FileRef_Message=